🎁个人主页:我们的五年
🔍系列专栏:贪吃蛇
🌷追光的人,终会万丈光芒
目录
🏝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;
}