snack.h
#ifndef __SNAKE_H__
#define __SNAKE_H__
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
enum Direction
{
UP = 1,
DOWN,
LEFT,
RIGHT
};
enum GameStatus
{
OK,//正常运行
NORMAL_END,//正常结束
KILL_BY_WALL,//撞墙
KILL_BY_SELF//咬到自己
};
#define WALL "■"
#define FOOD "●"
#define INIT_X 20
#define INIT_Y 10
typedef struct SnakeNode
{
int x;
int y;
struct SnakeNode* next;
}SnakeNode,*pSnakeNode;
typedef struct Snake
{
pSnakeNode _psnake;//维护蛇身的指针
pSnakeNode _pFood;//维护食物的位置
int _TotaiScore; //总分数
int _AddScore; //增加的分数
int _SleepTime; //休眠时间
enum Direction _Dir;
enum GameStatus _Status;
}
Snake,*pSnake;
void WelcomeToGame();
void CreateMap();
void initSnake(pSnake ps);
void CreateFood(pSnake ps);
void GameStart(pSnake ps);
void SetPos(int x, int y);
void GameRun(pSnake ps);
void GameEnd(pSnake ps);
void SnakeMove(pSnake ps);
void PrintHelpInfo();
void KillByWall();
void KillBySelf();
#endif //__SNAKE_H__
snack.c
#include "snake.h"
void WelcomeToGame()
{
SetPos(38,15);
printf("欢迎来到贪吃蛇小游戏");
SetPos(38,28);
system("pause"); //暂停界面
system("cls"); //清屏
SetPos(20,15);
printf("用↑.↓.←.→分别控制蛇的移动, F1为加速键, F2为减速键");
SetPos(38,28);
system("pause");
system("cls");
}
void SetPos(int x, int y)
{
COORD pos = {0};
HANDLE handle = 0;
handle = GetStdHandle (STD_OUTPUT_HANDLE );
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle,pos);
}
void CreateMap()
{
int i = 0;
//上
for(i=0 ; i<=58; i+=2)
printf(WALL);
//下
SetPos(0,26);
for(i=0 ; i<=58; i+=2)
printf(WALL);
//左
for(i=1 ; i<=25; i++)
{
SetPos(0,i);
printf(WALL);
}
//右
for(i=1 ; i<=25; i++)
{
SetPos(58,i);
printf(WALL);
}
}
pSnakeNode BuySnakeNode()
{
pSnakeNode p;
p = (pSnakeNode)malloc(sizeof(SnakeNode));
if(p == NULL)
{
printf("申请失败\n");
return NULL;
}
else
return p;
}
void initSnake(pSnake ps)
{
pSnakeNode cur = NULL;
int i = 0;
cur = BuySnakeNode();
cur->x = INIT_X;
cur->y = INIT_Y;
cur->next = NULL;
//蛇身初始长度为5
for(i=1;i<5;i++)
{
ps->_psnake = BuySnakeNode();
ps->_psnake ->next = cur;
ps->_psnake ->x = INIT_X+2*i;
ps->_psnake ->y = INIT_Y;
cur = ps->_psnake;
}
while(cur)
{
SetPos(cur->x ,cur->y );
printf(FOOD);
cur = cur->next;
}
SetPos(38,27);
}
void CreateFood(pSnake ps)
{
pSnakeNode pFood = NULL; //维护食物的节点
pSnakeNode cur = NULL; //指向蛇头节点
pFood = BuySnakeNode();
cur = ps->_psnake;
do{//产生的x坐标应该为2的倍数,这样才可能和蛇头坐标对齐
pFood->x = rand()%55+2;
}while(pFood->x %2 != 0);
pFood->y = rand()%25+1;
while(cur != NULL)
{
if(cur->x == pFood->x && cur->y == pFood->y)
{
CreateFood(ps);
return;
}
else
cur = cur->next;
}
ps->_pFood = pFood;
SetPos(pFood->x ,pFood->y);
printf(FOOD);
Sleep(100);
SetPos(38,27);
}
void Pause()
{
while(1)
{
Sleep(100);
if(GetAsyncKeyState(VK_SPACE))
{
break;
}
}
}
void KillByWall(pSnake ps)
{
//上
if(ps->_psnake->y == 0)
ps->_Status = KILL_BY_WALL;
//下
if(ps->_psnake->y == 26)
ps->_Status = KILL_BY_WALL;
//左
if(ps->_psnake->x == 0 )
ps->_Status = KILL_BY_WALL;
//右
if(ps->_psnake->x == 58)
ps->_Status = KILL_BY_WALL;
}
void KillBySelf(pSnake ps)
{
pSnakeNode cur = NULL;
cur = ps->_psnake;
while(cur->next)
{
if(ps->_psnake->x == cur->next->x && ps->_psnake->y == cur->next->y)
{
ps->_Status = KILL_BY_SELF;
}
cur = cur->next;
}
}
void GameRun(pSnake ps)
{
PrintHelpInfo();
do
{
if(GetAsyncKeyState(VK_UP) && ps->_Dir != DOWN)
{
ps->_Dir = UP;
}
if(GetAsyncKeyState(VK_DOWN) && ps->_Dir != UP)
{
ps->_Dir = DOWN;
}
if(GetAsyncKeyState(VK_LEFT) && ps->_Dir != RIGHT)
{
ps->_Dir = LEFT;
}
if(GetAsyncKeyState(VK_RIGHT) && ps->_Dir != LEFT)
{
ps->_Dir = RIGHT;
}
if(GetAsyncKeyState(VK_SPACE))
{
//暂停游戏
Pause();
}
if(GetAsyncKeyState(VK_ESCAPE))
{
//结束游戏
ps->_Status = NORMAL_END;
}
if(GetAsyncKeyState(VK_F1))
{
//加速
if(ps->_SleepTime >=40)
{
ps->_SleepTime -= 20;
ps->_AddScore += 2;
}
}
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);
}
int NextHasFood(pSnakeNode pn , pSnakeNode pf)
{
return ((pn->x == pf->x) &&(pn->y == pf->y));
}
void NoFood( pSnake ps,pSnakeNode pn)
{
pSnakeNode cur = NULL;
pn->next = ps->_psnake;
ps->_psnake = pn;
//处理尾节点
cur = ps->_psnake;
while(cur->next->next)
{
cur = cur->next;
}
SetPos(cur->next->x ,cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
//打印新加入的节点
SetPos(ps->_psnake->x,ps->_psnake->y);
printf(FOOD);
}
void EatFood(pSnake ps,pSnakeNode pn)
{
pn->next = ps->_psnake;
ps->_psnake = pn;
//打印新加的节点
SetPos(ps->_psnake->x ,ps->_psnake->y);
printf(FOOD);
ps->_TotaiScore += ps->_AddScore;
//创建新食物
CreateFood(ps);
}
void SnakeMove(pSnake ps)
{
pSnakeNode pNextNode = BuySnakeNode();
SetPos(60,10);
printf("总分:%d ",ps->_TotaiScore);
SetPos(60,11);
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
{
NoFood(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
{
NoFood(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
{
NoFood(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
{
NoFood(ps,pNextNode);
}
}
break;
}
}
void PrintHelpInfo()
{
SetPos(60,13);
printf("用↑.↓.←.→分别控制蛇的移动");
SetPos(60,14);
printf("F1为加速键");
SetPos(60,15);
printf("F2为减速键");
SetPos(60,16);
printf("ESC为退出键");
}
void GameStart(pSnake ps)
{
srand((unsigned int)time(NULL));
system("mode con cols=100 lines=30");//设置窗口大小
WelcomeToGame();
CreateMap();
initSnake(ps);
CreateFood(ps);
ps->_SleepTime = 200;
ps->_TotaiScore = 0;
ps->_Dir = RIGHT;
ps->_Status = OK;
ps->_AddScore = 10;
}
void GameEnd(pSnake ps)
{
pSnakeNode del = NULL;
if(ps->_Status == NORMAL_END)
{
SetPos(25,14);
printf("游戏结束");
SetPos(38,28);
}
if(ps->_Status == KILL_BY_SELF)
{
SetPos(25,14);
printf("很遗憾,蛇咬死了自己");
SetPos(38,28);
}
else if(ps->_Status == KILL_BY_WALL)
{
SetPos(25,14);
printf("很遗憾,蛇撞墙了");
SetPos(38,28);
}
while(ps->_psnake!=NULL)
{
del = ps->_psnake;
ps->_psnake = ps->_psnake->next;
free(del);
del = NULL;
}
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"
void test()
{
Snake p = {0};
GameStart(&p);
GameRun(&p);
GameEnd(&p);
}
int main()
{
test();
return 0;
}