C++基于EasyX制作贪吃蛇游戏(二)第一版代码与程序
本文首发于我的个人博客www.colourso.top,欢迎来访。
原文链接:http://www.colourso.top/c-snake-pro1/
原文写于2019-06-21,本次重新整理。
上一篇博客写了贪吃蛇第一版的文档,这一篇博客就把第一版本的贪吃蛇代码展示一下,附带源码与可执行文件的下载。
开发环境
原博客环境:
工具: VS2013
依赖: EasyX Library for C++ (Ver:20180727(beta)
整理时环境:
工具:VS2017
依赖:EasyX Library for C++ (Ver:20200520(beta))
VS2017属性页设置
注意字符集为Unicode字符集。
新版源代码
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
//蛇头方向预定义
#define UP 1 //↑
#define RIGHT 2 //→
#define DOWN 3 //↓
#define LEFT 4 //←
/*-------------结构体定义---------------*/
typedef struct Node //蛇的节点
{
int x; //横左边
int y; //纵坐标
struct Node *next; //指向下一个节点的指针
struct Node *pre; //指向前一个节点的指针
} *LinkNode;
struct Snake //蛇的结构体
{
LinkNode head; //指向头节点的指针
LinkNode tail; //指向尾节点的指针
int direction; //蛇头方向
int num; //节点数目
};
struct Food //食物结构体
{
int x; //横坐标
int y; //纵坐标
bool exist; //是否存在,1表示存在
};
/*-------------全局变量---------------*/
int g_score = 0; //获得分数
Snake snake; //游戏中的蛇本体
Food food; //食物
/*-------------函数声明---------------*/
void init(); //初始化
void drawgame(); //绘制界面
void gameplay(); //开始游戏
void close(); //释放资源
void drawfood(Food food); //绘制食物
void drawsnake(Snake snake); //绘制蛇
void drawsnakenode(Node node); //绘制蛇的结点
void clearsnakenode(Node node); //清除蛇的结点
void snakebodymove(Snake &snake); //蛇身体结点向前复制
bool collidesnake(Snake snake); //碰撞自身检测
void drawscore(); //绘制分数
void clearscore(); //清除分数
/*-------------程序入口---------------*/
int main()
{
init();
drawgame();
gameplay();
close();
return 0;
}
/*-------------函数实现---------------*/
//初始化
void init()
{
initgraph(640, 480); //初始化窗口
//setorigin(0, 480); //设置坐标原点
//setaspectratio(1, -1); //使y轴向上为正
//蛇与食物初始化
//食物初始坐标为(310,230)
food.x = 310;
food.y = 230;
food.exist = true;
//蛇初始长度为3,蛇头坐标为(210,230)
//在堆上开辟空间,防止此函数的生命周期结束后结点全部被释放掉
LinkNode nodes2 = (LinkNode)malloc(sizeof(Node));
nodes2->x = 170;
nodes2->y = 230;
nodes2->next = nullptr;
LinkNode nodes1 = (LinkNode)malloc(sizeof(Node));
nodes1->x = 190;
nodes1->y = 230;
nodes1->next = nodes2;
LinkNode nodes0 = (LinkNode)malloc(sizeof(Node));
nodes0->x = 210;
nodes0->y = 230;
nodes0->next = nodes1;
nodes2->pre = nodes1;
nodes1->pre = nodes0;
nodes0->pre = nullptr;
snake.head = nodes0;
snake.tail = nodes2;
snake.direction = RIGHT;
snake.num = 3;
//初始分数
g_score = (snake.num - 3) * 10;
}
//绘制界面
void drawgame()
{
//画宽度为2的棕色实线,分割区域
setlinecolor(BROWN);
setlinestyle(PS_SOLID, 2);
line(482, 0, 482, 480);
//绘制食物
drawfood(food);
//绘制蛇
drawsnake(snake);
//绘制分数
drawscore();
}
//开始游戏
void gameplay()
{
Node ends; //末尾结点
while (1)
{
ends.x = snake.tail->x;
ends.y = snake.tail->y;
if (!food.exist)
{
int x;
int y;
while (1)
{
srand(time(0));
x = (rand() % 24) * 20 + 10;
y = (rand() % 24) * 20 + 10;
//食物位置检测算法
LinkNode linknode = snake.head;
bool cont = true;
while (linknode != snake.tail->next)
{
if (linknode->x == x && linknode->y == y)
{
cont = false;
break;
}
linknode = linknode->next;
}
if (cont)
{
break;
}
}
food.x = x;
food.y = y;
food.exist = true;
drawfood(food);
}
//按键
if (_kbhit())
{
char key = _getch();
switch (key)
{
case 72: //↑
if (snake.direction != UP && snake.direction != DOWN)
snake.direction = UP;
break;
case 80: //↓
if (snake.direction != UP && snake.direction != DOWN)
snake.direction = DOWN;
break;
case 75: //←
if (snake.direction != LEFT && snake.direction != RIGHT)
snake.direction = LEFT;
break;
case 77: //→
if (snake.direction != LEFT && snake.direction != RIGHT)
snake.direction = RIGHT;
break;
}
}
//消除走过的尾部结点
clearsnakenode(ends);
//前进
switch (snake.direction)
{
case UP:
{
//头部y-20,x不变
snakebodymove(snake);
snake.head->y -= 20;
drawsnakenode(*(snake.head));
break;
}
case RIGHT:
{
//头部x+20,y不变
snakebodymove(snake);
snake.head->x += 20;
drawsnakenode(*(snake.head));
break;
}
case DOWN:
{
//头部y+20,x不变
snakebodymove(snake);
snake.head->y += 20;
drawsnakenode(*(snake.head));
break;
}
case LEFT:
{
//头部x-20,y不变
snakebodymove(snake);
snake.head->x -= 20;
drawsnakenode(*(snake.head));
break;
}
}
//蛇吃食物
if (snake.head->x == food.x && snake.head->y == food.y && food.exist)
{
food.exist = false;
//isClear = false;
//分数变化
g_score += 10;
//在末尾增加新的结点,维护双向链表的关系
LinkNode nodes = (LinkNode)malloc(sizeof(Node));
nodes->x = ends.x;
nodes->y = ends.y;
nodes->next = snake.tail->next;
nodes->pre = snake.tail;
snake.tail->next = nodes;
snake.tail = nodes;
++snake.num;
drawsnakenode(ends);
clearscore();
drawscore();
}
//碰撞判断
bool collidewall = snake.head->x < 10 || snake.head->x > 470 || snake.head->y < 10 || snake.head->y > 470;
if (collidewall || collidesnake(snake))
{
cleardevice();
TCHAR s[] = _T("game over");
settextstyle(48, 0, _T("黑体"));
outtextxy(230, 280, s);
break;
}
Sleep(150);
}
}
//释放资源
void close()
{
_getch();
closegraph();
}
//绘制食物
void drawfood(Food food)
{
//红色,全填充,无边框的圆
setfillcolor(RED);
setfillstyle(BS_SOLID);
solidcircle(food.x, food.y, 8);
}
//绘制蛇的结点
void drawsnakenode(Node node)
{
//绿色,全填充,无边框的正方形
setfillcolor(GREEN);
setfillstyle(BS_SOLID);
solidrectangle(node.x - 9, node.y + 9, node.x + 9, node.y - 9);
}
//清除蛇的结点
void clearsnakenode(Node node)
{
//黑色,全填充,无边框的正方形
setfillcolor(BLACK);
setfillstyle(BS_SOLID);
solidrectangle(node.x - 9, node.y + 9, node.x + 9, node.y - 9);
}
//绘制蛇
void drawsnake(Snake snake)
{
LinkNode linknode = snake.head;
while (linknode != snake.tail->next)
{
drawsnakenode(*linknode);
linknode = linknode->next;
}
}
//蛇身体结点向前复制
void snakebodymove(Snake &snake)
{
LinkNode linknode = snake.tail;
while (linknode != snake.head)
{
linknode->x = linknode->pre->x;
linknode->y = linknode->pre->y;
linknode = linknode->pre;
}
}
//碰撞自身检测
bool collidesnake(Snake snake)
{
if (snake.num <= 3)
return false;
LinkNode node = snake.head->next;
while (node != snake.tail->next)
{
if (node->x == snake.head->x && node->y == snake.head->y)
return true;
node = node->next;
}
return false;
}
//绘制分数
void drawscore()
{
TCHAR s[] = _T("获得分数:");
settextstyle(16, 0, _T("黑体"));
outtextxy(485, 300, s);
TCHAR t[5];
_stprintf_s(t, _T("%d"), g_score); // 高版本 VC 推荐使用 _stprintf_s 函数
outtextxy(560, 300, t);
}
//清除分数
void clearscore()
{
//黑色,全填充,无边框的正方形
setfillcolor(BLACK);
setfillstyle(BS_SOLID);
solidrectangle(485, 480, 640, 300);
}
程序展示
以下是B站视频
上面视频不能播放请移步:https://www.bilibili.com/video/BV1bA411Y7L9/
程序下载
原先:百度网盘链接:https://pan.baidu.com/s/1O3EqtcAeciukwt2uixC7RQ
提取码:tm95
新第一版:链接:https://pan.baidu.com/s/1hNfVsYZp-I6dH2875FR7iw
提取码:a4b2
Github地址:https://github.com/Colourso/Simple-CPP-project-by-Colourso/
其他
关于上述程序之中的一些问题,比如使用vs生成的文件结构、字符集设置的问题,还有_T()
是什么意思?
请查看这篇博客:VS开发C++的一些问题——VS项目工程文件、Debug与Relase模式、字符集问题以及_T()宏。