C/C++制作简易版贪吃蛇游戏
一、开发环境
使用Visual Stdio 2019,Visual Studio即可生成基于本机和托管基于MSBuild的应用程序的工具。安装此程序时,可以选择安装C ++编译器和库。
二、设计逻辑
蛇身体初始有三节,记录对应的蛇每一节的x和y坐标.通过键盘来控制蛇的身体的坐标的相应变化,从而在屏幕上呈现蛇的身体移动。食物将通过随机数来产生相应的食物坐标。
三、代码块
3.1 使用initgraph()函数
初始化屏幕大小 在有文件#include<graphics.h>下使用initgraph()函数对屏幕显示的大小和颜色进行调整。
`void Initialization_show()
{
initgraph(HEIGHT, WEIGHT);
}`
?其中的WEIGHT和WEIGHT是我对高度和宽度进行的宏定义,这里也可以直接输入整形变量。因为graphics.h是tc所特有的函数库,在vc和vs中是没有的,所以要借助插件Easyx图形库。 1、打开官网http://www.easyx.cn,选择下载 2、下载好后点击打开,它会自动识别vs2019的,然后按照下图操作
3.2定义蛇和食物的结构体
struct Snake
{
public:
int size;
int dir;
int speed;
POINT coor[MAX];
};
struct Snake_Food
{
public:
int Food_x;
int Food_y;
int Food_r;
bool Food_flag;
DWORD Food_color;
};
蛇和食物将通过绘制圆的方法实现,需要的是圆的半径和对应的圆心坐标,同样食物也是如此。其中蛇的身体需要定义有多少段,食物则定义了颜色和判断被吃条件。
3.3随机产生食物的坐标以及定义初始化的蛇的数据
Snake snake;
Snake_Food food;
void Food_Property()
{
srand((int)time(0));
food.Food_r = rand() % 10 + 5;
food.Food_x = rand() % (HEIGHT - food.Food_r);
food.Food_y = rand() % (WEIGHT - food.Food_r);
food.Food_color = RGB(rand() % 256, rand() % 256, rand() % 256);
food.Food_flag = true;
}
void Initialization_data()
{
snake.size = 3;
snake.speed =10;
snake.dir=RIGHT;
Food_Property();
for (int i=0; i <snake.size;i++)
{
snake.coor[i].x =40-10*i;
snake.coor[i].y = 10;
}
}
随机数可以是用#include <time.h>头文件下的rank和srand函数,
其中 srand((int)time(0));
rank()%(数字m),表示对产生的随机数进行区域,来控制随机数的上限。
3.3绘制对象
void GameDraw()
{
BeginBatchDraw();
setbkcolor(RGB(28, 115, 119));
cleardevice();
setfillcolor(RED);
if (food.Food_flag )
{
solidcircle(food.Food_x,food.Food_y,food.Food_r);
}
for (int i=0;i<snake.size;i++)
{
solidcircle(snake.coor[i].x, snake.coor[i].y, 5);
}
EndBatchDraw();
}
通过使用GameDraw()函数对蛇和食物进行绘制。
3.4 食物被吃和产生新的食物
void Eat_Food()
{
if (food.Food_x - food.Food_r <= snake.coor[0].x && snake.coor[0].x <= food.Food_x + food.Food_r &&
food.Food_y - food.Food_r <= snake.coor[0].y && snake.coor[0].y <= food.Food_y + food.Food_r &&
food.Food_flag)
{
food.Food_flag = false;
snake.size ++;
}
if (food.Food_flag == false)
{
Food_Property();
}
}
判断蛇头的坐标是否在食物构成的圆类,当蛇头坐标到达圆内同时食物还未被吃将执行蛇身体加长,重新调用食物属性函数随机产生食物。
3.5 按键控制
enum DIR
{
UP,
DOWN,
LEFT,
RIGHT,
};
void keyControl_S()
{
if (_kbhit())
{
switch (_getch())
{
case'W':
case'w':
case 72:if(snake.dir !=DOWN)
snake.dir = UP;
break;
case'S':
case's':
case 80:if(snake.dir!=UP)
snake.dir = DOWN;
break;
case'A':
case'a':
case 75:if(snake.dir != RIGHT)
snake.dir = LEFT;
break;
case'D':
case'd':
case 77:if (snake.dir != LEFT)
snake.dir = RIGHT;
break;
case ' ':
while (true)
{
if (_getch() == ' ')
{
return;
}
}
break;
}
}
}
通过使用按键按下的字符,给蛇方向变量进行赋值,枚举定义四个方向变量。
3.6 蛇的移动
void SnakeMove_Nodead()
{
int times = 200;
for (int i = snake.size - 1; i > 0; i--)
{
snake.coor[i] = snake.coor[i - 1];
}
,
switch (snake.dir)
{
case RIGHT:
snake.coor[0].x += snake.speed;
if (snake.coor[0].x - 10 >= HEIGHT)
{
snake.coor[0].x = 0;
}
Sleep(times);
break;
case LEFT:
snake.coor[0].x -= snake.speed;
if (snake.coor[0].x + 10 <= 0)
{
snake.coor[0].x = HEIGHT;
}
Sleep(times);
break;
case UP:
snake.coor[0].y -= snake.speed;
if (snake.coor[0].y+10 <= 0)
{
snake.coor[0].y = WEIGHT;
}
Sleep(times);
break;
case DOWN:
snake.coor[0].y += snake.speed;
if (snake.coor[0].y - 10 >= WEIGHT)
{
snake.coor[0].y = 0;
}
Sleep(times);
break;
}
}
通过刷新坐标对蛇进行移动,对按键获取到的键执行对应的坐标变换操作,对蛇头坐标变换后,蛇第二节取得之前蛇头坐标,蛇的第三节取得第二节的坐标…,依次进行对坐标的刷新
四、源代码下载
#include<iostream>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<graphics.h>
#include<time.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
#define MAX 500
#define HEIGHT 940
#define WEIGHT 580
using namespace std;
enum DIR
{
UP,
DOWN,
LEFT,
RIGHT,
};
void Initialization_show()
{
initgraph(HEIGHT, WEIGHT);
}
struct Snake
{
public:
int size;
int dir;
int speed;
POINT coor[MAX];
};
struct Snake_Food
{
public:
int Food_x;
int Food_y;
int Food_r;
bool Food_flag;
DWORD Food_color;
};
Snake snake;
Snake_Food food;
void Food_Property()
{
srand((int)time(0));
food.Food_r = rand() % 10 + 5;
food.Food_x = rand() % (HEIGHT - food.Food_r);
food.Food_y = rand() % (WEIGHT - food.Food_r);
food.Food_color = RGB(rand() % 256, rand() % 256, rand() % 256);
food.Food_flag = true;
}
void Initialization_data()
{
snake.size = 3;
snake.speed =10;
snake.dir=RIGHT;
Food_Property();
for (int i=0; i <snake.size;i++)
{
snake.coor[i].x =40-10*i;
snake.coor[i].y = 10;
}
}
void GameDraw()
{
BeginBatchDraw();
setbkcolor(RGB(28, 115, 119));
cleardevice();
setfillcolor(RED);
if (food.Food_flag )
{
solidcircle(food.Food_x,food.Food_y,food.Food_r);
}
for (int i=0;i<snake.size;i++)
{
solidcircle(snake.coor[i].x, snake.coor[i].y, 5);
}
EndBatchDraw();
}
void Eat_Food()
{
if (food.Food_x - food.Food_r <= snake.coor[0].x && snake.coor[0].x <= food.Food_x + food.Food_r &&
food.Food_y - food.Food_r <= snake.coor[0].y && snake.coor[0].y <= food.Food_y + food.Food_r &&
food.Food_flag)
{
food.Food_flag = false;
snake.size ++;
}
if (food.Food_flag == false)
{
Food_Property();
}
}
void SnakeMove_Nodead()
{
int times = 200;
for (int i = snake.size - 1; i > 0; i--)
{
snake.coor[i] = snake.coor[i - 1];
}
switch (snake.dir)
{
case RIGHT:
snake.coor[0].x += snake.speed;
if (snake.coor[0].x - 10 >= HEIGHT)
{
snake.coor[0].x = 0;
}
Sleep(times);
break;
case LEFT:
snake.coor[0].x -= snake.speed;
if (snake.coor[0].x + 10 <= 0)
{
snake.coor[0].x = HEIGHT;
}
Sleep(times);
break;
case UP:
snake.coor[0].y -= snake.speed;
if (snake.coor[0].y+10 <= 0)
{
snake.coor[0].y = WEIGHT;
}
Sleep(times);
break;
case DOWN:
snake.coor[0].y += snake.speed;
if (snake.coor[0].y - 10 >= WEIGHT)
{
snake.coor[0].y = 0;
}
Sleep(times);
break;
}
}
void keyControl_S()
{
if (_kbhit())
{
switch (_getch())
{
case'W':
case'w':
case 72:if(snake.dir !=DOWN)
snake.dir = UP;
break;
case'S':
case's':
case 80:if(snake.dir!=UP)
snake.dir = DOWN;
break;
case'A':
case'a':
case 75:if(snake.dir != RIGHT)
snake.dir = LEFT;
break;
case'D':
case'd':
case 77:if (snake.dir != LEFT)
snake.dir = RIGHT;
break;
case ' ':
while (true)
{
if (_getch() == ' ')
{
return;
}
}
break;
}
}
}
void test01()
{
while (true)
{
GameDraw();
SnakeMove_Nodead();
keyControl_S();
Eat_Food();
}
}
int main()
{
Initialization_show();
Initialization_data();
GameDraw();
SnakeMove_Nodead();
test01();
system("pause");
return 0;
}
其中使用了mciSendString函数进行了游戏背景音乐的添加。我也是刚接触C++两个多星期,本次设计是根据b站视频学的加以自己的理解,所表述可能存在问题。
|