unity3d-GUI制作井字棋游戏

使用Unity3D GUI 做井字棋游戏

井字棋游戏,英文名字Tic-Tac-Toe。是一款双人的游戏,在井字格中连O或X连成一条直线即算胜利。下面我们将用Unity3D的GUI来实现这一游戏,目的在于熟悉GUI的基本使用功能。

成品图

下面是成品图:

MonoBehaviour.OnGUI()

首先,我们要了解OnGUI这一函数的使用功能。在Unity的官方文档对 MonoBehaviour.OnGUI()中给出了如下定义:

OnGUI is called for rendering and handling GUI events.

This means that your OnGUI implementation might be called several times per frame (one call per event). For more information on GUI events see the Event reference. If the MonoBehaviour’s enabled property is set to false, OnGUI() will not be called.

也就是说OnGUI每一帧会被调用好几次,用来处理和GUI有关的事件。

在下面的游戏完成过程中,我们会使用到GUI.Button()、GUI.Label()这两个函数功能。

public static bool Button(Rect position, string text); 当按键被点击之后会返回true的布尔值。

public static void Label(Rect position, string text); 可以在屏幕上显示一行文字。

通过new Rect(x, y, width, heigh) 四个参数在(x,y)处创建一个长width,高height的长方形区域。

基本思路

所以我们的基本思路,就是写出一个c#脚本,直接将其挂载在摄像机上即可。在脚本中,每下一步就要判断是否有人胜利,胜利则游戏结束,不可以再进行点击,只能重新开始。未胜利则继续游戏。胜利的条件就是O或者X连成了一条线,可以是一行也可以是一列,也可以是主对角线或者副对角线。

记录游戏顺序,我们需要使用一个变量turn来标记是谁的回合,使用一个二维数组map来存储棋盘棋子。

1
// use 2 dimension arrary to store the game data, 1 means O, 2 means X, 0 means blank.
2
	private int[,] map = new int[3,3];
3
// 0 means O's turn, 1 means X'turn.
4
	private int turn = 0;

还需要有一个开始游戏的功能,刚开局或者重新开局之后就调用reset()这个函数。这个函数就是将棋盘清空,开手重置。

1
void reset() {
2
	// set the map blank
3
	int i = 0, j = 0;
4
	for (i = 0; i < 3; i++) {
5
		for (j = 0; j < 3; j++) {
6
			map [i,j] = 0;
7
		}
8
	}
9
	turn = 0;
10
}

判断胜负

判断胜利,从行、列、对角线的数组元素来进行判断。若一致则胜利

1
// 1 means O wins, 2 means X wins, 0 means playing.
2
	int check() {
3
		//check row
4
		int i = 0, j = 0;
5
		for (i = 0; i < 3; i++) {
6
			if (map [i,0] == map [i,1] && map [i,1] == map [i,2]) {
7
				return map [i,0];
8
			}
9
		}
10
		// check col
11
		for (j = 0; j < 3; j++) {
12
			if (map [0,j] == map [1,j] && map [1,j] == map [2,j]) {
13
				return map [0,j];
14
			}
15
		}
16
		// check diagonal
17
		if ((map [0, 0] == map [1, 1] && map [1, 1] == map [2, 2]) ||
18
		    (map [0, 2] == map [1, 1] && map [1, 1] == map [2, 0])) {
19
			return map [1, 1];
20
		}
21
		return 0;
22
	}

补充 OnGUI()函数

首先渲染重新开始按键,然后判断游戏状态:是否有胜利者,或者还在游戏中。然后通过两层循环渲染出棋盘和棋子。棋子具体是O、X还是空白,通过map数组来进行判断。当然要确保游戏有人胜利之后不能再继续下棋,则需要在改变map数组值的时候判断好游戏状态。

1
void OnGUI() {
2
    if (GUI.Button(new Rect(20,300,100,50),"Restart"))  
3
        reset();
4
    int result = check();
5
    // display the result
6
    if (result == 1) {
7
        GUI.Label (new Rect (50, 200, 100, 50), "O wins");
8
    } else if (result == 2) {
9
        GUI.Label (new Rect (50, 200, 100, 50), "X wins");
10
    }
11
12
    int i = 0, j = 0;
13
    for (i = 0; i < 3; i++) {
14
        for (j = 0; j < 3; j++) {
15
            if (map [i,j] == 1) {
16
                GUI.Button (new Rect (50 * i, 50 * j, 50, 50), "O");
17
            } else if (map [i,j] == 2) {
18
                GUI.Button (new Rect (50 * i, 50 * j, 50, 50), "X");
19
            } else {
20
                if (GUI.Button (new Rect (50 * i, 50 * j, 50, 50), "")) {
21
                    if (result == 0) {
22
                        if (turn == 0) {
23
                            map [i, j] = 1;
24
                            turn = 1;
25
                        } else {
26
                            map [i, j] = 2;
27
                            turn = 0;
28
                        }
29
                    }
30
                }
31
            }
32
        }
33
    }
34
}

完整代码

1
using UnityEngine;
2
using System.Collections;
3
4
public class Game : MonoBehaviour {
5
6
	// use 2 dimension arrary to store the game data, 1 means O, 2 means X, 0 means blank.
7
	private int[,] map = new int[3,3];
8
	// 0 means O's turn, 1 means X'turn.
9
	private int turn = 0;
10
11
	// Use this for initialization
12
	void Start () {
13
		reset ();
14
	}
15
16
	// OnGUI method will refresh automaticlly
17
	// method is OnGUI not OnGui
18
	void OnGUI() {
19
		if (GUI.Button(new Rect(20,300,100,50),"Restart"))  
20
			reset();
21
		int result = check();
22
		// display the result
23
		if (result == 1) {
24
			GUI.Label (new Rect (50, 200, 100, 50), "O wins");
25
		} else if (result == 2) {
26
			GUI.Label (new Rect (50, 200, 100, 50), "X wins");
27
		}
28
29
		int i = 0, j = 0;
30
		for (i = 0; i < 3; i++) {
31
			for (j = 0; j < 3; j++) {
32
				if (map [i,j] == 1) {
33
					GUI.Button (new Rect (50 * i, 50 * j, 50, 50), "O");
34
				} else if (map [i,j] == 2) {
35
					GUI.Button (new Rect (50 * i, 50 * j, 50, 50), "X");
36
				} else {
37
					if (GUI.Button (new Rect (50 * i, 50 * j, 50, 50), "")) {
38
						if (result == 0) {
39
							if (turn == 0) {
40
								map [i, j] = 1;
41
								turn = 1;
42
							} else {
43
								map [i, j] = 2;
44
								turn = 0;
45
							}
46
						}
47
					}
48
				}
49
			}
50
		}
51
	}
52
53
	void reset() {
54
		// set the map blank
55
		int i = 0, j = 0;
56
		for (i = 0; i < 3; i++) {
57
			for (j = 0; j < 3; j++) {
58
				map [i,j] = 0;
59
			}
60
		}
61
		turn = 0;
62
	}
63
64
	// 1 means O wins, 2 means X wins, 0 means playing.
65
	int check() {
66
		//check row
67
		int i = 0, j = 0;
68
		for (i = 0; i < 3; i++) {
69
			if (map [i,0] == map [i,1] && map [i,1] == map [i,2]) {
70
				return map [i,0];
71
			}
72
		}
73
		// check col
74
		for (j = 0; j < 3; j++) {
75
			if (map [0,j] == map [1,j] && map [1,j] == map [2,j]) {
76
				return map [0,j];
77
			}
78
		}
79
		// check diagonal
80
		if ((map [0, 0] == map [1, 1] && map [1, 1] == map [2, 2]) ||
81
		    (map [0, 2] == map [1, 1] && map [1, 1] == map [2, 0])) {
82
			return map [1, 1];
83
		}
84
		return 0;
85
	}
86
}

参考

Simba_Scorpio.Unity3D学习笔记(2)——用GUI制作井字棋游戏

您的支持将鼓励我继续创作!