中山大学3D游戏编程第一次作业之Unity井字棋

一,作业要求

用Unity实现井字棋

要求做到实体(数据),部件(逻辑),系统(交互与呈现)三者分离

二,实现效果

录制演示视频如下:

演示视频icon-default.png?t=L892http://www.bilibili.com/video/BV1CU4y1A77f?share_medium=android&share_source=copy_link&bbid=XY2E3E427016B34F1ED83BA686D35D655EE97&ts=1632319135153

三,实现过程及项目说明

1,定义数据

private int [,] board = new int [3,3];
private int turn = 0;
private int square_size = Screen.width / 10;
private int menu_width = Screen.width / 5, menu_height = Screen.width / 10;
private int mode = 0;
    
private GUIStyle bigStyle, yellowStyle, redStyle;
public Texture2D empty, icon1, icon2;
public Texture2D background;

依次是:

表示棋盘的一个二维数组

表示下棋顺序的turn

定义主菜单界面和每个棋格大小的参数

表示游戏模式,0表示主菜单,1表示游戏进行中,2表示游戏已结束

三种字体,应用于菜单界面和最后显示获胜者提示

2,OnGui函数的设计

    void OnGUI() {
        switch(mode) {
            case 0:
                mainMenu();
                break;
            case 1:
                playerVsPlayer();
                break;
            case 2:
                playerVsPlayer();
                break;           
        }       
    }

Ongui函数,就是它决定游戏每一帧应该怎么画,这里用switch来分别实现三种模式的交互模式。

我把mode1和mode2基本上写在一起了,但是中间试了很多种情况才最后实现了想要的效果。

3,主菜单的设计

void mainMenu() {

        string aa = "";
        GUIStyle bb = new GUIStyle();
        bb.normal.background = background;
        GUI.Label(new Rect(0, 0, Screen.width, Screen.height), aa, bb);

        GUI.Label(new Rect(Screen.width / 2 - menu_width * 0.8f, Screen.height * 0.1f, menu_width, menu_height), "Main Menu", bigStyle);
        if (GUI.Button(new Rect(Screen.width / 2 - menu_width / 2, Screen.height * 2 / 7, menu_width, menu_height), "Start!",redStyle)) {
            mode = 1;
        }
    }

 上面四行实现的是背景图片,后面实现两个文本,一个是label的,一个是button的start,label不能点击,button的可以点击,点击start开始游戏,进入模式1

4,检查游戏结果

int checkresult() {
        int res = -1;
        for (int i = 0; i < 3; ++i) {
            if (board[i,0] != 0 && board[i,0] == board[i,1] && board[i,0] == board[i,2]) {
                res = board[i,0];
                break;
            }
        }
        if (res == -1)
            for (int j = 0; j < 3; ++j) {
                if (board[0,j] != 0 && board[0,j] == board[1,j] && board[0,j] == board[2,j]) {
                    res = board[0,j];
                    break;
                }
            }
        if (res == -1)
            if (board[1,1] != 0 && (board[0,0] == board[1,1] && board[1,1] == board[2,2] || board[0,2] == board[1,1] && board[2,0] == board[1,1])) {
                res = board[1,1];
            }
        if (res == -1) {
            int cnt = 0;
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j){
                    if (board[i,j] == 0) {
                        cnt++;
                        break;
                    }
                }
            }
            if (cnt == 0) {
                res = 3;
            }
        }
        if (res == -1) return 0;
        return res;
    }
    

第一个checkresult函数检查游戏结果,用了两个变量来确定游戏的状态,这里主要是与游戏逻辑相关的,不在赘述,最后返回几个不同的值交给下一步中的函数做判断。

5,检查游戏状态

void checkState() {
        int res = checkresult();
        if (res == 0) return ;

        if (res == 1) {
            if (mode == 1 || mode == 2) {
                GUI.Label(new Rect(Screen.width / 2 - 3 * square_size, Screen.height / 2, square_size * 1.5f, square_size * 0.8f), "Sunflower wins!", yellowStyle);
                mode = 2;
            }
        }
        else if (res == 2) {
            if (mode == 1 || mode == 2) {
                GUI.Label(new Rect(Screen.width / 2 - 3 * square_size, Screen.height / 2, square_size * 1.5f, square_size * 0.8f), "Peashooter wins!", yellowStyle);
                mode = 2;
            }
        }
        else if (res == 3) {
            if (mode == 1 || mode == 2) {
                GUI.Label(new Rect(Screen.width / 2 - 3 * square_size, Screen.height / 2, square_size * 1.5f, square_size * 0.8f), "Tie!", yellowStyle);
                mode = 2;
        }
        }      
    }

 res为0,无变化,说明游戏还能继续,为1时,1号玩家获胜,为2时,2号玩家获胜,为3时,平局,根据对应状况,改变mode的值。

6,玩家落棋函数

void playerVsPlayer() {

        string aa = "";
        GUIStyle bb = new GUIStyle();
        bb.normal.background = background;
        GUI.Label(new Rect(0, 0, Screen.width, Screen.height), aa, bb);


        if(mode == 1 || mode == 2)
        {
            for (int i = 0; i < 3; ++i) {
                    for (int j = 0; j < 3; ++j) {
                        switch(board[i,j]) {
                            case 0:
                                if (GUI.Button(new Rect(Screen.width / 2 + (i - 1.5f) * square_size, Screen.height / 2 + (j - 1.5f)* square_size, square_size, square_size), empty)) {
                                    if(mode != 2)
                                    {
                                        board[i,j] = turn + 1;
                                        turn = 1 - turn;
                                    }
                                }
                                break;
                            case 1:
                                GUI.Button(new Rect(Screen.width / 2 + (i - 1.5f) * square_size, Screen.height / 2 + (j - 1.5f) * square_size, square_size, square_size), icon1);
                                break;
                            case 2:
                                GUI.Button(new Rect(Screen.width / 2 + (i - 1.5f) * square_size, Screen.height / 2 + (j - 1.5f) * square_size, square_size, square_size), icon2);
                                break;
                        }
                    }
                }
        }
        
        checkState();
        
        
        if(mode == 1 || mode ==2)
        {
            if (GUI.Button(new Rect(Screen.width - square_size , Screen.height - square_size * 0.7f, square_size, square_size * 0.7f), "Reset")) {
                    reset();
                    mode = 1;//注意
                }
                if (GUI.Button(new Rect(0 , Screen.height - square_size * 0.7f, square_size * 1.6f, square_size * 0.7f), "Return to Menu")) {
                    reset();
                    mode = 0;
                }
        }

    }

 
 

最开始四行画出背景不说了,其他主要是用PlayerMove函数实现玩家的落子,并在该函数中运行checkstate检查游戏状态,这里花了点时间,调试,mode=1,mode=2这两个状态的位置,最后终于实现了想要的效果,即当出现胜方或平局后,再点击button无变化,且屏幕上始终显示“甲赢了”或“平局”的结果,要求玩家必须点击“Reset”或者“back to menu”才可以。 

四,项目地址

基本上上一步中就是全部的代码了,完整代码:github链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值