需求分析
分析
整个游戏过程有3个类,
格子类
、网格类
还有游戏管理类
格子类代表16个格子中的每一个格子,
成员变量:行下标、列下标,格子代表的数,是否是第一次合并,因为是控制台程序所以不用颜色了
///
/// 格子类
///
class Box
{
private int row = 0;
private int cols = 0;
int num = 0;
bool isFirst = false;//是否是第一次合并
public int Num
{
get
{
return num;
}
set
{
num = value;
}
}
///
/// 获取行数
///
public int Row
{
get
{
return row;
}
set
{
row = value;
}
}
///
/// 获取列数
///
public int Cols
{
get
{
return cols;
}
}
public bool IsFirst
{
get
{
return isFirst;
}
set
{
isFirst = value;
}
}
public Box(int row,int cols)
{
this.row = row;
this.cols = cols;
this.Num = 0;
}
}
}
网格类
,负责接收用户的上下左右操作,然后让网格内的格子进行相应的移动。然后判断游戏的输赢.(主要操作)
成员变量有:行数,列数,所有格子数(二维数组储存),布尔型判断是否第一次产生随机数,产生随机数的数量,储存上一次生成的随机数的值,当前生成随机数的个数,游戏进行开关,合并开关集合
///
/// 网格类
///
public class Grid
{
int row = 4;//行数
int cols = 4;//列数
Box[,] boxList;//数组,储存
bool isFirst = true; //判断是否是第一次生成随机数
int count = 0; //选择产生每一次随机生成数字的数量,1or2
int num = 2; //储存上次随机生成数
int countNum = 0; //储存生成了的数字的数量,一到16个以便进行游戏输赢判断
bool gameBegin; //游戏开关
Queue isMerage;//判断是是否已经合并集合
Random r;
public Grid(int row, int cols)
{
this.row = row < 0 ? this.row : row;
this.cols = cols < 0 ? this.cols : cols;
boxList = new Box[row, cols];
r = new Random();
isMerage = new Queue();
gameBegin = true; //初始化游戏开始
}
///
/// 返回游戏开关
///
public bool GameBegin
{
get
{
return gameBegin;
}
}
///
/// 初始化布局
///
public void Init()
{
for (int i = 0; i < boxList.GetLength(0); i++)
{
for (int j = 0; j < boxList.GetLength(1); j++)
{
Box box = new Box(i, j);
boxList[i, j] = box;
}
}
RandomNum();
Test();
}
///
/// 随机生成数字
///
public void RandomNum()
{
//第一次生成两个数字
if (isFirst)
{
count = 2;
isFirst = false;
}
//后面每一次只生成一个数字
else
{
count = 1;
}
countNum += count;//生成一个随机数字,个数加一,以便胜负的判断
for (int i = 0; i < count;)//容易形成死循环,万一没有位置初始化随机数字容易陷入死循环
{
//随机生成下标
int rObj = r.Next(0, row);
int cObj = r.Next(0, cols);
if (boxList[rObj, cObj].Num != 0) {
continue;
}
//避免出现两个4
if (num == 4)
{
num = 2;
}
else
{
//随机生成2,4的概率 ,90%2,20%4
int chance = r.Next(1, 11);
if (chance > 10) num = 2;
else num = 4;
}
Console.WriteLine("生成的数:" + num);
boxList[rObj, cObj].Num = num;
i++;
}
}
///
/// 用户输入了按键,根据按键选择移动方向的方法
///
///
public void move(ConsoleKey keyValue)
{
switch (keyValue)
{
//W 向上
case ConsoleKey.W: GoUp(); break;
//S 向下
case ConsoleKey.S: GoDown(); break;
//A 向左
case ConsoleKey.A: GoLetf(); break;
//D 向右
case ConsoleKey.D: GoRight(); break;
default: Console.WriteLine("输入了错误的选择"); break;
}
ReSet();//做完一次操作后重置一下开关
}
///
/// 向右运动
///
private void GoRight()
{
//行下标循环
for (int r = 0; r < boxList.GetLength(0); r++)
{
//列下标循环
for (int c = boxList.GetLength(1) - 2; c >= 0; c--) //按照每行有多少列来循环,从右边到左边
{
Box box = boxList[r, c];
if (box.Num == 0) continue;
for (int nc = c + 1; nc < boxList.GetLength(1); nc++)//数字移动的3种情况
{
Box nextBox = boxList[r, nc];
if (nextBox.Num == 0) //如果前面格子里没有数,就往前移
{
nextBox.Num = box.Num;
box.Num = 0;
box = nextBox;
continue;
}
if (box.Num == nextBox.Num && !nextBox.IsFirst)//如果格子里的数和要往前移的格子里的数是相同的,就可以合并
{
nextBox.IsFirst = true;
nextBox.Num *= 2;
box.Num = 0;
countNum--;//合并后网格上的格子数减一
isMerage.Enqueue(nextBox);//添加了已经合并的数,便于修改合并开关
}
break;//不能移动格子,也不能合并,格子本身不做任何操作
}
}
}
GameSwitch();//判断游戏输赢
}
///
/// 向左移动
///
private void GoLetf()
{
//循环行下标
for (int r = 0; r < boxList.GetLength(0); r++)
{
//循环列下表
for (int c = boxList.GetLength(1) - 3; c < boxList.GetLength(1); c++)//按照每行有多少列来循环,从左边到右边
{
Box box = boxList[r, c];
if (box.Num == 0) continue;
for (int nc = c - 1; nc >= 0; nc--)
{
Box nextBox = boxList[r, nc];
if (box.Num == 0) continue;//检测当前盒子是否需要往下移动
if (nextBox.Num == 0)
{
nextBox.Num = box.Num;
box.Num = 0;
box = nextBox;
continue;
}
if (nextBox.Num == box.Num && !nextBox.IsFirst)//合并操作
{
nextBox.Num *= 2;
nextBox.IsFirst = true;
box.Num = 0;
countNum--;//合并网格的元素减一
isMerage.Enqueue(nextBox);//添加已经合并的数,以便重置合并开关
}
break;
}
}
}
GameSwitch();//判断游戏输赢
}
///
/// 向上移动
///
private void GoUp()
{
//循环列下标
for (int c = 0; c < boxList.GetLength(1); c++)
{
//循环行下标
for (int r = boxList.GetLength(0) - 3; r < boxList.GetLength(0); r++) //从下到上
{
Box box = boxList[r, c];
if (box.Num == 0) continue;//检测当前盒子是否需要往下移动
for (int k = r - 1; k >= 0; k--)
{
Box nextBox = boxList[k, c];
if (nextBox.Num == 0)//如果上一格元素为空,则可以移动
{
nextBox.Num = box.Num; //把前面的元素移动到后面的元素
box.Num = 0;
box = nextBox;
continue;
}
if (box.Num == nextBox.Num && !nextBox.IsFirst)
{
nextBox.Num *= 2;
nextBox.IsFirst = true;
box.Num = 0;
countNum--;//合并网格,随机数的个数元素减一
isMerage.Enqueue(nextBox);//添加已经合并的数,以便修改开关
}
break;
}
}
}
GameSwitch();//判断游戏输赢
}
///
/// 向下的方法
///
private void GoDown()
{
//循环列的下标
for (var c = 0; c < boxList.GetLength(1); c++)
{
for (var r = boxList.GetLength(0) - 2; r >= 0; r--)
{
Box box = boxList[r, c];//当前进行检测判断是否可以往下移动或者合并的格子
if (box.Num == 0) continue;
for (var k = r + 1; k < boxList.GetLength(0); k++)
{
Box nextBox = boxList[k, c];
//进行空白格子判断
if (nextBox.Num == 0)
{
//找到一个就往下移一个
nextBox.Num = box.Num;
box.Num = 0;
box = nextBox;
continue;
}
//进行格子合并的判断
if (nextBox.Num == box.Num && !nextBox.IsFirst)
{
nextBox.Num *= 2;
nextBox.IsFirst = true;
box.Num = 0;
isMerage.Enqueue(nextBox);//添加已经合并的数,以便重置开关
countNum--;//合并网格的元素减一
}
break;
}
}
}
GameSwitch();//判断游戏输赢
}
///
/// 打印布局
///
private void Test()
{
Console.WriteLine("-------------------------------");
for (int i = 0; i < boxList.GetLength(0); i++)
{
for (int j = 0; j < boxList.GetLength(1); j++)
{
if (boxList[i, j].Num==2048) //游戏胜利
{
Console.WriteLine("游戏胜利");
gameBegin = false;
}
Console.Write(boxList[i, j].Num + "\t");
}
Console.Write("\n");
}
Console.WriteLine("-------------------------------");
}
///
/// 重置开关
///
private void ReSet()
{
while (isMerage.Count > 0)
{
isMerage.Dequeue().IsFirst = false;
}
}
///
/// 选择实现随机数的的生成
///
private void GameSwitch()
{
if (countNum < 16)//数的个数小于等于16时才能随机生成
{
RandomNum();
}
if (countNum == 16)//该判断一下输赢了
{
IsGameOver();
}
Console.WriteLine("网格上的元素:" + countNum);
Test();
}
///
/// 判断游戏是否进行
///
public void IsGameOver()
{
for (int r = 0; r < row; r++)
{
for (int c = 0; c < cols; c++)
{
if (c + 1 < row)//如果该元素列相邻元素存在,就比较
{
if (boxList[r, c].Num == boxList[r, c+1].Num)
{
return;
}
}
if (r + 1 < cols)//如果该元素的行相邻元素存在,就比较
{
if (boxList[r, c].Num == boxList[r+1, c].Num)
{
return;//如果该数与行相邻相等,游戏还可以进行
}
}
}
}
gameBegin = false;
}
}
管理类,管理整个格局,游戏开始到游戏结束.
成员:格局类
///
/// 管理游戏类
///
class Maneger
{
Grid gird;
public Maneger()
{
gird = new Grid(4,4);
}
public void InitGame()
{
gird.Init();
Console.WriteLine("2048游戏开始,规则如下,通过aswd键滑动字符串");
Console.WriteLine("每滑动一次,所有的数字就会想滑动的方向靠拢");
Console.WriteLine("只要有一个格子出现2048,就取得游戏胜利");
}
///
/// 获取用户的输入
///
public void choice()
{
ConsoleKeyInfo key = Console.ReadKey();
while (key.Key != ConsoleKey.Escape){ //输出ESC退出
gird.move(key.Key);
//游戏是否结束
if (!gird.GameBegin)
{
IsOver();
break;
}
key = Console.ReadKey();
}
}
private void IsOver()
{
Console.WriteLine("游戏结束");
}
}
开始程序
class Program
{
static void Main(string[] args)
{
Maneger ma = new Maneger();
ma.InitGame();
ma.choice();
Console.ReadLine();
}
}
目前2048还有BUG ,我已经修改了些许BUG,在下一篇c#生成2048游戏(2)