開篇
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
