C# WinForms开发2048游戏:16无法合并为32的问题求助
2048 WinForms游戏16无法合并为32的问题
我用C# WinForms开发2048游戏,已完成数字合并逻辑,目前2可合并为4、4可合并为8、8可合并为16、32可合并为64,但16无法合并为32。除图片和文件名外,所有文件配置一致。
核心合并逻辑代码
以下是检测相同数字并合并的代码,该逻辑对其他数字有效,但16无法触发合并:
else if ((imageList[a, b].Tag == imageList[a + aChange, b + bChange].Tag) && imageList[a, b].Tag.ToString() != "0") { imageList[a + aChange, b + bChange].Tag = (int.Parse(imageList[a, b].Tag.ToString() ?? string.Empty) * 2).ToString(); imageList[a + aChange, b + bChange].Image = Image.FromFile(imageList[a + aChange, b + bChange].Tag.ToString() + ".jpg"); imageList[a, b].Image = null; imageList[a, b].Tag = "0"; move = true; }
排查情况
- 通过
MessageBox.Show(imageList[a + aChange, b + bChange].Tag.ToString());查看Tag值,合并其他数字时能正常显示新的Tag值(包括生成16); - 手动添加32时,能正常合并为64;
- 已复制所有文件排除资源文件问题。
临时有效代码
单独针对16写合并逻辑可以正常工作,但通用乘2逻辑失效:
else if (imageList[a, b].Tag.ToString() == "16") { imageList[a + aChange, b + bChange].Tag = "32"; imageList[a + aChange, b + bChange].Image = Image.FromFile("32.jpg"); imageList[a, b].Image = null; imageList[a, b].Tag = "0"; move = true; }
完整按键事件代码
private void Form1_KeyPress(object sender, KeyPressEventArgs e) { int aChange = 0; int bChange = 0; bool valid = false; if (e.KeyChar.ToString().ToLower() == "a") { aChange = -1; valid = true; } else if (e.KeyChar.ToString().ToLower() == "d") { aChange = 1; valid = true; } else if (e.KeyChar.ToString().ToLower() == "w") { bChange = -1; valid = true; } else if (e.KeyChar.ToString().ToLower() == "s") { bChange = 1; valid = true; } if (valid == true) { bool move = true; while (move) { move = false; for (int a = 0; a < 4; a++) { for (int b = 0; b < 4; b++) { if (a + aChange > -1 && a + aChange < 4 && b + bChange > -1 && b + bChange < 4) { if (imageList[a, b].Tag.ToString() != "0" && imageList[a + aChange, b + bChange].Tag.ToString() == "0") { imageList[a + aChange, b + bChange].Tag = imageList[a, b].Tag; imageList[a + aChange, b + bChange].Image = Image.FromFile((imageList[a + aChange, b + bChange].Tag.ToString() ?? string.Empty) + ".jpg"); imageList[a, b].Image = null; imageList[a, b].Tag = "0"; move = true; } else if ((imageList[a, b].Tag == imageList[a + aChange, b + bChange].Tag) && imageList[a, b].Tag.ToString() != "0") { imageList[a + aChange, b + bChange].Tag = (int.Parse(imageList[a, b].Tag.ToString() ?? string.Empty) * 2).ToString(); imageList[a + aChange, b + bChange].Image = Image.FromFile(imageList[a + aChange, b + bChange].Tag.ToString() + ".jpg"); imageList[a, b].Image = null; imageList[a, b].Tag = "0"; move = true; } } } } } bool cont = false; for (int a = 0; a < 4; a++) { for (int b = 0; b < 4; b++) { if (imageList[a, b].Tag.ToString() == "0") { cont = true; } } } if (cont) { while (cont) { Random r = new Random(); int x = r.Next(0, 4); int y = r.Next(0, 4); if (imageList[y, x].Tag.ToString() == "0") { imageList[y, x].Image = Image.FromFile("2.jpg"); imageList[y, x].Tag = "2"; cont = false; } } } else { MessageBox.Show("Game Over!"); } } }
PictureBox初始化代码
public partial class Form1 : Form { PictureBox[,] imageList = new PictureBox[4, 4]; public Form1() { InitializeComponent(); if (this.Width > this.Height) { tableLayoutPanel1.Size = new Size(this.ClientSize.Height, this.ClientSize.Height); tableLayoutPanel1.Location = new Point((this.ClientSize.Width / 2) - (this.ClientSize.Height / 2), 0); } else { tableLayoutPanel1.Size = new Size(this.ClientSize.Width, this.ClientSize.Width); tableLayoutPanel1.Location = new Point(0, (this.ClientSize.Height / 2) - (this.ClientSize.Width / 2)); } for (int a = 0; a < 4; a++) { for (int b = 0; b < 4; b++) { PictureBox newBox = new PictureBox { Dock = DockStyle.Fill, BackColor = Color.AntiqueWhite, BorderStyle = BorderStyle.None, SizeMode = PictureBoxSizeMode.StretchImage, Tag = "0" }; imageList[a, b] = newBox; tableLayoutPanel1.Controls.Add(newBox, a, b); } } }
问题原因分析
问题出在Tag的类型不一致:
- 初始化时Tag被设置为字符串
"0"; - 合并过程中,代码通过
int.Parse(...) * 2).ToString()生成新的Tag值,理论上还是字符串,但可能在某个环节中,16的Tag被意外转换成了int类型; - C#中
==运算符对不同类型的对象(比如string和int)比较时,会直接返回false,导致合并条件imageList[a, b].Tag == imageList[a + aChange, b + bChange].Tag不成立,16无法触发合并。
解决方案
1. 统一Tag的类型为int
初始化PictureBox时,把Tag设为int类型的0,避免字符串和int的类型混乱:
PictureBox newBox = new PictureBox { ..., Tag = 0 }; // 替换原来的Tag = "0"
2. 修改合并逻辑,移除多余的类型转换
将所有涉及Tag的操作统一为int类型,避免Parse和ToString的来回转换:
// 空单元格移动逻辑修改 if ((int)imageList[a, b].Tag != 0 && (int)imageList[a + aChange, b + bChange].Tag == 0) { imageList[a + aChange, b + bChange].Tag = imageList[a, b].Tag; int value = (int)imageList[a + aChange, b + bChange].Tag; imageList[a + aChange, b + bChange].Image = Image.FromFile(value.ToString() + ".jpg"); imageList[a, b].Image = null; imageList[a, b].Tag = 0; move = true; } // 合并逻辑修改 else if ((int)imageList[a, b].Tag == (int)imageList[a + aChange, b + bChange].Tag && (int)imageList[a, b].Tag != 0) { int newValue = (int)imageList[a, b].Tag * 2; imageList[a + aChange, b + bChange].Tag = newValue; imageList[a + aChange, b + bChange].Image = Image.FromFile(newValue.ToString() + ".jpg"); imageList[a, b].Image = null; imageList[a, b].Tag = 0; move = true; }
3. 统一其他Tag判断逻辑
比如空单元格检查和新数字生成逻辑:
// 空单元格检查 if ((int)imageList[a, b].Tag == 0) { cont = true; } // 新数字生成 imageList[y, x].Tag = 2; // 替换原来的"2"
内容的提问来源于stack exchange,提问作者forefie
相关产品推荐
相关产品推荐

