贪吃蛇游戏源码(VS编译环境)
🥕个人主页:开敲🍉
🔥所属专栏:C语言🍓
🌼文章目录🌼
1. Snake.h 头文件
2. Snake.c 源文件
3. Test.c 头文件
1. Snake.h 头文件
#include <windows.h>
#include <stdio.h>
#include <stdbool.h>
#include <locale.h>
#include <time.h>
#define INIT_COLS 40
#define INIT_LINES 10#define WALL L'■'
#define SNAKE_BODY L'●'
#define FOOD L'★'
//蛇的方向
enum SnakeDirection
{
UP = 1,
DOWN,
LEFT,
RIGHT
};
//游戏状态
enum GameStatus
{
OK,
KILL_BY_WALL,
KILL_BY_SELF,
END_NORMAL,
PAUSE
};//贪吃蛇蛇身的节点
typedef struct SnakeNode
{
int x;
int y;
struct SnakeNode* next;}SnakeNode;
//贪吃蛇的信息
typedef struct Snake
{
SnakeNode* snake;//指向蛇头的指针
SnakeNode* pfood;//指向食物节点的指针
enum GameStatus sta;//游戏的状态
enum SnakeDirection dir;//贪吃蛇的方向
int food_weight;//食物的分数
int score;//总分
int sleep_time;//贪吃蛇的速度
}Snake;//设置光标位置
void SetPos(int x, int y);
//初始化欢迎界面
void InitWelcome();
//创建游戏地图
void CreatGameMap();
//初始化蛇
void InitSnake(Snake* ps);
//创建食物
void CreatFood(Snake* ps);
//调整贪吃蛇
void ModifySnake(Snake* ps);
//移动贪吃蛇
void SnakeMove(Snake* ps);//吃掉食物
void EatFood(SnakeNode* pnext, Snake* ps);
//不是食物
void NotFood(SnakeNode* pnext, Snake* ps);
//初始化游戏
void InitGame(Snake* ps);
//运行游戏
void GameRun(Snake* ps);
//游戏结束
void GameOver(Snake* ps);
2. Snake.c 源文件
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1)?1:0)
#include "Snake.h"//设置光标位置
void SetPos(int x, int y)
{
//获取句柄
HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE);//设置光标坐标
COORD pos = { x,y };
SetConsoleCursorPosition(houtput, pos);
}
//初始化欢迎界面
void InitWelcome()
{
system("title 贪吃蛇");
SetPos(65, 17);
wprintf(L"欢迎来到贪吃蛇小游戏\n");
SetPos(68, 24);
system("pause");
system("cls");
SetPos(48, 24);
wprintf(L"使用 W、A、S、D 或 ↑、↓、←、→ 控制蛇的移动,Shift加速,Ctrl减速");
SetPos(68, 27);
system("pause");
system("cls");SetPos(65, 19);
wprintf(L"加速能够获取更高的分数!");
SetPos(68, 24);
system("pause");
system("cls");
}
//创建游戏地图
void CreatGameMap()
{
int i = 0;
SetPos(0, 0);
for (i = 0; i < 45; i++)
{
wprintf(L"%lc", WALL);
}
SetPos(0, 34);
for (i = 0; i < 45; i++)
{
wprintf(L"%lc", WALL);
}
for (i = 1; i <= 33; i++)
{
SetPos(0, i);
wprintf(L"%lc", WALL);
}
for (i = 1; i <= 33; i++)
{
SetPos(88, i);
wprintf(L"%lc", WALL);
}
//getchar();
}
//初始化蛇
void InitSnake(Snake* ps)
{
int i = 0;
SnakeNode* cur = NULL;
for (i = 0; i < 5; i++)
{
cur = (SnakeNode*)malloc(sizeof(SnakeNode));
if (cur == NULL)
{
perror("InitSnake()::malloc()");
return;
}
cur->next = NULL;
cur->x = INIT_COLS + i * 2;
cur->y = INIT_LINES;//头插法插入节点
if (ps->snake == NULL)
{
ps->snake = cur;
}
else
{
cur->next = ps->snake;
ps->snake = cur;
}
}
cur = ps->snake;
while (cur)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc", SNAKE_BODY);
cur = cur->next;
}
ps->dir = RIGHT;
ps->food_weight = 10;
ps->score = 0;
ps->sta = OK;
ps->sleep_time = 200;
}
//创建食物
void CreatFood(Snake* ps)
{
int x = 0;
int y = 0;again:
do
{
x = rand() % 85 + 2;
y = rand() % 33 + 1;} while (x % 2 != 0);
SnakeNode* cur = ps->snake;
while (cur)
{
if (x == cur->x && y == cur->y)
{
goto again;
}
cur = cur->next;
}SnakeNode* pFood = (SnakeNode*)malloc(sizeof(SnakeNode));
pFood->x = x;
pFood->y = y;
pFood->next = NULL;SetPos(x, y);
wprintf(L"%lc", FOOD);ps->pfood = pFood;
}
//初始化游戏
void InitGame(Snake* ps)
{
//获取窗口句柄
HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE);//设置光标不可见
CONSOLE_CURSOR_INFO Cursorinfo;
GetConsoleCursorInfo(houtput, &Cursorinfo);Cursorinfo.bVisible = false;
SetConsoleCursorInfo(houtput, &Cursorinfo);
//初始化欢迎界面
InitWelcome();//初始化游戏地图
CreatGameMap();
//初始化蛇
InitSnake(ps);
//创建食物
CreatFood(ps);
}
//打印帮助信息
void PrintHelpInfo(Snake* ps)
{
SetPos(100, 19);
wprintf(L"%ls", L"使用 W、A、S、D 或 ↑、↓、←、→ 控制蛇的移动");SetPos(100, 20);
wprintf(L"%ls", L"Shift加速(最高N档),Ctrl减速(最高N档)");SetPos(100, 21);
wprintf(L"%ls", L"按ESC退出游戏,按空格开始游戏(暂停游戏)");SetPos(114, 25);
wprintf(L"%ls", L"@开敲制作");
}//暂停游戏
void Pause()
{
while (1)
{
Sleep(200);
if (KEY_PRESS(VK_SPACE))
{
break;
}
}
}
//下一个节点是否是食物
int NextNodeWhetherFood(SnakeNode* pnext, Snake* ps)
{
return ((pnext->x == ps->pfood->x) && (pnext->y == ps->pfood->y));
}
//吃掉食物
void EatFood(SnakeNode* pnext, Snake* ps)
{
ps->pfood->next = ps->snake;
ps->snake = ps->pfood;
free(pnext);
pnext = NULL;
SnakeNode* cur = ps->snake;
while (cur)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc", SNAKE_BODY);
cur = cur->next;
}
ps->score += ps->food_weight;
CreatFood(ps);
}
//不是食物
void NotFood(SnakeNode* pnext, Snake* ps)
{
pnext->next = ps->snake;
ps->snake = pnext;
SnakeNode* cur = ps->snake;
while (cur->next->next)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc", SNAKE_BODY);
cur = cur->next;
}
SetPos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
}//撞墙
void KillByWall(Snake* ps)
{
if (ps->snake->x == 0 || ps->snake->x == 88 ||
ps->snake->y == 0 || ps->snake->y == 34)
ps->sta = KILL_BY_WALL;
}
//撞到自己
void KillBySelf(Snake* ps)
{
SnakeNode* cur = ps->snake->next;
while(cur)
{
if (cur->x == ps->snake->x && cur->y == ps->snake->y)
{
ps->sta = KILL_BY_SELF;
break;
}
cur = cur->next;
}
}
//移动贪吃蛇
void SnakeMove(Snake* ps)
{
SnakeNode* pnext = (SnakeNode*)malloc(sizeof(SnakeNode));
if (pnext == NULL)
{
perror("SnakeMove()::malloc()");
return;
}
pnext->next = NULL;
switch (ps->dir)
{
case UP:
pnext->x = ps->snake->x;
pnext->y = ps->snake->y - 1;
break;
case DOWN:
pnext->x = ps->snake->x;
pnext->y = ps->snake->y + 1;
break;
case LEFT:
pnext->x = ps->snake->x - 2;
pnext->y = ps->snake->y;
break;
case RIGHT:
pnext->x = ps->snake->x + 2;
pnext->y = ps->snake->y;
break;
}if (NextNodeWhetherFood(pnext, ps))
{
EatFood(pnext,ps);
}
else
{
NotFood(pnext,ps);
}//撞墙
KillByWall(ps);//撞到自己
KillBySelf(ps);
}//调整贪吃蛇
void ModifySnake(Snake* ps)
{
do
{
SetPos(100, 15);
wprintf(L"总分数:%2d 当前食物分数:%2d", ps->score, ps->food_weight);
if ((KEY_PRESS(VK_UP)|| KEY_PRESS(0x57)) && ps->dir != DOWN)
{
ps->dir = UP;
}
else if ((KEY_PRESS(VK_DOWN)|| KEY_PRESS(0x53)) && ps->dir != UP)
{
ps->dir = DOWN;
}
else if ((KEY_PRESS(VK_LEFT)|| KEY_PRESS(0x41)) && ps->dir != RIGHT)
{
ps->dir = LEFT;
}
else if ((KEY_PRESS(VK_RIGHT)|| KEY_PRESS(0x44)) && ps->dir != LEFT)
{
ps->dir = RIGHT;
}
else if (KEY_PRESS(VK_SPACE))
{
//暂停游戏
Pause();
}
else if (KEY_PRESS(VK_ESCAPE))
{
//退出游戏
ps->sta = END_NORMAL;
return;
}
else if (KEY_PRESS(VK_SHIFT))
{
//加速
if (ps->food_weight < 30)
{
ps->sleep_time -= 40;
ps->food_weight += 5;
}
}
else if (KEY_PRESS(VK_CONTROL))
{
//减速
if (ps->food_weight > 5)
{
ps->sleep_time += 40;
ps->food_weight -= 5;
}
}
SnakeMove(ps);//移动贪吃蛇
Sleep(ps->sleep_time);
} while (ps->sta == OK);
}
//运行游戏
void GameRun(Snake* ps)
{
//打印帮助信息
PrintHelpInfo(ps);
//调整贪吃蛇
ModifySnake(ps);
}
//游戏结束
void GameOver(Snake* ps)
{
int flag = 0;
SetPos(45, 17);
switch (ps->sta)
{
case END_NORMAL:
wprintf(L"结束游戏");
break;
case KILL_BY_WALL:
wprintf(L"很遗憾,你撞到墙了");
break;
case KILL_BY_SELF:
wprintf(L"很遗憾,你吃到自己了!");
break;
}
}
3. Test.c 头文件
#include "Snake.h"
void SnakeTest()
{
system("mode con cols=150 lines=40");
char ch = 0;
do
{
Snake snake = { 0 };
system("cls");
//初始化游戏
InitGame(&snake);
//运行游戏
GameRun(&snake);
//游戏结束
GameOver(&snake);
SetPos(45, 19);
wprintf(L"再来一局?(Y/N):");ch = getchar();
while (getchar() != '\n');
} while (ch == 'Y' || ch == 'y');
SetPos(0, 37);
}
int main()
{
setlocale(LC_ALL, "");
srand((unsigned int)time(NULL));
SnakeTest();
return 0;
}