基于C#的2048小游戏
项目简介
利用C#语言实现一个2048小游戏,通过编写程序实现游戏的操作过程。
2048游戏规则其实很简单,玩家每次可以选择上、下、左、右其中一个方向去移动,每移动一次,所有的数字方块都会往移动的方向靠拢。同时,系统也会在空白的地方随机出现新的数字方块,相同数字的方块在靠拢、相撞时会相加。系统给予的数字方块不是“2”就是“4”,玩家要想办法在这小小的16格范围中凑出“2048”这个数字方块,即为游戏胜利,否则游戏失败。
开发环境
(1)Windows 10系统;
(2)Visual Studio 2013软件。
项目流程
(1)打开Visual Studio软件,点击文件->新建->项目,在新建项目部分,选择visual C#,创建一个新的C#项目,输入项目名称,选择保存路径,将其命名为“game2048”,如图1所示。
图1-新建项目
(2)打开右侧的解决方案资源管理器,在此处可以看到刚刚新建的项目,在创建好的项目中添加一个新的.cs项目,将其命名为“Box.cs”,如图2所示。
图2-添加Box.cs
(3)在创建好的项目中添加一个新的.cs项目,将其命名为“Grid.cs”,如图3所示。
图3-添加Grid.cs
(4)在创建好的项目中添加一个新的.cs项目,将其命名为“Manager.cs”,如图4所示。
图4-添加Manager.cs
(5)在创建好的项目中编写类和相关程序代码,完善“Box.cs”、“Grid.cs”和“Manager.cs”,如图5所示。
图5-完善程序代码
(6)在完成程序代码的编写以后,运行程序,如图6所示。
图6-程序运行结果
**主要代码**
1.Box.cs
using System;
namespace game2048
{
class Box
{
public int Number { get; set; }
public Box(int num)
{
this.Number = num;
}}}
2.Grid.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace game2048
{
class Grid
{
private int row;
private int col;
private Box[,] grids;
private bool isFirst;
private int rdNumber;
public bool IsGameOver { get; private set; }
public Grid(int row, int col)
{
this.row = row;
this.col = col;
this.grids = new Box[row, col];
InitBoxs();
IsGameOver = false;
isFirst = true;
}
private void InitBoxs()
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
Box box = new Box(0);
grids[i, j] = box;
} } }
public void PrintGrid()
{
Console.WriteLine("==============================================");
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
Console.Write(grids[i, j].Number + "\t");
}
Console.WriteLine();
} Console.WriteLine("==============================================");
}
public void RandomBox()
{
int count = 1;
//首次生成两个数字
if (isFirst)
{
count = 2;
isFirst = false;
}
Random rd = new Random();
for (int i = 0; i < count; )
{
if (rdNumber == 4)
{
rdNumber = 2;
}
else
{
int num = rd.Next(1, 11);
if (num < 9)
{
rdNumber = 2;
}
else
{
rdNumber = 4;
} }
int boxRow = rd.Next(0, row);
int boxCol = rd.Next(0, col);
if (grids[boxRow, boxCol].Number == 0)
{
Console.WriteLine("随机生成点为:[{0},{1}]", boxRow, boxCol);
grids[boxRow, boxCol].Number = rdNumber;
}
else
{
continue;
}
i++;
} }
public bool MoveDirection(Direction dir)
{
bool isMove = false;
switch (dir)
{
case Direction.Up:
isMove = MoveUp();
break;
case Direction.Dowm:
isMove = MoveDown();
break;
case Direction.Left:
isMove = MoveLeft();
break;
case Direction.Right:
isMove = MoveRight();
break;
}
CheckIsGameOver();
return isMove;
}
//当矩阵满了的时候(数字都不为0),上下左右相邻没有数字相同的了,游戏就结束,否则游戏继续
private void CheckIsGameOver()
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (grids[i, j].Number == 0)
{
IsGameOver = false;
return;
} } }
//矩阵存满了不为0的数
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
//上下左右
if (i - 1 >= 0 && grids[i, j].Number == grids[i - 1, j].Number)
{
IsGameOver = false;
return;
}
if (i + 1 < row && grids[i, j].Number == grids[i + 1, j].Number)
{
IsGameOver = false;
return;
}
if (j - 1 >= 0 && grids[i, j].Number == grids[i, j - 1].Number)
{
IsGameOver = false;
return;
}
if (j + 1 < col && grids[i, j].Number == grids[i, j + 1].Number)
{
IsGameOver = false;
return;
} } }
IsGameOver = true;
}
//向下
private bool MoveDown()
{
bool isMoveBox = false; //是否移动格子
for (int j = 0; j < col; j++)
{
//将所有的格子往下面移
for (int i = row - 1; i >= 0; i--)
{
if (grids[i, j].Number == 0)
//如果为0,代表该格子为空,上面的格子往下移
{
for (int k = i - 1; k >= 0; k--)
{
if (grids[k, j].Number != 0)
{
isMoveBox = true;
grids[i, j].Number = grids[k, j].Number;
grids[k, j].Number = 0;
break;
} } } }
//合并格子
for (int i = row - 1; i >= 0; i--)
{
//如果遍历到最后一个格子 或者 当前格子的上面一个格子没有数字,结束循环
if (i == 0 || grids[i - 1, j].Number == 0)
{
break;
}
Console.WriteLine("==================");
if (grids[i, j].Number == grids[i - 1, j].Number)
{
isMoveBox = true;
grids[i - 1, j].Number = 0;
grids[i, j].Number *= 2;
//合并完格子,上面的格子(往上数2个)往下面移
for (int k = i - 2; k >= 0; k--)
{
if (grids[k, j].Number == 0)
{
break;
}
grids[k + 1, j].Number = grids[k, j].Number;
grids[k, j].Number = 0;
} } } }
return isMoveBox; }
//向上
private bool MoveUp()
{
bool isMoveBox = false;
for (int j = 0; j < col; j++)
{
//将所有的格子往上面移
for (int i = 0; i < row; i++)
{
if (grids[i, j].Number == 0)
//如果为0,代表该格子为空,下面的格子往上移
{
for (int k = i + 1; k < row; k++)
{
if (grids[k, j].Number != 0) {
isMoveBox = true;
grids[i, j].Number = grids[k, j].Number;
grids[k, j].Number = 0;
break;
} } } }
//合并格子
for (int i = 0; i < row; i++)
//如果遍历到最后一个格子 或者 当前格子的下面一个格子没有数字,结束循环
if (i == row - 1 || grids[i + 1, j].Number == 0)
{
break;
}
if (grids[i, j].Number == grids[i + 1, j].Number)
{
isMoveBox = true;
grids[i + 1, j].Number = 0;
grids[i, j].Number *= 2;
//合并完格子,下面的格子(往下数2个)往上面移
for (int k = i + 2; k < row; k++)
{
if (grids[k, j].Number == 0)
{
break;
}
grids[k - 1, j].Number = grids[k, j].Number;
grids[k, j].Number = 0;
} } } }
return isMoveBox;
}
//向左
private bool MoveLeft()
{
bool isMoveBox = false; //是否移动格子
for (int i = 0; i < row; i++)
{
//将所有的格子往左边移
for (int j = 0; j < col; j++)
{
if (grids[i, j].Number == 0)
//如果为0,代表该格子为空,右边的格子往左移
{
for (int k = j + 1; k < col; k++)
{
if (grids[i, k].Number != 0) {
isMoveBox = true;
grids[i, j].Number = grids[i, k].Number;
grids[i, k].Number = 0;
break;
} } } }
//合并格子
for (int j = 0; j < col; j++)
{
//如果遍历到最后一个格子 或者 当前格子的右边一个格子没有数字,结束循环
if (j == col - 1 || grids[i, j + 1].Number == 0)
{ break; }
if (grids[i, j].Number == grids[i, j + 1].Number)
{
isMoveBox = true;
grids[i, j + 1].Number = 0;
grids[i, j].Number *= 2;
//合并完格子,右边的格子(往右数2个)往左边移
for (int k = j + 2; k < col; k++)
{
if (grids[k, j].Number == 0)
{
break;
}
grids[i, k - 1].Number = grids[i, k].Number;
grids[i, k].Number = 0;
} } } }
return isMoveBox; }
//向右
private bool MoveRight()
{
bool isMoveBox = false; //是否移动格子
for (int i = 0; i < row; i++)
{
//将所有的格子往右边移
for (int j = col - 1; j >= 0; j--)
{
if (grids[i, j].Number == 0)
//如果为0,代表该格子为空,左边的格子往右移
{
for (int k = j - 1; k >= 0; k--)
{
if (grids[i, k].Number != 0)
{
isMoveBox = true;
grids[i, j].Number = grids[i, k].Number;
grids[i, k].Number = 0;
break;
} } } }
//合并格子
for (int j = col - 1; j >= 0; j--)
{
//如果遍历到最后一个格子 或者 当前格子的左边一个格子没有数字,结束循环
if (j == 0 || grids[i, j - 1].Number == 0)
{ break; }
if (grids[i, j].Number == grids[i, j - 1].Number)
{
isMoveBox = true;
grids[i, j - 1].Number = 0;
grids[i, j].Number *= 2;
//合并完格子,左边的格子(往右数2个)往右边移
for (int k = j - 2; k >= 0; k--)
{
if (grids[k, j].Number == 0)
{
break;
}
grids[i, k + 1].Number = grids[i, k].Number;
grids[i, k].Number = 0;
} } } }
return isMoveBox;
} }
enum Direction
{
Up,
Dowm,
Left,
Right
}}
3.Manager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace game2048
{
class Manager
{
private static Grid grid = new Grid(4, 4);
static void Main()
{
StartGame(); }
public static void StartGame()
{
grid.RandomBox();
grid.PrintGrid();
Console.WriteLine("请按上下左右键");
while (grid.IsGameOver == false)
{
if (PlayController() == false)
{
if (grid.IsGameOver)
{
Console.WriteLine("------------------------------------------"); Console.WriteLine("------------------------------------------"); Console.WriteLine("------------------------------------------");
Console.WriteLine("---------------【游戏结束】---------------");
Console.WriteLine("------------------------------------------"); Console.WriteLine("------------------------------------------"); Console.WriteLine("------------------------------------------");
break; }
continue; }
//随机生成box
grid.RandomBox();
Console.Clear();
grid.PrintGrid();
} }
public static bool PlayController()
{
bool isCanMove = false;
while (true)
{
bool isRightKey = false;
ConsoleKeyInfo info = Console.ReadKey();
switch (info.Key)
{
case ConsoleKey.UpArrow:
isRightKey = true;
isCanMove = grid.MoveDirection(Direction.Up);
if (isCanMove == false)
{
Console.WriteLine("不能向上移动了!");
}
break;
case ConsoleKey.DownArrow:
isRightKey = true;
isCanMove = grid.MoveDirection(Direction.Dowm);
if (isCanMove == false)
{
Console.WriteLine("不能向下移动了!");
}
break;
case ConsoleKey.LeftArrow:
isRightKey = true;
isCanMove = grid.MoveDirection(Direction.Left);
if (isCanMove == false)
{
Console.WriteLine("不能向左移动了!");
}
break;
case ConsoleKey.RightArrow:
isRightKey = true;
isCanMove = grid.MoveDirection(Direction.Right);
if (isCanMove == false)
{
Console.WriteLine("不能向右移动了!");
}
break; }
if (isRightKey)
{ break; } }
return isCanMove; } }}
运行结果
在编写完成的项目中,点击“运行”按钮,即可查看程序运行结果,详细内容如下:
1.游戏开始页面
点击运行即可查看游戏开始页面,如图7所示。
图7-游戏开始页面
2.游戏进行页面
在游戏进入开始页面以后,若用户按键进行操作,即开始游戏,进入游戏进行页面,如图8所示。
图8-游戏进行页面
3.提示“不能向上移动了!”
当用户按下“向上”按钮时,若当前游戏情况下已经不可以继续向上,则提示用户“不能向上移动了!”,如图9所示。
图9-提示“不能向上移动了!”
4.提示“不能向下移动了!”
当用户按下“向下”按钮时,若当前游戏情况下已经不可以继续向下,则提示用户“不能向下移动了!”,如图10所示。
图10-提示“不能向下移动了!”
5.提示“不能向左移动了!”
当用户按下“向左”按钮时,若当前游戏情况下已经不可以继续向左,则提示用户“不能向左移动了!”,如图11所示。
图11-提示“不能向左移动了!”
6.提示“不能向右移动了!”
当用户按下“向右”按钮时,若当前游戏情况下已经不可以继续向右,则提示用户“不能向右移动了!”,如图12所示。
图12-提示“不能向右移动了!”
7.游戏结束提示页面
若当前游戏情况下,玩家已经不可以继续操作,则提示用户“【游戏结束】”。
8.游戏成功提示页面
若玩家进行操作后,实现了“2048”的结果,则提示玩家“游戏成功”。
C#数组
数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合。
声明数组变量并不是声明 number0、number1、…、number99 一个个单独的变量,而是声明一个就像 numbers 这样的变量,然后使用 numbers[0]、numbers[1]、…、numbers[99] 来表示一个个单独的变量。数组中某个指定的元素是通过索引来访问的。
所有的数组都是由连续的内存位置组成的。最低的地址对应第一个元素,最高的地址对应最后一个元素。