【无标题】

unity井字棋改编——简易计算器

注:本游戏基于潘老师的第三次作业要求,在井字棋的基础上设计出简易计算器

源代码github地址:goodhuahua/unity-game: unity游戏开发学习之旅 (github.com)

游戏代码讲解/实现效果视频:小破站

MVC结构

在真正开始设计之前,我们需要首先了解下什么是MVC模式:

  1. Model(模型):模型代表游戏的数据和逻辑。在这个游戏中,模型主要包括以下方面的内容:
    • 棋盘状态(chessBoard):用于存储棋盘上每个格子的状态,表示棋盘的当前状态。
    • 玩家状态(player):表示当前玩家的状态,用于轮流确定下棋的玩家。
    • 胜利者状态(winner):表示当前的胜利者,用于判断游戏是否结束。
    • 计数器(count):用于记录已经放置的棋子数量。
  2. View(视图):视图负责游戏界面的展示和用户交互。在这个游戏中,视图主要包括以下方面的内容:
    • OnGUI()函数:用于绘制游戏界面,包括棋盘格子的按钮和背景矩形框。
    • 按钮点击事件:当玩家点击棋盘格子的按钮时,触发相应的事件处理函数。
  3. Controller(控制器):控制器负责协调模型和视图之间的交互。在这个游戏中,控制器主要包括以下方面的内容:
    • PutChess(int i, int j)方法:当玩家点击棋盘格子的按钮时,该方法被调用。它用于更新模型中的棋盘状态,将玩家的棋子放置在指定的格子上,并进行下一步操作(切换玩家、检查胜利条件等)。
    • Init()方法:用于初始化游戏的状态,包括清空棋盘、重置玩家状态、胜利者状态和计数器。

MVC模式对于整个游戏的开发具有很好的指导作用,能够使我们的代码逻辑性更加紧密。作为一个初学者,我们需要从开始就养成良好的编程习惯,为后续大型游戏的开发奠定良好的基础。

井字棋案例

以下为井字棋案例的代码:

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

/*
ECS or MVC conception is applied on the small game
Firstly, entitis and their states are defined as the game model.
And then, give some components/controls which can modify the game model.
The end, system handler OnGUI called by game circle provides a game UI view.
*/
public class ChessGame : MonoBehaviour
{
// Entities and their states / Model
private static int player;
private static int count;
private int winner;
private int[,] chessBoard = new int[3, 3];

// System Handlers
void Start()
{
    Init();
}

// View render entities / models
// Here! you cannot modify model directly, use components/controls to do it
void OnGUI()
{
    GUI.Box(new Rect(210, 25, 300, 300), "");
    if (GUI.Button(new Rect(310, 270, 100, 30), "Restart")) Init();
    if (!GameOver())
    {
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (chessBoard[i, j] == 0 && GUI.Button(new Rect(255 + j * 70, 50 + i * 70, 70, 70), ""))
                {
                    PutChess(i, j);
                }
                else if (chessBoard[i, j] == 1) GUI.Button(new Rect(255 + j * 70, 50 + i * 70, 70, 70), "O");
                else if (chessBoard[i, j] == 2) GUI.Button(new Rect(255 + j * 70, 50 + i * 70, 70, 70), "X");
            }
        }
    }
    else
    {
        if (winner != 0)
            GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nCongratulations!\n Player " + winner + " has won.");
        else
            GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\n\nThis is a draw!");
    }
}

// Components
// here! any ui can not be referenced
void Init()
{
    player = 1;
    winner = 0;
    count = 0;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            chessBoard[i, j] = 0;
}

void PutChess(int i, int j)
{
    chessBoard[i, j] = player;
    player = 3 - player;
    count++;
}

bool GameOver()
{
    for (int i = 0; i < 3; i++)
    {
        if (chessBoard[i, 0] != 0
            && chessBoard[i, 0] == chessBoard[i, 1] && chessBoard[i, 0] == chessBoard[i, 2]) winner = chessBoard[i, 0];

​        if (chessBoard[0, i] != 0
​            && chessBoard[0, i] == chessBoard[1, i] && chessBoard[0, i] == chessBoard[2, i]) winner = chessBoard[0, i];
​    }

​    if (chessBoard[0, 0] != 0 && chessBoard[0, 0] == chessBoard[1, 1] && chessBoard[0, 0] == chessBoard[2, 2]) winner = chessBoard[0, 0];
​    if (chessBoard[0, 2] != 0 && chessBoard[0, 2] == chessBoard[1, 1] && chessBoard[0, 2] == chessBoard[2, 0]) winner = chessBoard[0, 2];

​    if (count < 9 && winner == 0) return false;

​    return true;
}
}

具体的运行效果大家可以复制代码到unity中尝试,本博客的重点在于简易计算器的实现。

简易计算器改编

代码剖析

首先大家看看完整的代码实现:

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

public class Calculator : MonoBehaviour
{
    // Model
    private string displayText; // 显示的文本内容

    private void Start()
    {
        Init(); // 初始化
    }

    private void OnGUI()
    {
        // View
        GUI.Box(new Rect(260, 30, 360, 70), displayText, GUI.skin.textField); // 显示文本框

        // 绘制按钮
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                int number = i * 3 + j + 1;
                if (GUI.Button(new Rect(255 + j * 70, 100 + i * 70, 70, 70), number.ToString(), GUI.skin.button))
                {
                    // 用户点击按钮,交由 Controller 处理
                    AppendToDisplay(number.ToString());
                }
            }
        }

        // 其他按钮的处理
        if (GUI.Button(new Rect(255, 310, 140, 70), "0", GUI.skin.button))
        {
            AppendToDisplay("0");
        }

        if (GUI.Button(new Rect(395, 310, 70, 70), ".", GUI.skin.button))
        {
            AppendToDisplay(".");
        }

        if (GUI.Button(new Rect(475, 100, 70, 70), "+", GUI.skin.button))
        {
            AppendToDisplay("+");
        }

        if (GUI.Button(new Rect(475, 180, 70, 70), "-", GUI.skin.button))
        {
            AppendToDisplay("-");
        }

        if (GUI.Button(new Rect(475, 260, 70, 70), "*", GUI.skin.button))
        {
            AppendToDisplay("*");
        }

        if (GUI.Button(new Rect(475, 340, 70, 70), "/", GUI.skin.button))
        {
            AppendToDisplay("/");
        }

        if (GUI.Button(new Rect(555, 100, 70, 70), "C", GUI.skin.button))
        {
            ClearDisplay();
        }

        if (GUI.Button(new Rect(555, 180, 70, 230), "=", GUI.skin.button))
        {
            Calculate();
        }
    }

    // Controller

    private void Init()
    {
        displayText = ""; // 初始化文本内容为空
    }

    private void AppendToDisplay(string str)
    {
        // 将用户点击的按钮文本追加到显示文本中
        displayText += str;
    }

    private void ClearDisplay()
    {
        // 清除显示文本
        displayText = "";
    }

    private void Calculate()
    {
        try
        {
            // 执行计算
            var result = eval(displayText);
            displayText = result.ToString(); // 更新显示文本为计算结果
        }
        catch (System.Exception)
        {
            displayText = "错误"; // 计算错误时显示错误信息
        }
    }

    private double eval(string expression)
    {
        // 使用系统的 DataTable 类计算表达式结果
        var result = new System.Data.DataTable().Compute(expression, null);
        return System.Convert.ToDouble(result);
    }
}

下面我们来剖析整个代码结构:

同样地,我们使用MVC模式来分析代码结构:

  1. Model(模型):

    • 模型在这段代码中主要是displayText变量,它存储当前显示在计算器界面上的文本内容。这个变量用于表示计算器的数据状态。
  2. View(视图):

    • 视图主要体现在OnGUI()方法中,通过调用GUI类的方法来绘制计算器界面。在界面上展示了一个文本框(用于显示计算结果或用户输入的表达式)和一系列的按钮。
    • 按钮的点击事件被绑定到不同的操作,例如添加数字、运算符、清除显示等。用户通过点击按钮与视图进行交互。
  3. Controller(控制器):

    • 控制器在这段代码中可以看作是Calculator类本身,它负责处理用户的输入和更新模型和视图之间的交互。

    • AppendToDisplay()方法用于将用户点击的按钮的文本内容追加到displayText变量中,实现了用户输入的处理。

    • ClearDisplay()方法用于清除displayText变量的内容,实现了清除显示的操作。

    • Calculate()方法用于执行计算操作,它通过调用eval()方法将displayText中的字符串表达式进行计算,并将结果更新到displayText中。

      实现效果图

      初始化:

在这里插入图片描述
计算ing:
在这里插入图片描述

无效运行报错:
在这里插入图片描述

更多实现效果欢迎参考我的b站视频!

提升空间

我们可以看到简易计算器的字体大小,以及整体的样式效果有待提高,但由于时间有限精力有限,笔者尚未对此样式进行优化,未来有机会再作优化。

也欢迎大家访问我的github来改进此计算器,拥抱开源!unity go go go!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值