赞
踩
前言:首先在实现贪吃蛇小游戏之前,我们要先了解Win32 API的有关知识
Windows这个多作业系统除了协调应用程序的执行、分配内存、管理资源之外,它同时也是一个很大的服务中心,调佣这个中心的各种服务(每一种服务就是一个函数),它可以帮助应用程序达到开启视窗、秒回图形、使用周边设备等目的,由于这些函数的服务对象是应用程序,所以便称之为Application Pragramming Interface,简称API函数。Win32 API也就是Microsoft Windows32位平台的程序应用编程接口。
平常我们运用起来的黑框程序就是控制台程序
我们可以通过执行命令来改变控制台的长宽
在我们执行cmd命令之前,我们首先要先做以下事情
点开设置,然后将windows决定改为windows控制台主机,然后点击保存,我们就可以执行有关命令了,(如果控制台主机不可以,可以将其改为windows决定)
下面我介绍两个控制台窗口执行命令,可以用C语言函数的system来实现。
1.改变控制台窗口大小(mode命令)
- #include<stdio.h>
- #include<windows.h>
- int main()
- {
- system("mode con cols=50 lines=20");//控制台列改为50列,行就改为20行
- return 0;
- }
可以发现控制台行为20行,列为50行,但看起来却像个正方形,这是为什么呢?其实是因为控制台窗口行和列的比例并不是1:1的。
其坐标位置如下
2.改变控制台的窗口名字(title命令)
- #include<stdio.h>
- #include<windows.h>
- int main()
- {
- system("title 贪吃蛇");
- return 0;
- }
COORD是Windows API中定义的一个结构体,表示一个字符在控制台屏幕缓冲区上得坐标,坐标系(0,0)的原点位于缓冲区的顶部左侧单元格。
其中COORD的类型的声明为:
typedef struct _COORD
{
short x;
short y;
};
给坐标赋值为:
COORD pos={ 10, 15 };
GetStdHandle 是一个Windows API函数。它用于从一个特定的标准设备(标准输入、标准输出或标准错误)中取得一个句柄(用来标识不同设备的数值),使用这个句柄可以操作设备。
HANDLE GetStdHandle(DWORD nStdHandle);
- HANDLE hOutput = NULL;
- //获取标准输出的句柄(⽤来标识不同设备的数值)
- hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
其函数原型为:
BOOL WINAPI GetConsoleCursorInfo(
_In_ HANDLE hConsoleOutput,
_Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);
这个结构体包含有关控制台光标的信息
typedef struct _ CONSOLE_CURSOR_INFO {DWORD dwSize;BOOL bVisible;} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
其中dwSize为由光标填充的字符单元格的百分比。此值介于1到100之间。光标外观会变化,范围从完全填充单元格但单元底部的水平线条。
这里的黑色长方型为光标。
那么其占完全填充单元格的百分之多少呢?这里我们就可以通过一个代码来演示
- #include<stdio.h>
- #include<windows.h>
- int main()
- {
- HANDLE houtput = NULL;//返回void*的指针
- houtput = GetStdHandle(STD_OUTPUT_HANDLE);
-
- //定义一个光标信息的结构体
- CONSOLE_CURSOR_INFO cursor_info = { 0 };
- //获取与houtput句柄相关的控制台上的光标信息,并存放在cursor_info中
- GetConsoleCursorInfo(houtput, &cursor_info);
- printf("%d", cursor_info.dwSize);
- return 0;
- }
可以观察到其占完全填充光标的25%。
完全填充光标:
那如果我们想要将光标信息隐藏该怎么办呢?
bVisible表示游标的可见性。如果光标可见,则此成员为true.
- #include<stdio.h>
- #include<windows.h>
- #include<stdbool.h>
- int main()
- {
- HANDLE houtput = NULL;//返回void*的指针
- houtput = GetStdHandle(STD_OUTPUT_HANDLE);
-
- //定义一个光标信息的结构体
- CONSOLE_CURSOR_INFO cursor_info = { 0 };
- //获取与houtput句柄相关的控制台上的光标信息,并存放在cursor_info中
- GetConsoleCursorInfo(houtput, &cursor_info);
- cursor_info.bVisible = false;//隐藏光标
- return 0;
- }
但这样并不能隐藏光标信息,还需要借助一个函数SetConsoleCursorInfo来设置控制台屏幕缓冲区的光标大小和可见性。
其函数原型为:
BOOL WINAPI SetConsoleCursorInfo (HANDLE hConsoleOutput,const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo);
- #include<stdio.h>
- #include<windows.h>
- #include<stdbool.h>
- int main()
- {
- HANDLE houtput = NULL;//返回void*的指针
- houtput = GetStdHandle(STD_OUTPUT_HANDLE);
-
- //定义一个光标信息的结构体
- CONSOLE_CURSOR_INFO cursor_info = { 0 };
- //获取与houtput句柄相关的控制台上的光标信息,并存放在cursor_info中
- GetConsoleCursorInfo(houtput, &cursor_info);
- cursor_info.bVisible = false;//隐藏光标
- SetConsoleCursorInfo(houtput, &cursor_info);
- return 0;
- }
作用:设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的pos中,调用SetConsolePostion函数将光标位置设定到指定的位置。
函数原型:
BOOL WINAPI SetConsoleCursorPosition (HANDLE hConsoleOutput,COORD pos);
这里我们就用Set_Pos分装一个设置光标的函数
- void Set_Pos(short x,short y)
- {
- //获取标准输出设备的句柄
- HANDLE houtput = NULL;
- houtput=GetStdHandle(STD_OUTPUT_HANDLE);
- //定位光标的位置
- COORD pos = { x,y };
- SetConsoleCursorPosition(houtput, pos);
- }
获取按键情况,GetAsynKeyState的函数原型如下:
SHORT GetAsyncKeyState (int vKey);
将键盘上的每一个键的虚拟键值传递给函数,函数通过返回值来分辨键值的状态。
GetAsyncKeyState的返回值是short类型,在上一次调用GetAsyncKeyState函数后,如果返回的16为的short数据中,最高位是1,说明按键的状态时按下,如果最高位是0,说明按键的转台是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。
这里为了方便判断按键是否被按过,我们可以定义一个宏,来判断GetAsynKeyState返回值最低为是否为1.
#define KEY_PRESS(VK) (( GetAsyncKeyState(VK) & 0x1 )? 1 : 0)
参考:虚拟键码 (Winuser.h) - Win32 apps
这里虚拟键码就可以参照上面的链接。
讲完了上面的有关知识我们就可以开始实现贪吃蛇了
QQ202453-133347
这里为了实现游戏地图的打印,我们就需要讲解一下控制台有关知识,控制台窗口的坐标如下所示,横向的是x轴,纵向的是y轴,从上到下依次增长。
在游戏地图上,我们打印墙体使用的是宽字符:■,打印蛇使用宽字符●,打印食物使用的宽字符是★
那什么是宽字符呢?
普通字符是占一个字节的,宽字符是占两个字节的。
过去C语言并不适用于非英语国家使用,C语言最初假定字符都是单字节的。但是这些假定并不是在世界的任何地方都适用。后来为了适应C语言国际化·,C语言的标准不断加入了国际化的支持。比如:加入宽字符的类型wchar_t和宽字符的输入和输出函数。加入了<locale.h>头文件,提供了允许程序员针对特定地区调整程序行为的函数。
函数原型:char*setlocale(int category,const char*locale);
setlocale函数用于修改当前地区,可以针对一个类项,也可以所有类项,如果第一个参数是LC_ALL,就是影响所有的类项。
C标准给出了第二个参数定义了两种可能取值:“C”(正常模式)和“ ”(本地模式)。
从任意程序开始,都会隐藏执行调用:
setlocale(LC_ALL,"C");
如果想切换到本地模式就支持宽字符(汉字)的输出:
setlocale(LC_ALL," ");
宽字符的字面量必须加上前缀“L”,否则C语言会把字面量当做窄字符类型处理,前缀“L”在单引号面前,表示宽字符,对应wprintf()的占位付为%lc;在双引号面前,表示宽字符串,对应占位付就为%ls.
- #include <stdio.h>
- #include<locale.h>
- int main() {
- setlocale(LC_ALL, "");
- wchar_t ch = L'●';
-
- printf("%c%c\n", 'a', 'b');
-
- wprintf(L"%lc\n", ch);
- return 0;
- }
注:这个宽字符的实现要在Windows控制台主机上实现。
这里我们就实现棋盘27行,58列的棋盘,在围绕地图画出墙
这里我们蛇身的初始长度为5,在固定的一个坐标处开始,比如我们在(24,5)处开始打印,连续5个节点。
注:蛇的每个节点的x坐标必须是2个倍数,否则可能会出现蛇的⼀个节点有一半出现在墙体。
关于食物,就是在墙体内随机生成一个坐标(x的坐标必须是2的倍数),坐标不能和蛇的身体重合,然后打印★。
下面我们开始实现贪吃蛇(代码内含注释)
- #define _CRT_SECURE_NO_WARNINGS 1
-
- #define KEY_PRESS(VK) (( GetAsyncKeyState(VK) & 0x1 )? 1 : 0)
- #define POS_X 24
- #define POS_Y 5
- #define WALL L'■'
- #define BODY L'●'
- #define FOOD L'★'
- #include<stdio.h>
- #include<stdlib.h>
- #include<stdbool.h>
- #include<windows.h>
- #include<locale.h>
- #include<time.h>
- #include<conio.h>
-
- int choice;//选择穿墙还是不穿墙
-
- //蛇的方向
- enum DIRECTION
- {
- UP = 1,
- DOWN,
- LEFT,
- RIGHT
- };
-
- //蛇的状态
- //正常、撞墙、撞到自己、正常退出
- enum GAME_STATUS
- {
- OK,
- KILL_BY_WALL,
- KILL_BY_SELF,
- END_NORMAL
- };
-
- typedef struct SnakeNode
- {
- //坐标
- int x;
- int y;
- //指向下一个节点的指针
- struct SnakeNode* next;
- }SnakeNode, *pSnakeNode;
-
- typedef struct Snake
- {
- pSnakeNode _pSnake;//指向蛇头的指针
- pSnakeNode _pFood;//指向食物节点的指针
- enum DIRECTION _dir;//蛇的方向
- enum GAME_STATUS _status;//游戏的状态
- int _food_weight;//一个食物的分数
- int _score;//总分数
- int _sleep_time;//休息时间,时间越短,速度越快
- }Snake,*pSnake;
-
- //设置颜色
- void color(int c); //(每次置为其他颜色时都要将其再置为白色,方便设置其他颜色,(也可以根据自己需求设置))
-
- //定义光标
- void Set_Pos(short x, short y);
-
- //游戏初始化
-
- void GameStart(pSnake ps);
-
- //欢迎界面的打印
- void WelcomeToGame();
-
- //创建地图
- void CreateMap();
-
- //初始化蛇身
- void InitSnake(pSnake ps);
-
- //创建食物
- void CreateFood(pSnake ps);
-
- //游戏运行的逻辑
- void GameRun(pSnake ps);
-
- //蛇的移动-走一步
- void SnakeMove(pSnake ps);
- //判断下一个坐标是否为食物
- int NextIsFood(pSnakeNode pNextNode, pSnake ps);
- //吃掉食物
- void EatFood(pSnakeNode pNextNode, pSnake ps);
- //不是食物
- void NoFood(pSnakeNode pNextNode, pSnake ps);
- //蛇是否撞墙
- bool KillByWall(pSnake ps);
- //蛇撞墙不会死
- void WallSnakeMove(pSnake ps);
- //穿墙
- int NoKillByWall(pSnake ps, pSnakeNode pn);
- //蛇是否撞到自己
- bool KillBySelf(pSnake ps);
- //游戏结束
- void GameEnd(pSnake ps);
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"snake.h"
-
- void color(int c)
- {
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //颜色设置
- //注:SetConsoleTextAttribute是一个API(应用程序编程接口)
- }
-
- void Set_Pos(short x,short y)
- {
- //获取标准输出设备的句柄
- HANDLE houtput = NULL;
- houtput=GetStdHandle(STD_OUTPUT_HANDLE);
- //定位光标的位置
- COORD pos = { x,y };
- SetConsoleCursorPosition(houtput, pos);
- }
-
- void WelcomeToGame()
- {
- Set_Pos(38, 14);
- wprintf(L"欢迎来到贪吃蛇小游戏\n");
- Set_Pos(42, 20);
- system("pause");
- system("cls");
- Set_Pos(25, 14);
- wprintf(L"用↑,↓,←,→来控制蛇的移动,按F3加速,F4减速\n");
- Set_Pos(25,15);
- wprintf(L"加速能够得到更高的分数\n");
- Set_Pos(42, 20);
- system("pause");
- system("cls");
- }
-
- void CreateMap()
- {
- color(3);
- //UP
- for (int i = 1; i <= 29; i++)
- {
- wprintf(L"%lc",WALL);
- }
- //DOWN
- Set_Pos(0, 26);
- for (int i = 1; i <= 29; i++)
- {
- wprintf(L"%lc", WALL);
- }
- //LEFT
- for (int i = 1; i < 26; i++)
- {
- Set_Pos(0, i);
- wprintf(L"%lc", WALL);
- }
- //RIGHT
- for (int i = 1; i < 26; i++)
- {
- Set_Pos(56, i);
- wprintf(L"%lc", WALL);
- }
- color(7);
- }
-
- void InitSnake(pSnake ps)
- {
- pSnakeNode cur=NULL;
- for (int i = 0; i < 5; i++)
- {
-
- cur = (pSnakeNode)malloc(sizeof(SnakeNode));
- if (cur == NULL)
- {
- perror("InitSnake()::malloc()");
- return;
- }
- cur->next = NULL;
- cur->x = POS_X + 2 * i;
- cur->y = POS_Y;
-
- //头插
- if (ps->_pSnake == NULL)
- {
- ps->_pSnake = cur;
- }
- else
- {
- cur->next = ps->_pSnake;
- ps->_pSnake = cur;
- }
- }
- cur = ps->_pSnake;
- while (cur)
- {
- Set_Pos(cur->x, cur->y);
- wprintf(L"%lc",BODY);
- cur = cur->next;
- }
- //设置贪吃蛇的属性
- ps->_dir = RIGHT;//默认向右走
- ps->_score = 0;
- ps->_food_weight = 10;
- ps->_sleep_time = 200;
- ps->_status = OK;
- }
-
- void CreateFood(pSnake ps)
- {
- int x = 0;
- int y = 0;
- again:
- do
- {
- x = rand() % 53 + 2;
- y = rand() % 25 + 1;
- } while (x % 2 != 0);
- //x和y的坐标不能和蛇的身体坐标冲突
- pSnakeNode cur = ps->_pSnake;
- while (cur)
- {
- if (x == cur->x && cur->y == y)
- {
- goto again;
- }
- cur = cur->next;
- }
-
- //创建食物的节点
- pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
- if (pFood == NULL)
- {
- perror("CreateFood()::malloc()");
- return;
- }
- pFood->x = x;
- pFood->y = y;
- pFood->next = NULL;
-
- Set_Pos(x, y);
- color(12); //颜色设置为红色
- wprintf(L"%lc", FOOD);
- color(7); //颜色设置为白色
- ps->_pFood = pFood;
- }
-
-
- void GameStart(pSnake ps)
- {
- //0.设置窗口大小,光标隐藏
- ps->_pSnake = NULL;
- system("mode con cols=100 lines=30");
- system("title 贪吃蛇");
- HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_CURSOR_INFO CursorInfo = { 0 };
- GetConsoleCursorInfo(houtput, &CursorInfo);
- CursorInfo.bVisible = false;
- SetConsoleCursorInfo(houtput, &CursorInfo);
-
- //1.打印欢迎界面
- WelcomeToGame();
-
- //2.绘制地图
- CreateMap();
-
- //3.创建蛇
- InitSnake(ps);
-
- //4.创建食物
- CreateFood(ps);
- //5.设置游戏的相关信息
- }
-
- void PrintHelpInfo()
- {
- color(6);
- Set_Pos(64, 10);
- wprintf(L"%ls", L"不能穿墙,不能咬到自己\n");
- Set_Pos(64, 11);
- wprintf(L"%ls", L"用↑,↓,←,→来控制蛇的移动\n");
- Set_Pos(64, 12);
- wprintf(L"%ls", L"按F3加速,F4减速\n");
- Set_Pos(64, 13);
- wprintf(L"%ls", L"按ESC退出游戏,按空格暂停游戏\n");
-
- Set_Pos(64, 15);
- wprintf(L"%ls", L"贪吃蛇小游戏");
- color(7);
- }
-
- void Pause()
- {
- while (1)
- {
- Sleep(200);
- if (KEY_PRESS(VK_SPACE))
- break;
- }
- }
-
- int NextIsFood(pSnakeNode pNextNode, pSnake ps)
- {
- return (ps->_pFood->x == pNextNode->x && ps->_pFood->y == pNextNode->y);
- }
-
- void EatFood(pSnakeNode pNextNode, pSnake ps)
- {
- //头插
- ps->_pFood->next = ps->_pSnake;
- ps->_pSnake = ps->_pFood;
-
- //释放旧的节点
- free(pNextNode);
- pNextNode = NULL;
-
- pSnakeNode cur = ps->_pSnake;
- //将头置为红色
- color(12); //颜色设置为红色
- Set_Pos(cur->x, cur->y);
- wprintf(L"%lc", BODY);
- cur = cur->next;
- color(7); //颜色设置为白色
- while (cur)
- {
- Set_Pos(cur->x, cur->y);
- wprintf(L"%lc", BODY);
- cur = cur->next;
- }
- ps->_score += ps->_food_weight;
- Set_Pos(76, 8);//定位光标到分数旁边
- printf("+%2d", ps->_food_weight);
- Sleep(100);
- Set_Pos(76, 8);
- printf(" ");
- //重新创建食物
- CreateFood(ps);
- }
-
- bool KillByWall(pSnake ps)
- {
- if (ps->_pSnake->x == 0 || ps->_pSnake->x == 56
- || ps->_pSnake->y == 0 || ps->_pSnake->y == 26)
- {
- ps->_status = KILL_BY_WALL;
- return false;
- }
- return true;
- }
-
-
- bool KillBySelf(pSnake ps)
- {
- pSnakeNode cur = ps->_pSnake->next;
- while (cur)
- {
- if (cur->x == ps->_pSnake->x && cur->y == ps->_pSnake->y)
- {
- ps->_status = KILL_BY_SELF;
- return false;
- }
- cur = cur->next;
- }
- return true;
- }
-
- void NoFood(pSnakeNode pNextNode, pSnake ps)
- {
- //头插
- pNextNode->next = ps->_pSnake;
- ps->_pSnake = pNextNode;
- //撞墙
- if (!KillByWall(ps))
- {
- return;
- }
- //撞到自己
- if (!KillBySelf(ps))
- {
- return;
- }
- pSnakeNode cur = ps->_pSnake;
- //将头置为红色
- color(12); //颜色设置为红色
- Set_Pos(cur->x, cur->y);
- wprintf(L"%lc", BODY);
- cur = cur->next;
- color(7); //颜色设置为白色(每次置为其他颜色时都要将其再置为白色,以便下一次置色)
- while (cur->next->next != NULL)
- {
- Set_Pos(cur->x, cur->y);
- wprintf(L"%lc", BODY);
- cur = cur->next;
- }
- //把最后一个节点打印空格
- Set_Pos(cur->next->x, cur->next->y);
- printf(" ");//要两个空格
- //释放最后一个节点
- free(cur->next);
- //把倒数第二个节点的next置为空
- cur->next = NULL;
- }
-
- void SnakeMove(pSnake ps)
- {
- pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
- if (pNextNode == NULL)
- {
- perror("SnakeMove()::malloc()");
- return;
- }
- switch (ps->_dir)
- {
- case UP:
- pNextNode->x = ps->_pSnake->x;
- pNextNode->y = ps->_pSnake->y - 1;
- break;
- case DOWN:
- pNextNode->x = ps->_pSnake->x;
- pNextNode->y = ps->_pSnake->y + 1;
- break;
- case LEFT:
- pNextNode->x = ps->_pSnake->x - 2;
- pNextNode->y = ps->_pSnake->y;
- break;
- case RIGHT:
- pNextNode->x = ps->_pSnake->x + 2;
- pNextNode->y = ps->_pSnake->y;
- break;
- }
- //检测下一个坐标是否为食物
- if (NextIsFood(pNextNode, ps))
- {
- EatFood(pNextNode, ps);
- }
- else
- {
- NoFood(pNextNode, ps);
- }
- //撞墙
- KillByWall(ps);
- //撞到自己
- KillBySelf(ps);
- }
-
- int NoKillByWall(pSnake ps, pSnakeNode pn)
- {
- pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
- if (pNextNode == NULL)
- {
- perror("SnakeMove()::malloc()");
- exit(1);
- }
- if (pn->x == 0)
- {
- //将头节点穿墙
- pNextNode->x = 54;
- pNextNode->y = ps->_pSnake->y;
- pNextNode->next = NULL;
- //判断下一个节点是否为食物
- if (NextIsFood(pNextNode, ps))
- {
- EatFood(pNextNode, ps);
- }
- else
- {
- NoFood(pNextNode, ps);
- }
- free(pn);
- return 0;
- }
- else if (pn->x == 56)
- {
- //将头节点穿墙
- pNextNode->x = 2;
- pNextNode->y = ps->_pSnake->y;
- pNextNode->next = NULL;
- //判断下一个节点是否为食物
- if (NextIsFood(pNextNode, ps))
- {
- EatFood(pNextNode, ps);
- }
- else
- {
- NoFood(pNextNode, ps);
- }
- free(pn);
- pn = NULL;
- return 0;
- }
- else if (pn->y == 0)
- {
- //将头节点穿墙
- pNextNode->y = 25;
- pNextNode->x = ps->_pSnake->x;
- pNextNode->next = NULL;
- //判断下一个节点是否为食物
- if (NextIsFood(pNextNode, ps))
- {
- EatFood(pNextNode, ps);
- }
- else
- {
- NoFood(pNextNode, ps);
- }
- free(pn);
- pn = NULL;
- return 0;
- }
- else if (pn->y == 26)
- {
- //将头节点穿墙
- pNextNode->y = 1;
- pNextNode->x = ps->_pSnake->x;
- pNextNode->next = NULL;
- //判断下一个节点是否为食物
- if (NextIsFood(pNextNode, ps))
- {
- EatFood(pNextNode, ps);
- }
- else
- {
- NoFood(pNextNode, ps);
- }
- free(pn);
- pn = NULL;
- return 0;
- }
- return 1;
- }
-
- void WallSnakeMove(pSnake ps)
- {
- pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
- if (pNextNode == NULL)
- {
- perror("SnakeMove()::malloc()");
- return;
- }
- switch (ps->_dir)
- {
- case UP:
- pNextNode->x = ps->_pSnake->x;
- pNextNode->y = ps->_pSnake->y - 1;
- break;
- case DOWN:
- pNextNode->x = ps->_pSnake->x;
- pNextNode->y = ps->_pSnake->y + 1;
- break;
- case LEFT:
- pNextNode->x = ps->_pSnake->x - 2;
- pNextNode->y = ps->_pSnake->y;
- break;
- case RIGHT:
- pNextNode->x = ps->_pSnake->x + 2;
- pNextNode->y = ps->_pSnake->y;
- break;
- }
-
- if (NoKillByWall(ps, pNextNode))
- {
- if (NextIsFood(pNextNode, ps))
- {
- EatFood(pNextNode, ps);
- }
- else
- {
- NoFood(pNextNode, ps);
- }
- }
- //检测下一个坐标是否为食物
- //撞到自己
- KillBySelf(ps);
- }
-
- void GameRun(pSnake ps)
- {
- PrintHelpInfo();
- do
- {
- color(6);
- //打印总分数和食物的分值
- Set_Pos(64, 8);
- printf("总分数:%d\n", ps->_score);
- Set_Pos(64, 9);
- printf("当前食物的分数:%2d\n", ps->_food_weight);
- color(7);
-
- if (KEY_PRESS(VK_UP) && ps->_dir != DOWN)
- {
- ps->_dir = UP;
- }
- else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP)
- {
- ps->_dir = DOWN;
- }
- else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
- {
- ps->_dir = LEFT;
- }
- else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT)
- {
- ps->_dir = RIGHT;
- }
- else if (KEY_PRESS(VK_SPACE))
- {
- Pause();
- }
- else if (KEY_PRESS(VK_ESCAPE))
- {
- //正常退出游戏
- ps->_status = END_NORMAL;
- //退出
- }
- else if (KEY_PRESS(VK_F3))
- {
- //加速
- if (ps->_sleep_time > 80)
- {
- ps->_sleep_time -= 30;
- ps->_food_weight += 2;
- }
- }
- else if (KEY_PRESS(VK_F4))
- {
- //减速
- if (ps->_food_weight >= 2)
- {
- ps->_sleep_time += 30;
- ps->_food_weight -= 2;
- }
- }
- if (choice == '1')
- {
- WallSnakeMove(ps);//蛇可以穿墙
- }
- else
- {
- SnakeMove(ps);//蛇走一步的过程
- }
- Sleep(ps->_sleep_time);
- } while (ps->_status == OK);
- }
-
- void GameEnd(pSnake ps)
- {
- Set_Pos(24, 12);
- color(6);
- switch (ps->_status)
- {
- case END_NORMAL:
- printf("你主动结束游戏\n");
- break;
- case KILL_BY_WALL:
- printf("你寄了\n");
- break;
- case KILL_BY_SELF:
- printf("一不小心撞到自己了\n");
- break;
- }
- color(7);
- pSnakeNode cur = ps->_pSnake;
- while (cur)
- {
- pSnakeNode del = cur;
- cur = cur->next;
- free(del);
- }
- }
- #define _CRT_SECURE_NO_WARNINGS 1
-
- #include"snake.h"
- #include<locale.h>
-
-
- void test()
- {
- int ch = 0;
- do
- {
- color(6); //颜色设置为土黄色
- system("cls");
- //创建贪吃蛇
- Snake snake = { 0 };
- //初始化游戏
- //1.打印欢迎界面
- //2.功能介绍
- //3.绘制地图
- //4.创建蛇
- //5.创建食物
- //6.设置游戏的相关信息
-
- Set_Pos(38, 15);
- printf("1.穿墙");
- Set_Pos(38, 16);
- printf("2.不穿墙");
- Set_Pos(38, 18);
- printf("请选择模式:>");
- choice = getchar();
- while (getchar() != '\n');
- system("cls");
- GameStart(&snake);
- //运行游戏
- GameRun(&snake);
- //结束游戏
- GameEnd(&snake);
- while (_kbhit())
- {
- // 使用 _getch() 获取按下的键,不阻塞程序
- _getch();
- // 处理按键事件,可以根据需要进行相应的操作
- }
- Set_Pos(20, 15);
- color(6);
- printf("再来一句不老铁?>(Y/N):");
- ch = getchar();
- color(7);
- while (getchar() != '\n');
-
- } while (ch=='Y'||ch=='y');
- Set_Pos(0, 27);
- }
-
- int main()
- {
- setlocale(LC_ALL, "");
- srand((unsigned int)time(NULL));
- test();
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。