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

瓦片合并算法2048游戏

邓驰
2023-03-14

我正在尝试用C重新创建游戏2048,但我无法让算法移动或合并瓷砖在一起以正常运作。在最初的2048游戏中,你会像这样移动瓷砖:

 2 | 2 | 4 | 4                             4 | 8 |   |   
---+---+---+---  *swipes to the left* ->  ---+---+---+---
 8 |   | 8 |                               16|   |   |

所以两个相同的瓷砖可以合并成一个两倍大小的瓷砖。我的版本几乎是相同的,但我没有使用数字,而是使用合并时递增1的字符,因此[AA]将合并到[B]等。我这样做只是为了不必处理不同大小的瓷砖。

所以我的板存储为一个4*4字符数组,在一个我称之为网格的结构中(我知道可能有点多余)

typedef struct grid {
    char tiles[4][4];
} Grid;

我曾经尝试过制作算法来上下左右移动和合并,但它们并不能正常工作。

void pushLeft(Grid * grid)
{
    int i, j, k;
    for(i = 0; i < 4; i++) //Row number i
    {
        for(j = 1; j < 4; j++) //Column number j
        {
            if(grid->tiles[i][j] != ' ') //tile is not empty
            {
                int flag = 1; //flag to prevent merging more than one level at a time
                //Starting on column k, push tile as far to the left as possible
                for(k = j; k > 0; k--)
                {
                    if(grid->tiles[i][k-1] == ' ') //neighbor tile is empty
                    {
                        grid->tiles[i][k-1] = grid->tiles[i][k];
                        grid->tiles[i][k] = ' ';
                    }
                    else if(grid->tiles[i][k-1] == grid->tiles[i][k] && flag) //neighbor equals
                    {
                        grid->tiles[i][k-1]++;
                        grid->tiles[i][k] = ' ';
                        flag = 0;
                    }
                    else //Can't push or merge
                    {
                        flag = 1;
                        break;
                    }
                }
            }
        } // Done with row
    }
}

void pushRight(Grid * grid)
{
    int i, j, k;
    for(i = 0; i < 4; i++) //Row number i
    {
        for(j = 2; j >= 0; j--) //Column number j
        {
            if(grid->tiles[i][j] != ' ') //tile is not empty
            {
                int flag = 1; //flag to prevent merging more than one level at a time
                //Starting on column k, push tile as far to the right as possible
                for(k = j; k < 3; k++)
                {
                    if(grid->tiles[i][k+1] == ' ') //neighbor tile is empty
                    {
                        grid->tiles[i][k+1] = grid->tiles[i][k];
                        grid->tiles[i][k] = ' ';
                    }
                    else if(grid->tiles[i][k+1] == grid->tiles[i][k] && flag) //neighbor equals
                    {
                        grid->tiles[i][k+1]++;
                        grid->tiles[i][k] = ' ';
                        flag = 0;
                    }
                    else //Can't push or merge
                    {
                        flag = 1;
                        break;
                    }
                }
            }
        } // Done with row
    }
}

void pushUp(Grid * grid)
{
    int i, j, k;
    for(i = 0; i < 4; i++) //Column number i
    {
        for(j = 1; j < 4; j++) //Row number j
        {
            if(grid->tiles[j][i] != ' ') //tile is not empty
            {
                int flag = 1; //flag to prevent merging more than one level at a time
                //Starting on row k, push tile as far upwards as possible
                for(k = j; k > 0; k--)
                {
                    if(grid->tiles[k-1][i] == ' ') //neighbor tile is empty
                    {
                        grid->tiles[k-1][i] = grid->tiles[i][k];
                        grid->tiles[k][i] = ' ';
                    }
                    else if(grid->tiles[k-1][i] == grid->tiles[i][k] && flag) //neighbor equals
                    {
                        grid->tiles[k-1][i]++;
                        grid->tiles[k][i] = ' ';
                        flag = 0;
                    }
                    else //Can't push or merge
                    {
                        flag = 1;
                        break;
                    }
                }
            }
        } // Done with column
    }
}

void pushDown(Grid * grid)
{
    int i, j, k;
    for(i = 0; i < 4; i++) //Column number i
    {
        for(j = 2; j >= 0; j--) //Row number j
        {
            if(grid->tiles[j][i] != ' ') //tile is not empty
            {
                int flag = 1; //flag to prevent merging more than one level at a time
                //Starting on row k, push tile as far down as possible
                for(k = j; k < 3; k++)
                {
                    if(grid->tiles[k+1][i] == ' ') //neighbor tile is empty
                    {
                        grid->tiles[k+1][i] = grid->tiles[i][k];
                        grid->tiles[k][i] = ' ';
                    }
                    else if(grid->tiles[k+1][i] == grid->tiles[i][k] && flag) //neighbor equals
                    {
                        grid->tiles[k+1][i]++;
                        grid->tiles[k][i] = ' ';
                        flag = 0;
                    }
                    else //Can't push or merge
                    {
                        flag = 1;
                        break;
                    }
                }
            }
        } // Done with column
    }
}

我用一些硬编码的测试数据测试了这些算法。将瓷砖推到左边的算法似乎工作正常。pushRight几乎可以工作,但它同时合并两个级别,因此[BAA]合并为[C]但应该合并为[BB]

俯卧撑似乎几乎总是只是用空瓷砖(空格)擦拭整个木板。pushDows似乎正在移除一些瓷砖。

有没有人看到问题所在或者知道怎么做?我曾想过使用递归算法,但就是绕不过去。

共有1个答案

晋承运
2023-03-14

我个人将滑动分成两个步骤,因为滑动左和滑动右实际上功能相同,关于瓷砖组合。唯一的区别是剩余的瓷砖会根据方向向左或向右聚集。

下面是一个快速算法替换两个瓷砖与一个新的。我扫描左->right并用新的瓷砖替换左侧瓷砖,将右侧瓷砖归零,然后确保我从比较中排除了这个新瓷砖:

typedef struct grid {
    char tiles[4][4];
} Grid;

void eliminateHoriz (Grid* g)
{
    int row, col, col2;
    for (row=0; row<4; row++)
    {
        for (col=0; col<4; col++)
        {
            if (g->tiles[row][col])
            {
                for (col2=col+1; col2<4; col2++)
                {
                    if (g->tiles[row][col2])
                    {
                        if (g->tiles[row][col] == g->tiles[row][col2])
                        {
                            g->tiles[row][col++] *= 2;
                            g->tiles[row][col2] = 0;
                        }
                        break;
                    }
                }
            }
        }
    }
}

void showGrid (Grid* g)
{
    int row, col;
    for (row=0; row<4; row++)
        for (col=0; col<4; col++)
            printf ("%4d%c",
                g->tiles[row][col],
                col == 3 ? '\n' : ' ');
    printf ("\n");
}

int main() 
{
    Grid g = {{2,2,4,4, 
               8,0,8,0,
               8,8,8,4, 
               2,2,2,2}};

    showGrid (&g);
    eliminateHoriz (&g);
    showGrid (&g);

    system ("pause");
    return 0;
}

此输出:

   2    2    4    4
   8    0    8    0
   8    8    8    4
   2    2    2    2

   4    0    8    0
  16    0    0    0
  16    0    8    4
   4    0    4    0
 类似资料:
  • CocosEditor开源版 笔者历时一个晚上,终于完成了cocos2d-js开源版本,编码虽易,创意不易,且行且珍惜; 此版本包含了网上流行的各种版本。包括原版,朝代版,金庸版,星座,豪车等等近10个版本,代码开源,希望读者基于开源代码做出各种版本,供全名娱乐; 运行demo需要配置好CocosEditor,暂不支持其他工具。demo是跨平台的,可移植运行android,ios,html5网页等

  • 实现一个简单的2048小游戏。手指上下左右滑动屏幕可以移动方块。 2048游戏是什么:每次控制所有方块向同一个方向运动,两个相同数字的方块撞在一起之后合并成为他们的和,每次操作之后会在空白的方格处随机生成一个2或者4,最终得到一个“2048”的方块就算胜利了。如果16个格子全部填满并且相邻的格子都不相同也就是无法移动的话,那么游戏就会结束。

  • 编辑:这个问题不是重复什么是游戏2048的最优算法? 这个问题问“赢得比赛的最好方法是什么?” 这个问题问‘我们如何计算出游戏的复杂性?' 这让我想到了它的复杂性。对于像国际象棋这样的确定性游戏,它有可能(在理论上)计算出所有导致胜利状态的可能的走法,并向后工作,选择保持导致结果的最佳走法。我知道这导致了大量可能的移动(在宇宙中原子数量范围内的东西)…但2048年是不是比较复杂? PsudoCod

  • 本文向大家介绍javascript制作2048游戏,包括了javascript制作2048游戏的使用技巧和注意事项,需要的朋友参考一下 2048.html 2048.css 2048.js 以上所诉就是本文的全部内容了,希望大家能够喜欢。

  • 本文向大家介绍javascript版2048小游戏,包括了javascript版2048小游戏的使用技巧和注意事项,需要的朋友参考一下 没有技术含量,只是用来练习代码逻辑的。为了代码结构清晰,我把逻辑控制部分写在全局变量里,用户界面操作封装在UI对象里,大概就这样了。仅供参考。工作时候,我的编码风格有人吐槽太乱了,所以我想试着写一个不是那么乱的东西出来。。 以上就是本文所述的全部内容了,希望大家能

  • 此为在原版2048的基础上,添加了电脑AI解题,并稍微修改了UI添加按钮来触发AI。 AI的核心在/js/myAI.js里,相关函数在window.myPlugin里 核心算法是用dfs搜3步后使代价函数window.myPlugin.evalCost期望值最小的走法, 代价函数的设计目的是让块尽量按由大到小顺序堆叠在右上角,并合并。 实验效果是基本能保证到2048,偶尔到4096甚至8192(概率较小)。