【发布时间】:2015-02-10 12:48:44
【问题描述】:
我正在尝试用 C 语言重新创建游戏 2048,但我无法让算法将图块移动或合并在一起以正常运行。 在最初的 2048 游戏中,您可以像这样一起移动图块:
2 | 2 | 4 | 4 4 | 8 | |
---+---+---+--- *swipes to the left* -> ---+---+---+---
8 | | 8 | 16| | |
因此,两个相同的图块可以合并为一个大小为两倍的图块。我的版本几乎相同,但我没有使用数字,而是使用在它们合并时递增 1 的字符,所以[A|A] 将合并到[B] 等。我这样做只是为了不必处理不同大小的图块。
所以我的板子在我称为 grid 的结构中存储为 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 似乎正在移除一些图块。
有没有人发现问题或知道解决方法?我曾考虑过使用递归算法,但我就是想不通。
【问题讨论】:
-
一个瓦片不能在一次移动中合并两次,因此应考虑将合并结果的瓦片标记为这样。然后,您将在合并之前检查是否有如此标记的图块在此移动期间不符合合并条件。
-
感谢您的评论。我试图通过在最内层循环中使用一个标志来实现它,如果当前图块被合并,该标志会变为假。我现在看到这还不够,因为推送的下一个图块可以与之前推送的图块合并。