简单的unity小游戏--五子棋

前言:

          该小游戏的代码分为三个部分,分别是模型部分(model)、视图部分(view)和控制部分(controller)。使用训练数据-控制分离的编程思维,其中模型部分只包含游戏对象数据,视图部分只使用IMGUI构建UI,控制部分控制模型对象(数据)的基本操作逻辑,而整个系统指在游戏循环驱动下,运用部件完成游戏逻辑。

模型部分:

        首先是模型部分,模型部分包含了五子棋游戏所需要的游戏对象,分别是玩家编号(两名玩家),落子的个数(用于判断棋盘是否下满),胜利者的编号(用于保存胜利玩家编号),棋盘的大小(设置为一个10×10的矩阵)。并且重构Start()函数作为游戏的开始。

        模型部分代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class wuziGame : MonoBehaviour {

    // 模型部分(model)
    private static int player;         // 玩家编号,取值为1或2
    private static int count;          // 落子的个数
    private int winner;                // 胜利者编号
    private int[,] chessBoard = new int[10, 10];    // 棋盘矩阵大小为10*10

    void Start () {
        Init();         // 开始游戏时初始化
    }
    // ... 
}

 

视图部分:

        视图部分采用IMGUI绘制UI界面,而IMGUI会在每一帧都执行,因此重构OnGUI()函数,使其每一帧都能执行。采用GUI的盒子(box)部件来绘制一个矩形的边框,同时在底下绘制一个名为“restart”的按钮作为重新开始按钮,当按下时会执行初始化函数。在这之后,遍历10×10的棋盘矩阵,由于棋盘可能的取值为0,1,2,分别代表空白、玩家1和玩家2。

        当遍历到取值0的棋盘时,根据棋盘的所在位置关系(即横纵坐标255+j*21,50+i*21)绘制一个大小为21×21的矩形作为棋盘的格子,并命名为“ ”作为空格子,如果玩家按下这个格子,则会调用PutChess()函数在该格子处落子。

        当遍历到取值1的棋盘时,按照上述的绘画规则在相应的位置上绘制一个矩形,并命名为“○”,用来表示玩家1 。 当遍历到取值2的棋盘时,绘制一个矩形命名为“×”用来表示玩家2 。(由于IMGUI每一帧都会执行,因此每一帧都会遍历一次棋盘并绘制棋盘格子)

        在遍历完所有的棋盘格子后,通过GameOver()函数判断游戏是否结束。如果游戏结束,并且winner的值不为0(即有玩家胜利),则绘制一个矩形弹框显示胜利者的编号;如果游戏结束但是winner的值为0(即平局),则显示双方打出平手。

        视图部分代码如下:

    // 视图部分(view)
    void OnGUI() {
        GUI.Box(new Rect(210, 25, 300, 300), "");            // 游戏边框--矩形
        if (GUI.Button(new Rect(310, 270, 100, 30), "Restart")) Init();       //  重新开始游戏
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                if (chessBoard[i, j] == 0 && GUI.Button(new Rect(255 + j * 21, 50 + i * 21, 21, 21), "")) {
                    PutChess(i,j);                                                // 如果棋盘位置值为0,则落子
                }
                else if (chessBoard[i, j] == 1) GUI.Button(new Rect(255 + j * 21, 50 + i * 21, 21, 21), "O");   // 玩家1的位置画圆
                else if (chessBoard[i, j] == 2) GUI.Button(new Rect(255 + j * 21, 50 + i * 21, 21, 21), "X");   // 玩家2的位置画叉
                if(GameOver(i,j)){                       // 判断游戏是否结束
                    if (winner != 0)                     // 如果有人胜利,则显示胜利者              
                        GUI.Box(new Rect(255, 50, 210, 210), "\n\n\n\n\nCongratulations!\n Player "+winner+" has won.");
                    else                                 // 如果无人胜利,则显示平局
                        GUI.Box(new Rect(255, 50, 210, 210), "\n\n\n\n\n\nThis is a draw!");
                    break;
                }
            }
        }
    }

控制部分:

         控制部分首先有个初始化函数Init(),将player的值设置为1,从玩家1开始落子,并且将winner和count的值设置为0,将棋盘的所有位置都重置为0 。

        对于落子函数PutChess(),首先根据传入的参数(棋盘的横纵位置)将对应位置的编号设置为玩家编号,代表该玩家在此位置落子;然后用3减玩家编号,得到另一个玩家的编号;最后将落子数增加。

        对于判断游戏是否结束的函数GameOver(),根据传入的参数(棋盘的横纵坐标),依次判断所在位置的横向、纵向、以及两个对角方向是否达成五子连珠,如果达成五子连珠则游戏结束,所在位置的玩家取得胜利,否则游戏继续。若count值达到了100(棋盘已满)且winner值为0(没有玩家胜利),则说明两者达成平局。

        对于判断是否五子连珠的算法,以横向为例,首先用ii和jj变量记录下当前的位置(jj为列),横向有向左和向右两个方向,先用while语句判断右边有多少个与当前位置相同的值,用same变量记录相同的个数,再用while语句判断左边相同的个数,同样记录在same上;如果same的值达到5以上,则说明达成五子连珠,返回true代表游戏胜利;否则,重置ii、jj以及same的值,继续向下判断纵向、对角方向是否五子连珠。

        控制部分代码如下:

// 组件/控制部分(Components/ controller)
    void Init() {            // 初始化
        player = 1;          // 玩家编号,取值为1或2
        winner = 0;          // 胜利者编号
        count = 0;           // 落子的个数
        for(int i = 0; i < 10; i++)
            for(int j = 0; j < 10; j++)
                chessBoard[i, j] = 0;     // 初始化棋盘值为0
    }

    void PutChess(int i,int j) {       // 落子
        chessBoard[i, j] = player;     // 玩家落子,设置棋盘位置值
        player = 3 - player;           // 切换为另一个玩家
        count++;                       // 落子数量增加
    }

    bool GameOver(int i,int j) {              // 判断游戏是否结束
        int ii = i, jj = j;                   // ii为横坐标,jj为纵坐标
        int same=0;                           // 用于记录连续的棋子数,如果连续的棋子数大于5,则游戏结束
        while(jj <= 9 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {jj++;same++;}   //向右
        jj = j;
        while(jj >= 0 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {jj--;same++;}   //向左
        if(same > 5) {winner = chessBoard[i, j]; return true;}                   // 判断横向是否有五子连珠
        else{
            same=0;
            jj = j;
        }

        while(ii <= 9 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii++;same++;}   //向下
        ii = i;
        while(ii >= 0 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii--;same++;}   //向上
        if(same > 5) {winner = chessBoard[i, j]; return true;}                   // 判断纵向是否有五子连珠
        else{
            same=0;
            ii = i;
        }

        while(ii <= 9 && jj <= 9 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii++;jj++;same++;}   //左上到右下
        ii = i;jj = j;
        while(ii >= 0 && jj >= 0 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii--;jj--;same++;}   //右下到左上
        if(same > 5) {winner = chessBoard[i, j]; return true;}                     // 判断左上到右下是否有五子连珠
        else{
            same=0;
            ii = i;jj = j;
        }

        while(ii <= 9 && jj >= 0 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii++;jj--;same++;}   //左下到右上
        ii = i;jj = j;
        while(ii >= 0 && jj <= 9 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii--;jj++;same++;}   //右上到左下
        if(same > 5) {winner = chessBoard[i, j]; return true;}                  // 判断左下到右上是否有五子连珠
        else{
            same=0;
            ii = i;jj = j;
        }

        if (count < 100 && winner == 0) return false;            // 棋盘未满且无人胜利

        return true;
    }

综上,完整的代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class wuziGame : MonoBehaviour {

    // 模型部分(model)
    private static int player;         // 玩家编号,取值为1或2
    private static int count;          // 落子的个数
    private int winner;                // 胜利者编号
    private int[,] chessBoard = new int[10, 10];    // 棋盘矩阵大小为10*10

    void Start () {
        Init();         // 开始游戏时初始化
    }

    // 视图部分(view)
    void OnGUI() {
        GUI.Box(new Rect(210, 25, 300, 300), "");            // 游戏边框--矩形
        if (GUI.Button(new Rect(310, 270, 100, 30), "Restart")) Init();       //  重新开始游戏
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                if (chessBoard[i, j] == 0 && GUI.Button(new Rect(255 + j * 21, 50 + i * 21, 21, 21), "")) {
                    PutChess(i,j);                                                // 如果棋盘位置值为0,则落子
                }
                else if (chessBoard[i, j] == 1) GUI.Button(new Rect(255 + j * 21, 50 + i * 21, 21, 21), "O");   // 玩家1的位置画圆
                else if (chessBoard[i, j] == 2) GUI.Button(new Rect(255 + j * 21, 50 + i * 21, 21, 21), "X");   // 玩家2的位置画叉
                if(GameOver(i,j)){                       // 判断游戏是否结束
                    if (winner != 0)                     // 如果有人胜利,则显示胜利者              
                        GUI.Box(new Rect(255, 50, 210, 210), "\n\n\n\n\nCongratulations!\n Player "+winner+" has won.");
                    else                                 // 如果无人胜利,则显示平局
                        GUI.Box(new Rect(255, 50, 210, 210), "\n\n\n\n\n\nThis is a draw!");
                    break;
                }
            }
        }
    }

    // 组件/控制部分(Components/ controller)
    void Init() {            // 初始化
        player = 1;          // 玩家编号,取值为1或2
        winner = 0;          // 胜利者编号
        count = 0;           // 落子的个数
        for(int i = 0; i < 10; i++)
            for(int j = 0; j < 10; j++)
                chessBoard[i, j] = 0;     // 初始化棋盘值为0
    }

    void PutChess(int i,int j) {       // 落子
        chessBoard[i, j] = player;     // 玩家落子,设置棋盘位置值
        player = 3 - player;           // 切换为另一个
玩家
        count++;                       // 落子数量增加
    }

    bool GameOver(int i,int j) {              // 判断游戏是否结束
        int ii = i, jj = j;                   // ii为横坐标,jj为纵坐标
        int same=0;                           // 用于记录连续的棋子数,如果连续的棋子数大于5,则游戏结束
        while(jj <= 9 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {jj++;same++;}   //向右
        jj = j;
        while(jj >= 0 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {jj--;same++;}   //向左
        if(same > 5) {winner = chessBoard[i, j]; return true;}                   // 判断横向是否有五子连珠
        else{
            same=0;
            jj = j;
        }

        while(ii <= 9 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii++;same++;}   //向下
        ii = i;
        while(ii >= 0 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii--;same++;}   //向上
        if(same > 5) {winner = chessBoard[i, j]; return true;}                   // 判断纵向是否有五子连珠
        else{
            same=0;
            ii = i;
        }

        while(ii <= 9 && jj <= 9 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii++;jj++;same++;}   //左上到右下
        ii = i;jj = j;
        while(ii >= 0 && jj >= 0 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii--;jj--;same++;}   //右下到左上
        if(same > 5) {winner = chessBoard[i, j]; return true;}                     // 判断左上到右下是否有五子连珠
        else{
            same=0;
            ii = i;jj = j;
        }

        while(ii <= 9 && jj >= 0 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii++;jj--;same++;}   //左下到右上
        ii = i;jj = j;
        while(ii >= 0 && jj <= 9 && chessBoard[ii, jj] == chessBoard[i, j] && chessBoard[i,j]>0) {ii--;jj++;same++;}   //右上到左下
        if(same > 5) {winner = chessBoard[i, j]; return true;}                  // 判断左下到右上是否有五子连珠
        else{
            same=0;
            ii = i;jj = j;
        }

        if (count < 100 && winner == 0) return false;            // 棋盘未满且无人胜利

        return true;
    }

}

运行:

        如下图所示,将上述代码写入script文件中,并拖动至Main Camera中,保存之后点击运行按钮即可开始游戏。

        游戏界面如下:

        可以在棋盘上落子,如下图所示:

        当有一方胜利时,游戏结束:

        如果棋盘下满还是没有分出胜负,则显示平局,如下图所示:

游戏视频链接如下:

简单的unity小游戏--五子棋_哔哩哔哩bilibili

  • 21
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值