首页 文章

平铺合并算法2048游戏

提问于
浏览
4

我试图在C中重新创建游戏2048,但是我无法将算法移动或合并到一起以正常运行 . 在最初的2048游戏中,您可以像这样将瓷砖移动到一起:

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

因此,两个相同的图块可以合并为一个尺寸为两倍的图块 . 我的版本几乎相同,但不是使用数字,而是使用在合并时递增1的字符,因此 [A|A] 将合并到 [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几乎可以工作,但它同时合并两个级别,所以 [B|A|A] 合并到 [C] 但应该合并到 [B|B] .

pushUp似乎几乎总是用空的瓷砖(空格)擦拭整个电路板 . pushDows似乎正在移除一些瓷砖 .

有没有人看到问题或知道这样做的方法?我曾考虑使用递归算法,但我无法绕过它 .

2 回答

  • 0

    我会亲自将滑动分为两个步骤,因为向左滑动并向右滑动实际上在功能上与瓷砖组合相同 . 唯一的区别是剩余的瓷砖根据方向聚集在左侧或右侧 .

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

    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
    

    在此之后,可以进行简单的压缩步骤,或者实时输出到第二缓冲区,或者其他任何一个 . 减少重复 .

  • 0

    我只做了将线条向左推的情况,但每个方向都采用相同的方法 . 我拿了答案的代码并修改了它;看一看:

    typedef struct grid {
        int tiles[4][4];
    } Grid;
    
    /* Functions prototypes */
    
    void pushLeft(Grid* grid);
    void showGrid (Grid* g);
    void find_great_tile(Grid* grid);
    
    /*  Main function   */
    
    int main() 
    {
        Grid g = {{4,2,2,8, 
                   2,8,2,2,
                   16,2,0,2, 
                   128,128,64,64}};
    
        /*
    
        The sequence is:
    
        --> Show the grid
        --> PushLeft
        --> Find great tile
        --> PushLeft
        --> Show the grid
    
        */
    
        printf("\n\n\n\n");
        showGrid (&g);
        printf("\n\n\n\n");
        pushLeft(&g);
        showGrid (&g);
        printf("\n\n\n\n");
        find_great_tile(&g);
        showGrid(&g);
        printf("\n\n\n\n");
        pushLeft(&g);
        showGrid(&g);
        printf("\n\n\n\n");
    
        return 0;
    }
    
    /* Functions definitions */
    
    void pushLeft(Grid* grid){
    
        int row, col, col2;
    
        for (row = 0; row < 4; row++)
        {
            for (col = 0; col < 4; col++)
            {
                if (!grid->tiles[row][col])
                {
                    for (col2 = col+1; col2 < 4; col2++)
                    {
                        if (grid->tiles[row][col2])
                        {
    
                            /*
                            if (grid->tiles[row][col] == grid->tiles[row][col2])
                            {
                                grid->tiles[row][col++] *= 2;
                                grid->tiles[row][col2] = 0;
                            }
    
                            break;
                            */
    
                            grid->tiles[row][col] = grid->tiles[row][col2];
                            grid->tiles[row][col2] = 0;
    
                            break;
                        }
                    }
                }
            }
        }
    }
    
    void showGrid (Grid* grid){
    
        int row, col;
    
            for(row = 0; row < 4; row++){
    
                fprintf(stdout, "\t\t     |");
    
                for(col = 0; col < 4; col++)
                {
    
                /*
                 In case there's any number in the matrix, it will print those numbers, otherwise, it'll print a space (it is the alternative of putting a 0)
                 */
    
                    if(grid->tiles[row][col])
                    {
                        printf("%4d    |", grid->tiles[row][col]);
                    }else
                        printf("%4c    |", ' ');
                }
    
                fprintf(stdout, "\n\n");
            }
    }
    
    void find_great_tile(Grid* grid){
    
        int row, col, col2;
    
        for(row = 0; row < 4; row++)
        {
            for(col = 0; col < 4; col++)
            {
                if(grid->tiles[row][col])
                {
                    col2 = col+1;
    
                    if(grid->tiles[row][col2])
                    {
                        if(grid->tiles[row][col] == grid->tiles[row][col2])
                        {
                            grid->tiles[row][col++] *= 2;
    
                            grid->tiles[row][col2] = 0;
                        }
                    }
                }
            }
        }
    }
    

    输出:

    |   4    |   2    |   2    |   8    |
    
             |   2    |   8    |   2    |   2    |
    
             |  16    |   2    |        |   2    |
    
             | 128    | 128    |  64    |  64    |
    
    
    
    
    
             |   4    |   2    |   2    |   8    |
    
             |   2    |   8    |   2    |   2    |
    
             |  16    |   2    |   2    |        |
    
             | 128    | 128    |  64    |  64    |
    
    
    
    
    
             |   4    |   4    |        |   8    |
    
             |   2    |   8    |   4    |        |
    
             |  16    |   4    |        |        |
    
             | 256    |        | 128    |        |
    
    
    
    
    
             |   4    |   4    |   8    |        |
    
             |   2    |   8    |   4    |        |
    
             |  16    |   4    |        |        |
    
             | 256    | 128    |        |        |
    

    当然,您可以压缩以下步骤:

    • PushLeft

    • FindGreatTile

    • PushLeft

相关问题