曾经使用C#控制台应用程序写的一个2048,现在翻出来回顾一下
- Box类是2048中每一个小格子的相关信息,包括格子的横纵坐标、格子的值和格子是否刚合并这些信息。
- Grid类是网格的相关信息,包括网格的长宽(默认是4X4,也可以改成其他形式的),分数等。
- Manager2048类是个大杂烩的类,写的很乱,什么乱七八糟的方法都丢在了里面。
=================================贼好看的分割线=============
Program.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _031_test
{
/// <summary>
/// 2048
/// </summary>
class Program
{
static void Main(string[] args)
{
Manager2048 m2048 = new Manager2048();
m2048.Strat();
m2048.Control(); Console.ReadLine();
}
}
}
Program.CS
Box.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _031_test
{
/// <summary>
/// 格子
/// </summary>
class Box
{
//格子的坐标
int row;
int col;
public int Row { get { return row; } }
public int Col { get { return col; } }
//格子的值
public int Value { get; set; }
//是否已经合并
public bool IsMerge { get; set; } public Box(int row,int col)
{
this.row = row;
this.col = col;
//初始化默认值为0
this.Value = ;
this.IsMerge = false;
} }
}
Box.CS
Grid.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO; namespace _031_test
{
/// <summary>
/// 网格
/// </summary>
class Grid
{
//网格的长宽
int rows;
int cols;
public int Rows { get { return rows; } }
public int Cols { get { return cols; } } public int score; public int randomTimes = ;//判断游戏是否结束的标识位16结束
Random random;
//存放格子对象
public Box[,] bList;
//是否是第一次,第一次则出现两个数,否则只出现一个数
bool isFirst = true; public Grid(int rows, int cols)
{
this.random = new Random();
this.rows = rows < ? : rows;
this.cols = cols < ? : cols;
bList = new Box[rows, cols];
} //初始化
public void InitGrid()
{
//对网格中的每一个格子进行初始化,并将每一个格子对象存入bList中
for (int i = ; i < bList.GetLength(); i++)
{
for (int j = ; j < bList.GetLength(); j++)
{
Box box = new Box(i, j);
bList[i, j] = box;
}
}
RandomNum();
}
///////////////////////////////////
//随机---包括生成的数字和位置
public void RandomNum()
{
//count表示要生成的数字的个数,进行判断,初始化时候生成两个,否则就一个
int count;
if (isFirst) { count = ; isFirst = false; }
else count = ; int i = ;
while (i < count)
{
//随机出现数字的下标
int r = random.Next(, rows);
int c = random.Next(, cols);
//若随机到的位置已经有值了,则返回重新随机
if (bList[r, c].Value != ) continue;
//随机2和4 出现几率 80% 20%
int valuePercent = random.Next(, );
//将出现的值
int value;
if (valuePercent < ) value = ;
else value = ;
bList[r, c].Value = value;
i++;
//当randomTimes到16时说明所有格子都满了
randomTimes++;
}
} //显示游戏界
public void DisPlay()
{
Console.WriteLine("===============================");
for (var i = ; i < bList.GetLength(); i++)
{
for (var j = ; j < bList.GetLength(); j++)
{
Console.Write(bList[i, j].Value + "\t");
}
Console.WriteLine("\n");
}
Console.WriteLine("===============================");
Console.WriteLine("当前分数:" + score + "历史最高:" + Int32.Parse(File.ReadAllText("score.txt")));
} }
}
Grid.CS
Manager2048.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO; namespace _031_test
{
/// <summary>
/// 控制器
/// </summary>
class Manager2048
{
Grid g; public Manager2048()
{
g = new Grid(, );
} //开始游戏 public void Strat()
{
g.InitGrid();
g.DisPlay();
Console.WriteLine("游戏开始,请直接使用方向键进行操作");
} public void Control()
{
while (true)
{
//ConsoleKeyInfo可以直接接受一个字符不需要再按下回车键确认
ConsoleKeyInfo keyInfo = Console.ReadKey();
switch (keyInfo.Key)
{
case ConsoleKey.UpArrow: Up(); break;
case ConsoleKey.DownArrow: Down(); break;
case ConsoleKey.LeftArrow: Left(); break;
case ConsoleKey.RightArrow: Right(); break;
default: Console.WriteLine("按错了"); break;
}
if (g.randomTimes==g.Rows*g.Cols&&!CanWeMergeInFull())
{
Console.WriteLine("游戏结束");
break;
}
}
} public void Up()
{
bool ismove=false;
//遍历每一个box,检测该box是否要移动
for (int i = ; i < g.bList.GetLength(); i++)//向上移动不需要考虑第一行的上移,所以直接i=1
{
for (int j = ; j < g.bList.GetLength(); j++)
{
//如果该box值不是0,说明该box需要移动,否则继续遍历下一个box
if (g.bList[i, j].Value != )
{
int temp = g.bList[i, j].Value;
//从该box的上一行开始一直遍历到最顶上
int k = i - ;
while (k >= )
{
if (g.bList[k, j].Value != || k == ) break;
else k--;
}
//如果碰到了和要移动的box值一样的box,就要把他们合并(IsMerge:当这个box是这一轮合并来的box时,则不能合并)
if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge==false)
{
g.bList[i, j].Value = ;
g.bList[k, j].Value = temp * ;
g.score += temp * ;
if (g.score > Int32.Parse(File.ReadAllText("score.txt")))
{
File.WriteAllText("score.txt", g.score.ToString());
}
g.bList[k, j].IsMerge = true;
g.randomTimes--;
ismove = true;
}
else if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge==true)
{
g.bList[i, j].Value = ;
g.bList[k + , j].Value = temp;
//i=k+1表示该box并没有移动
if (i == k + ) ismove = false;
else ismove = true;
}
//值不一样的时候,就把要移动的box放到这个box下面去
else if (g.bList[k, j].Value != )
{
g.bList[i, j].Value = ;
g.bList[k + , j].Value = temp;
if (i == k + ) ismove = false;
else ismove = true;
}
//这种情况是遍历到最顶行的box且该box为0时,直接把要动的box移到这
else
{
g.bList[i, j].Value = ;
g.bList[k, j].Value = temp;
if (i == k) ismove = false;
else ismove = true;
}
}
}
}
if (ismove && !IsFull()) g.RandomNum();//当所有格子都满了时就不随机生成数字
else Console.WriteLine("该方向无法移动");
ResetIsMerge();//重置所有box的合并状态为false
g.DisPlay();
} public void Down()
{
bool ismove = false;
//错误写法:for (int i = 0; i < g.bList.GetLength(0) - 1; i++)
//以上写法会导致上层的数先被遍历从而导致先移动完毕,所以要从最后一个数开始遍历
for (int i = g.bList.GetLength() - ; i >= ; i--)
{
for (int j = g.bList.GetLength() - ; j >= ; j--)
{
if (g.bList[i, j].Value != )
{
int temp = g.bList[i, j].Value;
int k = i + ;
while (k <= g.bList.GetLength() - )
{
if (g.bList[k, j].Value != || k == g.bList.GetLength() - ) break;
else k++;
}
if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge == false)
{
g.bList[i, j].Value = ;
g.bList[k, j].Value = temp * ;
g.bList[k, j].IsMerge = true;
g.score += temp * ;
if (g.score > Int32.Parse(File.ReadAllText("score.txt")))
{
File.WriteAllText("score.txt", g.score.ToString());
}
g.randomTimes--;
ismove = true;
}
else if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge == true)
{
g.bList[i, j].Value = ;
g.bList[k - , j].Value = temp;
if (i == k - ) ismove = false;
else ismove = true;
}
else if (g.bList[k, j].Value != )
{
g.bList[i, j].Value = ;
g.bList[k - , j].Value = temp;
if (i == k - ) ismove = false;
else ismove = true;
}
else
{
g.bList[i, j].Value = ;
g.bList[k, j].Value = temp;
if (i == k) ismove = false;
else ismove = true;
}
}
}
}
if (ismove && !IsFull()) g.RandomNum();
else Console.WriteLine("该方向无法移动");
ResetIsMerge();
g.DisPlay();
} public void Left()
{
bool ismove = false;
for (int i = ; i < g.bList.GetLength(); i++)
{
for (int j = ; j < g.bList.GetLength(); j++)
{
if (g.bList[i, j].Value != )
{
int temp = g.bList[i, j].Value;
int k = j - ;
while (k >= )
{
if (g.bList[i, k].Value != || k == ) break;
else k--;
}
if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == false)
{
g.bList[i, j].Value = ;
g.bList[i, k].Value = temp * ;
g.score += temp * ;
if (g.score > Int32.Parse(File.ReadAllText("score.txt")))
{
File.WriteAllText("score.txt", g.score.ToString());
}
g.bList[k, j].IsMerge = true;
g.randomTimes--;
ismove = true;
}
else if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == true)
{
g.bList[i, j].Value = ;
g.bList[i, k + ].Value = temp;
if (j == k + ) ismove = false;
else ismove = true;
}
else if (g.bList[i, k].Value != )
{
g.bList[i, j].Value = ;
g.bList[i, k + ].Value = temp;
if (j == k + ) ismove = false;
else ismove = true;
}
else
{
g.bList[i, j].Value = ;
g.bList[i, k].Value = temp;
if (j == k) ismove = false;
else ismove = true;
}
}
}
}
if (ismove && !IsFull()) g.RandomNum();
else Console.WriteLine("该方向无法移动");
ResetIsMerge();
g.DisPlay();
} public void Right()
{
bool ismove = false;
//错误写法:for (int i = 0; i < g.bList.GetLength(0) - 1; i++)
//以上写法会导致上层的数先被遍历从而导致先移动完毕,所以要从最后一个数开始遍历
for (int i = g.bList.GetLength() - ; i >= ; i--)
{
for (int j = g.bList.GetLength() - ; j >= ; j--)
{
if (g.bList[i, j].Value != )
{
int temp = g.bList[i, j].Value;
int k = j + ;
while (k <= g.bList.GetLength() - )
{
if (g.bList[i, k].Value != || k == g.bList.GetLength() - ) break;
else k++;
}
if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == false)
{
g.bList[i, j].Value = ;
g.bList[i, k].Value = temp * ;
g.score += temp * ;
if (g.score > Int32.Parse(File.ReadAllText("score.txt")))
{
File.WriteAllText("score.txt", g.score.ToString());
}
g.bList[k, j].IsMerge = true;
g.randomTimes--;
ismove = true;
}
else if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == true)
{
g.bList[i, j].Value = ;
g.bList[i, k - ].Value = temp;
if (j == k - ) ismove = false;
else ismove = true;
}
else if (g.bList[i, k].Value != )
{
g.bList[i, j].Value = ;
g.bList[i, k - ].Value = temp;
if (j == k - ) ismove = false;
else ismove = true;
}
else
{
g.bList[i, j].Value = ;
g.bList[i, k].Value = temp;
if (j == k) ismove = false;
else ismove = true;
}
}
}
}
if (ismove && !IsFull()) g.RandomNum();
else Console.WriteLine("该方向无法移动");
ResetIsMerge();
g.DisPlay();
} //判断网格是否已满
public bool IsFull()
{
for (int i = ; i < g.Rows; i++)
{
for (int j = ; j < g.Cols; j++)
{
if (g.bList[i, j].Value == )
{
return false;
}
}
}
return true;
} //重置所有box合并状态
public void ResetIsMerge()
{
for (int i = ; i < g.Rows; i++)
{
for (int j = ; j < g.Cols; j++)
{
g.bList[i, j].IsMerge = false;
}
}
} //网格满时是否还可以继续合并 true表示还有能合并的
public bool CanWeMergeInFull()
{
for (int i = ; i < g.Rows; i++)
{
for (int j = ; j < g.Cols; j++)
{
//检测上方向
if (i - >= && g.bList[i, j].Value == g.bList[i - , j].Value)
{
return true;
}
//检测下方向
if (i + < g.Rows && g.bList[i, j].Value == g.bList[i + , j].Value)
{
return true;
}
//检测左方向
if (j - >= && g.bList[i, j].Value == g.bList[i, j - ].Value)
{
return true;
}
//检测右方向
if (j + < g.Cols && g.bList[i, j].Value == g.bList[i, j + ].Value)
{
return true;
}
}
}
return false;
} }
}
Manager2048.CS
=================================贼好看的分割线=============
最终效果: