一. 游戏效果
二. 游戏背景
贪吃蛇是久负盛名的游戏,它也和俄罗斯⽅块,扫雷等游戏位列经典游戏的⾏列。
贪吃蛇起源于1977年的投币式墙壁游戏《Blockade》,后移植到各种平台上。具体如下:
起源。1977年,投币式墙壁游戏生产商Gremlin推出了经典的街机游戏《Blockade》,两名玩家要分别控制角色移动,角色会不停长大,而且走过的地方会变成围栏,谁先碰到围栏或碰到自己的身体就算输。
贪吃蛇最初的版本是像素版本,后来又衍生出3D版本、多人对战版本等2 3。
三、游戏开发日志
四、知识准备
本次实现贪吃蛇会使⽤到的⼀些Win32 API知识,那么就学习⼀下
4.1 Win32 API
Windows 这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外, 它同时也是⼀个很⼤的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程式达到开启 视窗、描绘图形、使⽤周边设备等⽬的,由于这些函数服务的对象是应⽤程序(Application), 所以便 称之为 Application Programming Interface, 简称 API 函数。 WIN32 API也就是Microsoft Windows 32位平台的应⽤程序编程接⼝。
4.2 控制台程序
平常我们运⾏起来的⿊框程序其实就是控制台程序。
我们可以使⽤cmd命令来设置控制台窗⼝的⻓宽,也可以通过命令设置控制台窗⼝的名字:
设置控制台窗⼝的⼤⼩,30⾏,100列,设置控制台窗⼝的名字。
//控制台窗口设置 system("mode con cols=100 lines=35"); system("title 贪吃蛇");
4.3 控制台屏幕上的坐标COORD
COORD 是Windows API中定义的⼀种结构,表⽰⼀个字符在控制台屏幕上的坐标
typedef struct _COORD { SHORT X; SHORT Y; } COORD, *PCOORD;
4.4 GetStdHandle
GetStdHandle是⼀个Windows API函数。它⽤于从⼀个特定的标准设备(标准输⼊、标准输出或标准错误)中取得⼀个句柄(⽤来标识不同设备的数值),使⽤这个句柄可以操作设备。
HANDLE hOutput = NULL; //获取标准输出的句柄(⽤来标识不同设备的数值) hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
4.5 GetConsoleCursorInfo
检索有关指定控制台屏幕缓冲区的光标⼤⼩和可⻅性的信息
HANDLE hOutput = NULL; //获取标准输出的句柄(⽤来标识不同设备的数值) hOutput = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO CursorInfo; GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
4.5.1 CONSOLE_CURSOR_INFO
这个结构体,包含有关控制台游标的信息
typedef struct _CONSOLE_CURSOR_INFO { DWORD dwSize; BOOL bVisible; } CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
(1) dwSize,由光标填充的字符单元格的百分⽐。 此值介于1到100之间。 光标外观会变化,范围从完全填充单元格到单元底部的⽔平线条。
(2) bVisible,游标的可⻅性。 如果光标可⻅,则此成员为 TRUE。
CursorInfo.bVisible = false; //隐藏控制台光标
5.6 SetConsoleCursorInfo
设置指定控制台屏幕缓冲区的光标的⼤⼩和可⻅性。
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //影藏光标操作 CONSOLE_CURSOR_INFO CursorInfo; GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息 CursorInfo.bVisible = false; //隐藏控制台光标 SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态
5.7 SetConsoleCursorPosition
设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的pos中,调 ⽤SetConsoleCursorPosition函数将光标位置设置到指定的位置。
COORD pos = { 10, 5}; HANDLE hOutput = NULL; //获取标准输出的句柄(⽤来标识不同设备的数值) hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //设置标准输出上光标的位置为pos SetConsoleCursorPosition(hOutput, pos);
温馨提示:
这里我们可以将SetPos:封装⼀个设置光标位置的函数
//设置光标的坐标 void SetPos(short x, short y) { COORD pos = { x, y }; HANDLE hOutput = NULL; //获取标准输出的句柄(⽤来标识不同设备的数值) hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //设置标准输出上光标的位置为pos SetConsoleCursorPosition(hOutput, pos); }
5.8 GetAsyncKeyState
获取按键情况,将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态。
返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果 返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。
如果我们要判断⼀个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1.
我们这里定义一个宏:
#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )
5.9 宽字符打印
在游戏地图上,我们打印墙体使⽤宽字符:□,打印蛇使⽤宽字符●,打印⻝物使⽤宽字符■
普通的字符是占⼀个字节的,这类宽字符是俩个字节。
5.9.1 setlocale函数
char* setlocale (int category, const char* locale);
setlocale 函数⽤于修改当前地区,可以针对⼀个类项修改,也可以针对所有类项。 setlocale 的第⼀个参数如果是LC_ALL,就会影响所有的类项。
C标准给第⼆个参数仅定义了2种可能取值:"C"和" "。
在任意程序执⾏开始,都会隐藏式执⾏调⽤:
setlocale(LC_ALL, "C");
当地区设置为"C"时,库函数按正常⽅式执⾏.
当地区设置为" "时,这种模式下程序会适应本地环境。⽐如:切换到我们的本地模式后就⽀
持宽字符(汉字)的输出等。
setlocale(LC_ALL, " ");//切换到本地环境
宽字符的打印如下:
#include <stdio.h> #include<locale.h> int main() { setlocale(LC_ALL, ""); wchar_t ch1 = L'●'; wprintf(L"%c\n", ch1); return 0; }
五、游戏实现
5.1 游戏逻辑主体
#define _CRT_SECURE_NO_WARNINGS #include"snake.h" #include<locale.h> #include<stdio.h> int main() { char ch; setlocale(LC_ALL, "");//切换到本地环境,支持宽字符 srand((unsigned int)time(NULL)); do { Snake snake = { 0 }; GameInit(&snake); GameRun(&snake); GameOver(&snake); printf("小垃圾还要再来吗?是:Y,否:N\n"); ch = getchar(); getchar(); } while (ch == 'y' || ch == 'Y'); return 0; }
5.2 游戏初始化实现
#define _CRT_SECURE_NO_WARNINGS #include"snake.h" #define WALL L'□' #define BODY L'●' #define FOOD L'█' void SetPos(short x, short y) { COORD pos = { x, y }; HANDLE hOutput = NULL; //获取标准输出的句柄(⽤来标识不同设备的数值) hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //设置标准输出上光标的位置为pos SetConsoleCursorPosition(hOutput, pos); } void WelcomeToGame() { SetPos(40, 13); printf("欢迎来到贪吃蛇小游戏"); SetPos(42, 22); system("pause");//会显示按任意键继续的信息,按任意键后继续执行下一步 system("cls"); SetPos(25, 12); printf("↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速\n"); SetPos(42, 22); system("pause");//会显示按任意键继续的信息,按任意键后继续执行下一步 system("cls"); /*getchar();*/ } void CreateMap() { SetPos(0,0); int i = 0; for(i=0;i<58;i=i+2) { wprintf(L"%c", WALL); } SetPos(0, 26); for (i = 0; i < 58; i = i + 2) { wprintf(L"%c", WALL); } for (i = 1; i <26; i++) { SetPos(0, i); wprintf(L"%c", WALL); } for (i = 1; i < 26; i++) { SetPos(56, i); wprintf(L"%c", WALL); } /*getchar();*/ } void InitSnake(Snake* snake) { //初始化蛇身 for (int i = 0; i < 5; i++) { SnakeNode* node = (SnakeNode*)malloc(sizeof(SnakeNode)); node->x = 24 + 2 * i; node->y = 15; node->next = NULL; if (snake->pSnake== NULL) { snake->pSnake= node; } else { node->next = snake->pSnake; snake->pSnake = node; } } SnakeNode* cur = snake->pSnake; while (cur) { int x = cur->x; int y = cur->y; SetPos(x, y); wprintf(L"%c", BODY); cur = cur->next; } snake->status = RUN; snake->dir = RIGHT; snake->FoodWeight = 10; snake->pFood = NULL; snake->score = 0; snake->SleepTime = 200; } void CreateFood(Snake* snake) { int x = 0; int y = 0; again: do { x = rand() % 53 + 2; y = rand() % 24 + 1; } while (x % 2 != 0); SnakeNode* cur = snake->pSnake; do { if (x == cur->x && y == cur->y) { goto again; } cur = cur->next; } while (cur); SnakeNode* food = (SnakeNode*)malloc(sizeof(SnakeNode)); food->x = x; food->y = y; snake->pFood = food; SetPos(x, y); wprintf(L"%c", FOOD); /*getchar();*/ } void GameInit(Snake* snake) { //控制台窗口设置 system("mode con cols=100 lines=35"); system("title 贪吃蛇"); //隐藏光标 HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO CursorInfo; GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息 CursorInfo.bVisible = false; //隐藏控制台光标 SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态 //打印欢迎界面 WelcomeToGame(); //创建地图 CreateMap(); //初始化贪吃蛇 InitSnake(snake); //创建食物 CreateFood(snake); }
5.3 游戏运行实现
void PrintHelpInfo() { SetPos(60, 13); printf("1. 不能穿墙不能咬到自己\n"); SetPos(60, 14); printf("2.↑.↓.←.→分别控制蛇的移动\n"); SetPos(60, 15); printf("3. F3为加速,F4为减速\n"); SetPos(60, 16); printf("4. ESC-退出,空格-暂停\n"); } void Pause() { while (1) { Sleep(200); if (KEY_PRESS(VK_SPACE) == 1) { break; } } } void EatFood(Snake* snake, SnakeNode* snakenext) { snakenext->next = snake->pSnake; snake->pSnake = snakenext; SnakeNode* cur = snake->pSnake; while (cur) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } free(snake->pFood); snake->pFood = NULL; CreateFood(snake); } void NoEatFood(Snake* snake, SnakeNode* snakenext) { snakenext->next = snake->pSnake; snake->pSnake = snakenext; SnakeNode* cur = snake->pSnake; while (cur->next->next) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); SetPos(cur->next->x, cur->next->y); printf(" "); free(cur->next); cur->next = NULL; } void SnakeMove(Snake* snake) { SnakeNode* snakenext = (SnakeNode*)malloc(sizeof(SnakeNode)); if (snake->dir == UP) { snakenext->x = snake->pSnake->x; snakenext->y = snake->pSnake->y -1; snakenext->next = NULL; } else if (snake->dir == DOWN) { snakenext->x = snake->pSnake->x; snakenext->y = snake->pSnake->y +1; snakenext->next = NULL; } if (snake->dir == LEFT) { snakenext->x = snake->pSnake->x-2; snakenext->y = snake->pSnake->y ; snakenext->next = NULL; } if (snake->dir == RIGHT) { snakenext->x = snake->pSnake->x + 2; snakenext->y = snake->pSnake->y; snakenext->next = NULL; } //判断下一个节点是否为食物 if (snakenext->x == snake->pFood->x && snakenext->y == snake->pFood->y) { EatFood(snake,snakenext);//吃食物 snake->score += snake->FoodWeight; } else { NoEatFood(snake,snakenext);//不吃食物 } //碰撞检测 if (snake->pSnake->x == 0 || snake->pSnake->x == 56 || snake->pSnake->y == 0 || snake->pSnake->y == 26) { snake->status = KILL_BY_WALL; } SnakeNode* cur = snake->pSnake->next; while (cur) { if (cur->x == snake->pSnake->x && cur->y == snake->pSnake->y) { snake->status = KILL_BY_SELF; } cur = cur->next; } } void GameRun(Snake* snake) { //打印帮助信息 PrintHelpInfo(); do { SetPos(60, 8); printf("游戏总得分:%5d ", snake->score); SetPos(60, 9); printf("每个食物的分数:%2d ", snake->FoodWeight); if (KEY_PRESS(VK_UP) == 1&&snake->dir!=DOWN) { snake->dir = UP; } else if (KEY_PRESS(VK_DOWN) == 1 && snake->dir != UP) { snake->dir = DOWN; } else if (KEY_PRESS(VK_RIGHT) == 1 && snake->dir != LEFT) { snake->dir = RIGHT; } else if (KEY_PRESS(VK_LEFT) == 1 && snake->dir != RIGHT) { snake->dir =LEFT; } else if (KEY_PRESS(VK_F3) == 1) { if (snake->SleepTime>=80) { snake->SleepTime -= 30; snake->FoodWeight += 2; } } else if (KEY_PRESS(VK_F4) == 1) { if (snake->SleepTime<=320) { snake->SleepTime += 30; snake->FoodWeight -= 2; } } else if (KEY_PRESS(VK_ESCAPE) == 1) { snake->status = OVER; break; } else if (KEY_PRESS(VK_SPACE) == 1) { Pause(); } SnakeMove(snake); Sleep(snake->SleepTime);//每一帧停0.2s } while (snake->status==RUN); }
5.4 游戏结束实现
void GameOver(Snake* snake) { switch (snake->status) { case KILL_BY_WALL: SetPos(20, 15); printf("你已经撞墙了,小垃圾!\n"); break; case KILL_BY_SELF: SetPos(20, 15); printf("你已经自杀了,小垃圾!\n"); break; case OVER: SetPos(20, 15); printf("你退出游戏了,小垃圾!\n"); break; } SetPos(0, 29); }
六、 完整代码
6.1 snake.h
#define _CRT_SECURE_NO_WARNINGS #include<stdbool.h> #include<stdio.h> #include<windows.h> #include<stdlib.h> #include<time.h> #define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 ) enum direction{UP = 1, DOWN, LEFT, RIGHT};//蛇的方向 enum game_status{RUN,KILL_BY_WALL,KILL_BY_SELF,OVER}; typedef struct SnakeNode { int x; int y; struct SnakeNode* next; }SnakeNode; typedef struct Snake { SnakeNode* pSnake;//指向贪吃蛇头节点 SnakeNode* pFood;//指向食物的节点 int score; int FoodWeight; int SleepTime; enum direction dir;//蛇的方向 enum game_status status;//游戏状态 }Snake; void GameInit(Snake*snake); void WelcomeToGame(); void CreateMap(); void InitSnake(Snake* snake); void CreateFood(Snake* snake); void GameRun(Snake* snake); void PrintHelpInfo(); void Pause(); void SnakeMove(Snake* snake); void EatFood(Snake* snake,SnakeNode*snakenext); void NoEatFood(Snake* snake, SnakeNode* snakenext); void GameOver(Snake* snake);
6.2 snake.c
#define _CRT_SECURE_NO_WARNINGS #include"snake.h" #define WALL L'□' #define BODY L'●' #define FOOD L'█' void SetPos(short x, short y) { COORD pos = { x, y }; HANDLE hOutput = NULL; //获取标准输出的句柄(⽤来标识不同设备的数值) hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //设置标准输出上光标的位置为pos SetConsoleCursorPosition(hOutput, pos); } void WelcomeToGame() { SetPos(40, 13); printf("欢迎来到贪吃蛇小游戏"); SetPos(42, 22); system("pause");//会显示按任意键继续的信息,按任意键后继续执行下一步 system("cls"); SetPos(25, 12); printf("↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速\n"); SetPos(42, 22); system("pause");//会显示按任意键继续的信息,按任意键后继续执行下一步 system("cls"); /*getchar();*/ } void CreateMap() { SetPos(0,0); int i = 0; for(i=0;i<58;i=i+2) { wprintf(L"%c", WALL); } SetPos(0, 26); for (i = 0; i < 58; i = i + 2) { wprintf(L"%c", WALL); } for (i = 1; i <26; i++) { SetPos(0, i); wprintf(L"%c", WALL); } for (i = 1; i < 26; i++) { SetPos(56, i); wprintf(L"%c", WALL); } /*getchar();*/ } void InitSnake(Snake* snake) { //初始化蛇身 for (int i = 0; i < 5; i++) { SnakeNode* node = (SnakeNode*)malloc(sizeof(SnakeNode)); node->x = 24 + 2 * i; node->y = 15; node->next = NULL; if (snake->pSnake== NULL) { snake->pSnake= node; } else { node->next = snake->pSnake; snake->pSnake = node; } } SnakeNode* cur = snake->pSnake; while (cur) { int x = cur->x; int y = cur->y; SetPos(x, y); wprintf(L"%c", BODY); cur = cur->next; } snake->status = RUN; snake->dir = RIGHT; snake->FoodWeight = 10; snake->pFood = NULL; snake->score = 0; snake->SleepTime = 200; } void CreateFood(Snake* snake) { int x = 0; int y = 0; again: do { x = rand() % 53 + 2; y = rand() % 24 + 1; } while (x % 2 != 0); SnakeNode* cur = snake->pSnake; do { if (x == cur->x && y == cur->y) { goto again; } cur = cur->next; } while (cur); SnakeNode* food = (SnakeNode*)malloc(sizeof(SnakeNode)); food->x = x; food->y = y; snake->pFood = food; SetPos(x, y); wprintf(L"%c", FOOD); /*getchar();*/ } void GameInit(Snake* snake) { //控制台窗口设置 system("mode con cols=100 lines=35"); system("title 贪吃蛇"); //隐藏光标 HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO CursorInfo; GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息 CursorInfo.bVisible = false; //隐藏控制台光标 SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态 //打印欢迎界面 WelcomeToGame(); //创建地图 CreateMap(); //初始化贪吃蛇 InitSnake(snake); //创建食物 CreateFood(snake); } void PrintHelpInfo() { SetPos(60, 13); printf("1. 不能穿墙不能咬到自己\n"); SetPos(60, 14); printf("2.↑.↓.←.→分别控制蛇的移动\n"); SetPos(60, 15); printf("3. F3为加速,F4为减速\n"); SetPos(60, 16); printf("4. ESC-退出,空格-暂停\n"); } void Pause() { while (1) { Sleep(200); if (KEY_PRESS(VK_SPACE) == 1) { break; } } } void EatFood(Snake* snake, SnakeNode* snakenext) { snakenext->next = snake->pSnake; snake->pSnake = snakenext; SnakeNode* cur = snake->pSnake; while (cur) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } free(snake->pFood); snake->pFood = NULL; CreateFood(snake); } void NoEatFood(Snake* snake, SnakeNode* snakenext) { snakenext->next = snake->pSnake; snake->pSnake = snakenext; SnakeNode* cur = snake->pSnake; while (cur->next->next) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); SetPos(cur->next->x, cur->next->y); printf(" "); free(cur->next); cur->next = NULL; } void SnakeMove(Snake* snake) { SnakeNode* snakenext = (SnakeNode*)malloc(sizeof(SnakeNode)); if (snake->dir == UP) { snakenext->x = snake->pSnake->x; snakenext->y = snake->pSnake->y -1; snakenext->next = NULL; } else if (snake->dir == DOWN) { snakenext->x = snake->pSnake->x; snakenext->y = snake->pSnake->y +1; snakenext->next = NULL; } if (snake->dir == LEFT) { snakenext->x = snake->pSnake->x-2; snakenext->y = snake->pSnake->y ; snakenext->next = NULL; } if (snake->dir == RIGHT) { snakenext->x = snake->pSnake->x + 2; snakenext->y = snake->pSnake->y; snakenext->next = NULL; } //判断下一个节点是否为食物 if (snakenext->x == snake->pFood->x && snakenext->y == snake->pFood->y) { EatFood(snake,snakenext);//吃食物 snake->score += snake->FoodWeight; } else { NoEatFood(snake,snakenext);//不吃食物 } //碰撞检测 if (snake->pSnake->x == 0 || snake->pSnake->x == 56 || snake->pSnake->y == 0 || snake->pSnake->y == 26) { snake->status = KILL_BY_WALL; } SnakeNode* cur = snake->pSnake->next; while (cur) { if (cur->x == snake->pSnake->x && cur->y == snake->pSnake->y) { snake->status = KILL_BY_SELF; } cur = cur->next; } } void GameRun(Snake* snake) { //打印帮助信息 PrintHelpInfo(); do { SetPos(60, 8); printf("游戏总得分:%5d ", snake->score); SetPos(60, 9); printf("每个食物的分数:%2d ", snake->FoodWeight); if (KEY_PRESS(VK_UP) == 1&&snake->dir!=DOWN) { snake->dir = UP; } else if (KEY_PRESS(VK_DOWN) == 1 && snake->dir != UP) { snake->dir = DOWN; } else if (KEY_PRESS(VK_RIGHT) == 1 && snake->dir != LEFT) { snake->dir = RIGHT; } else if (KEY_PRESS(VK_LEFT) == 1 && snake->dir != RIGHT) { snake->dir =LEFT; } else if (KEY_PRESS(VK_F3) == 1) { if (snake->SleepTime>=80) { snake->SleepTime -= 30; snake->FoodWeight += 2; } } else if (KEY_PRESS(VK_F4) == 1) { if (snake->SleepTime<=320) { snake->SleepTime += 30; snake->FoodWeight -= 2; } } else if (KEY_PRESS(VK_ESCAPE) == 1) { snake->status = OVER; break; } else if (KEY_PRESS(VK_SPACE) == 1) { Pause(); } SnakeMove(snake); Sleep(snake->SleepTime);//每一帧停0.2s } while (snake->status==RUN); } void GameOver(Snake* snake) { switch (snake->status) { case KILL_BY_WALL: SetPos(20, 15); printf("你已经撞墙了,小垃圾!\n"); break; case KILL_BY_SELF: SetPos(20, 15); printf("你已经自杀了,小垃圾!\n"); break; case OVER: SetPos(20, 15); printf("你退出游戏了,小垃圾!\n"); break; } SetPos(0, 29); }
6.3 text.c
#define _CRT_SECURE_NO_WARNINGS #include"snake.h" #include<locale.h> #include<stdio.h> int main() { char ch; setlocale(LC_ALL, "");//切换到本地环境,支持宽字符 srand((unsigned int)time(NULL)); do { Snake snake = { 0 }; GameInit(&snake); GameRun(&snake); GameOver(&snake); printf("小垃圾还要再来吗?是:Y,否:N\n"); ch = getchar(); getchar(); } while (ch == 'y' || ch == 'Y'); return 0; }
七、穿墙版(进阶版)
穿墙也非常简单,只是将撞墙检测去除,改为
1)判断snakenext->y ==0,则snakenext->y =25
2)判断snakenext->y ==26,则snakenext->y =1
3)判断snakenext->x==0,则snakenext->x =54
4) 判断snakenext->x==56,则snakenext->x =2
其余状态为正常吃食物状态
只在snake.c中的void SnakeMove(Snake* snake)中略有改动,其余不变
void SnakeMove(Snake* snake) { SnakeNode* snakenext = (SnakeNode*)malloc(sizeof(SnakeNode)); if (snake->dir == UP) { snakenext->x = snake->pSnake->x; snakenext->y = snake->pSnake->y -1; snakenext->next = NULL; } else if (snake->dir == DOWN) { snakenext->x = snake->pSnake->x; snakenext->y = snake->pSnake->y +1; snakenext->next = NULL; } if (snake->dir == LEFT) { snakenext->x = snake->pSnake->x-2; snakenext->y = snake->pSnake->y ; snakenext->next = NULL; } if (snake->dir == RIGHT) { snakenext->x = snake->pSnake->x + 2; snakenext->y = snake->pSnake->y; snakenext->next = NULL; } //判断下一个节点是否为食物 if (snakenext->x == snake->pFood->x && snakenext->y == snake->pFood->y) { EatFood(snake,snakenext);//吃食物 snake->score += snake->FoodWeight; } else { if (snakenext->y == 0) { snakenext->y = 25; snakenext->next = snake->pSnake; snake->pSnake = snakenext; SnakeNode* cur = snake->pSnake; while (cur->next->next) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); SetPos(cur->next->x, cur->next->y); printf(" "); free(cur->next); cur->next = NULL; } else if (snakenext->y == 26) { snakenext->y =1; snakenext->next = snake->pSnake; snake->pSnake = snakenext; SnakeNode* cur = snake->pSnake; while (cur->next->next) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); SetPos(cur->next->x, cur->next->y); printf(" "); free(cur->next); cur->next = NULL; } else if (snakenext->x == 0) { snakenext->x = 54; snakenext->next = snake->pSnake; snake->pSnake = snakenext; SnakeNode* cur = snake->pSnake; while (cur->next->next) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); SetPos(cur->next->x, cur->next->y); printf(" "); free(cur->next); cur->next = NULL; } else if (snakenext->x == 56) { snakenext->x =2; snakenext->next = snake->pSnake; snake->pSnake = snakenext; SnakeNode* cur = snake->pSnake; while (cur->next->next) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); SetPos(cur->next->x, cur->next->y); printf(" "); free(cur->next); cur->next = NULL; } else { NoEatFood(snake, snakenext);//不吃食物 } } //穿墙检测 SnakeNode* cur = snake->pSnake->next; while (cur) { if (cur->x == snake->pSnake->x && cur->y == snake->pSnake->y) { snake->status = KILL_BY_SELF; } cur = cur->next; } }