先来看一下界面:
游戏帮助类
class GameCore { //游戏地图 private int[,] map = new int[4, 4]; //合并时用到的临时数组 private int[] mergeArr = new int[4]; //空位数量 private int emptyCount = 16; //所有空位位置 private Location[] emptyArr = new Location[16]; private Random random = new Random(); //画板 private Graphics gp = null; //用位图做画板 private Image image = null; // 游戏项大小 private const int ITEMSIZE = 80; //游戏得分 private int score = 0; public bool IsChange { get; set; } /// <summary> /// 当前得分 /// </summary> public int Score { get { return score; } } /// <summary> /// 空位数量 /// </summary> public int EmptyCount { get { return emptyCount; } } /// <summary> /// 游戏初始化 /// </summary> public GameCore() { ComputeEmptyCount(); // 初始化数组 Location loc1; GenerateNum(out loc1); ComputeEmptyCount(); GenerateNum(out loc1); //初始化画板 image = new Bitmap(ITEMSIZE * 4 + 5 * 8, ITEMSIZE * 4 + 5 * 8); gp = Graphics.FromImage(image); } #region 移动并合并相邻的相同数字 /// <summary> /// 移动单元格数据 /// </summary> /// <param name="direction"></param> public void Move(string direction) { IsChange = false; switch (direction) { case "Up": MoveUp(); break; case "Down": MoveDown(); break; case "Left": MoveLeft(); break; case "Right": MoveRight(); break; } } /// <summary> /// 上移 /// </summary> public void MoveUp() { //1 for (int c = 0; c < 4; c++)//列 { for (int r = 0, index = 0; r < 4; r++)//行 { if (map[r, c] != 0)//非零 { mergeArr[index++] = map[r, c];//放入合并数组 } //数字位置发生变化 if (mergeArr[r] != map[r, c]) { IsChange = true; } map[r, c] = 0;//将矩阵中取走的清零 } //2合并 MergeCell(); //3 将合并后的数据放入矩阵 for (int i = 0, r = 0; i < 4; i++) { if (mergeArr[i] != 0) { map[r++, c] = mergeArr[i]; mergeArr[i] = 0; } } } } /// <summary> /// 下移 /// </summary> public void MoveDown() { //1 for (int c = 0; c < 4; c++)//列 { for (int r = 3, index = 0; r >= 0; r--)//行 { if (map[r, c] != 0)//非零 { mergeArr[index++] = map[r, c];//放入合并数组 } if (mergeArr[3-r] != map[r, c]) { IsChange = true; } map[r, c] = 0;//将矩阵中取走的清零 } //2合并 MergeCell(); //3 将合并后的数据放入矩阵 for (int i = 0, r = 3; i < 4; i++) { if (mergeArr[i] != 0) { map[r--, c] = mergeArr[i]; mergeArr[i] = 0; } } } } /// <summary> /// 合并单元格 /// </summary> private void MergeCell() { for (int i = 0; i < 3; i++) { if (mergeArr[i] != 0 && mergeArr[i] == mergeArr[i + 1] ) { mergeArr[i] += mergeArr[i + 1]; score += mergeArr[i]; IsChange = true; mergeArr[i + 1] = 0; } } } /// <summary> /// 左移 /// </summary> public void MoveLeft() { //1 for (int r = 0; r < 4; r++)//行 { for (int c = 0, index = 0; c < 4; c++)//列 { if (map[r, c] != 0)//非零 { mergeArr[index++] = map[r, c];//放入合并数组 } if (mergeArr[c] != map[r, c]) { IsChange = true; } map[r, c] = 0;//将矩阵中取走的清零 } //2合并 MergeCell(); //3 将合并后的数据放入矩阵 for (int i = 0, c = 0; i < 4; i++) { if (mergeArr[i] != 0) { map[r, c++] = mergeArr[i]; mergeArr[i] = 0; } } } } /// <summary> /// 右移 /// </summary> public void MoveRight() { //1 for (int r = 0; r < 4; r++)//行 { for (int c = 3, index = 0; c >= 0; c--)//列 { if (map[r, c] != 0)//非零 mergeArr[index++] = map[r, c];//放入合并数组 if (mergeArr[3-c] != map[r, c]) IsChange = true; map[r, c] = 0;//将矩阵中取走的清零 } //2合并 MergeCell(); //3 将合并后的数据放入矩阵 for (int i = 0, c = 3; i < 4; i++) { if (mergeArr[i] != 0) { map[r, c--] = mergeArr[i]; mergeArr[i] = 0; } } } } #endregion /// <summary> /// 计算空位数量 /// </summary> public void ComputeEmptyCount() { emptyCount = 0; Array.Clear(emptyArr, 0, 16); for (int r = 0; r < 4; r++)//行 { for (int c = 0; c < 4; c++)//列 { if (map[r, c] == 0) { emptyArr[emptyCount++] = new Location(r, c); } } } } /// <summary> /// 生成新数字 /// </summary> public int GenerateNum(out Location location) { int index = random.Next(0, emptyCount); location = emptyArr[index]; map[location.X, location.Y] = random.Next() % 10 == 0 ? 4 : 2; return map[location.X, location.Y]; } /// <summary> /// 判断游戏是否结束 /// </summary> /// <returns></returns> public bool IsGameOver() { ComputeEmptyCount(); //如果还有空位,游戏未结束 if (EmptyCount > 0) return false; //检查横纵相邻单元格中是否有相同的数字, for (int r = 0; r < 4; r++) { for (int c = 0; c < 3; c++) { //横 if (map[r, c] == map[r, c + 1]) return false; //纵 if (map[c, r] == map[c + 1, r]) return false; } } return true; } #region 绘制游戏画面 /// <summary> /// 绘制游戏画面 /// </summary> /// <returns></returns> public Image DrawMap() { //清空画板原有内容 gp.Clear(Color.DarkGray); for (int r = 0; r < map.GetLength(0); r++) { for (int c = 0; c < map.GetLength(1); c++) { DrawItem(r, c, GetColor(map[r, c])); } } return image; } /// <summary> /// 通过数字从程序集资源中找图片 /// </summary> /// <param name="num"></param> /// <returns></returns> public Image GetColor(int num) { return Properties.Resources. ResourceManager. GetObject("_" + num.ToString()) as Image; } /// <summary> /// 绘制一个数字块 /// </summary> /// <param name="rowindex">行索引</param> /// <param name="columnIndex">列索引</param> /// <param name="img">要绘制的图片</param> private void DrawItem(int rowindex, int columnIndex, Image img) { //画在哪 rowindex columnindex int x = (columnIndex + 1) * 8 + columnIndex * ITEMSIZE; int y = (rowindex + 1) * 8 + rowindex * ITEMSIZE; //绘制内容img 画多大 itemSize gp.DrawImage(img, x, y, ITEMSIZE, ITEMSIZE); } #endregion }
定义一个结构:
struct Location { private int x; private int y; public Location(int x, int y) { this.x = x; this.y = y; } public int X { get { return x; } } public int Y { get { return y; } } }
窗体代码:
public partial class FrmMain : Form { private GameCore gameCore = null; public FrmMain() { InitializeComponent(); } public void DrawGameMap() { this.picMap.Image = gameCore.DrawMap(); } //开始游戏 private void FrmMain_Load(object sender, EventArgs e) { StartGame(); } private void StartGame() { //得分清零 lblScore.Text = "0"; gameCore = new GameCore(); DrawGameMap(); } private void btnStart_Click(object sender, EventArgs e) { StartGame(); } //用键盘控制游戏动作 private void FrmMain_KeyDown(object sender, KeyEventArgs e) { string keyString = e.KeyData.ToString(); switch (keyString) { case "Up": case "Down": case "Left": case "Right": gameCore.Move(keyString); //更新游戏地图 UpdateGameMap(); break; } } public void UpdateGameMap() { //游戏流程? //地图发生过变化 if (gameCore.IsChange) { //绘制游戏地图 DrawGameMap(); //刷新得分 this.lblScore.Text = gameCore.Score.ToString(); //重新计算空位 gameCore.ComputeEmptyCount(); //如果空位数大于0 if (gameCore.EmptyCount > 0) { //产生新数 Location loc; int num = gameCore.GenerateNum(out loc); //开启绘制新数的动画 异步调用 Action<int,int,int> handler = DrawNewNumber; handler.BeginInvoke(loc.X, loc.Y, num, null, null); } //判断游戏是否继续 if (gameCore.IsGameOver()) { MessageBox.Show("GAME OVER"); } } } public void DrawNewNumber(int r,int c,int num) { int xOfMap = (c + 1) * 8 + c * 80; int yOfMap = (r + 1) * 8 + r * 80; Graphics gp = this.picMap.CreateGraphics(); Image img = gameCore.GetColor(num); //数字出现由小及大,最小宽为10 最大为80 int w = 10; while (w <= 80) { int x =xOfMap+ 80 / 2 - w / 2; int y =yOfMap+ 80 / 2 - w / 2; gp.DrawImage(img, x, y, w, w); w += 5; System.Threading.Thread.Sleep(10); } } }
OK ,完成了。