我试图在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 回答
我会亲自将滑动分为两个步骤,因为向左滑动并向右滑动实际上在功能上与瓷砖组合相同 . 唯一的区别是剩余的瓷砖根据方向聚集在左侧或右侧 .
下面是一个快速算法,用一个新的瓷砖替换两个瓷砖 . 我向左扫描 - >向右扫描并用新的瓷砖替换左边的瓷砖,将右边的瓷砖归零,然后确保从比较中排除这个新的瓷砖:
输出:
在此之后,可以进行简单的压缩步骤,或者实时输出到第二缓冲区,或者其他任何一个 . 减少重复 .
我只做了将线条向左推的情况,但每个方向都采用相同的方法 . 我拿了答案的代码并修改了它;看一看:
输出:
当然,您可以压缩以下步骤: