请用安装了TC图形库的编译器运行,如果你有vs没有TC库,请点这个
安装TC库点这里
如果你连VS也没有的话,点这里
安装vs点这里
图片附上
运行代码前,请先将vs的属性里面的高级设置为多字节字符集,而且要关闭SDL
Code
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_SPACE 32
#define KEY_PAUSE 81
#define KEY_EXIT 69
const int MAX = 1000; //蛇最大是1000节
const int radius = 10;//蛇每节是个圆型,每个圆的半径为10
using namespace std;
char str[50];
int ID; //获取窗口句柄选择操作的整形数字
int score; //游戏中蛇的得分
HWND hwnd; //创建的图形界面的句柄
char key; //用来暂时存储玩家每次按下的键,以便于更新蛇的默认键,或者操作菜单界面
int SP = 100; //蛇移动的速度
int isGame;//判断是否进入了游戏界面,当进入游戏界面时这个值是1,在菜单界面值是0,进入游戏界面才可以进行暂停的操作
int num;//按了几次空格键,一次就暂停游戏,二次就又恢复游戏状态,默认是0,按了一次是1,再按一次是0
class COOR
{
public:
int x;
int y;
COOR() {}
COOR(int a, int b) :x(a), y(b) {}
~COOR() {} //析构函数,销毁类实例前调用
};
class SNAKE
{
public:
int node; //蛇的节数
struct COOR Spos[MAX]; //记录每节的坐标
char key; //此时蛇处于的移动按键状态
SNAKE() {}
~SNAKE() {}
};
SNAKE snake; //初始创建的蛇
class FOOD
{
public:
class COOR Fpos; //食物的坐标
bool iseat; //游戏中食物是否被吃掉,默认是被吃,便于创建食物
FOOD() {}
~FOOD() {}
};
FOOD food; //初始创建的食物
void GameInit()
{
srand((unsigned int)time(NULL));//初始化随机数种子
hwnd = initgraph(1000, 740); //游戏窗口,宽1000px,高740px
num = 1; //初始游戏是暂停的
isGame = 0; //初始是菜单界面,不是游戏界面,所以设置为0
food.iseat = true; //初始生成食物
setbkmode(TRANSPARENT); //设置文字背景为透明色,防止文字背景颜色干扰
snake.key = KEY_RIGHT; //初始蛇是朝向右边的
snake.node = 3; //初始蛇的节数是3节
snake.Spos[0].x = 260;snake.Spos[0].y = 240; //蛇头
snake.Spos[1].x = 240;snake.Spos[1].y = 240;
snake.Spos[2].x = 220;snake.Spos[2].y = 240;
score = 0; //初始游戏得分是0
}
void DrawSnake() //在图形界面画出蛇
{
isGame = 1; //1代表进入了游戏界面
BeginBatchDraw(); //开始批量画图
Sleep(SP);
for (int i = 0;i < snake.node;++i)
{
if (i == 0)
{
//setfillstyle(BS_HATCHED, HS_BDIAGONAL);//填充内部图形设置为斜线型(HS_BDIAGONAL)
setfillcolor(WHITE);
solidcircle(snake.Spos[i].x, snake.Spos[i].y, radius);
//setfillstyle(NULL);
}
else
{
setfillcolor(RGB(rand() % 256, rand() % 256, rand() % 256));//设置画填充图形的颜色为3种
//随机颜色的合成色
solidcircle(snake.Spos[i].x, snake.Spos[i].y, radius);//按照每节蛇的x,y坐标画一个无边界填充的圆
}
}
EndBatchDraw(); //结束批量画图
}
void SnakeMove()
{
for (int i = snake.node - 1;i > 0;--i)//迭代蛇的节点坐标,制作移动的效果
{
if (i == snake.node - 1) clearcircle(snake.Spos[i].x, snake.Spos[i].y, radius);
snake.Spos[i].x = snake.Spos[i - 1].x;
snake.Spos[i].y = snake.Spos[i - 1].y;
}
switch (snake.key) //蛇的移动归根结底就是蛇头的移动
{
case KEY_LEFT:snake.Spos[0].x -= 20; break;
case KEY_RIGHT:snake.Spos[0].x += 20; break;
case KEY_UP:snake.Spos[0].y -= 20; break;
case KEY_DOWN:snake.Spos[0].y += 20; break;
}
}
void GameOver() //游戏结束操作
{
isGame = 2; //此时是游戏结束阶段
num = 1; //游戏结束暂停界面,不能再操作
settextcolor(LIGHTRED); //设置字体为亮红色
settextstyle(120, 80, _T("Consolas"));
outtextxy(30, 280, "GameOver!");
settextcolor(YELLOW); //设置字体为亮红色
settextstyle(30, 30, _T("Consolas"));
outtextxy(100, 520, "按任意键退出游戏!");
if (_kbhit()) exit(0); //若此时按下键盘键,exit退出程序
}
void SnakeDeath() //判断蛇是否死亡的函数
{
if (snake.Spos[0].x >= 741 || snake.Spos[0].x <= 39 || snake.Spos[0].y <= 39 || snake.Spos[0].y >= 701) //撞墙死亡
{
GameOver();return;
}
else
{
for (int i = 1;i < snake.node;++i)
if (snake.Spos[i].x == snake.Spos[0].x && snake.Spos[i].y == snake.Spos[0].y)//撞到自己
{
GameOver();return;
}
}
}
void KeyBoard() //监控键盘输入
{
switch (key)
{
case KEY_LEFT:
if (snake.key != KEY_RIGHT && num != 1 && isGame == 1)
snake.key = key;
break;
case KEY_RIGHT:
if (snake.key != KEY_LEFT && num != 1 && isGame == 1)
snake.key = key;
break;
case KEY_UP:
if (snake.key != KEY_DOWN && num != 1 && isGame == 1)
snake.key = key;
break;
case KEY_DOWN:
if (snake.key != KEY_UP && num != 1 && isGame == 1)
snake.key = key;
break;
case KEY_SPACE:
if (num == 0 && isGame == 1) num = 1;
else if (num == 1 && isGame == 1) num = 0;
break;
case KEY_PAUSE:
num = 1;
ID = MessageBox(hwnd, "通过键盘上的方向键操控蛇的移动。空格键暂停游戏,E键退出游戏", "提示", MB_OK);
if (ID == IDOK) num = 0; //在阅读帮助文档的时候游戏暂停
break;
case KEY_EXIT:
num = 1;
ID = MessageBox(hwnd, "是否退出游戏", "警告", MB_YESNO);
if (ID == IDYES) exit(0);
else num = 0;
break;
}
}
void DrawMap() //搭建游戏的地图图形界面
{
setfillstyle(BS_HATCHED, HS_DIAGCROSS);//设置画填充格式的图案内部为网格状
BeginBatchDraw(); //开始批量画图
setfillcolor(LIGHTCYAN);
for (int i = 0;i < 37;++i) //画纵向的矩形边界
{
solidrectangle(0, i * 20, 30, (i + 1) * 20);
solidrectangle(750, i * 20, 780, (i + 1) * 20);
}
for (int i = 0;i < 24;++i) //画横向的矩形边界
{
solidrectangle(30 * (i + 1), 0, 30 * (i + 2), 30);
solidrectangle(30 * (i + 1), 710, 30 * (i + 2), 740);
}
setfillstyle(NULL);
EndBatchDraw(); //结束批量画图
}
char* inttowchar(int xnum) //字符串的转换
{
memset(str, '\0', sizeof(str));
sprintf(str, "%d", xnum);
return str;
}
void DrawData() //在右边灰色框写游戏数据
{
clearrectangle(780, 0, 1000, 740);
setfillcolor(0xAAAAAA); //设置描绘背景为浅灰色;
solidrectangle(780, 0, 1000, 740);
settextcolor(YELLOW); //设置为亮红色的画笔
settextstyle(20, 15, _T("黑体")); //设置文本字体高20px,宽15px,字体类型为“黑体”
outtextxy(800, 150, "author:");
outtextxy(800, 300, "蛇的长度:");
outtextxy(800, 450, "蛇头的坐标:");
outtextxy(800, 505, "x=");
outtextxy(900, 505, "y=");
outtextxy(800, 600, "游戏得分:");
settextcolor(RED);
outtextxy(800, 700, "帮助文档按Q键");
settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256));
settextstyle(20, 15, _T("微软黑体")); //设置文本字体高20px,宽15px,字体类型为“微软黑体”
outtextxy(790, 225, "YSJEmm");
outtextxy(850, 365, inttowchar(snake.node));
outtextxy(850, 505, inttowchar(snake.Spos[0].x));
outtextxy(950, 505, inttowchar(snake.Spos[0].y));
outtextxy(860, 650, inttowchar(score));
}
void DrawMenu() //描绘游戏的菜单(主界面选择menu)
{
settextcolor(BLUE); //设置字体为亮红色
settextstyle(180, 80, _T("宋体"));
outtextxy(205, 120, "贪吃蛇");
settextcolor(YELLOW); //设置字体为亮红色
settextstyle(20, 20, _T("宋体"));
outtextxy(350, 350, ">>J.开始游戏");
outtextxy(350, 400, ">>K.改变蛇速");
outtextxy(350, 450, ">>L.退出游戏");
key = _getch();
if (key == 'J')
{
ID = MessageBox(hwnd, "游戏初始界面是暂停的,按空格键开启游戏", "温馨提示", MB_OK);
if (ID == IDOK)
{
isGame = 1; //现在是游戏中的状态了
num = 1; //游戏刚刚开始暂停界面,按space键开始游戏
cleardevice();
DrawMap();
}
}
else if (key == 'K')
{
char mid[6];
InputBox(mid, 4, "请输入你想指定的蛇的速度(建议100-250)");//创建一个用户输入的框架窗口
sscanf(mid, "%d", &SP);
cleardevice();
DrawMenu();
}
else if (key == 'L')
{
ID = MessageBox(hwnd, "是否退出游戏", "警告", MB_YESNO);
if (ID == IDYES) exit(0);
cleardevice();
DrawMenu();
}
else { cleardevice(); DrawMenu(); }
}
void CreateFood() //随机生成食物
{
while (food.iseat == true)
{
int flag = 0;//判断食物产生的地方,不能出现在蛇身上
food.Fpos.x = (unsigned int)(rand() % 630) + 65;
food.Fpos.y = (unsigned int)(rand() % 600) + 65;
for (int i = 0;i < snake.node;++i)
{
if (fabs(food.Fpos.x - snake.Spos[i].x) <= 20 && fabs(food.Fpos.y - snake.Spos[i].y) <= 20)
{
flag = 1; //出现在蛇身上
break;
}
}
if (flag) continue;
else
{
food.iseat = false;
break;
}
}
}
void DrawFood() //画食物
{
setfillcolor(RED);
solidcircle(food.Fpos.x, food.Fpos.y, 10);
}
void SnakeEatFood() //蛇吃食物
{
if (fabs(snake.Spos[0].x - food.Fpos.x) < 15 && fabs(snake.Spos[0].y - food.Fpos.y) < 15)
{
++score; //分数加1
clearcircle(food.Fpos.x, food.Fpos.y, 10);
if (snake.key == KEY_LEFT)
{
snake.Spos[snake.node].x = snake.Spos[snake.node - 1].x + 20;
snake.Spos[snake.node].y = snake.Spos[snake.node - 1].y;
}
else if (snake.key == KEY_RIGHT)
{
snake.Spos[snake.node].x = snake.Spos[snake.node - 1].x - 20;
snake.Spos[snake.node].y = snake.Spos[snake.node - 1].y;
}
else if (snake.key == KEY_UP)
{
snake.Spos[snake.node].y = snake.Spos[snake.node - 1].y + 20;
snake.Spos[snake.node].x = snake.Spos[snake.node - 1].x;
}
else if (snake.key == KEY_DOWN)
{
snake.Spos[snake.node].y = snake.Spos[snake.node - 1].y - 20;
snake.Spos[snake.node].x = snake.Spos[snake.node - 1].x;
}
++snake.node; //蛇的节数+1
food.iseat = true; //此时食物已经被吃掉,需要重新生成
}
}
int main()
{
GameInit(); //游戏初始化
DrawMenu(); //进入菜单
while (1)
{
DrawMap();
DrawSnake();
DrawData();
if (num != 1)
{
SnakeMove();
CreateFood();
DrawFood();
SnakeEatFood();
}
SnakeDeath();
if (_kbhit() && isGame == 1)
{
key = _getch();
KeyBoard();
}
}
return 0;
}
想要添加功能,修改界面什么的可以加我QQ或者评论区留言,有时间我会更新代码,欢迎一起学习O(∩_∩)O~:
本人QQ:1712048533