首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >平铺合并算法2048游戏

平铺合并算法2048游戏
EN

Stack Overflow用户
提问于 2014-12-11 21:43:52
回答 2查看 8.1K关注 0票数 5

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

代码语言:javascript
复制
 2 | 2 | 4 | 4                             4 | 8 |   |   
---+---+---+---  *swipes to the left* ->  ---+---+---+---
 8 |   | 8 |                               16|   |   |

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

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

代码语言:javascript
复制
typedef struct grid {
    char tiles[4][4];
} Grid;

我试着做算法来移动和合并向上,向下,左和右,但它们不能正常工作。

代码语言:javascript
复制
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似乎正在移除一些瓷砖。

有人看到问题了吗?或者知道怎么做?我已经考虑过使用递归算法,但我就是不能把我的头脑围绕在它上面。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-11 23:10:32

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

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

代码语言:javascript
复制
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;
}

这方面的产出:

代码语言:javascript
复制
   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
EN

Stack Overflow用户

发布于 2017-05-07 18:22:58

我只做了向左推线的例子,但对每个方向都是一样的。我取下了答案的代码并修改了它;看一看:

代码语言:javascript
复制
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;
                    }
                }
            }
        }
    }
}

这方面的产出:

代码语言:javascript
复制
         |   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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27432964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档