头文件
代码语言:javascript复制#pragma once
#include<stdio.h>
#include<Windows.h>
#include<stdbool.h>
#include<locale.h>
#include<time.h>
#define KEY_PRESS(vk) ( (GetAsyncKeyState(vk) & 1) ? 1 : 0)
#define POS_X 24
#define POS_Y 5
#define FOOD L'鼠'
#define WALL L'墙'
#define BODY L'蛇'
//类型声明
//蛇方向
enum DIRECTION
{
UP = 1,//上
DOWM,//下
LEFT,//左
RIGHT//右
};
//蛇的状态
//正常 撞墙 自撞 正常退出
enum GAME_STATUS
{
OK,//正常
KILL_BY_WALL,//撞墙
KILL_BY_SELF,//撞自己
END_NORMAL//推出
};
//蛇身结点类型
typedef struct SnakeNode
{
//坐标
int x;
int y;
//指向下一个结点的指针
struct SnakeNode* next;
}SnakeNode,* pSnakeNode;
//贪吃蛇
typedef struct Snake
{
pSnakeNode _pSnake;//指向蛇头
pSnakeNode _pFood;//食物位置
enum DIRECTION _dir;//蛇头方向
enum GAME_STATUS _status;//状态
int _food_weight;//食物分数
int _score;//总成绩
int _sleep_time;//休息时间
}Snake,*pSnake;
//函数声明
void SetPos(short x, short y);
//游戏初始化
void GameStart(pSnake ps);
//游戏开始
void GameRun(pSnake ps);
//欢迎界面
void WelcomeToGame();
//打印地图
void CreateMap();
//初始化蛇
void InitSnake(pSnake ps);
//创建食物
void CreatteFood(pSnake ps);
//蛇的移动
void SnakeMove(pSnake ps);
//判断吃到了没?
int NextIsFood(pSnakeNode pNextNode,pSnake ps);
//吃了食物
void EatFood(pSnakeNode pNextNode, pSnake ps);
//没吃
void NoFood(pSnakeNode pNextNode, pSnake ps);
//撞墙和撞自己
void KillByWall(pSnake ps);
void KillBySelf(pSnake ps);
//游戏善后
void GameEnd(pSnake ps);
实现文件
代码语言:javascript复制#define _CRT_SECURE_NO_WARNINGS
#include"snake.h"
void SetPos(short x, short y)
{
COORD pos = { x, y };
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//设置标准输出上光标的位置为pos
SetConsoleCursorPosition(hOutput, pos);
}
void WelcomeToGame()
{
SetPos(40, 14);
printf("欢迎游玩贪吃蛇小游戏n");
SetPos(42, 20);
system("pause");
system("cls");
SetPos(40, 14);
wprintf(L"用 ↑ ↓ ← →,按F3加速 按F4减速n");
SetPos(40, 15);
wprintf(L"加速分数更高n");
SetPos(42, 20);
system("pause");
system("cls");
SetPos(0, 0);
}
void CreateMap()
{
//上
int i;
for(i = 0;i<29;i )
wprintf(L"%lc", WALL);
//左
for (i = 0; i <= 25; i )
{
SetPos(0, i);
wprintf(L"%lc", WALL);
}
//右
for (i = 0; i <= 25; i )
{
SetPos(56, i);
wprintf(L"%lc", WALL);
}
//下
SetPos(0, 26);
for (i = 0; i < 29; i )
wprintf(L"%lc", WALL);
}
void InitSnake(pSnake ps)
{
int i = 0;
pSnakeNode cur = NULL;
for (i = 0; i < 5; i )
{
cur = (pSnakeNode)malloc(sizeof(SnakeNode));
if (cur == NULL)
{
perror("InitSnake()::malloc()");
}
cur->next = NULL;
cur->x = POS_X 2 * i;
cur->y = POS_Y;
//头插法插入链表
if (ps->_pSnake == NULL)
{
ps->_pSnake = cur;
}
else
{
cur->next = ps->_pSnake;
ps->_pSnake = cur;
}
}
cur = ps->_pSnake;
while (cur)
{
SetPos(cur->x,cur->y);
wprintf(L"%lc", BODY);
cur = cur->next;
}
//方向
ps->_dir = RIGHT;//默认向右
ps->_score = 0;
ps->_food_weight = 10;
ps->_sleep_time = 200;//ms
ps->_status = OK;
}
void CreatteFood(pSnake ps)
{
int x = 0;
int y = 0;
//x 2~54
//y 1~25
again:
do
{
x = rand() % 53 2;
y = rand() % 25 1;
} while ((x % 2) != 0);
//x y 不能生成在蛇身上
pSnakeNode cur = ps->_pSnake;
while(cur)
{
if (x == cur->x && y == cur->y)
{
goto again;
}
cur = cur->next;
}
//创建食物结点
pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pFood == NULL)
{
perror("CreatFood::malloc()");
return;
}
pFood->x = x;
pFood->y = y;
pFood->next = NULL;
SetPos(x, y);
wprintf(L"%lc", FOOD);
ps->_pFood = pFood;
}
void GameStart(pSnake 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();
//绘制地图
CreateMap();
//创建蛇
InitSnake(ps);
//创建食物
CreatteFood(ps);
//设置游戏相关信息
}
void printfHelpInfo()
{
SetPos(64, 20);
wprintf(L"%ls",L"不能穿墙,不能啃自己");
SetPos(64, 21);
printf("欢迎游玩贪吃蛇小游戏n");
SetPos(64, 22);
wprintf(L"用 ↑ ↓ ← →,按F3加速 按F4减速n");
SetPos(64, 23);
wprintf(L"加速分数更高n");
SetPos(64, 24);
wprintf(L"空格是暂停哦");
SetPos(64, 25);
wprintf(L"By 我");
}
void Pause()
{
while (1)
{
Sleep(200);
if (KEY_PRESS(VK_SPACE))
break;
}
}
int NextIsFood(pSnakeNode pNextNode, pSnake ps)
{
return (ps->_pFood->x == pNextNode->x && ps->_pFood->y == pNextNode->y);
}
void EatFood(pSnakeNode pNextNode, pSnake ps)
{
//头插法
ps->_pFood->next = ps->_pSnake;
ps->_pSnake = ps->_pFood;
//释放NEXT的结点
free(pNextNode);
pNextNode = NULL;
pSnakeNode cur = ps->_pSnake;
//打印蛇
while (cur)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc", BODY);
cur = cur->next;
}
ps->_score = ps->_food_weight;
//重新创建食物
CreatteFood(ps);
}
void NoFood(pSnakeNode pNextNode, pSnake ps)
{
pNextNode->next = ps->_pSnake;
ps->_pSnake = pNextNode;
pSnakeNode cur = ps->_pSnake;
while (cur->next->next != NULL)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc", BODY);
cur = cur->next;
}
SetPos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
cur = NULL;
}
void KillByWall(pSnake ps)
{
if (ps->_pSnake->x == 0 || ps->_pSnake->x == 56 || ps->_pSnake->y == 0 || ps->_pSnake->y == 26)
ps->_status = KILL_BY_WALL;
}
void KillBySelf(pSnake ps)
{
pSnakeNode cur = ps->_pSnake->next;
while(cur)
{
if (ps->_pSnake->x == cur->x && ps->_pSnake->y == cur->y)
ps->_status = KILL_BY_SELF;
cur = cur->next;
}
}
void SnakeMove(pSnake ps)
{
//蛇要去的下一个结点
pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pNextNode == NULL)
{
perror("SNAKENODDE :: malloc()");
return;
}
switch (ps->_dir)
{
case UP:
pNextNode->x = ps->_pSnake->x;
pNextNode->y = ps->_pSnake->y - 1;
break;
case DOWM:
pNextNode->x = ps->_pSnake->x;
pNextNode->y = ps->_pSnake->y 1;
break;
case LEFT:
pNextNode->x = ps->_pSnake->x - 2;
pNextNode->y = ps->_pSnake->y;
break;
case RIGHT:
pNextNode->x = ps->_pSnake->x 2;
pNextNode->y = ps->_pSnake->y;
break;
}
//检测是否吃到了食物
if (NextIsFood(pNextNode,ps))
{
EatFood(pNextNode, ps); pNextNode = NULL;
}
else
{
NoFood(pNextNode, ps);
}
KillByWall(ps);
KillBySelf(ps);
}
void GameRun(pSnake ps)
{
//打印帮助信息
printfHelpInfo();
do
{
SetPos(64, 10);
printf("总分:�n",ps->_score);
SetPos(64, 11);
printf("当前食物分数:Mn", ps->_food_weight);
//调用宏
if (KEY_PRESS(VK_UP) && ps->_dir != DOWM)
{
ps->_dir = UP;
}
else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP)
{
ps->_dir = DOWM;
}
else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
{
ps->_dir = LEFT;
}
else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT)
{
ps->_dir = RIGHT;
}
else if (KEY_PRESS(VK_SPACE))
{
Pause();
}
else if (KEY_PRESS(VK_F3))//加速
{
if (ps->_food_weight <= 200)
{
ps->_sleep_time -= 30;
ps->_food_weight *= 2;
}
}
else if (KEY_PRESS(VK_F4))//减速
{
if (ps->_food_weight >= 2)
{
ps->_sleep_time = 30;
ps->_food_weight /= 2;
}
}
else if (KEY_PRESS(VK_ESCAPE))
{
ps->_status = END_NORMAL;
}
SnakeMove(ps);//走一步啊
Sleep(ps->_sleep_time);
//打印总分数和食物的分值
} while (ps->_status == OK);
}
void GameEnd(pSnake ps)
{
SetPos(24, 12);
switch (ps->_status)
{
case END_NORMAL:
printf("已主动结束游戏");
break;
case KILL_BY_WALL:
printf("您撞墙了");
break;
case KILL_BY_SELF:
printf("您撞到了自己");
break;
}
SetPos(0, 27);
//释放链表
pSnakeNode cur = ps->_pSnake;
while (cur)
{
pSnakeNode del = cur;
cur = cur->next;
free(del);
}
}
mian.c
代码语言:javascript复制#define _CRT_SECURE_NO_WARNINGS
#include"snake.h"
void test()
{
char ch = 'n';
do {
system("cls");
//创建贪吃蛇
Snake snake = { 0 };
//初始化游戏
GameStart(&snake);
//运行游戏
GameRun(&snake);
//游戏结束
GameEnd(&snake);
SetPos(20, 20);
printf("还玩么?玩的话输入Y(先删除空格):");
scanf("%c", &ch);
} while (ch == 'Y');
}
int main()
{
//设置本地化
setlocale(LC_ALL, "");
srand((unsigned int)time(NULL));
test();
return 1;
}