- 编译环境:VS2017(VS其他版本皆可),EasyX图形库
- 编程语言:c/c++
- 当前版本:snakeGame1.0
- 修改时间:2019/6/13
- 项目组成:
5.1 头文件:snake\snake.h,
5.2 源文件:main.cpp, snake\snake.cpp,
5.3 资源文件:1.mp3, jinbi.jpg, jinbi.mp3, siwang.mp3,
#pragma once
/*
* 贪吃蛇头文件
*/
#include
#include
#include
#include
#pragma comment(lib, "winmm.lib")
//蛇的状态,U:上; D:下; L:左; R:右.
constexpr auto U = 1;
constexpr auto D = 2;
constexpr auto L = 3;
constexpr auto R = 4;
//蛇类型
struct snake
{
int x, y; //坐标
int color; //颜色
struct snake* next; //下一节蛇身
};
//贪吃蛇游戏类
class snakeGame
{
public:
//全局变量
HWND hWnd; //窗口句柄
//IMAGE bk; //背景图片变量
int score; //金币
int add; //单价
int grade; //难度等级
int sleeptime; //每次运行的时间间隔
int endGamestatus; //游戏结束的情况,1:撞到墙; 2:咬到自己; 3:主动退出游戏.
int status; //蛇的状态
snake *head, *food; //蛇头指针和食物指针
snake *q; //遍历蛇用到的指针
IMAGE jinbi; //金币图片
//函数声明
snakeGame(int score = 0, int add = 10, int grade = 1,
int sleeptime = 150, int endGamestatus = 0); //拷贝构造函数
void initGame(); //游戏初始化
void drawGame(); //绘制游戏界面
void ctolGame(); //游戏控制
void initSnake(); //蛇身初始化
void creatMap(); //创建地图
void createFood(); //随机出现食物
void snakeMove(); //蛇移动
int endGame(); //游戏结束
int snakeMain(); //贪吃蛇主函数
};
#include "snake\snake.h"
int main()
{
snakeGame Snake;
Snake.snakeMain();
return 0;
}
#include "snake.h"
/*
* 贪吃蛇游戏函数定义
*/
//拷贝构造函数
snakeGame::snakeGame(int score, int add, int grade, int sleeptime, int endGamestatus)
{
this->score = score;
this->add = add;
this->grade = grade;
this->sleeptime = sleeptime;
this->endGamestatus = endGamestatus;
}
//游戏初始化
void snakeGame::initGame()
{
//创建地图
creatMap();
//蛇身初始化
initSnake();
//创建食物
createFood();
//加载背景音乐
mciSendString("open snake\\1.mp3", NULL, NULL, NULL);
//循环播放背景音乐
mciSendString("play snake\\1.mp3 repeat", NULL, NULL, NULL);
//加载金币图片
loadimage(&jinbi, "snake\\jinbi.jpg", 20, 20, true);
}
//绘制游戏界面
void snakeGame::drawGame()
{
char mon[32] = { NULL }; //金币
char vel[32] = { NULL }; //速度
char dif[32] = { NULL }; //困难
char one[32] = { NULL }; //单价
BeginBatchDraw();
setfillcolor(RGB(195, 195, 195)); //边框颜色
solidrectangle(0, 0, 680, 680);
setfillcolor(RGB(128, 255, 0)); //背景颜色
solidrectangle(20, 20, 660, 660);
setfillcolor(RGB(0, 0, 255)); //网格颜色
for (int i = 40; i <= 640; i += 20)
for (int j = 40; j <= 640; j += 20)
solidcircle(i, j, 1);
//绘制蛇身
q = head;
setfillcolor(YELLOW);
solidcircle(q->x + 10, q->y + 10, 10); //蛇头
q = q->next;
while (q != NULL)
{
setfillcolor(q->color);
solidcircle(q->x + 10, q->y + 10, 10); //蛇身
q = q->next;
}
//绘制食物
putimage(food->x, food->y, &jinbi);
//当前信息
setfillcolor(RGB(0, 0, 0)); //信息区背景颜色
solidrectangle(680, 0, 1020, 680);
setbkcolor(RGB(0, 0, 0)); //字体背景颜色
_itoa_s(score, mon, 10);
_itoa_s((10000 / sleeptime), vel, 10);
_itoa_s((300 - sleeptime) / 30, dif, 10);
_itoa_s(add, one, 10);
setcolor(RGB(255, 255, 255)); //字体颜色
outtextxy(730, 10, "金币:"); outtextxy(775, 10, mon);
outtextxy(730, 30, "速度:"); outtextxy(775, 30, vel);
outtextxy(730, 60, "难度:"); outtextxy(775, 60, dif);
outtextxy(730, 80, "单价:"); outtextxy(775, 80, one);
//说明界面
outtextxy(700, 150, "不能穿墙,不能咬到自己!");
outtextxy(700, 200, "控制方向:");
outtextxy(800, 200, "↑↓←→");
outtextxy(700, 250, "加速:F1");
outtextxy(780, 250, "减速:F2");
outtextxy(700, 270, "退出:Esc");
outtextxy(780, 270, "暂停:Space");
EndBatchDraw();
}
//游戏控制
void snakeGame::ctolGame()
{
if (GetAsyncKeyState(VK_UP) && status != D)
{ //上
status = U;
}
else if (GetAsyncKeyState(VK_DOWN) && status != U)
{ //下
status = D;
}
else if (GetAsyncKeyState(VK_LEFT) && status != R)
{ //左
status = L;
}
else if (GetAsyncKeyState(VK_RIGHT) && status != L)
{ //右
status = R;
}
else if (GetAsyncKeyState(VK_SPACE))
{ //暂停
while (1)
{
Sleep(300);
if (GetAsyncKeyState(VK_SPACE))
{ //再次按空格键退出死循环
break;
}
}
}
else if (GetAsyncKeyState(VK_ESCAPE))
{ //退出
while (1)
{ //松手检测
if (!GetAsyncKeyState(VK_ESCAPE))
{ //松开退出游戏
endGamestatus = 3;
endGame();
break;
}
}
}
else if (GetAsyncKeyState(VK_F1))
{ //加速
while (1)
{
if (!GetAsyncKeyState(VK_F1))
{ //松手检测
if (sleeptime > 60)
{ //速度不能太快
sleeptime = sleeptime - 30;
add = add + 2;
}
break;
}
}
}
else if (GetAsyncKeyState(VK_F2))
{ //减速
while (1)
{
if (!GetAsyncKeyState(VK_F2))
{ //松手检测
if (sleeptime < 270)
{ //单价不能小于0
sleeptime = sleeptime + 30;
add = add - 2;
}
break;
}
}
}
Sleep(sleeptime);
snakeMove();
}
//蛇身初始化
void snakeGame::initSnake()
{
snake *tail; //蛇尾指针
int i;
//从蛇尾开始,头插法,以x,y设定开始的位置
tail = (snake*)malloc(sizeof(snake));
tail->x = 200;
tail->y = 40;
tail->color = RGB(255, 0, 0);
tail->next = NULL;
//初始长度为4
for (i = 1; i <= 4; i++)
{
head = (snake*)malloc(sizeof(snake));
head->next = tail;
head->x = 200 + 20 * i;
head->y = 40;
head->color = RGB(255, 0, 0);
tail = head;
}
//蛇移动方向向右
status = R;
}
//创建地图
void snakeGame::creatMap()
{
hWnd = initgraph(1020, 680); //做窗口
//欢迎界面
MessageBox(hWnd, "欢迎来到贪吃蛇游戏!", "帅气的龙少提示你:", MB_OK);
outtextxy(320, 260, "用↑.↓.←.→分别控制蛇的移动, F1 为加速,F2为减速");
outtextxy(360, 280, "加速将能得到更高的分数");
getch();
cleardevice();
}
//随机出现食物
void snakeGame::createFood()
{
snake *food_1;
//为了防止每次产生的随机数相同,种子设置为time
srand((unsigned)time(NULL));
//创建食物
food_1 = (snake*)malloc(sizeof(snake));
if (food_1 == NULL) return createFood();
do
{ //保证其为10的倍数,使得食物能与蛇头对其
food_1->x = rand() % 620 + 20;
food_1->y = rand() % 620 + 20;
} while ((food_1->x % 20 != 0) || (food_1->y % 20 != 0));
food_1->color = RGB(rand() % 256, rand() % 256, rand() % 256);
q = head;
while (q)
{
if (q->x == food_1->x && q->y == food_1->y)
{ //判断蛇身是否与食物重合
free(food_1);
createFood();
return;
}
q = q->next;
}
//加载食物
food = food_1;
}
//蛇前进,上U,下D,左L,右R
void snakeGame::snakeMove()
{
snake * nexthead = (snake*)malloc(sizeof(snake));
if (nexthead == NULL) return snakeMove();
if (status == U)
{
nexthead->x = head->x;
nexthead->y = head->y - 20;
nexthead->color = RGB(255, 0, 0);
if (nexthead->x == food->x && nexthead->y == food->y)//如果下一个有食物//
{
mciSendString("open snake\\jinbi.mp3 alias media", NULL, NULL, NULL);
mciSendString("set media time format milliseconds", NULL, NULL, NULL);
mciSendString("play media from 0", NULL, NULL, NULL);
nexthead->next = head;
head = nexthead;
q = head;
while (q != NULL)
{
q = q->next;
}
score = score + add;
createFood();
}
else //如果没有食物//
{
nexthead->next = head;
head = nexthead;
q = head;
while (q->next->next != NULL)
{
q = q->next;
}
free(q->next);
q->next = NULL;
}
}
if (status == D)
{
nexthead->x = head->x;
nexthead->y = head->y + 20;
nexthead->color = RGB(255, 0, 0);
if (nexthead->x == food->x && nexthead->y == food->y) //有食物
{
mciSendString("open snake\\jinbi.mp3 alias media", NULL, NULL, NULL);
mciSendString("set media time format milliseconds", NULL, NULL, NULL);
mciSendString("play media from 0", NULL, NULL, NULL);
nexthead->next = head;
head = nexthead;
q = head;
while (q != NULL)
{
q = q->next;
}
score = score + add;
createFood();
}
else //没有食物
{
nexthead->next = head;
head = nexthead;
q = head;
while (q->next->next != NULL)
{
q = q->next;
}
free(q->next);
q->next = NULL;
}
}
if (status == L)
{
nexthead->x = head->x - 20;
nexthead->y = head->y;
nexthead->color = RGB(255, 0, 0);
if (nexthead->x == food->x && nexthead->y == food->y)//有食物
{
mciSendString("open snake\\jinbi.mp3 alias media", NULL, NULL, NULL);
mciSendString("set media time format milliseconds", NULL, NULL, NULL);
mciSendString("play media from 0", NULL, NULL, NULL);
nexthead->next = head;
head = nexthead;
q = head;
while (q != NULL)
{
q = q->next;
}
score = score + add;
createFood();
}
else //没有食物
{
nexthead->next = head;
head = nexthead;
q = head;
while (q->next->next != NULL)
{
q = q->next;
}
free(q->next);
q->next = NULL;
}
}
if (status == R)
{
nexthead->x = head->x + 20;
nexthead->y = head->y;
nexthead->color = RGB(255, 0, 0);
if (nexthead->x == food->x && nexthead->y == food->y)//有食物
{
mciSendString("open snake\\jinbi.mp3 alias media", NULL, NULL, NULL);
mciSendString("set media time format milliseconds", NULL, NULL, NULL);
mciSendString("play media from 0", NULL, NULL, NULL);
nexthead->next = head;
head = nexthead;
q = head;
while (q != NULL)
{
q = q->next;
}
score = score + add;
createFood();
}
else //没有食物
{
nexthead->next = head;
head = nexthead;
q = head;
while (q->next->next != NULL)
{
q = q->next;
}
free(q->next);
q->next = NULL;
}
}
//判断蛇是否会咬到自己
snake *self;
self = head->next;
while (self)
{ //蛇自己指针遍历
if (self->x == head->x && self->y == head->y)
{
endGamestatus = 2;
endGame();
}
self = self->next;
}
if (head->x < 20 || head->x > 640 || head->y < 20 || head->y > 640)
{ //不能穿墙
endGamestatus = 1;
endGame();
}
}
//结束游戏
int snakeGame::endGame()
{
mciSendString("stop snake\\1.mp3", NULL, NULL, NULL);
mciSendString("open snake\\siwang.mp3", NULL, NULL, NULL);
mciSendString("play snake\\siwang.mp3", NULL, NULL, NULL);
switch (endGamestatus)
{
case 1: MessageBox(hWnd, "对不起,您撞到墙了,结束游戏!", "帅气的龙少提示你:", NULL); break;
case 2: MessageBox(hWnd, "对不起,您咬到自己了,结束游戏!", "帅气的龙少提示你:", NULL); break;
case 3: MessageBox(hWnd, "您的游戏已经结束了!", "帅气的龙少提示你:", NULL); break;
}
closegraph();//关闭图形界面
exit(0);//退出
}
//贪吃蛇游戏主函数
int snakeGame::snakeMain()
{
initGame();
while (1)
{
drawGame();
ctolGame();
}
return 0;
}
百度网盘提取码:xpdm
百度网盘提取码:pq7b
百度网盘提取码:sow8
百度网盘提取码:xc1n