C# 在我的2048实现中,我如何确定哪些分片移动和合并?

C# 在我的2048实现中,我如何确定哪些分片移动和合并?,c#,string,algorithm,C#,String,Algorithm,我正在构建一个小小的2048 WinForms游戏,只是为了好玩 请注意,这不是一个简单的问题。我只是想做一个2048年的游戏,可以让人类玩 我首先决定用0-17来表示瓷砖。0表示空磁贴。1表示一个2平铺。2代表一个4瓦。3表示8瓦,依此类推 然后我在考虑如何计算结果板,给定运动方向和运动前的板。以下是我的想法: 要向上移动,只需将电路板逆时针旋转90度,向左移动,然后将电路板向后旋转 要向右移动,只需将电路板顺时针旋转180度,向左移动,然后再向后旋转 要向下移动,只需将电路板顺时针旋转90

我正在构建一个小小的2048 WinForms游戏,只是为了好玩

请注意,这不是一个简单的问题。我只是想做一个2048年的游戏,可以让人类玩

我首先决定用0-17来表示瓷砖。0表示空磁贴。1表示一个2平铺。2代表一个4瓦。3表示8瓦,依此类推

然后我在考虑如何计算结果板,给定运动方向和运动前的板。以下是我的想法:

  • 要向上移动,只需将电路板逆时针旋转90度,向左移动,然后将电路板向后旋转
  • 要向右移动,只需将电路板顺时针旋转180度,向左移动,然后再向后旋转
  • 要向下移动,只需将电路板顺时针旋转90度,向左移动,然后再向后旋转
所以我只需要知道当玩家向左移动时,如何计算得到的棋盘,然后我就可以通过旋转棋盘,向左移动,再向后旋转来计算出剩下的方向。然后我带着这个非常奇怪的向左移动的算法来到了p

  • 通过添加96并转换为
    char
    ,将每个初始板的整数转换为字符。现在,一个反勾(`)表示一个空磁贴,
    a
    表示一个2磁贴,
    b
    表示一个4磁贴,依此类推,一直到
    p
  • 将字符连接成4个字符串,每个字符串表示电路板的一行
  • 示例板可能如下所示:

    aa``
    ````
    ```b
    ``cb
    
  • 对于每个字符串

    • 去掉所有的背虱
    • 使用正则表达式(是的,我在2048游戏中使用正则表达式)
      ([a-p])\1
      并获得字符串的第一个匹配项
    • 用新磁贴替换第一个匹配的磁贴
    • 匹配尚未匹配的字符串的其余部分,直到找不到更多匹配项为止
  • 如果字符串少于4个字符,请向右填充该字符串
  • 通过减去96,将每个字符串返回到整数数组
这就是我评估每一行的方法:

    int[] EvaluateRow(int[] row) {
        // RowToString converts an int[] to a string like I said above
        StringBuilder rowString = new StringBuilder(RowToString(row));
        rowString.Replace("`", "");
        var regex = new Regex("([a-p])\\1");
        int lastIndex = -1;
        while (true) {
            var match = regex.Match(rowString.ToString(), lastIndex + 1);
            if (match.Success) {
                // newChar is the new tile after the merge
                char newChar = (char)(match.Value[0] + 1);
                rowString.Remove(match.Index, match.Length);
                rowString.Insert(match.Index, newChar);
                lastIndex = match.Index;

                Score += // some calculation for score, irrelevant
            } else {
                break;
            }
        }
        // StringToRow converts a string to an int[]
        return StringToRow(rowString.ToString());
    }
然而,我目前的算法有一个很大的问题。这个算法只告诉我移动的最终结果,但我不知道我需要移动哪个图片框(我使用图片框来显示瓷砖),每个图片框应该移动多少空间,以及哪些图片框需要显示新图像。我真的不想使用其他解决方案,我只想对当前解决方案进行一些更改

以下是我需要从每一行(字符串)中获取的内容:

  • 一个
    列表
    。每个元素表示需要移动哪个磁贴(x坐标),以及它应该移动多少空间(
    空间
  • 一个
    列表
    。每个元素表示合并到中的分幅的x坐标
如何从行字符串中获取这些信息?例如:

行字符串:

`a`a

将生成一个类似于
[(1,1)、(3,3)]
的列表和另一个类似于
[1]

的列表。我不认为对字符的转换真的会增加任何有用的内容。如果您坚持使用数字表示法(0=空),那么您可以使用以下逻辑来查找目标配置和哪个块去了哪里。这是伪代码(
):


见我的解决方案在下面的帖子。我创建了自己的按钮数组(您可以使用图片框代替)。我创建了一个继承标准button类的类,然后添加了诸如row number和column number之类的属性,这样我就可以很容易地分辨出按下了哪个按钮:@jdweng我可以毫不费力地找出哪个图片框对应于哪个行和列。我只是不知道在执行特定方向的移动时移动了哪些平铺。您可以向继承的类添加属性,以便更好地识别每个图片框。您可以添加图片的名称或其他任何可以提供更多信息的内容。在您的情况下,磁贴名称可能会有所帮助。您能举个例子吗?如果行是
[0,1,0,1]
,那么
fromTo
result
会是什么?为什么?我添加了几个示例。对于
fromTo
,第一个将具有
[-1,0,-1,0]
。-1是默认值,当初始位置没有块时,不会接触这些值。两个零表示位置1和3处的块都将转到位置0(它们将在那里合并)<代码>结果将在第一个位置反映此合并:
[2,0,0,0]
。其他零是默认值,表示该位置为空。
fromTo = [-1, -1, -1, -1];
result = [0, 0, 0, 0];
prevVal = 0;
pos = 0;

for (i = 0; i < 4; i++) {
    if (row[i]) { // Not empty
        if (row[i] == prevVal) {
            result[pos-1]++; // merged
            fromTo[i] = pos-1;
            prevVal = 0; // avoid triple merge
        } else {
            result[pos] = row[i];
            fromTo[i] = pos;
            prevVal = row[i];
            pos++;
        }
    }
}
row         |   fromTo       |   result
------------+----------------+-----------
[0,1,0,1]   |  [-1,0,-1,0]   |  [2,0,0,0]
[0,1,1,1]   |  [-1,0,0,1]    |  [2,1,0,0]
[1,1,1,1]   |  [0,0,1,1]     |  [2,2,0,0]
[1,2,2,3]   |  [0,1,1,2]     |  [1,3,3,0]