玩法简介
游戏的玩法非常简单,消除九宫格中的“X”,完成一组加1分。
玩家需要做的是在30s内获得尽可能高的分数。
游戏规则
时间限制
游戏只有30s,玩家需要在有限的时间获得更高的分数。
惩罚机制
如果点击到“O”,将直接结束游戏。
得分机制
只要完成一组消除,就能得到1分。
具体代码实现
该游戏的具体实现也比较简单,只需要一个unity中的C#脚本就可以实现。
代码主要分为三个部分模型(Model)部分、视图(View)部分、控制器(Controller)/ 部件(Components)部分。
模型(Model)部分
模型部分主要包含游戏对象的数据。
// Model
private static int score = 0; //分数
private int[,] board = new int[3, 3]; //用于记录九宫格状态
private int level = 1; //游戏难度
public List<int> rangeList = new List<int>(); //存放生成的随机数
public GUIStyle rightButtonStyle; //用于修改按钮样式
public GUIStyle wrongButtonStyle; //用于修改按钮样式
private float countdownTimer = 30f;//倒计时30s
视图(View)部分
视图代表游戏模型包含的数据的可视化。
// View
void OnGUI()
{
GUI.Box(new Rect(300, 35, 300, 320), "Kill The Difference"); //显示标题
GUI.Box(new Rect(345, 60, 70, 30), "Score: " + score); //显示分数
// 显示倒计时
GUI.Box(new Rect(485, 60, 70, 30), "Time: " + Mathf.Ceil(countdownTimer) + "s");
// 设定按钮样式
rightButtonStyle = new GUIStyle(GUI.skin.button);
wrongButtonStyle = new GUIStyle(GUI.skin.button);
rightButtonStyle.normal.textColor = Color.red;
wrongButtonStyle.normal.textColor = Color.blue;
// 重启游戏
if (GUI.Button(new Rect(345, 300, 100, 30), "Restart")) Init();
// 修改难度
if (GUI.Button(new Rect(485, 300, 70, 30), "Level:" + level)) ChangeLevel();
// 如果游戏还未结束,进行以下一系列操作;游戏结束就显示结算页面
if (!GameOver())
{
// 完成一组消除
if (Win())
{
WinMove();
}
// 更新每个按钮的状态
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i, j] == 0 && GUI.Button(new Rect(345 + j * 70, 90 + i * 70, 70, 70), "O", wrongButtonStyle))
{
Click_0(i, j);
}
else if (board[i, j] == 1 && GUI.Button(new Rect(345 + j * 70, 90 + i * 70, 70, 70), "X", rightButtonStyle))
{
Click_1(i, j);
}
}
}
}
else
{
GUI.Box(new Rect(345, 90, 210, 210), "\n\n\n\nGame Over\nYour score is:" + score + "\nlevel is:" + level);
}
}
控制器(Controller)/ 部件(Components)部分
该部分实现了对模型包含的数据的修改,从而完成游戏要实现的逻辑。
在控制器部分,主要实现了随机选定“X”方块,点击按钮操作,判断游戏结束,判断游戏胜利,改变游戏难度,倒计时的逻辑。
初始化
其中未提及的函数将在下文给出。
void Init()
{
ClearBoard();
SetColor();
StopCountdown();
countdownTimer = 30f;
StartCountdown();
score = 0;
}
//重设棋盘
void ClearBoard()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
board[i, j] = 0;
}
}
}
随机选定“X”方块
CreateRandom()函数通过循环语句生成随机数,并判断是否与之前的相等,实现了生成不同的随机数,个数等同于游戏难度。
//生成随机数
void CreateRandom()
{
rangeList.Clear();
while (rangeList.Count < level)
{
int temp_nums = Random.Range(0, 9);
//判断列表中是否有此次生成的随机数,没有则把temp_nums加入列表,否则重新生成
if (!rangeList.Contains(temp_nums))
{
rangeList.Add(temp_nums);
}
else
{
continue;
}
}
}
//选出要点击的方块
void SetColor()
{
CreateRandom();
for (int i = 0; i < rangeList.Count; i++)
{
int x = rangeList[i] / 3;
int y = rangeList[i] % 3;
board[x, y] = 1;
}
}
可以看到“X”方块是随机生成的,并且“X”的个数和游戏难度相等:
点击按钮操作
令方块的值等于2,表明该方块被点击。
//点击按钮操作
void Click(int i, int j)
{
board[i, j] = 2;
}
注意到,在View部分,是方块的值等于2时是不显示按钮的。如下图所示,此时board[1, 0] = board[2, 1] = 2:
判断游戏结束
主要分为倒计时结束和点错按钮结束。
//判断游戏结束
bool GameOver()
{
// 小技巧:将countdownTimer一直设为0,就可以在游戏结束的时候,让剩余时间一直显示为0
if (countdownTimer <= 0)
{
countdownTimer = 0;
return true;
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
// 如果按钮被点击,但不在所选随机数中,说明点错按钮了
if (board[i, j] == 2 && !rangeList.Contains(i * 3 + j))
{
countdownTimer = 0;
return true;
}
}
}
return false;
}
游戏结束界面如下:
判断游戏胜利
//判断游戏胜利
//如果点击正确按钮的个数和游戏难度相等则该轮游戏胜利
bool Win()
{
int count = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i, j] == 2 && rangeList.Contains(i * 3 + j))
{
count++;
}
}
}
return count == level;
}
//胜利后重设棋盘,并加分
void WinMove()
{
score++;
ClearBoard();
SetColor();
}
改变游戏难度
每点击一次level按钮,游戏难度+1,当游戏难度为5时,再点击一次回到1。
每次改变游戏难度都会使游戏重新开始。
// 改变游戏难度
void ChangeLevel()
{
level %= 5;
level++;
Init();
}
倒计时
此处主要运用了InvokeRepeating方法,用于以指定的时间间隔重复调用游戏对象上的一个方法,此处是在一秒的间隔内重复调用UpdateCountdown函数,模拟倒计时。
//开始倒计时
void StartCountdown()
{
InvokeRepeating("UpdateCountdown", 1.0f, 1.0f);
}
//更新状态
void UpdateCountdown()
{
countdownTimer -= 1.0f;
}
//结束倒计时
void StopCountdown()
{
CancelInvoke("UpdateCountdown");
}
成品
请看视频:
最终视频
代码
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class Killthedifference : MonoBehaviour
{
// Model
private static int score = 0; //分数
private int[,] board = new int[3, 3]; //用于记录九宫格状态
private int level = 1; //游戏难度
public List<int> rangeList = new List<int>(); //存放生成的随机数
public GUIStyle rightButtonStyle; //用于修改按钮样式
public GUIStyle wrongButtonStyle; //用于修改按钮样式
private float countdownTimer = 30f;//倒计时30s
// System Handlers
void Start()
{
Init();
}
// View
void OnGUI()
{
GUI.Box(new Rect(300, 35, 300, 320), "Kill The Difference"); //显示标题
GUI.Box(new Rect(345, 60, 70, 30), "Score: " + score); //显示分数
// 显示倒计时
GUI.Box(new Rect(485, 60, 70, 30), "Time: " + Mathf.Ceil(countdownTimer) + "s");
// 设定按钮样式
rightButtonStyle = new GUIStyle(GUI.skin.button);
wrongButtonStyle = new GUIStyle(GUI.skin.button);
rightButtonStyle.normal.textColor = Color.red;
wrongButtonStyle.normal.textColor = Color.blue;
// 重启游戏
if (GUI.Button(new Rect(345, 300, 100, 30), "Restart")) Init();
// 修改难度
if (GUI.Button(new Rect(485, 300, 70, 30), "Level:" + level)) ChangeLevel();
// 如果游戏还未结束,进行以下一系列操作;游戏结束就显示结算页面
if (!GameOver())
{
// 完成一组消除
if (Win())
{
WinMove();
}
// 更新每个按钮的状态
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i, j] == 0 && GUI.Button(new Rect(345 + j * 70, 90 + i * 70, 70, 70), "O", wrongButtonStyle))
{
Click(i, j);
}
else if (board[i, j] == 1 && GUI.Button(new Rect(345 + j * 70, 90 + i * 70, 70, 70), "X", rightButtonStyle))
{
Click(i, j);
}
}
}
}
else
{
GUI.Box(new Rect(345, 90, 210, 210), "\n\n\n\n\nGame Over\nYour score is:" + score + "\nlevel is:" + level);
}
}
// Components /controls
void Init()
{
ClearBoard();
SetColor();
StopCountdown();
countdownTimer = 30f;
StartCountdown();
score = 0;
}
//选出要点击的方块
void SetColor()
{
CreateRandom();
for (int i = 0; i < rangeList.Count; i++)
{
int x = rangeList[i] / 3;
int y = rangeList[i] % 3;
board[x, y] = 1;
}
}
//生成随机数
void CreateRandom()
{
rangeList.Clear();
while (rangeList.Count < level)
{
int temp_nums = Random.Range(0, 9);
//判断列表中是否有此次生成的随机数,没有则把temp_nums加入列表,否则重新生成
if (!rangeList.Contains(temp_nums))
{
rangeList.Add(temp_nums);
}
else
{
continue;
}
}
}
//重设棋盘
void ClearBoard()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
board[i, j] = 0;
}
}
}
//点击按钮操作
void Click(int i, int j)
{
board[i, j] = 2;
}
//判断游戏结束
bool GameOver()
{
// 小技巧:将countdownTimer一直设为0,就可以在游戏结束的时候,让剩余时间一直显示为0
if (countdownTimer <= 0)
{
countdownTimer = 0;
return true;
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
// 如果按钮被点击,但不在所选随机数中,说明点错按钮了
if (board[i, j] == 2 && !rangeList.Contains(i * 3 + j))
{
countdownTimer = 0;
return true;
}
}
}
return false;
}
//判断游戏胜利
bool Win()
{
int count = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i, j] == 2 && rangeList.Contains(i * 3 + j))
{
count++;
}
}
}
return count == level;
}
//胜利后重设棋盘,并加分
void WinMove()
{
score++;
ClearBoard();
SetColor();
}
// 改变游戏难度
void ChangeLevel()
{
level %= 5;
level++;
Init();
}
//开始倒计时
void StartCountdown()
{
InvokeRepeating("UpdateCountdown", 1.0f, 1.0f);
}
//更新状态
void UpdateCountdown()
{
countdownTimer -= 1.0f;
}
//结束倒计时
void StopCountdown()
{
CancelInvoke("UpdateCountdown");
}
}