2048(1)的链接
修正BUG
如果无法进行移动和合并,就无法生成随机数字
增加功能
可以将最大的分数储存在本地,并读取
游戏界面
游戏文件密码: f3ma
代码主要更新了Grid类其他类没有改动
代码
using System;
using System.Collections.Generic;
using System.IO;
namespace Project2048
{
/// <summary>
/// 网格类
/// </summary>
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<Box> isMerage;//判断是是否已经合并集合
Random r;
bool isMakeRandom; //无法移动格局上的数时,无法产生随机数
int BoxNum; //存储当前格子里叠加的数,如果是2048则取得游戏胜利
private int scorce;//当前分数
private int maxScore;//最高分数
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<Box>();
gameBegin = true; //初始化游戏开始
isMakeRandom = false;
scorce = 0;
maxScore = getMaxScore() ;
}
/// <summary>
/// 获取在文件里面的最高分数
/// </summary>
/// <returns></returns>
private int getMaxScore()
{
//55.txt用来储存最高分数
byte[] scoreByte;
try
{
scoreByte = File.ReadAllBytes("55.txt");
}
catch (FileNotFoundException e) //如果文件没有找到,说明还没有储存分数
{
return 0;
}
return Int32.Parse(System.Text.UnicodeEncoding.UTF8.GetString(scoreByte));
}
/// <summary>
/// 返回游戏开关
/// </summary>
public bool GameBegin
{
get
{
return gameBegin;
}
}
/// <summary>
/// 初始化布局
/// </summary>
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();
}
/// <summary>
/// 随机生成数字
/// </summary>
private 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;
}
boxList[rObj, cObj].Num = num;
i++;
}
}
/// <summary>
/// 用户输入了按键,根据按键选择移动方向的方法
/// </summary>
/// <param name="keyValue"></param>
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();//做完一次操作后重置一下开关
}
/// <summary>
/// 向右运动
/// </summary>
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) //如果前面格子里没有数,就往前移
{
isMakeRandom = true;//可以移动就产生随机数
nextBox.Num = box.Num;
box.Num = 0;
box = nextBox;
continue;
}
if (box.Num == nextBox.Num && !nextBox.IsFirst)//如果格子里的数和要往前移的格子里的数是相同的,就可以合并
{
isMakeRandom = true;//可以合并,就可以产生随机数
//合并操作
nextBox.IsFirst = true;
nextBox.Num *= 2;
box.Num = 0;
scorce += nextBox.Num; //合并添加分数
countNum--;//合并后网格上的格子数减一
isMerage.Enqueue(nextBox);//添加了已经合并的数,便于修改合并开关
}
break;//不能移动格子,也不能合并,格子本身不做任何操作
}
}
}
GameSwitch();//判断游戏输赢
}
/// <summary>
/// 向左移动
/// </summary>
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)
{
isMakeRandom = true;
nextBox.Num = box.Num;
box.Num = 0;
box = nextBox;
continue;
}
if (nextBox.Num == box.Num && !nextBox.IsFirst)//合并操作
{
isMakeRandom = true;
nextBox.Num *= 2;
nextBox.IsFirst = true;
box.Num = 0;
scorce += nextBox.Num;
countNum--;//合并网格的元素减一
isMerage.Enqueue(nextBox);//添加已经合并的数,以便重置合并开关
}
break;
}
}
}
GameSwitch();//判断游戏输赢
}
/// <summary>
/// 向上移动
/// </summary>
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)//如果上一格元素为空,则可以移动
{
isMakeRandom = true;//只要进行了移动就可以产生随机数
nextBox.Num = box.Num; //把前面的元素移动到后面的元素
box.Num = 0;
box = nextBox;
continue;
}
if (box.Num == nextBox.Num && !nextBox.IsFirst)
{
isMakeRandom = true;
nextBox.Num *= 2;
nextBox.IsFirst = true;
box.Num = 0;
scorce += nextBox.Num;
countNum--;//合并网格,随机数的个数元素减一
isMerage.Enqueue(nextBox);//添加已经合并的数,以便修改开关
}
break;
}
}
}
GameSwitch();//判断游戏输赢
}
/// <summary>
/// 向下的方法
/// </summary>
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)
{
isMakeRandom = true; //移动则可以残生随机数
//找到一个就往下移一个
nextBox.Num = box.Num;
box.Num = 0;
box = nextBox;
continue;
}
//进行格子合并的判断
if (nextBox.Num == box.Num && !nextBox.IsFirst)
{
isMakeRandom = true;
//合并一下
nextBox.Num *= 2;
nextBox.IsFirst = true;
box.Num = 0;
scorce += nextBox.Num;
isMerage.Enqueue(nextBox);//添加已经合并的数,以便重置开关
countNum--;//合并网格的元素减一
}
break;
}
}
}
GameSwitch();//判断游戏输赢
}
/// <summary>
/// 打印布局
/// </summary>
private void Test()
{
Console.WriteLine("当前分数:{0} 最高分数:{1}",scorce,maxScore);
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) //游戏胜利
{
BoxNum = boxList[i, j].Num;
}
Console.Write(boxList[i, j].Num + "\t");
}
Console.Write("\n");
}
Console.WriteLine("-------------------------------");
}
/// <summary>
/// 重置开关
/// </summary>
private void ReSet()
{
while (isMerage.Count > 0)
{
isMerage.Dequeue().IsFirst = false;
}
}
/// <summary>
/// 选择实现随机数的的生成
/// </summary>
private void GameSwitch()
{
if (BoxNum == 2048)//游戏胜利
{
Console.WriteLine("游戏胜利");
LayScorce();
gameBegin = false;
}
if (isMakeRandom)//可以移动或者合并才能生成随机数,或者答应格局
{
RandomNum();
Test();
}
isMakeRandom = false;//重置开关
if (countNum == 16)//该判断一下输赢了
{
IsGameOver();
}
}
/// <summary>
/// 判断游戏是否输了了
/// </summary>
private 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;//如果该数与行相邻相等,游戏还可以进行
}
}
}
}
LayScorce();//存储分数
gameBegin = false;
}
/// <summary>
/// 储存游戏
/// </summary>
private void LayScorce()
{
if (scorce > maxScore)//只储存最大的分数
{
Byte[] scorceByte = System.Text.Encoding.UTF8.GetBytes(scorce.ToString());
File.WriteAllBytes("55.txt",scorceByte);
}
}
}
}