概述
前言
最近学校要求我们使用EasyX做一些游戏,于是我打算先做一个简易的贪吃蛇。
纸上谈兵终觉浅,在开发过程中也遇到了之前没有想到的问题,于是我打算写一篇博客记录。
特别提示:本代码使用c++20标准,在部分ide上可能不支持
演示
准备
贪吃蛇是基于帧驱动,而不是事件驱动的程序。
开发者只需要处理每一帧蛇的变化,而不是处理出现的事件(用户输入,蛇吃到食物)。
easyX提供了绘制填充矩形的API fillrectangle
。
我们把窗口分割成无数个小方格,蛇的身体和食物绘制在方格的点中。
贪吃蛇中的蛇,是一个集合,储存是每个方块的x和y坐标。
蛇移动的本质是 头 向当前方向移动一个单元格,然后其他的身体格坐标变成上一个格的坐标。
食物是一个点,只需要储存x和y坐标就可以表示。
只有蛇头碰到食物才算吃到食物,蛇的身体变长,实质上是蛇是吃到食物后移动时,加入一个位置,并设置成移动前最后一个位置的坐标
根据上述描述,我们可以构建对应的结构体;
#include <graphics.h>
#include <conio.h>
#include <vector>
#include <cstdio>
#include<time.h>
#define UNIT 20 //定义每个方格的单位像素大小
using namespace std;
struct Coord {//储存坐标的结构体
int x;
int y;
};
enum Direct {//方向的枚举
LEFT, TOP, RIGHT, BOTTOM
};
struct Box {//食物
Coord XY;
};
struct Body {//蛇
vector<Coord> xy;//蛇身体的每一个位置的坐标
Coord nextCoord;//尾巴的位置
Direct mDirect = RIGHT;//当前蛇移动的方向
};
static Body head;//蛇
static Box box;//食物
static int HEIGHT;//窗口高度
static int WIDTH;//窗口宽度
我们再来实现具体的细节
首先我们初始化一条蛇
void initSnake() {
Coord xy{3, 0};
head.xy.push_back(xy);
}
然后我们再生成一个食物
void createBox() {
box.XY.x = rand() % (WIDTH / UNIT);
box.XY.y = rand() % (HEIGHT / UNIT);
for (auto &i: head.xy)//这里的作用是判断生成的食物是否在蛇占据的位置中,如果在的话,重新生成
if (box.XY.x == i.x && box.XY.y == i.y) {
createBox();
break;
}
}
有了蛇有了食物,我们还需要代码监听用户的输入
void keyDown() {
if (_kbhit())//判断是否正在输入
switch (_getch()) {//获取输入的内容,然后修改方向
case 'a':
if (head.mDirect != RIGHT)
head.mDirect = LEFT;
break;
case 'w':
if (head.mDirect != BOTTOM)
head.mDirect = TOP;
break;
case 'd':
if (head.mDirect != LEFT)
head.mDirect = RIGHT;
break;
case 's':
if (head.mDirect != TOP)
head.mDirect = BOTTOM;
break;
default:
break;
}
}
获取到了方向,我们还需要让蛇动起来
void moveSnake() {
head.nextCoord = head.xy[head.xy.size() - 1];//这里是实现身体变成的核心部分
for (int i = head.xy.size() - 1; i >= 1; i--)//让后一个部分的坐标变成前一个部分的坐标
head.xy[i] = head.xy[i - 1];
switch (head.mDirect) {//根据方向改变头的下一个坐标
case RIGHT:
head.xy[0].x += 1;
break;
case LEFT:
head.xy[0].x -= 1;
break;
case TOP:
head.xy[0].y -= 1;
break;
case BOTTOM:
head.xy[0].y += 1;
break;
}
}
蛇可以移动了,我们还需要让他能吃到食物
void eatFood() {
if (head.xy[0].x == box.XY.x && head.xy[0].y == box.XY.y) {//很简单的代码
head.xy.push_back(head.nextCoord);
createBox();
}
}
蛇每次移动后,我们需要判断蛇是否吃到自己,是否越界
bool gameOver() {//只需要判断头即可
if (head.xy[0].x<0 || head.xy[0].x>(WIDTH / UNIT - 1) || head.xy[0].y<0 || head.xy[0].y>(HEIGHT / UNIT - 1))
return true;
for (int i = 1; i < head.xy.size(); i++)
if (head.xy[0].x == head.xy[i].x && head.xy[0].y == head.xy[i].y)
return true;
return false;
}
我们还需要渲染食物和蛇
void drawFood() {
setfillcolor(YELLOW);
fillrectangle(box.XY.x * UNIT, box.XY.y * UNIT, (box.XY.x + 1) * UNIT, (box.XY.y + 1) * UNIT);
}
void drawSnake() {
for (int i = 0; i < head.xy.size(); i++) {
setfillcolor(i == 0 ? BLUE : RED);
fillrectangle(head.xy[i].x * UNIT, head.xy[i].y * UNIT, (head.xy[i].x + 1) * UNIT,
(head.xy[i].y + 1) * UNIT);
}
}
贪吃蛇的各个功能已经完成,最后我们可以通过while(true)进行帧驱动
int main() {
int num=init();
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(95, 183, 72));
initSnake();
createBox();
drawSnake();
while (true) {
Sleep(num);//两帧的间隔时间,单位ms
BeginBatchDraw();//批量渲染,防止闪烁
cleardevice();//每次渲染需要清屏
keyDown();
moveSnake();
if (gameOver())break;
eatFood();
drawFood();
drawSnake();
EndBatchDraw();//开始渲染
}
closegraph();
system("cls");
printf("nnn阵亡了nnn");
printf("你的长度:%dn", head.xy.size());
printf("输入x(小写)退出");
while (_getch()!='x');
return 0;
}
完整代码如下
#include <graphics.h>
#include <conio.h>
#include <vector>
#include <cstdio>
#include<time.h>
#define UNIT 20
using namespace std;
struct Coord {
int x;
int y;
};
enum Direct {
LEFT, TOP, RIGHT, BOTTOM
};
struct Box {
Coord XY;
};
struct Body {
vector<Coord> xy;
Coord nextCoord;
Direct mDirect = RIGHT;
};
static Body head;
static Box box;
static int HEIGHT;
static int WIDTH;
void initSnake() {
Coord xy{3, 0};
head.xy.push_back(xy);
}
void drawSnake() {
for (int i = 0; i < head.xy.size(); i++) {
setfillcolor(i == 0 ? BLUE : RED);
fillrectangle(head.xy[i].x * UNIT, head.xy[i].y * UNIT, (head.xy[i].x + 1) * UNIT,
(head.xy[i].y + 1) * UNIT);
}
}
void moveSnake() {
head.nextCoord = head.xy[head.xy.size() - 1];
for (int i = head.xy.size() - 1; i >= 1; i--)
head.xy[i] = head.xy[i - 1];
switch (head.mDirect) {
case RIGHT:
head.xy[0].x += 1;
break;
case LEFT:
head.xy[0].x -= 1;
break;
case TOP:
head.xy[0].y -= 1;
break;
case BOTTOM:
head.xy[0].y += 1;
break;
}
}
void keyDown() {
if (_kbhit())
switch (_getch()) {
case 'a':
if (head.mDirect != RIGHT)
head.mDirect = LEFT;
break;
case 'w':
if (head.mDirect != BOTTOM)
head.mDirect = TOP;
break;
case 'd':
if (head.mDirect != LEFT)
head.mDirect = RIGHT;
break;
case 's':
if (head.mDirect != TOP)
head.mDirect = BOTTOM;
break;
default:
break;
}
}
void createBox() {
box.XY.x = rand() % (WIDTH / UNIT);
box.XY.y = rand() % (HEIGHT / UNIT);
for (auto &i: head.xy)
if (box.XY.x == i.x && box.XY.y == i.y) {
createBox();
break;
}
}
void drawFood() {
setfillcolor(YELLOW);
fillrectangle(box.XY.x * UNIT, box.XY.y * UNIT, (box.XY.x + 1) * UNIT, (box.XY.y + 1) * UNIT);
}
void eatFood() {
if (head.xy[0].x == box.XY.x && head.xy[0].y == box.XY.y) {
head.xy.push_back(head.nextCoord);
createBox();
}
}
bool gameOver() {
if (head.xy[0].x<0 || head.xy[0].x>(WIDTH / UNIT - 1) || head.xy[0].y<0 || head.xy[0].y>(HEIGHT / UNIT - 1))
return true;
for (int i = 1; i < head.xy.size(); i++)
if (head.xy[0].x == head.xy[i].x && head.xy[0].y == head.xy[i].y)
return true;
return false;
}
int init() {
int num;
srand((int)time(0));
printf("玩法:n w(小写):向上移动n s(小写):向下移动n a(小写):向左移动n d(小写):向右移动n");
printf("请输入单元格数:");
scanf_s("%d", &num);
WIDTH = UNIT * num;
HEIGHT = UNIT * num;
printf("n");
printf("请输入刷新间隔(单位ms):");
scanf_s("%d", &num);
return num;
}
int main() {
int num=init();
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(95, 183, 72));
initSnake();
createBox();
drawSnake();
while (true) {
Sleep(num);
BeginBatchDraw();
cleardevice();
keyDown();
moveSnake();
if (gameOver())break;
eatFood();
drawFood();
drawSnake();
EndBatchDraw();
}
closegraph();
system("cls");
printf("nnn阵亡了nnn");
printf("你的长度:%dn", head.xy.size());
printf("输入x(小写)退出");
while (_getch()!='x');
return 0;
}
最后
以上就是贪玩大神为你收集整理的EasyX实现简易贪吃蛇前言演示准备的全部内容,希望文章能够帮你解决EasyX实现简易贪吃蛇前言演示准备所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复