- 首先我们要考虑,在整个贪吃蛇的过程中,都需要定义什么变量;
- 比如:蛇身的组成,蛇所在的位置,我们假设蛇是一小块一小块连接起来的,所以有蛇吃到一个食物后,蛇会增长一小节,所以还需要链表;
- 蛇走的方向:”上下左右“
- 蛇的状态:”OK,撞墙,撞到自己,游戏结束“
- 整个游戏里面还需要的小部分:分数,休眠时间(控制蛇身的速度)等
#ifndef __SNACK_H__
#define __SNACK_H__
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
#include<time.h>
#define WALL "@"
#define FOOD "$"
#define INIT_X 20
#define INIT_Y 10
typedef struct SnackNode//组成蛇身
{
int x;
int y;
struct SnackNode* next;定义一个结构体指针,指向下一次个与当前节点数据类型相同的节点
}SnackNode,*pSnackNode;*pSnackNode等价于struct SnackNode*
enum Direction
{
UP,
DOWN,
LEFT,
RIGHT,
};
enum GameStatus
{
OK,
NORMAL_END,
KILL_BY_WALL,
KILL_BY_SELF,
};
typedef struct Snack
{
pSnackNode _psanck;//维护蛇身的指针
pSnackNode _pFood; //维护食物的指针
int _TotalScore; //总分数
int _AddScore; //增加的分数
int _SleepTime; //休眠时间
enum Direction _Dir;//方向
enum GameStatus _Status;
}Snack,*pSnack;
void GameStart(pSnack ps);
void WelcomeToGame();
void CreateMap();
void InitSnack(pSnack ps);
void CreateFood(pSnack ps);
void GameRun(pSnack ps);
void SnackMove(pSnack ps);
void SetPos(int x,int y);
pSnackNode BuyNode();
void Pause();
int NextHasFood(pSnackNode pn,pSnackNode pf);//下一个节点是否有食物
void EatFood(pSnack ps,pSnackNode pn);//吃到食物
void NoFood(pSnack ps,pSnackNode pn);//没有食物
void KillByWall(pSnack ps);//撞墙
void KillBySelf(pSnack ps);//撞到自己
void PrintHelpInfo();
void GameEnd(pSnack ps);
void CreateDiamond(pSnack ps);
#endif
- 游戏跑起来需要的一些函数
#include"snack.h"
void SetPos(int x,int y)//设置位置
{
COORD pos = {0};
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取光标
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle,pos);//设置标准输出上光标的位置
}
void WelcomeToGame()
{
system("mode con cols=100 lines=30"); //控制台窗口大小设置
SetPos(38,14);
printf("欢迎来到贪吃蛇小游戏!\n");
SetPos(38,28);
system("pause");//暂停
system("cls");//清空屏幕
SetPos(33,13);
printf("用↑,↓,←,→来控制蛇的移动,F1为加速,F2为减速!");
SetPos(33,15);
printf("加速可以使分数增多!");
SetPos(33,17);
printf("按空格键可以暂停游戏!\n");
SetPos(33,19);
printf("按Esc键可以退出游戏!\n");
SetPos(40,28);
system("pause");
system("cls");
}
void CreateMap()
{
int i = 0;
//上
for(i=0;i<=58;i+=2)
{
SetPos(i,0);
printf(WALL);
}
//下
for(i=0;i<=58;i+=2)
{
SetPos(i,27);
printf(WALL);
}
//左
for(i=1;i<=26;i++)
{
SetPos(0,i);
printf(WALL);
}
//右
for(i=1;i<=26;i++)
{
SetPos(58,i);
printf(WALL);
}
}
pSnackNode BuyNode()
{
pSnackNode pRet = (pSnackNode)malloc(sizeof(pSnackNode));
if(pRet == NULL)
{
perror("BuyNode::malloc()");
exit(EXIT_FAILURE);
}
pRet->x = 0;
pRet->y = 0;
pRet->next = NULL;
}
void InitSnack(pSnack ps)
{
pSnackNode first;
pSnackNode cur = NULL;
int i = 0;
first = BuyNode();
first->x = INIT_X;
first->y = INIT_Y;
for(i=0;i<4;i++)
{
cur = BuyNode();
cur->x = first->x+2;
cur->y = first->y;
cur->next = first;
first = cur;
}
//cur = first;
while(cur)
{
SetPos(cur->x,cur->y);
printf(FOOD);
cur = cur->next;
}
ps->_psanck = first;
printf("\n");
}
void CreateFood(pSnack ps)
{
pSnackNode pfood = BuyNode();
pSnackNode cur = ps->_psanck;
pfood->y = rand()%26+1;
do
{
pfood->x = rand()%55+2;
}while(pfood->x%2 != 0);
while(cur)
{
if(cur->x == pfood->x && cur->y == pfood->y)
{
CreateFood(ps);
return;
}
cur = cur->next;
}
ps->_pFood = pfood;
SetPos(pfood->x,pfood->y);
printf(FOOD);
}
void GameStart(pSnack ps)
{
//欢迎界面
WelcomeToGame();
//创建地图
CreateMap();
//初始化蛇
InitSnack(ps);
//初始化食物
CreateFood(ps);
//CreateDiamond(ps);
ps->_AddScore = 10;
ps->_TotalScore = 0;
ps->_Dir = RIGHT;
ps->_Status = OK;
ps->_SleepTime = 200;
}
void Pause()
{
while(1)
{
Sleep(100);
if(GetAsyncKeyState(VK_SPACE))
{
break;
}
}
}
int NextHasFood(pSnackNode pn,pSnackNode pf)
{
return ((pn->x==pf->x) && (pn->y==pf->y));
}
void EatFood(pSnack ps,pSnackNode pn)
{
pSnackNode cur = NULL;
pn->next = ps->_psanck;
ps->_psanck = pn;
ps->_TotalScore += ps->_AddScore;
cur = ps->_psanck;
while(cur)
{
SetPos(cur->x,cur->y);
printf(FOOD);
cur = cur->next;
}
CreateFood(ps);
}
void NoFood(pSnack ps,pSnackNode pn)
{
pSnackNode cur = NULL;
pn->next = ps->_psanck;
ps->_psanck = pn;
cur = ps->_psanck;
while(cur->next->next)
{
SetPos(cur->x,cur->y);
printf(FOOD);
cur = cur->next;
}
SetPos(cur->x,cur->y);
printf(FOOD);
SetPos(cur->next->x,cur->next->y);
printf(" ");
//free(cur->next);
cur->next = NULL;
}
void SnackMove(pSnack ps)
{
pSnackNode pNextNode = BuyNode();
SetPos(65,8);
printf("总分:%d",ps->_TotalScore);
SetPos(65,10);
printf("食物得分:%d ",ps->_AddScore);
switch(ps->_Dir)
{
case UP:
{
pNextNode->x = ps->_psanck->x;
pNextNode->y = ps->_psanck->y-1;
if(NextHasFood(pNextNode,ps->_pFood))
{
//下一个结点是食物
EatFood(ps,pNextNode);
}
else
{
NoFood(ps,pNextNode);
}
}
break;
case DOWN:
{
pNextNode->x = ps->_psanck->x;
pNextNode->y = ps->_psanck->y+1;
if(NextHasFood(pNextNode,ps->_pFood))
{
//下一个结点是食物
EatFood(ps,pNextNode);
}
else
{
NoFood(ps,pNextNode);
}
}
break;
case LEFT:
{
pNextNode->x = ps->_psanck->x-2;
pNextNode->y = ps->_psanck->y;
if(NextHasFood(pNextNode,ps->_pFood))
{
//下一个结点是食物
EatFood(ps,pNextNode);
}
else
{
NoFood(ps,pNextNode);
}
}
break;
case RIGHT:
{
pNextNode->x = ps->_psanck->x+2;
pNextNode->y = ps->_psanck->y;
if(NextHasFood(pNextNode,ps->_pFood))
{
//下一个结点是食物
EatFood(ps,pNextNode);
}
else
{
NoFood(ps,pNextNode);
}
}
break;
}
}
void KillByWall(pSnack ps)
{
if(ps->_psanck->x==0 ||
ps->_psanck->x==58 ||
ps->_psanck->y==1 ||
ps->_psanck->y==27)
{
ps->_Status = KILL_BY_WALL;
}
}
void KillBySelf(pSnack ps)
{
pSnackNode pNext = ps->_psanck->next;
while(pNext)
{
if((pNext->x==ps->_psanck->x)&&(pNext->y==ps->_psanck->y))
{
ps->_Status = KILL_BY_SELF;
return;
}
pNext = pNext->next;
}
}
void PrintHelpInfo()
{
SetPos(65,12);
printf("用↑,↓,←,→键来操作蛇的方向!\n");
SetPos(65,17);
printf("按空格键可以暂停游戏!\n");
SetPos(65,19);
printf("按Esc键可以退出游戏!\n");
}
void GameRun(pSnack ps)
{
PrintHelpInfo();
do
{
//确定方向
if(GetAsyncKeyState(VK_UP) && ps->_Dir != DOWN)
{
ps->_Dir = UP;
}
else if(GetAsyncKeyState(VK_DOWN) && ps->_Dir != UP)
{
ps->_Dir = DOWN;
}
else if(GetAsyncKeyState(VK_LEFT) && ps->_Dir != RIGHT)
{
ps->_Dir = LEFT;
}
else if(GetAsyncKeyState(VK_RIGHT) && ps->_Dir != LEFT)
{
ps->_Dir = RIGHT;
}
else if(GetAsyncKeyState(VK_SPACE))
{
//暂停
Pause();
}
else if(GetAsyncKeyState(VK_ESCAPE))
{
//结束
ps->_Status = NORMAL_END;
break;
}
else if(GetAsyncKeyState(VK_F1))
{
//加速
if(ps->_SleepTime >= 40)
{
ps->_SleepTime -= 20;
ps->_AddScore += 2;
}
}
else if(GetAsyncKeyState(VK_F2))
{
//减速
if(ps->_SleepTime <= 300)
{
ps->_SleepTime += 20;
ps->_AddScore -= 2;
}
if(ps->_SleepTime >= 300)
{
ps->_AddScore = 1;
}
}
Sleep(ps->_SleepTime);
//蛇的移动
SnackMove(ps);
KillByWall(ps);
KillBySelf(ps);
}while(ps->_Status == OK);
}
void GameEnd(pSnack ps)
{
pSnackNode cur = ps->_psanck;
pSnackNode food = ps->_pFood;
//SetPos(45,14);
if(ps->_Status == NORMAL_END)
{
printf("游戏正常结束!\n");
SetPos(65,28);
system("pause");
}
else if(ps->_Status == KILL_BY_SELF)
{
SetPos(22,25);
printf("蛇撞上自己了,游戏OVER!\n");
SetPos(65,28);
system("pause");
}
else if(ps->_Status == KILL_BY_WALL)
{
SetPos(22,25);
printf("蛇撞上墙了,游戏OVER!\n");
SetPos(65,28);
system("pause");
}
while(cur)
{
pSnackNode del = cur;
cur = cur->next;
//free(del);
del = NULL;
}
//free(food);
food = NULL;
}
- 测试一下吧
#include"snack.h"
void test()
{
Snack snack = {0}; //创建的贪吃蛇
srand((unsigned int)time(NULL));
GameStart(&snack);
GameRun(&snack);
GameEnd(&snack);
}
int main()
{
test();
system("pause");
return 0;
}