IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 3D游戏编程-井字棋 -> 正文阅读

[游戏开发]3D游戏编程-井字棋

3D游戏编程-井字棋

作业要求

利用unity制作井字棋小游戏。


项目配置

Windows 10
Unity 2020.3.17f1c1


项目演示

视频演示

点击此处可以前往

文字说明

  1. 在Asset>Scenes中create一个C# script,命名为Chess_1
  2. 编辑Chess_1,输入项目代码并且保存
  3. 将Chess_1拖拉到Main Camera
  4. 运行,预览的比例使用Free Aspect即可
  5. 井字棋起手者为O,点击下方九宫格棋盘就可以游玩,并且在任何时候都可以进行restart

项目截图

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


实现过程和方法(算法)

ECS框架

Entity,是一个Component的组合,它的意义就在于对其上的Component进行生命周期管理。(如一个cube,它是一个entity,他有自己的坐标,偏角,缩放的属性)

Component,是一个只包含数据的组件,将每个可能单独使用的对象属性归纳,里面只有数据没有任何方法,每个Entity是由多个Component组合而成,共享一个生命周期。(如坐标,偏角,缩放这些属性就是component)

System,是用来处理数据的系统,里面只有方法,没有任何数据,每个System只关注于干好一件事情,它只关心那件事作用于游戏世界里同类的一组对象的每单个个体,或是这类对象的某种特定的交互行为。

项目构思

井字棋的entity有:

  1. 九宫格(matrix),实际上是九宫格的每一个格子;
  2. 回合轮次。

component:

  1. 格子的component就是每一个格子目前的状态,是被O所下、被X所下、还是为空;
  2. 轮次的component是轮到玩家O还是玩家X。

system:

  1. reset,重置整个棋盘;
  2. check是检查当前步是否出现胜者,或者是否平局;
  3. click用作处理当一个格子被下棋之后,修改格子的状态。

UI的部分分为两个,一个是文字显示目前的回合轮到哪一位玩家,以及战况;一个是游戏的界面, 包括背景、九宫格的按钮和restart按钮。

算法

  1. 建立二维数组matrix记录棋盘,0表示格子为空,1表示玩家O下棋,2表示玩家X下棋。
  2. click函数负责修改格子的状态,以及回合轮次。
  3. 每次刷新时,check函数检查棋盘有没有竖线、横线、斜线是相同的(为1或者2,不能为0),有的话则出现胜者;或者检查棋盘是否已经下满九个棋子并且没有胜者,此时平手。
  4. 棋盘的情况要反映在UI上,于是OnGUI显示的bottom根据matrix[i,j]的状态,显示“O”、“X”、空白
  5. 对战情况的文字UI也根据有否出现胜者而改变显示(这个依赖result的输出来告知),并且每个回合轮到哪位玩家也要显示。

项目代码

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

public class Chess_1 : MonoBehaviour
{
    GUIStyle myStyle;
    private int turn = 1;
    private int chess_num = 0;

    private int[,] matrix = new int[3,3];
    int middle = Screen.width / 2;//用于UI,得到屏幕中央位置

    void reset(){
        turn = 1;
        chess_num = 0;
        for(int i = 0 ;  i < 3  ; i ++){
            for(int j = 0 ; j < 3 ; j ++)
                matrix[i,j] = 0;
        }
        print("game reseted.");
    }

    int check(){
        for(int i =  0 ; i < 3 ; i ++){
            // 列的检测
            if(matrix[i,0] != 0 && (matrix[i,0] == matrix[i,1] && matrix[i,0] == matrix[i,2]) ){
                return matrix[i,0];
            }    
            // 行的检测
            if(matrix[0,i] != 0 && (matrix[0,i] == matrix[1,i] && matrix[0,i] == matrix[2,i]) ){
                return matrix[0,i];
            } 
        }
        // 对角线检测
        if(matrix[0,0] != 0 && (matrix[0,0] == matrix[1,1] && matrix[0,0] == matrix[2,2]) ){
            return matrix[0,0];
        }
        if(matrix[0,2] != 0 && (matrix[0,2] == matrix[1,1] && matrix[0,2] == matrix[2,0]) ){
            return matrix[0,2];
        }
        // 对局还没结束
        if (chess_num < 9) return 0;
        // 平局
        return 3;
    }

    void result(int res){
        switch(res){
            case 0: 
                // 对局还没结束,显示目前轮到谁的场次
                if(turn == 1) 
                    GUI.Box(new Rect(middle - 45, 55, 100, 35), "O is going");
                else if(turn == 2)
                    GUI.Box(new Rect(middle - 45, 55, 100, 35), "X is going");
                break;
            case 1:
                GUI.Box(new Rect(middle - 45, 55, 100, 35), "O Win!");
                break;
            case 2:
                GUI.Box(new Rect(middle - 45, 55, 100, 35), "X Win!");
                break;
            case 3:
                GUI.Box(new Rect(middle - 45, 55, 100, 35), "Draw!");
                break;
        }

    }

    void click(int i, int j){
        matrix[i,j] = turn;
        chess_num ++;
        if(turn == 1) 
            turn = 2;
        else 
            turn = 1;
    }

    void OnGUI(){
        // 游戏背景的box
        GUI.Box(new Rect(middle - 120, 30, 252, 330), "tictactoe");
        // restart按钮
        if (GUI.Button(new Rect(middle - 35, 95, 75, 30), "Restart")){
            reset();
        }
       
        int res = check();
        for(int i = 0 ; i < 3 ; i ++){
            for(int j = 0 ; j < 3 ; j ++){
                if(matrix[i,j] == 1){
                    GUI.Button(new Rect(middle - 120 + i*84, 135 + j*70 , 84, 70), "O");
                }
                if(matrix[i,j] ==2){
                    GUI.Button(new Rect(middle - 120 + i*84, 135 + j*70 , 84, 70), "X");
                }
                if(GUI.Button(new Rect(middle - 120 + i*84, 135 + j*70 , 84, 70), "")){
                    click(i,j);
                }
            }
        }
        result(res);
    }
}

项目笔记

    int middle = Screen.width;// 获取屏幕宽
    int middle = Screen.height;// 获取屏幕高

    GUI.Box(new Rect(middle - 45, 55, 100, 35), "O is going");
    // GUI.Box(位置(x, y, 宽, 高), "标题文字");
    GUI.Button(new Rect(middle - 120 + i*84, 135 + j*70 , 84, 70), "X");
    // GUI.Button(位置(x, y, 宽, 高), "标题文字");

    // 下面这个方式,可以在Asset中拖拉对象到属性视图,这样显示的button就是拖拉的对象
    public Texture2D X;
    GUI.Button(new Rect(middle - 120 + i*84, 135 + j*70 , 84, 70), X);

参考资料

  1. 框架设计:浅谈ECS设计思想(一)
  2. Unity3D笔记(二)使用GUI做井字棋小游戏
  3. Unity3d 游戏设计(一)井字棋
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-09-20 16:04:04  更:2021-09-20 16:04:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 4:32:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码