游戏规则
游戏规则,玩家需要控制所有方块向同一个方向运动,两个相同数字方块撞在一起后会合并成为它们的和,每次操作后会随机生成一个2或者4,最终得到一个“2048”的方块就算胜利。
C#代码实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _2019年8月16日
{
class Program
{
static void Main(string[] args)
{
int[,] arr = new int[4, 4]
{
//{8,8,2,0 },
//{8,4,0,4 },
//{2,0,2,0 },
//{0,0,0,0 },
//{0,8,2,0 },
//{0,4,0,4 },
//{2,0,2,0 },
//{0,0,0,0 },
{0,0,2,0 },
{0,0,0,0 },
{2,0,0,0 },
{0,0,0,0 },
};
_2048 a2048 = new _2048(arr);
Console.WriteLine("原数组:");
a2048.PrintArr(arr);
while (true)
{
ConsoleKeyInfo info = Console.ReadKey();//获取按键信息
switch (info.Key)
{
case ConsoleKey.LeftArrow://如果是向左键
Console.WriteLine("←");
a2048.Print_Left();
break;
case ConsoleKey.UpArrow://如果是向上键
Console.WriteLine("↑");
a2048.Print_Up();
break;
case ConsoleKey.RightArrow://如果是向右键
Console.WriteLine("→");
a2048.Print_Right();
break;
case ConsoleKey.DownArrow://如果是向下键
Console.WriteLine("↓");
a2048.Print_Down();
break;
default:
break;
}
}
}
}
//2048小游戏类
class _2048
{
private int[,] arr;
public _2048(int[,] arr)
{
this.arr = arr;
}
//打印数组
public void PrintArr(int[,] newArr)
{
for (int i = 0; i < newArr.GetLength(0); i++)
{
for (int j = 0; j < newArr.GetLength(1); j++)
{
Console.Write(newArr[i, j] + "\t");
}
Console.WriteLine();
}
Console.WriteLine();
}
//打印向右合并数组
public void Print_Right()
{
int[,] rightArr = ToRigth(arr);
//arr = rightArr;//更新arr数组
arr = Rand2048(rightArr);//更新能随机生成数字的arr数组
PrintArr(rightArr);
}
//打印向上合并数组
public void Print_Up()
{
int[,] upArr = ToUp(arr);
//arr = upArr;
arr = Rand2048(upArr);
PrintArr(upArr);
}
//打印向下合并数组
public void Print_Down()
{
int[,] downArr = ToDown(arr);
//arr = downArr;
arr = Rand2048(downArr);
PrintArr(downArr);
}
//打印向左合并数组
public void Print_Left()
{
int[,] leftArr = ToLeft(arr);
//arr = leftArr;
arr = Rand2048(leftArr);
PrintArr(leftArr);
}
//顺时针旋转90°
private int[,] CW90(int[,] arr)
{
int[,] newArr = new int[arr.GetLength(1), arr.GetLength(0)];//定义新数组
for (int r = 0, c_newArr = newArr.GetLength(1) - 1; r < arr.GetLength(0); r++)
{
for (int c = 0, r_newArr = 0; c < arr.GetLength(1); c++)
{
newArr[r_newArr, c_newArr] = arr[r, c];
r_newArr++;
}
c_newArr--;
}
return newArr;
}
//逆时针旋转90°
private int[,] ACW90(int[,] arr)
{
int[,] newArr = new int[arr.GetLength(1), arr.GetLength(0)];//定义新数组
for (int r = 0, c_newArr = 0; r < arr.GetLength(0); r++)
{
for (int c = 0, r_newArr = newArr.GetLength(0) - 1; c < arr.GetLength(1); c++)
{
newArr[r_newArr, c_newArr] = arr[r, c];
r_newArr--;
}
c_newArr++;
}
return newArr;
}
//垂直翻转
private int[,] FZ(int[,] arr)
{
int[,] newArr = new int[arr.GetLength(0), arr.GetLength(1)];//定义新数组
for (int r = 0; r < arr.GetLength(0); r++)
{
for (int c = 0, c_n = newArr.GetLength(1) - 1; c < arr.GetLength(1); c++, c_n--)
{
newArr[r, c_n] = arr[r, c];
}
}
return newArr;
}
//向右合并
private int[,] ToRigth(int[,] arr)
{
//向右
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int k = 0; k < arr.GetLength(1) - 1; k++)//逐行将0左对齐
{
for (int j = arr.GetLength(1) - 1; j > k; j--)
{
if (arr[i, j] == 0)
{
int temp = arr[i, j];
arr[i, j] = arr[i, j - 1];
arr[i, j - 1] = temp;
}
}
}
}
//合并
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = arr.GetLength(1) - 1; j > 0; j--)
{
if (arr[i, j] == arr[i, j - 1] && arr[i, j] != 0)//相邻数字相同且不等于0时
{
arr[i, j] *= 2;
arr[i, j - 1] = 0;
}
}
}
//再次向右
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int k = 0; k < arr.GetLength(1) - 1; k++)//逐行将0左对齐
{
for (int j = arr.GetLength(1) - 1; j > k; j--)
{
if (arr[i, j] == 0)
{
int temp = arr[i, j];
arr[i, j] = arr[i, j - 1];
arr[i, j - 1] = temp;
}
}
}
}
return arr;
}
//向上合并
private int[,] ToUp(int[,] arr)
{
//先使数组顺时针旋转90°
int[,] newArr = CW90(arr);
//再向右合并
newArr = ToRigth(newArr);
//最后使数组逆时针旋转90°(转回来)
newArr = ACW90(newArr);
return newArr;
}
//向下合并
private int[,] ToDown(int[,] arr)
{
//先使数组逆时针旋转90°
int[,] newArr = ACW90(arr);
//再向右合并
newArr = ToRigth(newArr);
//最后使数组顺时针旋转90°
newArr = CW90(newArr);
return newArr;
}
//向左合并
private int[,] ToLeft(int[,] arr)
{
//先使数组垂直翻转一次
int[,] newArr = FZ(arr);
//再向右合并
newArr = ToRigth(newArr);
//最后再使数组翻转回来
newArr = FZ(newArr);
return newArr;
}
//在数字为0的地方随机生成2或者4
private int[,] Rand2048(int[,] arr)
{
Random rand = new Random();
int r_ran = rand.Next(arr.GetLength(0));//获取随机行索引
int c_ran = rand.Next(arr.GetLength(1));//获取随机列索引
if (arr[r_ran, c_ran] == 0)//如果该随机数原来等于0
{
int num = rand.Next(10);
if (num == 0)//随机生成4的概率为10%
{
arr[r_ran, c_ran] = 4;
}
else//随机生成2的概率为90%
{
arr[r_ran, c_ran] = 2;
}
}
return arr;
}
}
}
小结
本次游戏实现通过写一个2048游戏类,声明一个二维数组字段,并且在类构造函数中通过传参实现二维数组的初始化。
在2048游戏类中有打印数组方法,打印向左、向右、向上、向下合并数组方法,这些方法主要作用是显示合并的最终结果。
接下来首先写出向右合并方法,接着向上、向下和向左合并方法可以分别通过将原数组旋转和翻转后调用向右合并方法实现。
根据上面的思路,类中还应该有顺逆时针旋转、垂直翻转二维数组的方法,以便于在除向右合并方法的其他合并方法中使用。
最后是实现操作一次,随机生成一个2或者4在二维数组里,这个利用C#类库中的Random类就可以了,据说生成2的概率和生成4的概率是不同的,前者概率是90%,后者是10%。