1.确定游戏大体内容
我设置的贪吃蛇小游戏基本规则:
用↑,↓,←,→来控制蛇的移动,f3加速(能量>=3),f4减速,不能撞墙,不能咬到自己,能量大于等于3即可加速;
空格暂停游戏,再按空格继续游戏,Esc键正常退出游戏;
一共有两种食物,蛇吃到一种食物就蛇身就增加一个节点,更新分数能量。
记录获得分数,能量多少。
2.游戏初始化界面
1.设置窗口大小:我设置的窗口行数30,列数100:
system("mode con cols=100 lines=30");
2.设置更改窗口名:
system("title 贪吃蛇");
3:初始化界面前,我先进行了隐藏控制台的光标(不然一直闪影响体验);
然后弄一个将控制台光标弄到指定位置的函数,方便打印(可以将光标跳到控制台任意位置),
然后再弄一个宽字符的打印(蛇身,墙体等)(普通字符占一个字节,而有些字符占两个字节)(所以需要)
用到的头文件及一些定义:
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<stdbool.h>
#include<locale.h>
#include<time.h>
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&1)==1?1:0)
#define POS_X 24 //初始位置
#define POS_Y 5
#define WALL L'□' //墙
#define BODY L'●' //蛇的身体
#define FOOD L'★' // 蛇的食物1
#define FOOD2 L'$' //蛇的食物2
3.1:隐藏控制台光标:
HANDLE houtput=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标
CursorInfo.bVisible = false;
SetConsoleCursorInfo(houtput, &CursorInfo);
3.2:将控制台光标弄到指定位置的函数:
void set_pos(short x, short y) {
HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE); //获取标准输出色被的句柄
COORD pos = { x,y }; //定位光标位置
SetConsoleCursorPosition(houtput, pos);
}
3.3宽字符的打印
需要在开头有:
setlocale(LC_ALL, ""); //切换到本地环境
然后就可以直接使用wprintf打印宽字符了;egg: wprintf(L"lc",●);别忘了加L;
4.初始化界面:
欢迎界面函数:system("cls")用来清理屏幕;system("pause")可以定格,按任意键继续。
WelcomeToGame() {
set_pos(40, 17); wprintf(L"欢迎来到贪吃蛇小游戏");
set_pos(42, 20); system("pause");
system("cls");
set_pos(40, 17); wprintf(L"用↑,↓,←,→来控制蛇的移动,f3加速,f4减速");
set_pos(40, 18); wprintf(L"加速能更快的得到分数");
set_pos(42, 20); system("pause");
system("cls");
}
5.打印地图
打印蛇能活动的范围地图;这里我打印了58*26的大小;一个蛇的节点宽2字节 高1字节;我在开头定义了 #define WALL L'□'
#define WALL L'□' //墙
void CreatMap() {
int i;
//up
set_pos(0, 1); for (i = 0; i < 58; i++)wprintf(L"%lc",WALL);
//down
set_pos(0, 26); for (i = 0; i < 58; i++)wprintf(L"%lc",WALL);
//left
for (i = 1; i <= 26; i++) { set_pos(0, i); wprintf(L"%lc",WALL); }
//right
for (i = 1; i <= 26; i++) { set_pos(58, i); wprintf(L"%lc",WALL); }
}
6.创建并初始化我们的蛇
#define WALL L'□' //墙
#define BODY L'●' //蛇的身体
#define FOOD L'★' // 蛇的食物1
#define FOOD2 L'$' //蛇的食物2
enum DIRECTION {
UP = 1,
DOWN ,
LEFT ,
RIGHT
}; //枚举蛇的方向
enum GAME_STATUS{
OK,
KILL_BY_WALL,
KILL_BY_SELE,//正常,撞墙,撞到自己,正常退出//蛇的状态
END_NORMAL
}; //枚举蛇的状态(游戏状态)
typedef struct SnackNode {
int x; int y;
struct SnackNode* next;
}SnackNode,*pSnackNode; //蛇的单节点,节点位置,和下一节点地址
typedef struct Snack {
pSnackNode PSnack; //蛇头
pSnackNode fFood; //存放蛇食物1的节点
pSnackNode fFOOD2; //存放蛇食物2的节点
enum DIRECTION dir; //蛇的方向
enum GAME_STATUS status; //游戏状态
int energe; //蛇的neng能量
int sum; //吃掉的食物个数存储
int score; //总成绩
int sleep_time; //休息时间,小速度大,反比;蛇的速度
}Snack,*pSnack;
蛇的初始化函数:(在开头定义了 #define POS_X 24 #define POS_Y 5)(方便修改初始位置)
#define POS_X 24 //初始位置
#define POS_Y 5
void InitSnake(pSnack ps) {
int i = 0; pSnackNode cur = NULL;
for (i = 0; i < 5; i++) {
cur = (pSnackNode)malloc(sizeof(SnackNode));
if (cur == NULL) {
perror("InitSnack()::malloc()");
return;
}
cur->next = NULL;
cur->x = POS_X + i;
cur->y = POS_Y ; //头插法插入节点,默认初始蛇的节点有五个
if (ps->PSnack == NULL) {
ps->PSnack = cur;
}
else {
cur->next = ps->PSnack;
ps->PSnack = cur;
}
}
cur = ps->PSnack;
while (cur) {
set_pos(cur->x, cur->y);
wprintf(L"%lc",BODY);
cur = cur->next;
}
//设置贪吃蛇的属性
ps->dir = RIGHT; //默认初始方向向右
ps->sum=0;
ps->energe = 6;
ps->score = 0;
ps->status = OK;
ps->sleep_time = 200;
}
7.蛇的移动函数实现(逐帧)
int NextIsFood(pSnackNode pn,pSnack ps) {
if (pn->x == ps->fFood->x && pn->y == ps->fFood->y)return 1;
if (pn->x == ps->fFOOD2->x && pn->y == ps->fFOOD2->y)return 2;
return 0;
//判断下一步即将到达的节点是否是蛇存储的食物节点1或2的位置,还是无食物节点
}
///
void Food_Creat(pSnack ps) {
int x=0, y=0; //食物节点1的创建
again:
do {
x = rand() % 53 + 2;
y = rand() % 24 + 2;
} while (x % 2 != 0 ); //蛇的宽度为2;位置x轴必须偶数
pSnackNode cur; cur = ps->PSnack; //判断食物节点是否与蛇重合;且蛇食物2节点存在,生成
//食物节点一不能与之重合
while (cur) {
if (ps->fFOOD2 == NULL) { if (cur->x ==x && cur->y == y) goto again; }
else {
if((cur->x == x && cur->y == y) || (cur->next == ps->fFOOD2->x && cur->y == ps->fFOOD2->y))goto again;
}cur = cur->next;
}
pSnackNode Food_snack = (pSnackNode)malloc(sizeof(SnackNode)); //创建食物1节点
if (Food_snack == NULL) {
perror("Food_Creat()::malloc()");
}
Food_snack->x = x;
Food_snack->y = y; // 赋予蛇的蛇的食物1新节点位置
set_pos(x, y);
wprintf(L"%Lc", FOOD); //并打印食物
ps->fFood = Food_snack; //更新蛇的食物节点
}
///
void Food_creat2(pSnack ps) { //食物节点2的创建
int x1=0, y1=0;
once:
do {
x1 = rand() % 53 + 2;
y1 = rand() % 24 + 2; //上同食物一的创建,创建食物二的时候食物一一定存在
} while (x1 % 2 ==1);
pSnackNode cur2; cur2 = ps->PSnack;
while (cur2) {
if ((cur2->x == x1 && cur2->y == y1) || (cur2->x == ps->fFood->x && cur2->y == ps->fFood->y))goto once;
cur2 = cur2->next;
}
pSnackNode foo = (pSnackNode)malloc(sizeof(SnackNode));
if (foo == NULL) {
perror("Food_creat2::malloc()");
}
foo->x = x1; foo->y = y1;
set_pos(x1, y1);
wprintf(L"%Lc", FOOD2);
ps->fFOOD2 = foo;
}
//
void EatFood(pSnackNode pn, pSnack ps) { //吃掉食物1
ps->fFood->next = ps->PSnack;
ps->PSnack = ps->fFood; //下一个节点是蛇存储的食物1节点位置
free(pn); //头插法插入节点,释放多余的pn所指向,(两个要删除一个)
Food_Creat(ps); //食物1被吃掉, 重新创建蛇的食物新节点
pn = NULL;
pSnackNode cur;
cur = ps->PSnack;
while (cur) {
set_pos(cur->x, cur->y); //打印蛇
wprintf(L"%Lc", BODY);
cur = cur->next;
}
ps->score += 5; ps->sum++; ps->energe++; //更新蛇的分数,能量,食食物个数
}
///
void EatFood2(pSnackNode pn, pSnack ps) {
ps->fFOOD2->next = ps->PSnack; //吃掉食物2,上同
ps->PSnack=ps->fFOOD2;
free(pn);
Food_creat2(ps);
pn = NULL;
pSnackNode cur= ps->PSnack;
while (cur) {
set_pos(cur->x, cur->y);
wprintf(L"%Lc", BODY);
cur = cur->next;
}
ps->score += 10; ps->sum++; ps->energe=ps->energe+2;
}
/
void NoFood(pSnackNode pn, pSnack ps) { //蛇即将到达的位置不是蛇的食物节点位置的移动
pn->next = ps->PSnack;
ps->PSnack = pn;
pSnackNode cur = ps->PSnack; //头插法插入即将到达的节点位置,将末尾节点释放掉
while (cur->next->next != NULL) { //并将原来倒数第二个节点的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);
cur->next = NULL;
set_pos(cur->x, cur->y); wprintf(L"%Lc", BODY);
}
void KillByWall(pSnack ps) {
if (ps->PSnack->x == 0 || ps->PSnack->x == 58 || ps->PSnack->y == 1 || ps->PSnack->y == 26) {
ps->status = KILL_BY_WALL; //判断蛇头是否撞墙
}
}
void KillBySelf(pSnack ps) {
pSnackNode cur = ps->PSnack->next; //判断蛇头是否撞到自己
while (cur) {
if (cur->x == ps->PSnack->x && cur->y == ps->PSnack->y) {
ps->status = KILL_BY_SELE;
}
cur = cur->next;
}
}
/
void SnackMove(pSnack ps) {
pSnackNode psnode = (pSnackNode)malloc(sizeof(SnackNode));
//蛇即将到的下一个节点的位置
if (psnode == NULL) {
perror("malloc()::malloc()");
return;
}
switch (ps->dir) { //格局蛇的方向和头节点判断下一个即将到的节点位置并存储起来
case UP:
psnode->x = ps->PSnack->x; psnode->y = ps->PSnack->y - 1;
break;
case DOWN:
psnode->x = ps->PSnack->x; psnode->y = ps->PSnack->y + 1;
break;
case LEFT:
psnode->x = ps->PSnack->x - 2; psnode->y = ps->PSnack->y;
break;
case RIGHT:
psnode->x = ps->PSnack->x + 2; psnode->y = ps->PSnack->y;
break;
}
if (NextIsFood(psnode,ps)==1) {
EatFood(psnode, ps); //判断即将到达的位置是否是食物一节点的位置
}
else if (NextIsFood(psnode, ps) == 2) {
EatFood2(psnode, ps); //判断即将到达的位置是否是食物2节点的位置
}
else {
NoFood(psnode, ps); //没有食物蛇的移动
}
KillByWall(ps); //判断蛇的状态 //检查蛇是否撞墙
KillBySelf(ps); //检查蛇是否撞到自己
}
8.蛇的移动运行,检测按键输入
需要的虚拟按键的罗列:
• 上:VK_UP
• 下:VK_DOWN
• 左:VK_LEFT
• 右:VK_RIGHT
• 空格:VK_SPACE
• ESC:VK_ESCAPE
• F3:VK_F3
如下:检测按键情况,if逐个判断,如果按下的按键与虚拟按键一致,就返回一,按键按下后改对应的状态;
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&1)==1?1:0)
//
void Pause() {
while (1) {
Sleep(200); //暂停,按下空格结束
if (KEY_PRESS(VK_SPACE)) {
break;
}
}
}
/
void Game_Run(pSnack ps) {
Print_Help(ps);
do {
PrintM(ps); set_pos(70, 6); printf(" ");
if ( KEY_PRESS(VK_RIGHT) && ps->dir != LEFT) {
ps->dir = RIGHT;
}
else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT) { //确定按下的是什么按键,改变蛇
//的方向
ps->dir = LEFT;
}
else 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_SPACE)) {
Pause(); //按下空格暂停
}
else if (KEY_PRESS(VK_ESCAPE) ){
ps->status = END_NORMAL; //正常退出
}
else if (KEY_PRESS(VK_F3) ) {
if (ps->energe >= 3 && ps->sleep_time>80) {
ps->sleep_time -= 30;
ps->energe -= 3;// 加速
set_pos(59, 5); u1++; printf("成功加速%d次",u1);
}
else {
set_pos(80, 5); fail_up++; printf("加速失败%d次", fail_up);
} 按下F3加速,减少蛇的sleep_time,每一次移动时暂停时间减少
}
else if (KEY_PRESS(VK_F4)) {
if (ps->sleep_time >= 300) { set_pos(70, 6); printf("无法在减速!速度已经超低了"); }
else {
ps->sleep_time += 30;
set_pos(59, 7); s1++; printf("成功减速%d次", s1); //减速
} 按下F4加速,增加蛇的sleep_time,每一次移动时暂停时间增加
}
if (ps->sleep_time <= 80) {
set_pos(70, 6); printf("已无法加速,速度已最高");
}
SnackMove(ps); //蛇的移动函数,上一步
Sleep(ps->sleep_time); //每一帧动画暂停多少秒
} while (ps->status ==OK);
}
9.一场游戏的结束函数
判断蛇的状态,确定结束原因并打印相关信息,删除释放蛇的节点
void GameEnd(pSnack ps) {pSnackNode cur=ps->PSnack;
switch (ps->status) {
case KILL_BY_SELE:
set_pos(24, 14); printf("你撞到了自己,游戏结束\n");
break;
case KILL_BY_WALL:
set_pos(24, 14); printf("你撞到了墙,游戏结束\n");
break;
case END_NORMAL:
set_pos(24, 14); printf("你已正常退出游戏成功\n");
break;
}
while (cur) {
pSnackNode del;
del = cur;
cur = cur->next;
free(del);
}
}
10.设置主体运行函数,框架
void test() {
int f = 1;
//创建贪吃蛇(链表)
do {
f = 1;
system("cls");
u1 = 0; s1 = 0; fail_up = 0; fail_low = 0;
Snack snack = { 0 };
//初始化游戏
GAMESTART(&snack);
Food_Creat(&snack);
Food_creat2(&snack);
//运行游戏
Game_Run(&snack);
//结束游戏
GameEnd(&snack);
set_pos(10,22); printf("再来一局吗?(按下空格再来一局,按下Esc退出游戏)");
while (1) {
Sleep(200);
if (KEY_PRESS(VK_SPACE))break;
if (KEY_PRESS(VK_ESCAPE)) {
f = 0; break;
}
}
} while (f);
set_pos(0, 28);
}
我的主函数的内容很少
int main() {
srand((unsigned)time(NULL));
setlocale(LC_ALL, "");
test();
return 0;
}
然后大体就结束了。
11.我的全部代码
我的全部代码,很乱,写成一团的。有两个文件分别是snack.h和snack.c
snack.h的文件内容:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<stdbool.h>
#include<locale.h>
#include<time.h>
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&1)==1?1:0)
#define POS_X 24 //初始位置
#define POS_Y 5
#define WALL L'□' //墙
#define BODY L'●' //蛇的身体
#define FOOD L'★' // 蛇的食物1
#define FOOD2 L'$' //蛇的食物2
//类型声明
int u1 = 0, s1 = 0, fail_up; int fail_low;
enum DIRECTION {
UP = 1,
DOWN ,
LEFT ,
RIGHT
};
enum GAME_STATUS{
OK,
KILL_BY_WALL,
KILL_BY_SELE,//正常,撞墙,撞到自己,正常退出//蛇的状态
END_NORMAL
};
typedef struct SnackNode {
int x; int y;
struct SnackNode* next; //蛇的坐标
}SnackNode,*pSnackNode;
typedef struct Snack {
pSnackNode PSnack;//蛇头
pSnackNode fFood;//食物
pSnackNode fFOOD2;
enum DIRECTION dir;//蛇的方向
enum GAME_STATUS status;//游戏状态
int energe;//neng能量
int sum;//吃掉了多少食物
int score; //总成绩
int sleep_time;//休息时间,小速度大,反比;
}Snack,*pSnack;
//函数声明
void set_pos(short x, short y) {
HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE); //获取标准输出色被的句柄
COORD pos = { x,y }; //定位光标位置
SetConsoleCursorPosition(houtput, pos);
}
WelcomeToGame() {
set_pos(40, 17); wprintf(L"欢迎来到贪吃蛇小游戏");
set_pos(42, 20); system("pause");
system("cls");
set_pos(40, 17); wprintf(L"用↑,↓,←,→来控制蛇的移动,f3加速,f4减速");
set_pos(40, 18); wprintf(L"加速能更快的得到分数");
set_pos(42, 20); system("pause");
system("cls");
}
void InitSnake(pSnack ps) {
int i = 0; pSnackNode cur = NULL;
for (i = 0; i < 5; i++) {
cur = (pSnackNode)malloc(sizeof(SnackNode));
if (cur == NULL) {
perror("InitSnack()::malloc()");
return;
}
cur->next = NULL;
cur->x = POS_X + i;
cur->y = POS_Y ;//头插法
if (ps->PSnack == NULL) {
ps->PSnack = cur;
}
else {
cur->next = ps->PSnack;
ps->PSnack = cur;
}
}
cur = ps->PSnack;
while (cur) {
set_pos(cur->x, cur->y);
wprintf(L"%lc",BODY);
cur = cur->next;
}
//设置贪吃蛇的属性
ps->dir = RIGHT;
ps->sum=0;
ps->energe = 6;
ps->score = 0;
ps->status = OK;
ps->sleep_time = 200;
}
void CreatMap() {
int i;
//up
set_pos(0, 1); for (i = 0; i < 58; i++)wprintf(L"%lc",WALL);
//down
set_pos(0, 26); for (i = 0; i < 58; i++)wprintf(L"%lc",WALL);
//left
for (i = 1; i <= 26; i++) { set_pos(0, i); wprintf(L"%lc",WALL); }
//right
for (i = 1; i <= 26; i++) { set_pos(58, i); wprintf(L"%lc",WALL); }
}
void Food_Creat(pSnack ps) {
int x=0, y=0;
again:
do {
x = rand() % 53 + 2;
y = rand() % 24 + 2;
} while (x % 2 != 0 );
//判断是否与蛇重合;
pSnackNode cur; cur = ps->PSnack;
while (cur) {
if (ps->fFOOD2 == NULL) { if (cur->x ==x && cur->y == y) goto again; }
else {
if((cur->x == x && cur->y == y) || (cur->next == ps->fFOOD2->x && cur->y == ps->fFOOD2->y))goto again;
}cur = cur->next;
}
//创建食物节点
pSnackNode Food_snack = (pSnackNode)malloc(sizeof(SnackNode));
if (Food_snack == NULL) {
perror("Food_Creat()::malloc()");
}
Food_snack->x = x;
Food_snack->y = y;
set_pos(x, y);
wprintf(L"%Lc", FOOD);
ps->fFood = Food_snack;
}
void Food_creat2(pSnack ps) {
int x1=0, y1=0;
once:
do {
x1 = rand() % 53 + 2;
y1 = rand() % 24 + 2;
} while (x1 % 2 ==1);
pSnackNode cur2; cur2 = ps->PSnack;
while (cur2) {
if ((cur2->x == x1 && cur2->y == y1) || (cur2->x == ps->fFood->x && cur2->y == ps->fFood->y))goto once;
cur2 = cur2->next;
}
pSnackNode foo = (pSnackNode)malloc(sizeof(SnackNode));
if (foo == NULL) {
perror("Food_creat2::malloc()");
}
foo->x = x1; foo->y = y1;
set_pos(x1, y1);
wprintf(L"%Lc", FOOD2);
ps->fFOOD2 = foo;
}
//1. //窗口大小,光标隐藏,打印环境界面,功能介绍,绘制地图,创建蛇,创建食物,设置游戏相关信息
void GAMESTART(pSnack ps){
system("mode con cols=100 lines=30");
system("title 贪吃蛇");
HANDLE houtput=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标
CursorInfo.bVisible = false;
SetConsoleCursorInfo(houtput, &CursorInfo);
WelcomeToGame();//●↑→●●界面
CreatMap(); //27.58 地图
InitSnake(ps);
}
void Print_Help(pSnack ps) {
set_pos(66, 2);
wprintf(L"你的分数:%d", ps->score);
set_pos(60, 10);
wprintf(L"%ls", L"不能撞墙,不能咬到自己");
set_pos(60, 11);
wprintf(L"%ls", L"用↑,↓,←,→来控制蛇的移动,f3加速,f4减速");
set_pos(60, 12);
wprintf(L"%ls", L"能量大于等于3即可加速");
set_pos(60, 14);
wprintf(L"%ls", L"Esc退出游戏,空格暂停游戏");
}
void PrintM(pSnack ps) {
set_pos(66,2 );
wprintf(L"你的分数:%d", ps->score);
set_pos(66, 3);
wprintf(L"已食食物个数:%d",ps->sum );
set_pos(66, 4);
if (ps->energe >= 10)wprintf(L"你的能量:%d", ps->energe); else {
wprintf(L"你的能量: %d", ps->energe);
}
}
void Pause() {
while (1) {
Sleep(200);
if (KEY_PRESS(VK_SPACE)) {
break;
}
}
}
int NextIsFood(pSnackNode pn,pSnack ps) {
if (pn->x == ps->fFood->x && pn->y == ps->fFood->y)return 1;
if (pn->x == ps->fFOOD2->x && pn->y == ps->fFOOD2->y)return 2;
return 0;
}
void EatFood(pSnackNode pn, pSnack ps) {
ps->fFood->next = ps->PSnack;
ps->PSnack = ps->fFood;
free(pn);
Food_Creat(ps);
pn = NULL;
pSnackNode cur;
cur = ps->PSnack;
while (cur) {
set_pos(cur->x, cur->y);
wprintf(L"%Lc", BODY);
cur = cur->next;
}
ps->score += 5; ps->sum++; ps->energe++;
}
void EatFood2(pSnackNode pn, pSnack ps) {
ps->fFOOD2->next = ps->PSnack;
ps->PSnack=ps->fFOOD2;
free(pn);
Food_creat2(ps);
pn = NULL;
pSnackNode cur= ps->PSnack;
while (cur) {
set_pos(cur->x, cur->y);
wprintf(L"%Lc", BODY);
cur = cur->next;
}
ps->score += 10; ps->sum++; ps->energe=ps->energe+2;
}
void NoFood(pSnackNode pn, pSnack ps) {
pn->next = ps->PSnack;
ps->PSnack = pn;
pSnackNode cur = ps->PSnack;
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);
cur->next = NULL;
set_pos(cur->x, cur->y); wprintf(L"%Lc", BODY);
}
void KillByWall(pSnack ps) {
if (ps->PSnack->x == 0 || ps->PSnack->x == 58 || ps->PSnack->y == 1 || ps->PSnack->y == 26) {
ps->status = KILL_BY_WALL;
}
}
void KillBySelf(pSnack ps) {
pSnackNode cur = ps->PSnack->next;
while (cur) {
if (cur->x == ps->PSnack->x && cur->y == ps->PSnack->y) {
ps->status = KILL_BY_SELE;
}
cur = cur->next;
}
}
void SnackMove(pSnack ps) {
pSnackNode psnode = (pSnackNode)malloc(sizeof(SnackNode)); //蛇即将到的下一个节点
if (psnode == NULL) {
perror("malloc()::malloc()");
return;
}
switch (ps->dir) {
case UP:
psnode->x = ps->PSnack->x; psnode->y = ps->PSnack->y - 1;
break;
case DOWN:
psnode->x = ps->PSnack->x; psnode->y = ps->PSnack->y + 1;
break;
case LEFT:
psnode->x = ps->PSnack->x - 2; psnode->y = ps->PSnack->y;
break;
case RIGHT:
psnode->x = ps->PSnack->x + 2; psnode->y = ps->PSnack->y;
break;
}
if (NextIsFood(psnode,ps)==1) {
EatFood(psnode, ps);
}
else if (NextIsFood(psnode, ps) == 2) {
EatFood2(psnode, ps);
}
else {
NoFood(psnode, ps);
}
KillByWall(ps);
KillBySelf(ps);
}
void GameEnd(pSnack ps) {pSnackNode cur=ps->PSnack;
switch (ps->status) {
case KILL_BY_SELE:
set_pos(24, 14); printf("你撞到了自己,游戏结束\n");
break;
case KILL_BY_WALL:
set_pos(24, 14); printf("你撞到了墙,游戏结束\n");
break;
case END_NORMAL:
set_pos(24, 14); printf("你已正常退出游戏成功\n");
break;
}
while (cur) {
pSnackNode del;
del = cur;
cur = cur->next;
free(del);
}
}
void Game_Run(pSnack ps) {
Print_Help(ps);
do {
PrintM(ps); set_pos(70, 6); printf(" ");
if ( KEY_PRESS(VK_RIGHT) && ps->dir != LEFT) {
ps->dir = RIGHT; //向右
}
else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT) {
ps->dir = LEFT; //向左
}
else 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_SPACE)) {
Pause(); //暂停
}
else if (KEY_PRESS(VK_ESCAPE) ){
ps->status = END_NORMAL; //正常退出
}
else if (KEY_PRESS(VK_F3) ) {
if (ps->energe >= 3 && ps->sleep_time>80) {
ps->sleep_time -= 30;
ps->energe -= 3;// 加速
set_pos(59, 5); u1++; printf("成功加速%d次",u1);
}
else {
set_pos(80, 5); fail_up++; printf("加速失败%d次", fail_up);
}
}
else if (KEY_PRESS(VK_F4)) {
if (ps->sleep_time >= 300) { set_pos(70, 6); printf("无法在减速!速度已经超低了"); }
else {
ps->sleep_time += 30;
set_pos(59, 7); s1++; printf("成功减速%d次", s1); //减速
}
}
if (ps->sleep_time <= 80) {
set_pos(70, 6); printf("已无法加速,速度已最高");
}
SnackMove(ps);//过程
Sleep(ps->sleep_time);
} while (ps->status ==OK);
}
//蛇的头、速度、方向。食物。食物分数、总分,蛇的状态
void test() {
int f = 1;
//创建贪吃蛇(链表)
do {
f = 1;
system("cls");
u1 = 0; s1 = 0; fail_up = 0; fail_low = 0;
Snack snack = { 0 };
//初始化游戏
GAMESTART(&snack);
Food_Creat(&snack);
Food_creat2(&snack);
//运行游戏
Game_Run(&snack);
//结束游戏
GameEnd(&snack);
set_pos(10,22); printf("再来一局吗?(按下空格再来一局,按下Esc退出游戏)");
while (1) {
Sleep(200);
if (KEY_PRESS(VK_SPACE))break;
if (KEY_PRESS(VK_ESCAPE)) {
f = 0; break;
}
}
} while (f);
set_pos(0, 28);
}
snack.c的内容:
#include"snake.h"
int main() {
srand((unsigned)time(NULL));
setlocale(LC_ALL, "");
test();
return 0;
}
到这里就结束了,感谢观看。