You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 04:24:49