用Unity3D实现简单的井字棋小游戏
用Unity3D實現簡單的井字棋小游戲
項目地址
井字棋小游戲
完成效果圖
實現思路
首先定義游戲的數據部分:
/* 井字棋中每一個棋格中的邏輯控制常量,代表這個棋格的狀態 */ private const int NOPLAYER = 0; // 0代表這個棋格沒有玩家 private const int PLAYER1 = 1; // 1代表玩家1占據這個棋格 private const int PLAYER2 = 2; // 2代表玩家2占據這個棋格/* 整個游戲需要用到的邏輯控制變量 */ private int gameTurn = PLAYER1; // 游戲回合,PLAYER1代表這個游戲回合是玩家1的,PLAYER2代表是玩家2的回合 private int totalMoves = 0; // 兩個玩家總共進行的回合數 private int totalPlayer = 0; // 游戲的玩家數,0代表還未選擇游戲模式,1代表與電腦進行對決,2代表雙人游戲 private int [,] chessBoard = new int [3, 3]; // 井字棋盤/* 井字棋棋格的布局設置 */ private static int buttonWidth = 80; // 每個棋格的寬度 private static int buttonHeight = 80; // 每個棋格的高度 // 井字棋中最左上角第一個棋格的橫坐標位置 private static int firstButtonX = (Screen.width - 3 * TicTacToe.buttonWidth) / 2; // 井字棋中最左上角第一個棋格的縱坐標位置 private static int firstButtonY = Screen.height - 3 * TicTacToe.buttonHeight - 10;/* 游戲界面設計用到的變量 */ public Texture2D backgroundImage; // 游戲背景圖片 public GUISkin gameSkin; // 游戲控件的皮膚風格接著確定游戲界面組成部分:
可以看到,游戲界面由四個部分組成:背景、標題、提示框、按鈕,其中按鈕又分為游戲模式選擇按鈕、棋格按鈕、重置按鈕三個部分,所以在最終顯示場景的OnGUI()方法中,只有一個PlayGameSystem()方法,在PlayGameSystem()方法中,只有AddBackground()、AddTitle()、AddTip()、AddButton()四個方法,分別添加背景、標題、提示框、按鈕這四個部分。
在AddBackground()、AddTitle()這兩個方法中,沒有使用到什么復雜的邏輯,直接創建背景和標題即可:
/* 添加游戲背景 */ void AddBackground() {GUIStyle backgroundStyle = new GUIStyle();// 設置游戲背景圖片backgroundStyle.normal.background = backgroundImage;GUI.Label(new Rect(0, 0, 710, 388), "", backgroundStyle); }/* 添加游戲標題 */ void AddTitle() {// 設置標題樣式GUIStyle titleStyle = new GUIStyle();titleStyle.fontSize = 40;titleStyle.fontStyle = FontStyle.Bold;titleStyle.normal.textColor = Color.black;// 標題顯示內容為TicTacToe GameGUI.Label(new Rect(Screen.width / 2 - 150, 20, 300, 50), "TicTacToe Game", titleStyle); }在AddTip()這個方法中,除了設置皮膚風格外,還有一個GetTipText()方法,根據游戲的不同狀態和是否有贏家,提示框的顯示內容都在其中進行處理,方法代碼如下:
/* 添加提示框 */ void AddTip() {// 選擇Label的皮膚風格GUI.skin = gameSkin;// 根據是否有贏家獲得提示框中的內容string text = GetTipText();// 繪制出提示框GUI.Label(new Rect(Screen.width / 2 - 320, 70, 650, 50), text); }/* 根據是否有贏家獲得提示框中的內容 */ string GetTipText() {// 檢查是否有贏家int winner = CheckWinner();switch (winner) {// 如果沒有贏家case NOPLAYER:// 如果總玩家數為0,即還未選擇游戲模式,那么提示選擇游戲模式if (totalPlayer == 0) {return "Please choose a game mode.";} else if (totalMoves == 0) { // 如果總回合數為0,說明還未開始游戲,提示點擊棋格并進行游戲return "Click and play the game.";} else if (totalMoves == 9) { // 如果總回合數為9,說明游戲結束且無玩家勝出,提示沒有贏家return "No Winner!";} else {// 如果是單人模式且游戲正在進行,提醒正在進行單人游戲模式if (totalPlayer == 1) {return "1 Player Mode Playing...";} else if (totalPlayer == 2) { // 如果是雙人模式且游戲正在進行,提醒正在進行雙人游戲模式return "2 Players Mode Playing...";}return "";}// 如果玩家1勝出case PLAYER1:// 提示框顯示玩家1勝出return "Player1(O) Wins!";// 如果玩家2勝出case PLAYER2:// 提示框顯示玩家2勝出return "Player2(X) Wins!";default:return "";} }檢查是否有贏家,需要用到表示棋盤狀態的一個二維數組chessBoard,聲明如下:
private int [,] chessBoard = new int [3, 3]; // 井字棋盤在這個用二維整型數組表示的棋盤中,0代表棋格沒有玩家,1代表玩家1占據這個棋格,2代表玩家2占據這個棋格,用CheckWinner()方法對這個棋盤進行檢查,可以知道是否存在贏家,代碼如下(NOPLAYER代表0,PLAYER1代表1,PLAYER2代表2):
/* 檢查是否有贏家 */ int CheckWinner() {// 一共有8種贏的情況,首先檢查3行3列的6種贏的情況for (int i = 0; i < 3; ++i) {if (chessBoard[i, 0] != NOPLAYER && chessBoard[i, 0] == chessBoard[i, 1] && chessBoard[i, 1] == chessBoard[i, 2]) {// 有玩家勝出,那么游戲回合置為NOPLAYER,返回這個玩家對應的值,1代表玩家1,2代表玩家2gameTurn = NOPLAYER;return chessBoard[i, 0];}if (chessBoard[0, i] != NOPLAYER && chessBoard[0, i] == chessBoard[1, i] && chessBoard[1, i] == chessBoard[2, i]) {gameTurn = NOPLAYER;return chessBoard[0, i];}}// 檢查對角線的2種贏的情況if (chessBoard[1, 1] != NOPLAYER) {if ((chessBoard[0, 0] == chessBoard[1, 1] && chessBoard[1, 1] == chessBoard[2, 2]) || (chessBoard[0, 2] == chessBoard[1, 1] && chessBoard[1, 1] == chessBoard[2, 0])) {gameTurn = NOPLAYER;return chessBoard[1, 1];}}// 沒人勝出,那么返回NOPLAYER,代表沒有贏家return NOPLAYER; }根據游戲狀態和贏家判斷,就會在提示框顯示相應的內容。
最后是AddButton()方法,里面處理設置按鈕風格以外,由三個方法AddGameButton()、AddResetButton()、AddChooseGameModeButton()組成,分別是添加棋盤、添加重置按鈕、添加游戲模式選擇按鈕:
/* 添加按鈕實現的井字棋格和功能按鈕 */ void AddButton() {// 選擇按鈕的皮膚風格GUI.skin = gameSkin;// 添加井字棋格AddGameButton();// 添加重置按鈕AddResetButton();// 添加游戲模式選擇按鈕AddChooseGameModeButton(); }在AddResetButton()、AddChooseGameModeButton()方法中,沒有用到過于復雜的邏輯,只有用到一個InitGameWithTotalPlayer(int playersNum)的初始化游戲方法,代碼如下:
/* 添加重置按鈕 */ void AddResetButton() {GUIStyle resetStyle = new GUIStyle("button");resetStyle.fontSize = 20;// 按下重置按鈕,游戲被初始化if (GUI.Button(new Rect(firstButtonX + 3 * buttonWidth + 50, Screen.height - 70, 80, 50), "Reset", resetStyle)) {InitGameWithTotalPlayer(totalPlayer);} }/* 添加游戲模式選擇按鈕 */ void AddChooseGameModeButton() {GUIStyle resetStyle = new GUIStyle("button");resetStyle.fontSize = 20;// 按下單人游戲模式按鈕,游戲被初始化,游戲玩家人數變為1if (GUI.Button(new Rect(firstButtonX - 200, Screen.height - 2 * buttonHeight - 40, 180, 50), "1 Player Mode", resetStyle)) {InitGameWithTotalPlayer(1);}// 按下雙人游戲模式按鈕,游戲被初始化,游戲玩家人數變為2if (GUI.Button(new Rect(firstButtonX - 200, Screen.height - buttonHeight - 40, 180, 50), "2 Players Mode", resetStyle)) {InitGameWithTotalPlayer(2);} }/* 用游戲的玩家數初始化游戲 */ void InitGameWithTotalPlayer(int playersNum) {// 游戲回合從Player1開始gameTurn = PLAYER1;// 總進行回合數設為0totalMoves = 0;// 設置游戲的玩家數totalPlayer = playersNum;// 棋盤的每一格都還沒被玩家占據for (int i = 0; i < 3; ++i) {for (int j = 0; j < 3; ++j) {chessBoard[i, j] = NOPLAYER;}} }在AddGameButton()方法中,按照坐標從左往右,從上往下設置棋格按鈕的樣式和功能,用到的是GetGameButtonText(int xIndex, int yIndex)和SetGameButtonFunction(int xIndex, int yIndex)方法,這個方法根據游戲模式以及chessBoard中的棋格狀態,設置按鈕的功能和內容,代碼如下:
/* 添加井字棋格 */ void AddGameButton() {// 按照坐標從左往右,從上往下設置棋格按鈕的樣式和功能for (int xIndex = 0; xIndex < 3; ++xIndex) {for (int yIndex = 0; yIndex < 3; ++yIndex) {// 按照橫縱坐標找到棋格相應的位置int buttonX = firstButtonX + xIndex * buttonWidth;int buttonY = firstButtonY + yIndex * buttonHeight;string text = GetGameButtonText(xIndex, yIndex);if (GUI.Button(new Rect(buttonX, buttonY, buttonWidth, buttonHeight), text)) {SetGameButtonFunction(xIndex, yIndex);}}} }/* 根據橫坐標和縱坐標獲取棋盤相應位置從而獲取井字棋格內容 */ string GetGameButtonText(int xIndex, int yIndex) {// 按照橫縱坐標找到棋格相應的位置int buttonX = firstButtonX + xIndex * buttonWidth;int buttonY = firstButtonY + yIndex * buttonHeight;// 獲取對應坐標中棋格的信息int Player = chessBoard[yIndex, xIndex];switch (Player) {// 如果這個棋格中為NOPLAYERcase NOPLAYER:// 設置按鈕中不顯示任何內容return "";// 如果這個棋格中為PLAYER1case PLAYER1:// 棋格中顯示內容為Oreturn "O";// 如果這個棋格中為PLAYER2case PLAYER2:// 棋格中顯示內容為Xreturn "X";default:return "";} }/* 根據橫坐標和縱坐標獲取棋盤相應位置從而設置相應棋格功能 */ void SetGameButtonFunction(int xIndex, int yIndex) {int Player = chessBoard[yIndex, xIndex];switch (Player) {// 如果這個棋格中為NOPLAYERcase NOPLAYER:// 如果還未選擇游戲模式,那么進行提示,且點擊按鈕無反應if (totalPlayer == 0) {return;}// 選擇游戲模式并點擊棋格后,該棋格設置為這個游戲回合對應的玩家,游戲回合轉換,總回合數加一chessBoard[yIndex, xIndex] = gameTurn;gameTurn = (gameTurn == PLAYER1 ? PLAYER2 : PLAYER1);totalMoves++;// 如果是單人游戲模式且游戲還未結束,那么電腦直接來走一步if (totalPlayer == 1 && totalMoves < 9 && CheckWinner() == NOPLAYER) {ComputerMove();}break;// 如果這個棋格中為PLAYER1,無反應case PLAYER1:break;// 如果這個棋格中為PLAYER2,無反應case PLAYER2:break;} }最后在PlayGameSystem()方法中添加背景、標題、提示框、游戲按鈕,游戲就可以運行了,代碼如下:
/* 進行游戲 */ void PlayGameSystem() {AddBackground(); // 添加游戲背景AddTitle(); // 添加游戲標題AddTip(); // 添加提示框AddButton(); // 添加游戲按鈕 }void OnGUI() {PlayGameSystem(); }游戲截圖:
玩家1勝出:
玩家2勝出:
打成平局:
總結
以上是生活随笔為你收集整理的用Unity3D实现简单的井字棋小游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统实验报告18:硬盘柱面访问调度算
- 下一篇: 用Unity3D实现简单的牧师与魔鬼游戏