基于C#用WinForm实现的2048小游戏

您所在的位置:网站首页 4399游戏键盘控制不了 基于C#用WinForm实现的2048小游戏

基于C#用WinForm实现的2048小游戏

2023-12-12 13:29| 来源: 网络整理| 查看: 265

     2048游戏规则比较简单,玩家通过上、下、左、右四个方向来控制方块的移动,每一次移动,所有的方块都会朝这个方向进行移动,而此时则会在某个随机空的地区产生一个新的数字方块,在移动过程中,若方块上的数字与移动方向后一个的方块上的数字相同,则会碰撞成一个新的方块,数字为两个方块数字之和。若所有地方都被填满方块,且每个方块与相邻方块之间的数字均不相同,则游戏结束。

    运行结果:

    所需控件:一个button用于重置游戏,两个label来显示分数,一个panel容器来装16个textbox用于显示实时数字。

如出现上图情况,将每个textbox的TabStop属性改为false,也可以用label来代替textbox。

  本程序使用W、A、S、D四个键来操作方块的移动。记得将Form1的KeyPreview属性改为true。

首先,定义变量

public class Variables { public static int score; //分数 public static int[] Num = new int[16]; public static int[,] TempNum = new int[4, 4]; //移动 public static int[] num = new int[16]; }

    本程序是采用一个长度为16的数组来存放每个方块(即每个textbox)的数字。

 移动方法:

public void MovingW() { for (int i = 0; i < 4; i++) { ArrayList arr = new ArrayList(); //将某一列所有不为0的元素的索引找出来 for (int j = 0; j < 4; j++) { if (Num[i+j*4] != 0) { arr.Add(j); } } if (arr.Count == 1) { TempNum[0, i] = Num[i+Convert.ToInt32(arr[0])*4]; TempNum[1, i] = 0; TempNum[2, i] = 0; TempNum[3, i] = 0; } if (arr.Count == 2) { if (Num[Convert.ToInt32(arr[0])*4+i] == Num[Convert.ToInt32(arr[1])*4+i]) { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+i] + Num[Convert.ToInt32(arr[1])*4+i]; TempNum[1, i] = 0; TempNum[2, i] = 0; TempNum[3, i] = 0; score += (TempNum[0, i]) / 2; } else { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+i]; TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+i]; TempNum[2, i] = 0; TempNum[3, i] = 0; } } if (arr.Count == 3) { if (Num[Convert.ToInt32(arr[0])*4+i] == Num[Convert.ToInt32(arr[1])*4+i]) { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+i] + Num[Convert.ToInt32(arr[1])*4+i]; TempNum[1, i] = Num[Convert.ToInt32(arr[2])*4+ i]; TempNum[2, i] = 0; TempNum[3, i] = 0; score += (TempNum[0, i]) / 2; } else { if (Num[Convert.ToInt32(arr[1])*4+i] == Num[Convert.ToInt32(arr[2])*4+i]) { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i]; TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i] + Num[Convert.ToInt32(arr[2])*4+ i]; TempNum[2, i] = 0; TempNum[3, i] = 0; score += (TempNum[1, i]) / 2; } else { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i]; TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i]; TempNum[2, i] = Num[Convert.ToInt32(arr[2])*4+ i]; TempNum[3, i] = 0; } } } if (arr.Count == 4) { if (Num[Convert.ToInt32(arr[0])*4+ i] == Num[Convert.ToInt32(arr[1])*4+ i]) { if (Num[Convert.ToInt32(arr[2])*4+ i] == Num[Convert.ToInt32(arr[3])*4+ i]) { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i] + Num[Convert.ToInt32(arr[1])*4+ i]; TempNum[1, i] = Num[Convert.ToInt32(arr[2])*4+ i] + Num[Convert.ToInt32(arr[3])*4+ i]; TempNum[2, i] = 0; TempNum[3, i] = 0; score += (TempNum[0, i] + TempNum[1, i]) / 2; } else { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i] + Num[Convert.ToInt32(arr[1])*4+ i]; TempNum[1, i] = Num[Convert.ToInt32(arr[2])*4+ i]; TempNum[2, i] = Num[Convert.ToInt32(arr[3])*4+ i]; TempNum[3, i] = 0; score += (TempNum[0, i]) / 2; } } else { if (Num[Convert.ToInt32(arr[1])*4+ i] == Num[Convert.ToInt32(arr[2])*4+ i]) { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i]; TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i] + Num[Convert.ToInt32(arr[2])*4+ i]; TempNum[2, i] = Num[Convert.ToInt32(arr[3])*4+ i]; TempNum[3, i] = 0; score += (TempNum[1, i]) / 2; } else { if (Num[Convert.ToInt32(arr[2])*4+ i] == Num[Convert.ToInt32(arr[3])*4+ i]) { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i]; TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i]; TempNum[2, i] = Num[Convert.ToInt32(arr[2])*4+ i] + Num[Convert.ToInt32(arr[3])*4+ i]; TempNum[3, i] = 0; score += (TempNum[2, i]) / 2; } else { TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i]; TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i]; TempNum[2, i] = Num[Convert.ToInt32(arr[2])*4+ i]; TempNum[3, i] = Num[Convert.ToInt32(arr[3])*4+ i]; } } } } } }

 此为向上运动的方法,即W。根据方阵每一列的非0的个数以及相互之间的相等情况来计算移动的结果,只有在有方块进行相加时才有分数产生。其余三个方向与其类似,就不赘述。

判断是否游戏结束

public bool GameOver() { bool over1 = false; //判断格子是否已满 for (int i = 0; i < Num.Length; i++) { if (Num[i] == 0) over1 = true; } //判断是否有相邻相同的 //四个角 if (Num[0] == Num[1] || Num[0] == Num[4] || Num[3] == Num[2] || Num[3] == Num[7] || Num[12] == Num[8] || Num[12] == Num[13] || Num[15] == Num[14] || Num[15] == Num[11]) over1 = true; //四条边 int[] lines1 = { 1, 2, 4, 8, 7, 11, 13, 14 }; foreach (int i in lines1) { switch (i) { case 1: case 2: if (Num[i] == Num[i - 1] || Num[i] == Num[i + 1] || Num[i] == Num[i + 4]) over1 = true; break; case 4: case 8: if (Num[i] == Num[i - 4] || Num[i] == Num[i + 1] || Num[i] == Num[i + 4]) over1 = true; break; case 7: case 11: if (Num[i] == Num[i - 4] || Num[i] == Num[i - 1] || Num[i] == Num[i + 4]) over1 = true; break; case 13: case 14: if (Num[i] == Num[i - 1] || Num[i] == Num[i - 4] || Num[i] == Num[i + 1]) over1 = true; break; default: break; } } //中间四块 if (Num[5] == Num[6] || Num[6] == Num[10] || Num[5] == Num[9] || Num[9] == Num[10]) over1 = true; return over1; }

 游戏结束的规则就是方阵被填满,且没有两个相邻的数字。

首先判断是否方阵被填满,只有Num中有一个数字为0,则游戏继续。

再来判断相邻情况。由于方阵中每个位置的相邻情况都不一样,所以需要分开来讨论。

首先看四个角的相邻情况,每个角均与两个方块相邻。然后是每条边的中间两个均与三个方块相邻。最后是中间四个都与四个方块相邻。只有这些相邻情况中有一个为真,即返回值为true,游戏没有结束。

程序加载时

private void Form1_Load(object sender, EventArgs e) { label2.Text = "0"; //随机赋初值 Random r = new Random(); int k = r.Next(0, Num.Length); Num[k] = 2; timer1.Start(); MessageBox.Show("开始!"); }

程序加载时,初始化分数为0,并随机在方阵中产生一个数字“2”。计时器是用来将Num数组的值赋给textbox并实时刷新显示。此处可以根据textbox不同值来设定不同的背景色,以便于区分。

private void timer1_Tick(object sender, EventArgs e) { #region 数字显示 if (Num[0] != 0) textBox1.Text = Num[0].ToString(); if (Num[1] != 0) textBox2.Text = Num[1].ToString(); if (Num[2] != 0) textBox3.Text = Num[2].ToString(); if (Num[3] != 0) textBox4.Text = Num[3].ToString(); if (Num[4] != 0) textBox5.Text = Num[4].ToString(); if (Num[5] != 0) textBox6.Text = Num[5].ToString(); if (Num[6] != 0) textBox7.Text = Num[6].ToString(); if (Num[7] != 0) textBox8.Text = Num[7].ToString(); if (Num[8] != 0) textBox9.Text = Num[8].ToString(); if (Num[9] != 0) textBox10.Text = Num[9].ToString(); if (Num[10] != 0) textBox11.Text = Num[10].ToString(); if (Num[11] != 0) textBox12.Text = Num[11].ToString(); if (Num[12] != 0) textBox13.Text = Num[12].ToString(); if (Num[13] != 0) textBox14.Text = Num[13].ToString(); if (Num[14] != 0) textBox15.Text = Num[14].ToString(); if (Num[15] != 0) textBox16.Text = Num[15].ToString(); #endregion #region 设置字体及颜色 foreach (Control ctr in panel1.Controls) { if (ctr is TextBox) { ctr.Font = new Font("宋体", 12, ctr.Font.Style); ctr.ForeColor = Color.Black; switch (ctr.Text) { case "": ctr.BackColor = Color.White; break; case "2": ctr.BackColor = Color.Blue; break; case "4": ctr.BackColor = Color.Pink; break; case "8": ctr.BackColor = Color.Orange; break; case "16": ctr.BackColor = Color.Gray; break; case "32": ctr.BackColor = Color.Green; break; case "64": ctr.BackColor = Color.Brown; break; case "128": ctr.BackColor = Color.Goldenrod; break; case "256": ctr.BackColor = Color.LightBlue; break; case "512": ctr.BackColor = Color.Violet; break; case "1024": ctr.BackColor = Color.Yellow; break; case "2048": ctr.BackColor = Color.MediumTurquoise; break; } } } #endregion label2.Text = score.ToString(); }

把方阵移动前后进行比较,即Num在Moving方法调用前后进行比较,如果不同则在方阵移动完以后,随机在此时方阵空的,即值为0的地方生成一个2或者4,如果相同则不会生成新的数。

public int[] NewNumber() { Random a = new Random(); int i; ArrayList arr = new ArrayList { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, }; //生成数的范围,2多4少 int[] Select; Select = ArraylistToInt(arr); //list转int数组 i = GetOneIndex(Num); //在Num中随机得到一个索引即生成的位置 if (i != 99) Num[i] = GetOneNumber(Select); return Num; } public int GetOneNumber(int[] arr) //在数组中随机获得一个数 { Random index = new Random(); int i; if (arr.Length == 1) i = 0; else i = index.Next(0, arr.Length); return arr[i]; } public int GetOneIndex(int[] a) //在数组中随机得到一个为0的索引 { ArrayList arr = new ArrayList(); for (int i = 0; i < a.Length; i++) { if (a[i] == 0) { arr.Add(i); } } Random r = new Random(); int k; if (arr.Count == 0) { k = 99; } else { if (arr.Count == 1) k = 0; else k = r.Next(0, arr.Count); } return (int)arr[k]; } public int[] ArraylistToInt(ArrayList arr) { int[] s = new int[arr.Count]; for (int i = 0; i < arr.Count; i++) { s[i] = Convert.ToInt16(arr[i]); } return s; } //判断运动前后是否相同 for(int i=0;i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3