🎁个人主页:我们的五年
🔍系列专栏:贪吃蛇
🌷追光的人,终会万丈光芒
目录
🏝1.头文件:
🏝2.实现文件:
🏝3.测试文件 :
前言:这个在学习C语言的对知识点进行巩固的一个小游戏,后面也会持续带来一下小游戏。喜欢的帖子们可以点点关注。
相关系列文章:贪吃蛇
🏝1.头文件:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<locale.h>
#include<windows.h>
#include<time.h>
#define POS_X 24
#define POS_Y 5
#define WALL L'□'
#define BODY L'●'
#define FOOD L'●'
//类型声明
//蛇的方向
enum DIECTION {
UP = 1,
DOWN,
LEFT,
RIGHT
};
//贪吃蛇的状态
// 正常,撞墙,撞到自己,正常退出。
enum GAME_STATUS
{
OK, //正常
KILL_BY_WALL, //撞墙
KILL_BY_SLEF, //撞到自己
END_NORMAL //正常退出
};
//蛇身节点
typedef struct SnakeNode {
short x;
short y;
struct SncakeNode* 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 GameStart(pSnake snake);
//欢迎界面打印
void WelcomeToGame();
//初始化蛇
void InitSnake(pSnake ps);
//创建食物
void CreateFood(pSnake ps);
//游戏运行
void GameRun(pSnake ps);
int NextIsFood(pSnakeNode pn, pSnake ps);
void SnakeMove(pSnake ps);
void EatFood(pSnakeNode pn, pSnake ps);
void NotFood(pSnakeNode pn, pSnake ps);
void KillByWall(pSnake ps);
void KillBySelf(pSnake ps);
void Game_End(pSnake ps);
🏝2.实现文件:
#define _CRT_SECURE_NO_WARNINGS 1
#include"snake.h"
void SetPos(short x, short y)
{
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x,y };
SetConsoleCursorPosition(houtput, pos);
}
void WelcomeToGame()
{
SetPos(35, 13);
wprintf(L"欢迎来到贪吃蛇小游戏\n");
SetPos(37, 20);
system("pause");
system("cls");
SetPos(35, 8);wprintf(L"按↑向上移动");
SetPos(35, 9);wprintf(L"按↓向下移动");
SetPos(35, 10);wprintf(L"按←向左移动");
SetPos(35, 11);wprintf(L"按→向右移动");
SetPos(35, 12);wprintf(L"按F3减速");
SetPos(35, 13);wprintf(L"按F4加速");
SetPos(35, 14); wprintf(L"加速可以得到更高的分数");
SetPos(35, 18);
system("pause");
system("cls");
}
CreateMap()
{
//上
for (int i = 0; i < 29; i++)
wprintf(L"%lc", L'□');
//下
SetPos(0, 26);
for (int i = 0; i < 29; i++)
wprintf(L"%lc", L'□');
//左
for (int i = 1; i <=25; i++)
{
SetPos(0, i);
wprintf(L"%lc\n", L'□');
}
//右
for (int i = 1; i <= 25; i++)
{
SetPos(56, i);
wprintf(L"%lc\n", L'□');
}
}
void InitSnake(pSnake ps)
{
int i = 0;
pSnakeNode cur = NULL;
for (; i < 5; i++)
{
cur = (pSnakeNode)malloc(sizeof(SnakeNode));
if (cur == NULL)
{
perror("InitSnake::malloc()");
return;
}
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->_status = OK;
ps->_food_weight = 10;
ps->_sleep_time = 200;
//设置贪吃蛇属性
}
void CreateFood(pSnake ps)
{
int x = 0;
int y = 0;
//生成食物的坐标是2的倍数
//且在方框里面
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("CreateFood()::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)
{
//0.设置窗口大小,光标影藏
system("mode con cols=100 lines=30");//设置窗口大小为100列,30行
system("title 贪吃蛇"); //设置窗口名字为:贪吃蛇
//影藏光标
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursor;
GetConsoleCursorInfo(houtput, &cursor);
cursor.bVisible = false;
SetConsoleCursorInfo(houtput, &cursor);
//1.打印欢迎界面
//功能介绍
WelcomeToGame();
//2.绘制地图
CreateMap();
//3.创建蛇
InitSnake(ps);
//4.创建食物
CreateFood(ps);
SetPos(64, 13);
wprintf(L"0.用↑←→↓控制蛇的移动");
SetPos(64, 14);
wprintf(L"1.不能穿墙,不能咬到自己");
SetPos(64, 15);
wprintf(L"2.F3减速,F4加速");
SetPos(64, 16);
wprintf(L"3.exc退出游戏");
SetPos(64, 17);
wprintf(L"4.按空格暂停游戏");
}
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&1)?1:0)
void Pause()
{
while (1)
{
Sleep(100);
if(KEY_PRESS(VK_SPACE))
break;
}
}
void EatFood(pSnakeNode pn, pSnake ps)
{
//头插
ps->_pFood->next = ps->_pSnake;
ps->_pSnake = ps->_pFood;
//释放下一个节点;
free(pn);
pn = NULL;
pSnakeNode cur = ps->_pSnake;
while (cur)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc\n", BODY);
cur = cur->next;
}
ps->_score += ps->_food_weight;
CreateFood(ps);
}
void NotFood(pSnakeNode pn, pSnake ps)
{
pn->next = ps->_pSnake;
ps->_pSnake = pn;
pSnakeNode cur = ps->_pSnake;
pSnakeNode prev = ps->_pSnake;
while (cur->next)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc", BODY);
prev = cur;
cur = cur->next;
}
prev->next = NULL;
SetPos(cur->x, cur->y);
wprintf(L" ");
free(cur);
cur = NULL;
}
int NextIsFood(pSnakeNode pn,pSnake ps)
{
return (pn->x == ps->_pFood->x && pn->y == ps->_pFood->y);
}
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_SLEF;
break;
}
cur=cur->next;
}
}
void SnakeMove(pSnake ps)
{
pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pNextNode == NULL)
{
perror("SnakeMove()::malloc");
return;
}
switch (ps->_dir)
{
case UP:
pNextNode->x = ps->_pSnake->x;
pNextNode->y = ps->_pSnake->y - 1;
break;
case DOWN:
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);
}
else
{
NotFood(pNextNode,ps);
}
//撞到自己
KillByWall(ps);
//撞墙
KillBySelf(ps);
}
void Game_End(pSnake ps)
{
SetPos(24, 12);
switch (ps->_status)
{
case KILL_BY_SLEF:
printf("你撞到了自己,游戏结束\n");
break;
case KILL_BY_WALL:
printf("你撞到墙了,游戏结束\n");
break;
case END_NORMAL:
printf("你主动结束了游戏\n");
break;
}
pSnakeNode cur = ps->_pSnake;
while (cur)
{
pSnakeNode del = cur;
cur = cur->next;
free(del);
}
}
void GameRun(pSnake ps)
{
//打印帮助信息
do
{
//打印总分数和食物的分值
SetPos(64, 8);
wprintf(L"总分数:%3d\n",ps->_score);
SetPos(64, 9);
wprintf(L"当前食物分数:%2d",ps->_food_weight);
if (KEY_PRESS(VK_UP)&&ps->_dir!=DOWN)
{
ps->_dir = UP;
}
else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP)
{
ps->_dir = DOWN;
}
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->_sleep_time < 320)
{
ps->_sleep_time += 30;
ps->_food_weight -= 2;
}
}
else if (KEY_PRESS(VK_F4))
{
//加速
if (ps->_sleep_time > 80)
{
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);
}
🏝3.测试文件 :
#define _CRT_SECURE_NO_WARNINGS 1
#include"snake.h"
//完成的是对游戏的测试
void test()
{
int ch;
do
{
//创建贪吃蛇
Snake snake = { 0 };
//初始化游戏
GameStart(&snake);
//运行游戏
GameRun(&snake);
//结束游戏—善后工作
Game_End(&snake);
SetPos(20, 13);
printf("游戏结束,再来一局吗?Y/N");
SetPos(20, 14);
ch=getchar();
while(getchar()!='\n');
} while (ch == 'y' || ch == 'Y');
SetPos(0, 26);
}
int main()
{
//设置适配本地环境
setlocale(LC_ALL, "");
srand((unsigned int)time(NULL));
test();
return 0;
}