本文主要是介绍c语言->贪吃蛇实战技巧结合EasyX简单实现页面管理(简单实现),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉
🍎个人主页:再无B~U~G-CSDN博客
1. 游戏背景
2. 游戏效果演⽰
屏幕录制
3. 课程⽬标
4. 课程定位
5. 技术要点
课前准备:
调好项目适应本地化
了解EasyX的坐标体系
6. 控制台程序
6.1 控制台程序
设置如下:
6.1 相关函数的使用
<locale.h>本地化
全部来自于EasyX简单图形库
6.2pause
6.3 outtextxy
两个一个输出字符,一个输出字符串
案例:
6.4cleardevice
6.5图片设置
相关用法:
6.6rectangle
6.7setlinecolor设置线条颜色
7. 游戏实现
7.1地图坐标
7.2 蛇⾝和⻝物
7.3 数据结构设计
蛇的⽅向,可以⼀⼀列举,使⽤枚举
7.4 游戏流程设计
8. 核⼼逻辑实现分析
8.1 游戏主逻辑
8.2 游戏开始前面的准备
8.2.1 打印欢迎界⾯
看看效果:
8.2.2 创建地图
8.2.3 初始化蛇⾝
蛇的图片是:
8.2.4 创建第⼀个⻝物
先随机⽣成⻝物的坐标
- x坐标必须是15的倍数
- ⻝物的坐标不能和蛇⾝每个节点的坐标重复
- 创建⻝物节点,打印⻝物
创建⻝物的函数:CreateFood
8.3 游戏运⾏过程
8.3.1 KEY_PRESS
检测按键状态,我们封装了⼀个宏
# define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)
8.3.2 PrintHelpInfo 打印规则信息
8.3.3 蛇⾝移动
8.3.3.1 NextIsFood
8.3.3.2 EatFood
8.3.3.3 NoFood
8.3.3.4 KillByWall
8.3.3.5 KillBySelf
8.4 游戏结束
戏状态不再是OK(游戏继续)的时候,要告知游戏结束的原因,并且释放蛇⾝节点。
9. 参考代码
test.cpp
#include"snake.h"void test()
{//修改适配本地中文环境setlocale(LC_ALL, "");bool c = false;char str[4] = " ";do{Snake snake = { 0 };GameStart(&snake);//游戏开始前的初始化GameRun(&snake);//玩游戏的过程GameEnd(&snake);//善后的工作outtextxy(350, 500, "再来一局吗?(Yes/No):");scanf("%s", str);c = Determine(str);} while (c);
}
int main()
{//修改适配本地中文环境setlocale(LC_ALL, "");test();return 0;
}
snake.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
#include<stdlib.h>
#include<locale.h>
#include<windows.h>
#include<stdbool.h>
#include <graphics.h>
#include <conio.h>#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )//蛇默认的起始坐标
#define POS_X 300
#define POS_Y 200
//背景单位
#define SIZE_X 15
#define SIZE_Y 20//游戏的状态
enum GAME_STATUS
{OK = 1,//正常运行ESC, //按了ESC键退出,正常退出KILL_BY_WALL,//撞墙KILL_BY_SELF //撞到自身
};typedef struct snake {int x;int y;struct snake* next;
}SnakeNode, * pSnakeNode;//结构体指针重命名//蛇行走的方向
enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT//向右
};//贪吃蛇应该有的属性
typedef struct Snake
{pSnakeNode pSnake;//维护整条蛇的指针,是指向蛇头pSnakeNode pFood;//指向食物的指针int Score;//当前累积的分数int FoodWeight;//一个食物的分数int SleepTime;//蛇休眠的时间,休眠的时间越短,蛇的速度越快,休眠的时间越长,蛇的速度越慢enum GAME_STATUS status;//游戏当前的状态enum DIRECTION dir;//蛇当前走的方向//...
}Snake, * pSnake;//游戏前的初始化
void GameStart(pSnake p);//打印欢迎信息
void WelcomeToGame();//绘制地图
void CreateMap();//初始化蛇
void InitSnake(pSnake ps);//打印图片
void picture(int x, int y);//创建食物
void CreateFood(pSnake ps);//玩游戏的过程
void GameRun(pSnake ps);//打印帮助(规则)信息
void PrintHelpInfo();//当前分数情况
void Score(pSnake ps);//游戏要暂停
void pause();//蛇走一步
void SnakeMove(pSnake ps);//下一个坐标是不是食物
bool NextIsFood(pSnake ps, pSnakeNode pNext);//是食物就吃掉
void EatFood(pSnake ps, pSnakeNode pNext);//不是食物就正常一步
void NotEatFood(pSnake ps, pSnakeNode pNext);//检测撞墙
void KillByWall(pSnake ps);//检测撞到自己
void KillBySelf(pSnake ps);//结束游戏后的工作
void GameEnd(pSnake ps);//判断是否再来一局
bool Determine(char str[]);
snake.cpp
#include"snake.h"void GameStart(pSnake ps) {//设置控制台信息,窗口大小,窗口名initgraph(1300, 720, EX_SHOWCONSOLE);//打印欢迎信息WelcomeToGame();//绘制地图CreateMap();//初始化蛇InitSnake(ps);//创建食物CreateFood(ps);
}//打印欢迎信息
void WelcomeToGame() {//欢迎信息system("title 贪吃蛇");outtextxy(500, 350, "欢迎来到贪吃蛇小游戏");outtextxy(600, 400, "随意点击屏幕继续. . .");//随意点击屏幕system("pause");//清空屏幕,换画面cleardevice();//功能介绍信息outtextxy(400, 350, "1.用 ↑ ↓ ← → 来控制蛇的移动,F3是加速,F4是减速");outtextxy(400, 370, "2.加速能得到更高的分数");outtextxy(600, 400, "随意点击屏幕继续. . .");//打印尾巴信息system("pause");//清空桌面cleardevice();}
//绘制地图
void CreateMap() {IMAGE img1;//玩游戏背景图loadimage(&img1, "picture.jpg\\picture.jpg", 900, 700, true);//从0,开始画图putimage(0, 0, &img1);//画线矩形setlinecolor(GREEN);//rectangle(0, 0, 900, 699);//rectangle(3, 3, 897, 697);//上int i = 0;for (i = 0; i <= 900; i += 15){rectangle(i, 0, i + 13, 13);}//下for (i = 0; i <= 900; i += 15){rectangle(i, 700, i + 13, 700 + 13);}//左for (i = 20; i < 700; i += 20){rectangle(0, i , 0 + 13, i + 17);}//右for (i = 1; i < 700; i += 20){rectangle(900, i, 900 + 13, i + 17);}}//初始化蛇
void InitSnake(pSnake ps) {//创建5个节点pSnakeNode cur = NULL;for (int i = 0; i < 5; i++) {cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL) {perror("malloc fail!");return;}cur->x = POS_X + i * 15;cur->y = POS_Y;cur->next = NULL;if (ps->pSnake == NULL) {ps->pSnake = cur;}else {cur->next = ps->pSnake;ps->pSnake = cur;}}//打印蛇的位置cur = ps->pSnake;while (cur) {picture(cur->x, cur->y);cur = cur->next;}//初始化贪吃蛇其他属性ps->dir = RIGHT;//向右ps->pFood = NULL;ps->Score = 0;ps->FoodWeight = 10;ps->SleepTime = 200;ps->status = OK;
}
//打印蛇身
void picture(int x, int y) {IMAGE img1;loadimage(&img1, "picture.jpg\\picture2.jpg", SIZE_X, SIZE_Y, true);putimage(x, y, &img1);
}//创建食物
void CreateFood(pSnake ps) {pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNext == NULL) {perror("pNext malloc fail!");return;}int x = 0;int y = 0;
circulate:do {//避免出现在(0,0)x = rand() % 871 + 15 ;y = rand() % 681 + 20;} while (x % 15 != 0 || y % 20 != 0);pSnakeNode cur = ps->pSnake;while (cur) {if (cur->x == x && cur->y == y) {goto circulate;}cur = cur->next;}pNext->x = x;pNext->y = y;pNext->next = NULL;//维护食物ps->pFood = pNext;//打印食物IMAGE img3;loadimage(&img3, "picture.jpg\\R-C (1).jpg", 15, 20, true);putimage(x, y, &img3);}
//玩游戏的过程
void GameRun(pSnake ps) {//打印帮助(规则)信息PrintHelpInfo();do {//当前分数情况Score(ps);//向上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->FoodWeight < 16) {ps->FoodWeight += 2;ps->SleepTime -= 50;}}//减速else if (KEY_PRESS(VK_F4)) {if (ps->FoodWeight > 4) {ps->FoodWeight -= 2;ps->SleepTime += 50;}}//退出游戏else if (KEY_PRESS(VK_ESCAPE)) {ps->status = ESC;}//走一步SnakeMove(ps);//休眠Sleep(ps->SleepTime);} while (ps->status == OK);}//打印帮助(规则)信息
void PrintHelpInfo() {//规则setlinecolor(MAGENTA);rectangle(918, 50, 1250, 180);outtextxy(930, 60, "1.不能穿墙,不能咬到自己");outtextxy(930, 80, "2.用 ↑.↓.←.→ 来控制蛇的移动");outtextxy(930, 100, "3.F3是加速,F4是减速");outtextxy(930, 120, "4.一个食物基础分10分");outtextxy(930, 140, "5.加速一次加2分,最大加6分");outtextxy(930, 160, "6.减速一次减2分,最大减6分");}
//当前分数情况
void Score(pSnake ps) {char num1[10];char num2[10];sprintf(num1, "%d", ps->Score);sprintf(num2, "%d", ps->FoodWeight);outtextxy(930, 300, "当前总积分:");outtextxy(1020, 300, num1);outtextxy(930, 340, "当前一个食物积分:");outtextxy(1065, 340, num2);
}
//游戏要暂停
void pause() {while (true) {if (KEY_PRESS(VK_SPACE)) {break;}Sleep(200);}
}
//蛇走一步
void SnakeMove(pSnake ps) {//生成下一个走过的节点pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNext == NULL) {perror("malloc tail");return;}pNext->next = NULL;//向上if (ps->dir == UP) {pNext->x = ps->pSnake->x;pNext->y = ps->pSnake->y - 20;}//向下else if (ps->dir == DOWN) {pNext->x = ps->pSnake->x;pNext->y = ps->pSnake->y + 20;}//向右else if (ps->dir == LEFT) {pNext->x = ps->pSnake->x - 15;pNext->y = ps->pSnake->y;}//向左else if (ps->dir == RIGHT) {pNext->x = ps->pSnake->x + 15;pNext->y = ps->pSnake->y;}//下一个坐标处是否是食物if (NextIsFood(ps, pNext)){//是食物就吃掉EatFood(ps, pNext);}else{//不是食物就正常一步NotEatFood(ps, pNext);}//检测撞墙KillByWall(ps);//检测撞到自己KillBySelf(ps);
}
//判断下一个坐标是不是食物
bool NextIsFood(pSnake ps, pSnakeNode pNext) {if (ps->pFood->x == pNext->x && ps->pFood->y == pNext->y) {return true;}else {return false;}
}//是食物就吃掉
void EatFood(pSnake ps, pSnakeNode pNext) {//头插pNext->next = ps->pSnake;ps->pSnake = pNext;//打印蛇pSnakeNode cur = ps->pSnake;while (cur) {picture(cur->x, cur->y);Scur = cur->next;}//改变分数ps->Score += ps->FoodWeight;//释放旧的食物free(ps->pFood);//重新生成食物CreateFood(ps);
}
//不是食物就正常一步
void NotEatFood(pSnake ps, pSnakeNode pNext) {//头插pNext->next = ps->pSnake;ps->pSnake = pNext;pSnakeNode cur = ps->pSnake;while (cur->next->next) {picture(cur->x, cur->y);cur = cur->next;}//把尾巴打印成背景图片 IMAGE img4;loadimage(&img4, "picture.jpg\\picture4.jpg", SIZE_X, SIZE_Y, true);putimage(cur->next->x, cur->next->y, &img4);//释放尾部free(cur->next);cur->next = NULL;
}
//检测撞墙
void KillByWall(pSnake ps) {if (ps->pSnake->x == 885 ||ps->pSnake->y == 680 ||ps->pSnake->x == 15 ||ps->pSnake->y == 20){ps->status = KILL_BY_WALL;return;}
}
//检测撞到自己
void KillBySelf(pSnake ps) {pSnakeNode cur = ps->pSnake->next;while (cur) {if (cur->x == ps->pSnake->x && cur->y == ps->pSnake->y){ps->status = KILL_BY_SELF;return;}cur = cur->next;}
}
//结束游戏后的工作
void GameEnd(pSnake ps)
{switch (ps->status){case ESC:outtextxy(330, 300, "主动退出游戏,正常退出\n");break;case KILL_BY_WALL:outtextxy(330, 300, "很遗憾,撞墙了,游戏结束\n");break;case KILL_BY_SELF:outtextxy(330, 300, "很遗憾,咬到自己了,游戏结束\n");break;}//释放贪吃蛇的链表资源pSnakeNode cur = ps->pSnake;pSnakeNode del = NULL;while (cur){del = cur;cur = cur->next;free(del);}//把最后打印的食物打印成背景图片IMAGE img4;loadimage(&img4, "picture.jpg\\picture4.jpg", SIZE_X, SIZE_Y, true);putimage(ps->pFood->x, ps->pFood->y, &img4);free(ps->pFood);ps = NULL;
}//判断是否再来一局
bool Determine(char str[]) {char arr[4] = "Yes";int ret = strcmp(str, arr);if (ret == 0) {return true;}else {return false;}
}
好啦今天的分享就到这里了,感谢观看。
这篇关于c语言->贪吃蛇实战技巧结合EasyX简单实现页面管理(简单实现)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!