/* Clear the screen and print out the grid. */ voidprintGrid() { clearScreen(); int x, y; for (y = 0; y < GRID_HEIGHT; ++y) { for (x = 0; x < GRID_WIDTH; ++x) { putchar(grid[y][x]); } putchar('\n'); } }
这里我们又用到了一个我们没有实现的函数 clearScreen() ,我们希望每次输出界面的时候都先清空屏幕,经过查资料,在 Linux 系统上,我们只需要调用 system("clear") 就能实现我们的目的。
1 2 3 4
/* Clear the screen. */ voidclearScreen() { system("clear"); }
/* Read in only one character and discard the following characters. */ /* If no character is read, return space character. */ charreadInput() { char ch; if (scanf("%c", &ch)) { while (getchar() != '\n') continue; return ch; } else { return' '; } }
让蛇动起来
实现完输出输入函数之后,我们就要开始真正的任务了:让我们的蛇可以动起来,也就是实现 snakeMove(int dx, int dy) 函数。
思路是什么呢?从前面数据结构的定义来看,坐标数组的下标为 snakeLength - 1 的元素就是我们蛇头的坐标,其余都是蛇身的坐标。首先,蛇身部分则依次往前挪一个单位,也就是用第 i 个坐标代替第 i - 1 个坐标(这里,1 <= i <= snakeLength - 1),然后蛇头根据方向进行坐标变换,这样我们的蛇就像是在动起来了。
而移动之前,我们要先让原来的蛇在地图上消失,然后移动之后再画上去,这样就不会出现重复的蛇了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* Move the snake one step according to dx and dy */ voidsnakeMove(int dx, int dy) { int i; /* Clear the original snake */ clearSnake();
/* Propagate the movement first */ for (i = 0; i < snakeLength - 1; ++i) { snakeX[i] = snakeX[i + 1]; snakeY[i] = snakeY[i + 1]; }
/* Set the new head */ snakeX[snakeLength - 1] = snakeX[snakeLength - 1] + dx; snakeY[snakeLength - 1] = snakeY[snakeLength - 1] + dy;
/* Clear the snake */ voidclearSnake() { int i; for (i = 0; i < snakeLength; ++i) { int x = snakeX[i]; int y = snakeY[i]; grid[y][x] = CHAR_GRID_BLANK; } }
/* Draw the snake */ voiddrawSnake() { int i; for (i = 0; i < snakeLength; ++i) { int x = snakeX[i]; int y = snakeY[i]; grid[y][x] = (snakeLength - 1) == i ? CHAR_SNAKE_HEAD : CHAR_SNAKE_BODY; } }
/* See if our lovely snake has eaten a food */ inteatFood(int dx, int dy) { /* Get future head coordinates */ int headX = snakeX[snakeLength - 1] + dx; int headY = snakeY[snakeLength - 1] + dy;
if (grid[headY][headX] == CHAR_GRID_FOOD) { /* Will it be too long? */ if (snakeLength + 1 > SNAKE_MAX_LENGTH) return0;
intmanhattanDist(int x1, int y1, int x2, int y2) { returnabs(x1 - x2) + abs(y1 - y2); }
/* Caculate and make an intelligent move */ charnextMove() { /* Find a direction that is near one food */ int i = 0; int headX = snakeX[snakeLength - 1]; int headY = snakeY[snakeLength - 1]; int distMin = 9999; char direction = 'D'; for (i = 0; i < foodNumber; ++i) { int fX = foodX[i]; int fY = foodY[i]; int dist = 0; if (predictMovable(UP)) { dist = manhattanDist(headX, headY - 1, fX, fY); if (dist < distMin) { distMin = dist; direction = 'W'; } }
if (predictMovable(DOWN)) { dist = manhattanDist(headX, headY + 1, fX, fY); if (dist < distMin) { distMin = dist; direction = 'S'; } }
if (predictMovable(LEFT)) { dist = manhattanDist(headX - 1, headY, fX, fY); if (dist < distMin) { distMin = dist; direction = 'A'; } }
if (predictMovable(RIGHT)) { dist = manhattanDist(headX + 1, headY, fX, fY); if (dist < distMin) { distMin = dist; direction = 'D'; } } }
if (distMin == 9999) { if (predictMovable(RIGHT)) direction = 'D'; if (predictMovable(LEFT)) direction = 'A'; if (predictMovable(UP)) direction = 'W'; if (predictMovable(DOWN)) direction = 'S'; }