瓷砖合并算法2048游戏
我试图在C中重新创建游戏2048,但我无法使算法移动或合并拼贴以正常运行。 在原来的2048游戏中,你会像这样移动拼贴:
2 | 2 | 4 | 4 4 | 8 | |
---+---+---+--- *swipes to the left* -> ---+---+---+---
8 | | 8 | 16| | |
因此,两个相同的拼贴可以合并为一个大小为两倍的拼贴。 我的版本几乎相同,但不是使用数字,而是使用合并时增加1的字符,因此[A|A]
会合并为[B]
等。我这样做只是为了不必处理不同的大小瓷砖。
所以我的电路板作为一个4 * 4字符数组存储在一个叫做grid的结构中(我知道可能有点多余)
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似乎正在删除一些瓷砖。
有没有人看到这个问题或知道一种方法来做到这一点? 我曾考虑过使用递归算法,但我无法围绕它进行思考。
我会亲自将刷卡分成两步,因为左侧刷卡和右侧刷卡实际上在组合方面功能上相同。 唯一的区别是剩余的瓷砖根据方向分成左右两侧。
下面是一个快速算法,用一个新的替换两个瓷砖。 我扫描左侧 - >右侧,并用新瓷砖替换左侧瓷砖,将右侧瓷砖置零,然后确保从比较中排除此新瓷砖:
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
在此之后,可以进行简单的压缩步骤,或者实时输出到第二个缓冲区,或者进行任何一个。 减少重复。
我只做过将线条推向左侧的情况,但对于每个方向都是相同的方法。 我拿出答案的代码并对其进行修改; 看一看:
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("nnnn");
showGrid (&g);
printf("nnnn");
pushLeft(&g);
showGrid (&g);
printf("nnnn");
find_great_tile(&g);
showGrid(&g);
printf("nnnn");
pushLeft(&g);
showGrid(&g);
printf("nnnn");
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, "tt |");
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, "nn");
}
}
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
链接地址: http://www.djcxy.com/p/6847.html