开篇

2048游戏现在很火啊,很多人应该已经玩过了。在博客园上也看见有人模仿做的GDI+版 2048游戏,鄙人暂且不做那么多动画的东西,毕竟是个小东东,在此奉上一个《控制台版2048》。

本文程序源码下载:http://pan.baidu.com/s/1mg8zntu

程序结构相对简单,一共200+行代码,注释很少,大家大概也看得懂,我在这解释下程序中各个方法的含义:
Main 方法程序入口,
RePaint 类似Win32程序中的刷新界面,
SquareRot90 矩形矩阵顺时针旋转90度角(参数可以为负,表示逆时针)。
Merge 向左移动,合并单元格中值相同的元素,并进行整理(将所有元素靠左放置)
RandomPoint 随机生成点,从矩阵的空位置(值为0)中随机生成一个点,若不存在空位置返回null。
CanMove 判断是否可以继续移动,也是判断游戏是否结束的方法。
IsEquals 判断两矩阵的值是否相同。
CopyToB 将矩阵复制一份。
流程图如下:
上代码
 
主函数Main
static void Main(string[] args)
{
int[,] a = new int[4, 4];
a[1, 2] = 2;
a[2, 2] = 2;
a[2, 1] = 2;
RePaint(a);
while (true)
{
ConsoleKeyInfo key = Console.ReadKey();
switch (key.Key)
{
case ConsoleKey.UpArrow:
a = SquareRot90(a, 3);
a = Merge(a);
a = SquareRot90(a, -3);
break;
case ConsoleKey.DownArrow:
a = SquareRot90(a, 1);
a = Merge(a);
a = SquareRot90(a, -1);
break;
case ConsoleKey.LeftArrow:
a = Merge(a);
break;
case ConsoleKey.RightArrow:
a = SquareRot90(a, 2);
a = Merge(a);
a = SquareRot90(a, -2);
break;
}
Point cp = RandomPoint(a);
if (cp != null)
{
a[cp.X, cp.Y] = 2;
RePaint(a);
}
if (cp == null && !CanMove(a))
{
RePaint(a, "Game Over");
}
}
}

  

矩阵旋转方法
/// 矩形顺时针旋转90°
/// </summary>
/// <param name="rotNum">旋转次数</param>
public static int[,] SquareRot90(int[,] a, int rotNum)
{
while (rotNum < 0)
{
rotNum += 4;
}
for (int rot_i = 0; rot_i < rotNum; rot_i++)
{
int[,] b = new int[a.GetLength(1), a.GetLength(0)];
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
b[j, a.GetLength(0) - i - 1] = a[i, j];
}
}
a = b;
}
return a;
}

  

随机点方法
public static Point RandomPoint(int[,] a)
{
List<Point> lstP = new List<Point>();
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
if (a[i, j] == 0)
{
lstP.Add(new Point(i, j));
}
}
}
if (lstP.Count == 0)
{
return null;
}
int rnd = new Random().Next(lstP.Count);
return lstP[rnd];
}

  

矩阵向左合成方法
public static int[,] Merge(int[,] a)
{
for (int i = 0; i < a.GetLength(0); i++)
{
int lastNum = 0;
int last_j = 0;
for (int j = 0; j < a.GetLength(1); j++)//合并
{
if (lastNum != a[i, j] && a[i, j] != 0)
{
lastNum = a[i, j];
last_j = j;
}
else if (lastNum == a[i, j])
{
a[i, last_j] = 0;
a[i, j] = lastNum + a[i, j];
}
}
last_j = 0;
for (int j = 0; j < a.GetLength(1); j++)//整理
{
if (a[i, j] != 0)
{
a[i, last_j] = a[i, j];
if (last_j != j)
a[i, j] = 0;
last_j++;
}
}
}
return a;
}

  

是否可以继续移动CanMove方法
public static bool CanMove(int[,] a)
{
bool res = false;
int[,] b = CopyToB(a);
b = Merge(b);
if (!IsEquals(a, b))
res = true;
b = CopyToB(a);
b = SquareRot90(b, 1);
b = Merge(b);
b = SquareRot90(b, -1);
if (!IsEquals(a, b))
res = true;
b = CopyToB(a);
b = SquareRot90(b, 2);
b = Merge(b);
b = SquareRot90(b, -2);
if (!IsEquals(a, b))
res = true;
b = CopyToB(a);
b = SquareRot90(b, 3);
b = Merge(b);
b = SquareRot90(b, -3);
if (!IsEquals(a, b))
res = true;
return res;
}

  

CanMove中用到的IsEquals方法,判断矩阵相等
public static bool IsEquals(int[,] a, int[,] b)
{
bool res = true;
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
if (b[i, j] != a[i, j])
{
res = false;
break;
}
}
if (!res)
break;
}
return res;
}

  

CanMove中用到的矩阵复制方法CopyToB
public static int[,] CopyToB(int[,] a)
{
int[,] b = new int[a.GetLength(0), a.GetLength(1)];
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
b[i, j] = a[i, j];
}
}
return b;
}

  

两个RePain方法,重新打印,前面的表示GameOver
public static void RePaint(int[,] a, string s)
{
while (true)
{
Console.Clear();
RePaint(a);
Console.WriteLine("\n\n\n\n\t\t" + s + "\n\n");
Console.ReadKey();
}
}
public static void RePaint(int[,] a)
{
Console.Clear();
for (int j = 0; j < a.GetLength(1); j++)
{
Console.Write("───");
}
Console.Write("\n");
for (int i = 0; i < a.GetLength(0); i++)
{
Console.Write("│");
for (int j = 0; j < a.GetLength(1); j++)
{
string s = "";
if (a[i, j] == 0)
s = " ";
else if (a[i, j] < 10)
s = " " + a[i, j] + " ";
else if (a[i, j] < 100)
s = "" + a[i, j] + " ";
else
s = "" + a[i, j];
Console.Write(s + "│");
}
Console.Write("\n");
for (int j = 0; j < a.GetLength(1); j++)
{
Console.Write("───");
}
Console.Write("\n");
}
}

  

辅助类Point
class Point
{
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
public int X
{
get;
set;
}
public int Y
{
get;
set;
}
}

  

结束语
     其实要写一个游戏并不是像想像中那么容易,要处理算法等问题,必须要事先仔细的设计,需要一张草纸作为设计图,这样会让工作效率大大提高。之前贴过毕设的游戏《保卫萝卜》,由于时间关系迟迟没有整理,等毕设答辩完成后,一定好好整理,给大家分享。现在功能基本完成了,在这先贴一个缩减版的游戏程序,链接: http://pan.baidu.com/s/1sjvxO7N 。程序有什么问题、BUG,希望大家多多留言。源码整理后再上传。
     过几天是蓝桥杯比赛,哈哈,北京我来了。
本文程序源码下载:http://pan.baidu.com/s/1mg8zntu 
 

最新文章

  1. 理解SQL Server是如何执行查询的 (1/3)
  2. hdu-1213-How Many Tables
  3. W-数据库基础
  4. 034. asp.netWeb用户控件之三通过用户控件实现用户注册和登录
  5. [转]Try Cloud Messaging for Android
  6. 记录一些容易忘记的属性 -- UIView
  7. 每日会议&lt;第二天&gt;
  8. Android Service学习
  9. json中文编码问题
  10. poj 1177 picture
  11. Java基础学习
  12. Windows10中“SQL Server 配置管理器”哪去了?
  13. jQuery防京东浮动网站楼层导航代码
  14. 小子给大家分享一个或者多个新手创建tableview经常会遇到的坑(动态创建控件,xib的重用)
  15. Python从菜鸟到高手(6):获取用户输入、函数与注释
  16. JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数
  17. Hystrix浅谈
  18. ORACLE 从一个实例迁移到另外一个实例实战记录
  19. 内联函数 —— C 中关键字 inline 用法解析
  20. Node复习

热门文章

  1. .NET中生成水印更好的方法
  2. Hexo+NexT(四):Hexo站点及Next主题配置详解
  3. Spring_two
  4. Spring Batch 入门级示例教程
  5. python 基础学习笔记(2)---字符串功能函数
  6. LBXF时间管理法2.0
  7. SpringMVC框架的简单理解
  8. 如何正确使用Profibus插头以及终端电阻
  9. lleetcode 1 two sum c++
  10. 嵊州D2T1 “我只是来打个电话”