1.游戏介绍
这是一款有点烧脑的小游戏,需要玩家拥有强大的一位数加法能力以及战略选择能力。游戏会给出玩家需要达到的目标值以及能输入数字的次数,玩家需要在规定的输入数字的次数内按下数字按键以输入数字,输入数字的范围为1到9,每一个数字只能输入一次,游戏会自动加上玩家输入的数字,当输入次数等于游戏给出能输入数字的次数时,如果加到的总值等于游戏给出的玩家需要达到的目标值,游戏胜利,否则游戏失败。
例如,游戏随机更新的目标值和输入次数为16和5,如果玩家输入的5个数字分别为1、2、3、4、6,由于1+2+3+4+6=16,则玩家胜利。如果玩家输入的5个数字分别为1、2、3、4、5,由于1+2+3+4+5=15,并非16,则游戏失败。
2.游戏编写
本游戏基于Unity引擎编写,使用的脚本文件语言为C#,首先需要确保保证电脑中安装Unity引擎,我的版本是2023.3.8f1c1,还需下载VSCode或VStudio用于编写代码,还需要Unity的Plastic SCM用于管理代码,具体安装方法这里不过多介绍。
接着我们打开Unity,找到项目,选择新项目。
选择3D,项目命名为NumberGame,保存地址我选择的是D盘。(启动版本管理可选可不选)
现在我们进入了Unity引擎界面,如图所示,什么内容也没有。
在Assets栏中空白区用鼠标右键点击,选择Create中的C# Script生成我们游戏的游戏脚本
将脚本命名为NumberGame。(该名称在后续无法修改,请一定不要拼写错误)
点击我们刚刚生成的脚本,如果按装了VS或VSCode,电脑会自动使用VS或VSCode打开,我的电脑使用了VSCode打开,现在脚本中代码如图所示:
本游戏代码只需要如下三个头文件:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
脚本中自带了类如下:
public class NumberGame : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
我们只需要Start()不需要Update(),现在在此基础上进行修改。
先添加几个全局变量。
private static int count; //用于记录玩家输入的总值
private static int chance; //用于记录玩家能输入几次
private static int total; //用于记录目标值
private static int time; //用于记录玩家输入了几次
private int[,] KeyBoard = new int[3, 3]; //用于判断按钮是否被按过
private int[,] NumberBoard = new int[3, 3]; //用于记录每个按钮对应的数字
private Rect window0 = new Rect(550, 20, 200, 200); //提示窗口坐标信息
private bool showWindow = false; //用于显示提示窗口
然后在Start()中添加函数 Init(),至于 Init()的函数内容我们到后面再编写。
void Start()
{
Init();
}
当玩家重复点击同一个数字按钮时,我们需要使用一个新窗口提示他,效果如图所示:
Unity中GUI显示窗口的代码格式如下:
GUI.Window(窗口编号, 窗口坐标, 窗口函数, "content“)
其中每个窗口都有唯一的窗口编号;窗口坐标为相对于背景的坐标和窗口的长宽,也就是我们上文全局变量中的window0;窗口函数可实现在该窗口内实现某些功能,显示某些内容。在我的新窗口中窗口函数显示了一个Box,实现了一个按钮用于关闭新窗口;content显示在窗口上边栏,例如我的新窗口的content便是warnning。
现在我们编写窗口函数oneWindow。
void oneWindow(int windowID)
{
GUI.Box(new Rect(10, 50, 180, 30), "同一个数字按钮不能多次按下");
if (GUI.Button(new Rect(10, 120, 150, 50), "关闭"))
{
showWindow = false;
}
}
其中Rect中前两位分别是横坐标和纵坐标,后两位分别是长与宽。
Unity中GUI的按钮Button的代码格式如下:
if (GUI.Button(new Rect(x,y,h,w),"content")
{
//按钮按下后需要实现的函数
}
if (GUI.Button(new Rect(x,y,h,w),"content")会按照Rect中的内容创建一个按钮,上面显示的名称为content。我们在这个if中写下我们想要实现的功能,例如我们九让showWindow=false,这样新窗口就不可见了。程序执行完后会返回true。
现在我们编写GUI部分,我们先创造一个没有内容的box作为背景,然后创建Restart按钮,if函数里面写Inti()用于重置参数,Init()同样到后面再写。再用两个Lable表明目标值以及能输入的次数。当玩家输入次数还未到达游戏给出能输入的次数前时,我们创建1-9这9个按钮。需要说明的是,我们使用KeyBorad[i,j]用于记录该按钮是否被按过,若KeyBorad[i,j]未按过,则KeyBorad[i,j]=0;若KeyBorad[i,j]按过,则KeyBorad[i,j]=1。如果KeyBorad[i,j]=0,说明没按过,我们执行函数Press(),这个函数我们后面再编写。如果KeyBorad[i,j]=1,说明按过,我们弹出提示框。
当玩家输入次数到达游戏给出能输入的次数时,我们用GameOver函数判断玩家是否胜利,该函数到后面再编写,若玩家胜利,我们生成一个小Box表明玩家胜利;若玩家失败,我们生成一个小Box表明玩家失败。
代码如下:
void OnGUI()
{
GUI.Box(new Rect(210, 25, 300, 300), "");
if (GUI.Button(new Rect(310, 270, 100, 30), "Restart"))
{
Init();
}
string total_content = "您的目标值为:" + total.ToString();
GUI.Label(new Rect(225, 26, 100, 30), total_content);
string chance_content = "您能输入的次数为:" + chance.ToString();
GUI.Label(new Rect(335, 26, 120, 30), chance_content);
if (showWindow)
{
GUI.Window(0, window0, oneWindow, "warnning");
}
if (time < chance)
{
if (GUI.Button(new Rect(255 + 0 * 70, 50 + 0 * 70, 70, 70), "1"))
{
if (KeyBoard[0, 0] == 0)
{
Press(0, 0);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 1 * 70, 50 + 0 * 70, 70, 70), "2"))
{
if (KeyBoard[0, 1] == 0)
{
Press(0, 1);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 2 * 70, 50 + 0 * 70, 70, 70), "3"))
{
if (KeyBoard[0, 2] == 0)
{
Press(0, 2);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 0 * 70, 50 + 1 * 70, 70, 70), "4"))
{
if (KeyBoard[1, 0] == 0)
{
Press(1, 0);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 1 * 70, 50 + 1 * 70, 70, 70), "5"))
{
if (KeyBoard[1, 1] == 0)
{
Press(1, 1);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 2 * 70, 50 + 1 * 70, 70, 70), "6"))
{
if (KeyBoard[1, 2] == 0)
{
Press(1, 2);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 0 * 70, 50 + 2 * 70, 70, 70), "7"))
{
if (KeyBoard[2, 0] == 0)
{
Press(2, 0);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 1 * 70, 50 + 2 * 70, 70, 70), "8"))
{
if (KeyBoard[2, 1] == 0)
{
Press(2, 1);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 2 * 70, 50 + 2 * 70, 70, 70), "9"))
{
if (KeyBoard[2, 2] == 0)
{
Press(2, 2);
}
else
{
showWindow = true;
}
}
}
else if (time == chance)
{
if (GameOver() == true)
{
GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nCongratulations!\n you has won.");
}
if (GameOver() == false)
{
GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nYou loss!\n please try again.");
}
}
}
现在编写Init(),我们分别初始化我们的全局变量count和time,至于chance用1-10内的随机数初始化,minTotal和maxTotal分别规定了total的随机取值上下界,假如随机生成的chance=5,那么我们的total的最小值只能为1-5这5个数之和,即15;total的最大值只能为5-9这5个数之和,即35。我们必须这样随机生成total,不然会出现total过大或过小导致玩家无法完成游戏。值得说明的是,NumberBoard与按键一一对应,方便后面计算count。
代码如下:
void Init()
{
count = 0;
time = 0;
chance = Random.Range(1, 10);
int minTotal = 0;
int maxTotal = 0;
for (int i = 1; i <= chance; i++)
{
minTotal += i;
}
for (int i = 9; i >= 10 - chance; i--)
{
maxTotal += i;
}
total = Random.Range(minTotal, maxTotal + 1);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
KeyBoard[i, j] = 0;
}
}
int temp = 1;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
NumberBoard[i, j] = temp;
temp++;
}
}
}
现在编写Press函数,每次执行Press,KeyBoard相应位置会由0变成1,我们的count要累加NumberBoard对应值,玩家已输入次数需要加1.
代码如下:
void Press(int i, int j)
{
KeyBoard[i, j] = 1;
count += NumberBoard[i, j];
time++;
}
现在编写GameOver函数,如果玩家输入的值不等于目标值,返回false,即游戏失败,如果玩家输入的值等于目标值,则游戏胜利。
代码如下:
bool GameOver()
{
if (count != total)
{
return false;
}
return true;
}
3.游戏代码
游戏完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NumberGame : MonoBehaviour
{
// Entities and their states / Model
private static int count; //用于记录玩家输入的总值
private static int chance; //用于记录玩家能输入几次
private static int total; //用于记录目标值
private static int time; //用于记录玩家输入了几次
private int[,] KeyBoard = new int[3, 3]; //用于判断按钮是否被按过
private int[,] NumberBoard = new int[3, 3]; //用于记录每个按钮对应的数字
private Rect window0 = new Rect(550, 20, 200, 200); //提示窗口坐标信息
private bool showWindow = false; //用于显示提示窗口
// System Handlers
void Start()
{
Init();
}
// View to render entities / models
void OnGUI()
{
GUI.Box(new Rect(210, 25, 300, 300), "");
if (GUI.Button(new Rect(310, 270, 100, 30), "Restart"))
{
Init();
}
string total_content = "您的目标值为:" + total.ToString();
GUI.Label(new Rect(225, 26, 100, 30), total_content);
string chance_content = "您能输入的次数为:" + chance.ToString();
GUI.Label(new Rect(335, 26, 120, 30), chance_content);
if (showWindow)
{
GUI.Window(0, window0, oneWindow, "warnning");
}
if (time < chance)
{
if (GUI.Button(new Rect(255 + 0 * 70, 50 + 0 * 70, 70, 70), "1"))
{
if (KeyBoard[0, 0] == 0)
{
Press(0, 0);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 1 * 70, 50 + 0 * 70, 70, 70), "2"))
{
if (KeyBoard[0, 1] == 0)
{
Press(0, 1);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 2 * 70, 50 + 0 * 70, 70, 70), "3"))
{
if (KeyBoard[0, 2] == 0)
{
Press(0, 2);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 0 * 70, 50 + 1 * 70, 70, 70), "4"))
{
if (KeyBoard[1, 0] == 0)
{
Press(1, 0);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 1 * 70, 50 + 1 * 70, 70, 70), "5"))
{
if (KeyBoard[1, 1] == 0)
{
Press(1, 1);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 2 * 70, 50 + 1 * 70, 70, 70), "6"))
{
if (KeyBoard[1, 2] == 0)
{
Press(1, 2);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 0 * 70, 50 + 2 * 70, 70, 70), "7"))
{
if (KeyBoard[2, 0] == 0)
{
Press(2, 0);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 1 * 70, 50 + 2 * 70, 70, 70), "8"))
{
if (KeyBoard[2, 1] == 0)
{
Press(2, 1);
}
else
{
showWindow = true;
}
}
if (GUI.Button(new Rect(255 + 2 * 70, 50 + 2 * 70, 70, 70), "9"))
{
if (KeyBoard[2, 2] == 0)
{
Press(2, 2);
}
else
{
showWindow = true;
}
}
}
else if (time == chance)
{
if (GameOver() == true)
{
GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nCongratulations!\n you has won.");
}
if (GameOver() == false)
{
GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nYou loss!\n please try again.");
}
}
}
void oneWindow(int windowID)
{
GUI.Box(new Rect(10, 50, 180, 30), "同一个数字按钮不能多次按下");
if (GUI.Button(new Rect(10, 120, 150, 50), "关闭"))
{
showWindow = false;
}
}
// Components /controls
void Init()
{
count = 0;
time = 0;
chance = Random.Range(1, 10);
//Debug.Log("随机生成的chance: " + chance);
int minTotal = 0;
int maxTotal = 0;
for (int i = 1; i <= chance; i++)
{
minTotal += i;
}
for (int i = 9; i >= 10 - chance; i--)
{
maxTotal += i;
}
total = Random.Range(minTotal, maxTotal + 1);
//Debug.Log("随机生成的total: " + maxTotal);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
KeyBoard[i, j] = 0;
}
}
int temp = 1;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
NumberBoard[i, j] = temp;
temp++;
}
}
}
void Press(int i, int j)
{
KeyBoard[i, j] = 1;
count += NumberBoard[i, j];
time++;
}
bool GameOver()
{
if (count != total)
{
return false;
}
return true;
}
}
4.游戏演示
3D游戏建模与设计作业2 基于unity平台个人设计的一款数字游戏