You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
7.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include<iostream>
using namespace std;
#include<easyx.h> //包含图形库头文件
#include<stdlib.h>
#include<time.h>
#define WIDTH 1040 //定义场景大小
#define HEIGHT 640
#define SIZE 20 //定义食物以及蛇的大小 一个格子的大小
#define UP 1 //定义蛇的朝向
#define DOWN -1
#define LEFT 2
#define RIGHT -2
#define MAX 2000 //蛇的最大长度
typedef struct
{
int x;
int y;
}SnakeNode;
SnakeNode temp[MAX]; //用另外一个数组来存储蛇原来的位置
int speed = 150; //蛇的速度
//创建蛇的类
class Snake
{
friend class Food;
public:
Snake(); //初始化
void Move(); //移动
void Draw(); //绘制蛇
bool Eat(Food food); //吃食物
bool Defeat(); //失败判定
private:
int dirt; //朝向
int length; //长度
SnakeNode node[MAX]; //蛇的坐标
};
//创建食物的类
class Food
{
friend class Snake;
public:
Food(Snake snake); //食物初始化
void Draw(); //绘制食物
private:
int x, y; //坐标
};
//蛇的初始化
Snake::Snake()
{
dirt = RIGHT;
length = 3;
//下标是0的位置为蛇的头部
for (int i = 0; i < length; i++)
{
node[i].x = 60 - ((i + 1) * SIZE);//坐标带上20
node[i].y = 0;
} //固定刚开始蛇的位置
//蛇一开始从屏幕的左上角出现
}
//移动
void Snake::Move()
{
for (int i = 0; i < length; i++) //将原来的蛇结点拷贝一份
{
temp[i].x = node[i].x;
temp[i].y = node[i].y;
}
int status = 0; //用来判断是否点击了转向按键
if (dirt == RIGHT) //四个方向,讨论现在的方向,分别判断是否转向,不能反向。
{
//判断是否转向
if (GetAsyncKeyState('W') && status == 0) //捕捉键盘输入为weasyx 判断转向
{
dirt = UP; //去了if(dirt==up)的else
status = 1;
}
else if (GetAsyncKeyState('S') && status == 0)
{
dirt = DOWN;
status = 1;
}
else
{
node[0].x = node[0].x + SIZE;
}
}
if (dirt == DOWN)
{
//判断是否转向
if (GetAsyncKeyState('A') && status == 0)
{
dirt = LEFT;
status = 1;
}
else if (GetAsyncKeyState('D') && status == 0)
{
node[0].x = node[0].x + SIZE;
dirt = RIGHT;
status = 1;
}
else
{
node[0].y = node[0].y + SIZE;
}
}
if (dirt == LEFT)
{
//判断是否转向
if (GetAsyncKeyState('W') && status == 0)
{
dirt = UP;
status = 1;
}
else if (GetAsyncKeyState('S') && status == 0)
{
node[0].y = node[0].y + SIZE;
dirt = DOWN;
status = 1;
}
else
{
node[0].x -= SIZE;
}
}
if (dirt == UP)
{
//判断是否转向
if (GetAsyncKeyState('A') && status == 0)
{
node[0].x = node[0].x - SIZE;
dirt = LEFT;
status = 1;
}
else if (GetAsyncKeyState('D') && status == 0)
{
node[0].x = node[0].x + SIZE;
dirt = RIGHT;
status = 1;
}
else
{
node[0].y = node[0].y - SIZE;
//改变坐标
}
}
//移动
for (int i = 1; i < length; i++)
{
node[i].x = temp[i - 1].x;
node[i].y = temp[i - 1].y;
}
Sleep(speed); //休眠这么长时间,停顿一下
}
//绘制蛇
void Snake::Draw()
{
cleardevice(); //清空原先的绘图
srand((unsigned)time(NULL)); //设置颜色随机数setfillcolor)时用
for (int i = 0; i < length; i++)
{
setfillcolor(RGB(rand() % 256, rand() % 256, rand() % 256)); //五颜六色的蛇
fillrectangle(node[i].x, node[i].y, node[i].x + SIZE, node[i].y + SIZE);
}
}
//吃食物
bool Snake::Eat(Food food)
{
if (food.x == node[0].x && food.y == node[0].y) //头有没有碰到食物
{
if (node[length - 1].x - node[length - 2].x == 0 && node[length - 1].y - node[length - 2].y == -20)
{
//判断蛇尾巴的方向(数组最后两个点的位置关系),新点加在尾巴后面
length++;
node[length - 1].x = node[length - 2].x;
node[length - 1].y = node[length - 2].y - SIZE;
}
else if (node[length - 1].x - node[length - 2].x == 0 && node[length - 1].y - node[length - 2].y == 20)
{
length++;
node[length - 1].x = node[length - 2].x;
node[length - 1].y = node[length - 2].y + SIZE;
}
else if (node[length - 1].x - node[length - 2].x == 20 && node[length - 1].y - node[length - 2].y == 0)
{
length++;
node[length - 1].x = node[length - 2].x + SIZE;
node[length - 1].y = node[length - 2].y;
}
else if (node[length - 1].x - node[length - 2].x == -20 && node[length - 1].y - node[length - 2].y == 0)
{
length++;
node[length - 1].x = node[length - 2].x - SIZE;
node[length - 1].y = node[length - 2].y;
}
return true;
}
return false;
}
//失败判定
bool Snake::Defeat()
{
//碰到边界
if (node[0].x < 0 || node[0].x >= WIDTH || node[0].y < 0 || node[0].y >= HEIGHT)
return true;
//碰到自己的身体
for (int i = 1; i < length; i++)
{
if (node[0].x == node[i].x && node[0].y == node[i].y)
return true;
}
return false;
}
//食物的初始化
Food::Food(Snake snake)
{
table:
srand((unsigned)time(NULL)); //设计随机种子,产生随机数
x = (rand() % (WIDTH / SIZE)) * SIZE;
y = (rand() % (HEIGHT / SIZE)) * SIZE;
for (int i = 0; i < snake.length; i++)
{
if (snake.node[i].x == x && snake.node[i].y == y)
goto table; //如果食物在蛇身上,则重新初始化
}
}
//绘制食物
void Food::Draw()
{
setfillcolor(GREEN); //食物是绿色
fillrectangle(x, y, x + SIZE, y + SIZE); //绘制食物为矩形,四个顶点坐标。
}
int main()
{
initgraph(WIDTH, HEIGHT);
Snake snake;
table:
Food food(snake);
while (1)
{
BeginBatchDraw();
FlushBatchDraw(); //双缓冲,防止屏幕一闪一闪的
snake.Draw();
food.Draw();
FlushBatchDraw(); //双缓冲,防止屏幕一闪一闪的
EndBatchDraw();
/*双缓冲,防止屏幕一闪一闪的*/
if (snake.Eat(food))
{
goto table; //如果吃到食物,就再设置一个食物
}
if (snake.Defeat())
{
break;
}
snake.Move();
}
HWND window = GetHWnd(); //弹窗,提示游戏失败
SetWindowText(window, L"提示"); //修改窗口标题,设置成提示
MessageBox(window, L"游戏失败", L"提示", MB_OKCANCEL);
//提示失败信息 MB_OKCANCEL下面有两个按键确定或取消
return 0;
}