当前位置: 首页 > 知识库问答 >
问题:

我如何计算出在我的2048实现中哪些瓷砖移动和合并?

汪建白
2023-03-14

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

注意,这不是关于一个2048的AI。我只是想做一个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并获得字符串的第一个匹配项。
    • 将第一个匹配项替换为新的平铺
    • 匹配尚未匹配的字符串的其余部分,直到找不到更多匹配项。

    这就是我对每一行的评估方式:

        int[] Evahtml" target="_blank">luateRow(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());
        }
    

    但是,我现在的算法确实有一个很大的问题。这个算法只告诉我一个移动的最终结果,但我不知道我需要移动哪个图片框(我正在用图片框来展示瓷砖),每个图片框应该移动多少个空格,以及哪些图片框需要展示一个新的图像。我真的不想使用另一个解决方案,我只想对我当前的解决方案做一些更改。

    下面是我需要从每一行(字符串)获得的东西:

    • 一个列表<(int x,int spaces)>。每个元素表示需要移动哪个块(x坐标),以及它应该移动多少个空格(spaces)。
    • 一个列表 。每个元素表示合并到的瓷砖的x坐标。

    如何从行字符串中获取这些信息?示例:

    `a`a
    

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

  • 共有1个答案

    呼延才
    2023-03-14

    我不认为对角色的转换真的是添加了什么有用的东西。如果您坚持使用数字表示法(0=空),那么您可以使用以下逻辑来查找目标配置以及哪个块去了哪里。这是伪代码(row):

    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++;
            }
        }
    }
    

    现在,fromto数组将为每个索引指明原始位置的块去了哪里。result将具有最终值。从这两条信息中,您还可以知道哪些块被合并了。当result[fromto[i]]!=row[i]时,合并原始位置i处的块。您还知道块将行进的距离:i-fromto[i]。简而言之,您拥有为每个块设置动画的所有信息。

    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]
    
     类似资料:
    • 我使用的是Spring 3.0 tiles。我为所有页面创建了带有锚定标记的公共菜单,并为相同页面应用了css。我使用Jquery在单击菜单时动态更改菜单的css类。 选择菜单/链接时,将应用“selectedTab”css类,对于所有正常链接,将应用“tab”css类。我面临的问题是,每次请求/单击菜单时,都会应用style类,然后在响应后再次取消应用。也就是说,样式仍然应用于请求和响应之间。但

    • 我试图使用Struts 2 我在 glassfish 服务器上上传时遇到以下错误: 部署过程中发生错误:加载应用程序时出现异常:java.lang.IllegalState异常:ContainerBase.add子级:开始:org.apache.catalina.生命周期异常:java.lang.NoClassDefFoundError: org/spingframewor /core/io/su

    • 问题内容: 我有一个图块(或div)容器,我希望该容器居中,而图块在容器中对齐。 因此,如果窗口很小: 如果窗口扩大了一点: 进一步: 我试过了: 但这似乎不起作用。 我希望此功能至少可以在Chrome中运行,但最终还需要支持最新的FF,Safari和IE 10+ 问题答案: FWIW:现在是2017年,网格布局模块可以立即使用(codependemo)。如果浏览器支持适合您,请使用grid。如果

    • 在用CV::SolvePnPransac估计摄像机姿态时,输入是objectPoints和ImagePoints。输出是旋转和平移矩阵,加上内点数 利用遗传算法生成一个新的旋转平移矩阵。我喜欢用我的新的旋转和平移来计算内点的数目。 谢谢你的支持

    • 在 Stuts2 中,我正在使用 Tiles 插件为网站(菜单、页脚、页眉等)创建在每个页面上一致的布局。 现在每个磁贴只是一个静态的超文本标记语言内容。 是否可以通过每次呈现页脚时调用<code>Footer</code>动作类来使平铺更动态?例如:从数据库获取页脚内容。 如果我在应用程序中的每个页面的action类中都这样做,这将导致非常不可用的代码... 所以也许从瓷砖的角度来看是可能的?

    • 我有一个球,我可以在由大小相等的瓷砖组成的地图上移动。玩家应该不能在较暗且有黑色边框的瓷砖上行走。我有一个多维的瓷砖阵列,我用它来检查哪些瓷砖是实心的。 我希望玩家在水平和垂直移动时,可以靠墙滑动。问题是,如果他那样做,他就会固执己见。我设法使它在每个轴上都能完美工作,但是分开的。下面是我的水平碰撞检查代码: level.isBlocked() 方法检查数组的索引是否被实心磁贴占用。i 和 j 变