贪吃蛇游戏——C语言双向链表实现
采用了双向链表结点来模拟蛇身结点;
通过C语言光标控制函数来打印地图、蛇身和食物;
/************************** *************************** 贪吃蛇游戏 C语言数据结构 作者:Dew 时间:2019年3月23日 版本:1.0 *************************** **************************/ #include <stdio.h> #include <stdlib.h> #include <Windows.h> #include <conio.h> #define N 30 #define TRUE 1 #define FALSE 0 #define TIME 300 #define LEFT 37 #define UP 38 #define RIGHT 39 #define DOWN 40 void initMap(); void showGame(); void initSnake(); void control(int key); void updateSnake(int next_head_x, int next_head_y); void gotoxy(int x, int y); //光标控制 void gameRun(); void moveUp(); void moveDown(); void moveLeft(); void moveRight(); void createFood(); void addSnakeNode(int cur_tail_x, int cur_tail_y); void crashTest(int head_x, int head_y); struct snakeNode { int pos_x; int pos_y; snakeNode* pre; snakeNode* next; }; struct foodNode { int pos_x; int pos_y; }; int map[N][N]; int keyPress; int key; int next_head_x, next_head_y; int cur_tail_x, cur_tail_y; snakeNode* snake_head = (snakeNode *)malloc(sizeof(snakeNode)); snakeNode* snake_tail = (snakeNode *)malloc(sizeof(snakeNode)); foodNode* food = (foodNode *)malloc(sizeof(foodNode)); int main() { initSnake(); initMap(); gameRun(); return 0; } void initMap() { int i, j; for(i = 0; i < N; i++) for (j = 0; j < N; j++) { if (i == 0 || i == N - 1) map[i][j] = 1; else if (j == 0 || j == N - 1) map[i][j] = 1; else map[i][j] = 0; } } void showGame() { int i, j; for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { if (map[i][j] == 1) { gotoxy(j*2, i); printf("□"); } else if (map[i][j] == 0) { gotoxy(j*2, i); printf(" "); } } printf("\n"); } gotoxy(snake_head->pos_y * 2, snake_head->pos_x); printf("●"); gotoxy(snake_tail->pos_y * 2, snake_tail->pos_x); printf("●"); gotoxy(food->pos_y * 2, food->pos_x); printf("◇"); } void initSnake() { snake_head->pos_x = 15; snake_head->pos_y = 15; snake_head->pre = NULL; snake_head->next = snake_tail; snake_tail->pre = snake_head; snake_tail->pos_x = snake_tail->pre->pos_x + 1; snake_tail->pos_y = snake_tail->pre->pos_y; snake_tail->next = NULL; food->pos_x = rand() % 28 + 1; food->pos_y = rand() % 28 + 1; } void control(int direction) { if (direction == UP) { moveUp(); } else if (direction == DOWN) { moveDown(); } else if (direction == LEFT) { moveLeft(); } else if (direction == RIGHT) { moveRight(); } } void updateSnake(int next_head_x, int next_head_y) { snakeNode* p = snake_tail; while (p != snake_head) { p->pos_x = p->pre->pos_x; p->pos_y = p->pre->pos_y; p = p->pre; } p->pos_x = next_head_x; p->pos_y = next_head_y; } void gotoxy(int x, int y) { COORD pos; HANDLE hOutput; pos.X = x; pos.Y = y; hOutput = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorPosition(hOutput, pos); } void gameRun() { showGame(); control(UP); while (TRUE) { if (GetAsyncKeyState(VK_RIGHT)) { control(RIGHT); Sleep(TIME); } else if (GetAsyncKeyState(VK_LEFT)) { control(LEFT); Sleep(TIME); } else if (GetAsyncKeyState(VK_UP)) { control(UP); Sleep(TIME); } else if (GetAsyncKeyState(VK_DOWN)) { control(DOWN); Sleep(TIME); } } } void moveUp() { while (TRUE) { next_head_x = snake_head->pos_x - 1; next_head_y = snake_head->pos_y; cur_tail_x = snake_tail->pos_x; cur_tail_y = snake_tail->pos_y; updateSnake(next_head_x, next_head_y); gotoxy(next_head_y * 2, next_head_x); printf("●"); crashTest(next_head_x, next_head_y); if (next_head_x == food->pos_x && next_head_y == food->pos_y) { addSnakeNode(cur_tail_x, cur_tail_y); createFood(); } else { gotoxy(cur_tail_y * 2, cur_tail_x); printf(" "); } Sleep(TIME); if (GetAsyncKeyState(VK_RIGHT)) { control(RIGHT); Sleep(TIME); } else if (GetAsyncKeyState(VK_LEFT)) { control(LEFT); Sleep(TIME); } else if (GetAsyncKeyState(VK_UP)) { control(UP); Sleep(TIME); } else if (GetAsyncKeyState(VK_DOWN)) { continue; } } } void moveDown() { while (TRUE) { next_head_x = snake_head->pos_x + 1; next_head_y = snake_head->pos_y; cur_tail_x = snake_tail->pos_x; cur_tail_y = snake_tail->pos_y; updateSnake(next_head_x, next_head_y); gotoxy(next_head_y * 2, next_head_x); printf("●"); crashTest(next_head_x, next_head_y); if (next_head_x == food->pos_x && next_head_y == food->pos_y) { addSnakeNode(cur_tail_x, cur_tail_y); createFood(); } else { gotoxy(cur_tail_y * 2, cur_tail_x); printf(" "); } Sleep(TIME); if (GetAsyncKeyState(VK_RIGHT)) { control(RIGHT); Sleep(TIME); } else if (GetAsyncKeyState(VK_LEFT)) { control(LEFT); Sleep(TIME); } else if (GetAsyncKeyState(VK_UP)) { continue; } else if (GetAsyncKeyState(VK_DOWN)) { control(DOWN); Sleep(TIME); } } } void moveLeft() { while (TRUE) { next_head_x = snake_head->pos_x; next_head_y = snake_head->pos_y - 1; cur_tail_x = snake_tail->pos_x; cur_tail_y = snake_tail->pos_y; updateSnake(next_head_x, next_head_y); gotoxy(next_head_y * 2, next_head_x); printf("●"); crashTest(next_head_x, next_head_y); if (next_head_x == food->pos_x && next_head_y == food->pos_y) { addSnakeNode(cur_tail_x, cur_tail_y); createFood(); } else { gotoxy(cur_tail_y * 2, cur_tail_x); printf(" "); } Sleep(TIME); if (GetAsyncKeyState(VK_RIGHT)) { continue; } else if (GetAsyncKeyState(VK_LEFT)) { control(LEFT); Sleep(TIME); } else if (GetAsyncKeyState(VK_UP)) { control(UP); Sleep(TIME); } else if (GetAsyncKeyState(VK_DOWN)) { control(DOWN); Sleep(TIME); } } } void moveRight() { while (TRUE) { next_head_x = snake_head->pos_x; next_head_y = snake_head->pos_y + 1; cur_tail_x = snake_tail->pos_x; cur_tail_y = snake_tail->pos_y; updateSnake(next_head_x, next_head_y); gotoxy(next_head_y * 2, next_head_x); printf("●"); crashTest(next_head_x, next_head_y); if (next_head_x == food->pos_x && next_head_y == food->pos_y) { addSnakeNode(cur_tail_x, cur_tail_y); createFood(); } else { gotoxy(cur_tail_y * 2, cur_tail_x); printf(" "); } Sleep(TIME); if (GetAsyncKeyState(VK_RIGHT)) { control(RIGHT); Sleep(TIME); } else if (GetAsyncKeyState(VK_LEFT)) { continue; } else if (GetAsyncKeyState(VK_UP)) { control(UP); Sleep(TIME); } else if (GetAsyncKeyState(VK_DOWN)) { control(DOWN); Sleep(TIME); } } } void createFood() { food->pos_x = rand() % 28 + 1; food->pos_y = rand() % 28 + 1; gotoxy(food->pos_y * 2, food->pos_x); printf("◇"); } void addSnakeNode(int cur_tail_x, int cur_tail_y) { snakeNode* tempNode = (snakeNode *)malloc(sizeof(snakeNode)); tempNode->pos_x = cur_tail_x; tempNode->pos_y = cur_tail_y; tempNode->next = NULL; snake_tail->next = tempNode; tempNode->pre = snake_tail; snake_tail = tempNode; } void crashTest(int head_x, int head_y) { snakeNode* p = snake_head->next; while (p != NULL) { if (p->pos_x == head_x && p->pos_y == head_y) { gotoxy(32 * 2, 15); printf("...发生撞击!......游戏结束..."); getchar(); } if (p->pos_x == 1 || p->pos_x == N - 2 || p->pos_y == 1 || p->pos_y == N - 2) { gotoxy(32 * 2, 15); printf("...发生撞击!......游戏结束..."); getchar(); } p = p->next; } }