实现一个贪食蛇游戏
具有的功能:
- 实现蛇的移动,通过上下左右键控制蛇移动的方向
- 蛇每次吃到食物分数会在增加,蛇身变长
- 不能撞墙或者碰到自己的蛇身
代码实现
snake.h
#ifndef __SNAKE_H__
#define __SANKE_H__
#include
#include
#include
#include
typedef struct SnakeNode
{
int x;
int y;
struct SnakeNode * next;
}SnakeNode, *pSnakeNode;
enum Direction
{
UP = 1,
DOWN,
LEFT,
RIGHT
};
enum GameStatus
{
OK,
NORMAL_END,
KILL_BY_WALL,
KILL_BY_SELF
};
typedef struct Snake{
pSnakeNode _psnake;
pSnakeNode _pFood;
enum Direction _dir;
enum GameStatus _Status;
int TotalScore;
int _AddScore;
int _SleepTime;
}Snake,*pSnake;
#define WALL "■"
#define FOOD "●"
#define X_INIT 20
#define Y_INIT 10
void WelcomToGame();
void CreateMap();
void InitSnake(pSnake ps);
void CreateFood(pSnake ps);
void Pause();
void SnakeMove(pSnake ps);
int NextHasFood(pSnakeNode pn, pSnakeNode pf);
void EatFood(pSnake ps, pSnakeNode pn);
void NotFood(pSnake ps, pSnakeNode pn);
void KillByWall(pSnake ps);
void KillBySelf(pSnake ps);
void GameStart(pSnake ps);
void GameRun(pSnake ps);
void GameEnd(pSnake ps);
#endif
snake.c
#include"snake.h"
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void SetPos(int x,int y)
{
COORD pos = { 0 };
HANDLE handle = NULL;
handle = GetStdHandle(STD_OUTPUT_HANDLE);
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
void WelcomToGame()
{
system("mode con cols=100 lines=30");
SetPos(39,13);
printf("alisa 欢迎您来到贪吃蛇小游戏\n");
SetPos(40, 28);
system("pause");
system("cls");
SetPos(25, 13);
printf("用↑.↓.←.→来控制蛇的移动。F1为加速,F2为减速.");
SetPos(25, 14);
printf("加速获得分数更多");
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);
}
}
pSnakeNode BuyNode()
{
pSnakeNode pRet = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pRet == NULL)
{
perror("BuyNode::malloc()");
exit(EXIT_FAILURE);
}
pRet->next = NULL;
pRet->x = 0;
pRet->y = 0;
return pRet;
}
void InitSnake(pSnake ps)
{
pSnakeNode first = BuyNode();
first->x = X_INIT;
first->y = Y_INIT;
for (int i = 0; i < 4; i++)
{
pSnakeNode cur = BuyNode();
cur->x = first->x + 2 ;
cur->y = first->y;
cur->next = first;
first = cur;
}
pSnakeNode pCur = first;
while (pCur != NULL)
{
SetPos(pCur->x, pCur->y);
printf(FOOD);
pCur = pCur->next;
}
printf("\n");
ps->_psnake = first;
}
void CreateFood(pSnake ps)
{
pSnakeNode pFood = BuyNode();
pSnakeNode pCur = ps->_psnake;
pFood->y = rand() % 26 + 1;
do
{
pFood->x = rand()%55+2;
} while (pFood->x%2!=0);
while (pCur)
{
if (pCur->x == pFood->x&&pCur->y == pFood->y)
{
}
pCur = pCur->next;
}
ps->_pFood = pFood;
SetPos(pFood->x,pFood->y);
printf(FOOD);
}
void GameStart(pSnake ps)
{
WelcomToGame();
CreateMap();
InitSnake(ps);
CreateFood(ps);
ps->_AddScore = 10;
ps->TotalScore = 0;
ps->_dir = RIGHT;
ps->_SleepTime = 200;
ps->_Status = OK;
}
void Pause()
{
while (1)
{
Sleep(100);
if (GetAsyncKeyState(VK_SPACE))
{
break;
}
}
}
int NextHasFood(pSnakeNode pn,pSnakeNode pf)
{
return (pn->x == pf->x)&& (pn->y == pf->y);
}
void EatFood(pSnake ps, pSnakeNode pn)
{
pSnakeNode Cur = NULL;
pn->next = ps->_psnake;
ps->_psnake = pn;
Cur = ps->_psnake;
ps->TotalScore += ps->_AddScore;
while (Cur)
{
SetPos(Cur->x, Cur->y);
printf(FOOD);
Cur = Cur->next;
}
CreateFood(ps);
}
void NotFood(pSnake ps, pSnakeNode pn)
{
pSnakeNode Cur = NULL;
pn->next = ps->_psnake;
ps->_psnake = pn;
Cur = ps->_psnake;
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 SnakeMove(pSnake ps)
{
pSnakeNode pNextNode = BuyNode();
SetPos(65, 8);
printf("总分:%d ", ps->TotalScore);
SetPos(65,9);
printf("每个食物的得分:%d ", ps->_AddScore);
switch (ps->_dir){
case UP:
{
pNextNode->x = ps->_psnake->x;
pNextNode->y = ps->_psnake->y - 1;
if (NextHasFood(pNextNode, ps->_pFood))
{
EatFood(ps, pNextNode);
}
else{
NotFood(ps, pNextNode);
}
}
break;
case DOWN:
{
pNextNode->x = ps->_psnake->x;
pNextNode->y = ps->_psnake->y + 1;
if (NextHasFood(pNextNode, ps->_pFood))
{
EatFood(ps, pNextNode);
}
else{
NotFood(ps, pNextNode);
}
}
break;
case LEFT:
{
pNextNode->x = ps->_psnake->x - 2;
pNextNode->y = ps->_psnake->y;
if (NextHasFood(pNextNode, ps->_pFood))
{
EatFood(ps, pNextNode);
}
else{
NotFood(ps, pNextNode);
}
}
break;
case RIGHT:
{
pNextNode->x = ps->_psnake->x+2;
pNextNode->y = ps->_psnake->y;
if (NextHasFood(pNextNode, ps->_pFood))
{
EatFood(ps, pNextNode);
}
else{
NotFood(ps, pNextNode);
}
}
break;
}
}
void KillByWall(pSnake ps)
{
if (ps->_psnake->x == 2
|| ps->_psnake->x == 58
|| ps->_psnake->y == 0
|| ps->_psnake->y == 27)
{
ps->_Status = KILL_BY_WALL;
}
}
void KillBySelf(pSnake ps)
{
pSnakeNode pNext= ps->_psnake->next;
while(pNext)
{
if ((pNext->x == ps->_psnake->x) && (pNext->y == ps->_psnake->y))
{
ps->_Status = KILL_BY_SELF;
return;
}
pNext = pNext->next;
}
}
void PrintHelpInfo()
{
SetPos(65, 12);
printf("用↑.↓.←.→来控制蛇的移动");
SetPos(65, 13);
printf("F1为加速,F2为减速");
SetPos(65, 14);
printf("按ESC退出游戏");
SetPos(65, 15);
printf("按空格暂停游戏");
SetPos(65, 14);
printf("按ESC退出游戏");
}
void GameRun(pSnake ps)
{
HideCursor();
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);
SnakeMove(ps);
KillByWall(ps);
KillBySelf(ps);
} while (ps->_Status == OK);
}
void GameEnd(pSnake ps)
{
pSnakeNode pCur = ps->_psnake;
SetPos(26, 14);
if (ps->_Status == NORMAL_END)
{
printf("正常结束游戏\n");
}
else if (ps->_Status == KILL_BY_SELF)
{
printf("撞上自己\n");
}
else if (ps->_Status == KILL_BY_WALL)
{
printf("撞墙\n");
}
while (pCur)
{
pSnakeNode pDel = pCur;
pCur = pCur->next;
free(pDel);
pDel = NULL;
}
ps->_psnake = NULL;
free(ps->_pFood);
ps->_pFood = NULL;
}
main.c
#include
#include"snake.h"
void test()
{
Snake snake = { 0 };
srand((unsigned int)time(NULL));
GameStart(&snake);
GameRun(&snake);
GameEnd(&snake);
}
int main()
{
test();
return 0;
}
效果如下图: