用C语言写一个简单的贪吃蛇游戏(用到easyx图形库)
学习内容:1.游戏的存储与读写
2.制作游戏菜单
3.制作定时器
目录
一、需要用到的头文件、全局变量和一些函数
二、定时器
三、数据的初始化和绘制
四、蛇的运行和吃食物
五、游戏菜单界面
六、游戏存储与读写
七、其他函数
八、主函数入口
主菜单
游戏内容
一、需要用到的头文件、全局变量和一些函数
#include<stdio.h>
#include<easyx.h>
#include<time.h>
#include<conio.h>
#pragma comment (lib,"winmm.lib")#define WIDTH 600//屏幕宽度与高度
#define HEIGHT 500
#define MAX_SNAKE 30//最大蛇长度//全局变量
int game_state = 1;//游戏状态:1.游戏菜单选项 2.运行游戏 3.退出游戏
int option;//菜单栏状态bool game_pause;
bool snake_die;
MOUSEMSG m1;
MOUSEMSG m2;//定一个方向枚举
enum DIR
{up,down,left,right
};//蛇结构体
struct Snake
{POINT coord[MAX_SNAKE];int num;int len;int exis;int score;int dir;
}snake;//食物结构体
struct Food
{POINT fd;int exis;
}food;//需要用到的函数
void InitData();//初始化数据
void DrawImag();//绘制图画
void ReadGame();//读取要保存的数据
void SaveGame();//保存数据
void EatFood();//吃食物
void GameOver();//游戏结束
void GameMenu();//游戏菜单
void UpdataWithInput();//有数据输入
void UpdataWithoutInput();//无数据输入
void SnakeMove();//蛇的移动
void KeyControl();//键盘输入
二、定时器
用static 定义 start避免循环时被覆盖
开始start与end处以同一时间,start保存的时间不变,end时间一直在变化,直至end和start时间差大于等于ms,当相等时,再将start与end时间同步,重复以上操作,用时间差来控制程序运行快慢。
作用:满足时间要求时可进行某个操作,也不影响其他操作的进行。(可用于蛇的运动快慢)
bool timer(int ms, int id)
{static int start[6] = { clock() };int end = clock();if (end - start[id] >= ms){start[id] = end;return true;}return false;
}
三、数据的初始化和绘制
void InitData()
{initgraph(WIDTH, HEIGHT, 1);//1表示显示控制台//播放背景音乐mciSendString("open .\\resource\\bk1.mp3 alias bgm1", NULL, 0, NULL);mciSendString("play bgm1 repeat", NULL, 0, NULL);//初始化蛇snake.len = 10;snake.num = 3;snake.dir = right;snake.score = 0;snake.coord[2].x = 0;snake.coord[2].y = 0;snake.coord[1].x = snake.len;snake.coord[1].y = 0;snake.coord[0].x = 2 * snake.len;//作为蛇头snake.coord[0].y = 0;// 画食物food.fd.x = rand() % (WIDTH / 10) * 10;food.fd.y = rand() % (HEIGHT / 10) * 10;food.exis = 1;//按键选项初始化0option = 0;//蛇是否死亡snake_die = false;//游戏是否暂停初始化为否game_pause = false;
}//绘制图形画面
void DrawImag()
{setbkcolor(GREEN);cleardevice();BeginBatchDraw();while (game_state == 1){GameMenu();}//画蛇for (int i = snake.num - 1; i >= 0; i--){setfillcolor(YELLOW);setlinecolor(BLACK);fillrectangle(snake.coord[i].x, snake.coord[i].y, snake.coord[i].x + snake.len, snake.coord[i].y + snake.len);//printf("%d,%d\n", snake.coord[i].x, snake.coord[i].y);}//画食物setfillcolor(RED);solidellipse(food.fd.x, food.fd.y, food.fd.x + snake.len, food.fd.y + snake.len);settextstyle(25, 0, "黑体");outtextxy(20, 20,"得分:");TCHAR c[3];sprintf(c, "%02d", snake.score);outtextxy(90, 20, c);setbkmode(TRANSPARENT);//画出暂停与返回菜单界面按键char button_name1[10] = { "暂停游戏" };char button_name2[10] = { "继续游戏" };char button_name3[10] = { "返回菜单" };//按键框(仅供参考,可以自己在做一个小按键隐藏按钮,避免遮挡视线)setfillcolor(WHITE);fillrectangle(10, 400, 130, 440);fillrectangle(10, 450, 130, 490);setlinecolor(WHITE);//当鼠标不再范围内边框变白rectangle(10, 400, 130, 440);rectangle(10, 450, 130, 490);setbkmode(TRANSPARENT);settextcolor(BLACK);outtextxy(10 + 60 - textwidth(button_name3) / 2, 450 + 20 - textheight(button_name3) / 2, button_name3);if (game_pause){outtextxy(10 + 60 - textwidth(button_name1) / 2, 400 + 20 - textheight(button_name1) / 2, button_name2);}else{outtextxy(10 + 60 - textwidth(button_name2) / 2, 400 + 20 - textheight(button_name2) / 2, button_name1);}if (m2.x >= 10 && m2.x <= 130 && m2.y >= 400 && m2.y <= 440){setlinecolor(RED);//鼠标在方形区域时边框变红rectangle(10, 400, 130, 440);option = 1;}if (m2.x >= 10 && m2.x <= 130 && m2.y >= 450 && m2.y <= 490){setlinecolor(RED);rectangle(10, 450, 130, 490);option = 2;}//当游戏结束时if (snake_die){setbkmode(TRANSPARENT);settextcolor(RED);settextstyle(40, 20, "黑体");outtextxy(100, 200, "吃到自己了,游戏结束!!");outtextxy(100, 240, "是否继续游戏!!");outtextxy(100, 280, "继续请按Y 否请按N");}FlushBatchDraw();
}
四、蛇的运行和吃食物
//蛇的移动
void SnakeMove()
{for (int i = snake.num - 1; i > 0; i--){snake.coord[i].x = snake.coord[i - 1].x;snake.coord[i].y = snake.coord[i - 1].y;}//snake.coord[0].x += 10;switch (snake.dir){case up:snake.coord[0].y -= 10;if (snake.coord[0].y +10 == 0){snake.coord[0].y = HEIGHT;}break;case down:snake.coord[0].y += 10;if (snake.coord[0].y - 10 == HEIGHT){snake.coord[0].y = 0 ;}break;case right:snake.coord[0].x += 10;if (snake.coord[0].x -10 == WIDTH){snake.coord[0].x = 0;}break;case left:snake.coord[0].x -= 10;if (snake.coord[0].x +10 == 0){snake.coord[0].x = WIDTH;}break;default:break;}//判断蛇是不是吃到自己了for (int i = 3; i < snake.num; i++)//当蛇身只有三个时吃不到自己{if (snake.coord[0].x == snake.coord[i].x&&snake.coord[0].y == snake.coord[i].y){snake_die = true;}}
}//用键盘控制
void KeyControl()
{if (GetAsyncKeyState(VK_UP) && snake.dir != down){snake.dir = up;}if (GetAsyncKeyState(VK_DOWN) && snake.dir != up){snake.dir = down;}if (GetAsyncKeyState(VK_RIGHT) && snake.dir != left){snake.dir = right;}if (GetAsyncKeyState(VK_LEFT) && snake.dir != right){snake.dir = left;}
}//吃食物
void EatFood()
{srand((unsigned int)time(NULL));if (snake.coord[0].x == food.fd.x&&snake.coord[0].y == food.fd.y){food.fd.x = rand() % (WIDTH / 10) * 10;food.fd.y = rand() % (HEIGHT / 10) * 10;snake.num++;snake.score++;}
}
五、游戏菜单界面
//游戏 界面菜单
void GameMenu()
{cleardevice();BeginBatchDraw();//游戏名字char game_name[20] = { "贪吃蛇" };setbkcolor(TRANSPARENT);settextcolor(GREEN);settextstyle(40, 20, "华文琥珀");outtextxy(WIDTH / 2 - textwidth(game_name) / 2, 40, game_name);if (MouseHit()){m1 = GetMouseMsg();if (m1.uMsg == WM_LBUTTONDOWN){//开始新游戏if (option == 1) {game_state = 2;mciSendString("close bgm1", NULL, 0, NULL);Sleep(400);mciSendString("open .\\resource\\bk2.mp3 alias bgm2", NULL, 0, NULL);mciSendString("play bgm2 repeat", NULL, 0, NULL);}else if (option == 2) { ReadGame(); game_state = 2; mciSendString("close bgm1", NULL, 0, NULL);Sleep(400);mciSendString("open .\\resource\\bk2.mp3 alias bgm2", NULL, 0, NULL);mciSendString("play bgm2 repeat", NULL, 0, NULL);}//读取进度开始游戏else if (option == 3) { SaveGame(); closegraph(); _exit(0); }//保存并退出游戏}}option = 0;char select1[9] = { "游戏开始" };char select2[9] = { "继续游戏" };char select3[9] = { "保存退出" };int textw = 140;int texth = 40;settextcolor(WHITE);//开始游戏按钮if (m1.x >= WIDTH*0.39 &&m1.x <= WIDTH*0.39 + textw &&m1.y >= HEIGHT*0.3&&m1.y <= HEIGHT*0.3 + texth){//settextcolor(RED);settextstyle(35, 0, "华文彩云");//悬浮在按钮上outtextxy(WIDTH*0.39, HEIGHT*0.3, select1);option = 1;//getchar();}else { settextstyle(35, 0, "黑体"); //不在按钮上outtextxy(WIDTH*0.39, HEIGHT*0.3, select1);}//继续游戏if (m1.x >= WIDTH*0.39 &&m1.x <= WIDTH*0.39 + textw &&m1.y >= HEIGHT*0.5&&m1.y <= HEIGHT*0.5 + texth){settextstyle(35, 0, "华文彩云");outtextxy(WIDTH*0.39, HEIGHT*0.5, select2);option = 2;}else{settextstyle(35, 0, "黑体");outtextxy(WIDTH*0.39, HEIGHT*0.5, select2);}//保存并退出游戏if (m1.x >= WIDTH*0.39 &&m1.x <= WIDTH*0.39 + textw &&m1.y >= HEIGHT*0.7&&m1.y <= HEIGHT*0.7 + texth){settextstyle(35, 0, "华文彩云");outtextxy(WIDTH*0.39, HEIGHT*0.7, select3);option = 3;}else{settextstyle(35, 0, "黑体");outtextxy(WIDTH*0.39, HEIGHT*0.7, select3);}FlushBatchDraw();//clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1);//用背景色清除当前区域
}
六、游戏存储与读写
文件打开失败没有连接其他功能,可自行添加
打开文件之后需要关闭文件
//存档
void SaveGame()
{char ch[20];sprintf(ch, "del storage.txt");system(ch);//删除已有存档FILE* stor;if ((stor = fopen("storage.txt", "w+")) == NULL)//打开失败{cleardevice();setbkmode(TRANSPARENT);settextcolor(RED);settextstyle(40, 20, "黑体");outtextxy(200, 300, "存档失败!!");}else{fwrite(&(snake.num), sizeof(snake.num), 1, stor);fwrite(&(snake.score), sizeof(snake.score), 1, stor);fwrite(&(snake.score), sizeof(snake.score), 1, stor);fwrite(&(snake.dir), sizeof(snake.dir), 1, stor);fwrite(&(snake.len), sizeof(snake.len), 1, stor);fwrite(&(food.fd), sizeof(food.fd), 1, stor);fwrite(&(food.exis), sizeof(food.exis), 1, stor);for (int i = 0; i <= snake.num; i++){fwrite(&snake.coord[i], sizeof(snake.coord[i]), 1, stor);}}fclose(stor);
}//读取游戏
void ReadGame()
{FILE* stor;if ((stor = fopen("storage.txt", "r")) == NULL){cleardevice();setbkmode(TRANSPARENT);settextcolor(RED);settextstyle(40, 20, "黑体");outtextxy(200, 300, "读写失败,可能没有存档!!");getchar();}else{fread(&(snake.num), sizeof(snake.num), 1, stor);fread(&(snake.score), sizeof(snake.score), 1, stor);fread(&(snake.exis), sizeof(snake.exis), 1, stor);fread(&(snake.dir), sizeof(snake.dir), 1, stor);fread(&(snake.len), sizeof(snake.len), 1, stor);fread(&(food.fd), sizeof(food.fd), 1, stor);fread(&(food.exis), sizeof(food.exis), 1, stor);for (int i = 0; i <= snake.num ; i++){fread(&snake.coord[i] , sizeof(snake.coord[i]) , 1, stor);}}fclose(stor);
}
七、其他函数
//当蛇吃到自己时游戏结束
void GameOver()
{if (snake_die){char ch;ch = _getch();switch (ch){case 'Y':case 'y':closegraph();InitData();mciSendString("close bgm1", NULL, 0, NULL);break;case'N':case'n':EndBatchDraw();closegraph();_exit(0);break;default:break;}}
}//需输入更新
void UpdataWithInput()
{KeyControl();//判断是否有鼠标介入while (MouseHit()){m2 = GetMouseMsg();if (m2.uMsg == WM_LBUTTONDOWN){if (option == 1){game_pause = true;}else if (option == 2){game_state = 1;mciSendString("close bgm2", NULL, 0, NULL);mciSendString("open .\\resource\\bk1.mp3 alias bgm1", NULL, 0, NULL);mciSendString("play bgm1 repeat", NULL, 0, NULL);}}//游戏暂停将会一直在此循环直到点击继续游戏或者返回主页菜单while (game_pause){DrawImag();while (MouseHit()){m2 = GetMouseMsg();if (m2.uMsg == WM_LBUTTONDOWN){if (option == 1){game_pause = false;}else if (option == 2){game_state = 1;mciSendString("close bgm2", NULL, 0, NULL);mciSendString("open .\\resource\\bk1.mp3 alias bgm1", NULL, 0, NULL);mciSendString("play bgm1 repeat", NULL, 0, NULL);}}}}}
}//无需输入更新
void UpdataWithoutInput()
{if (timer(100, 0)){SnakeMove();}GameOver();EatFood();}
八、主函数入口
//主入口
int main()
{InitData();while (true){DrawImag();UpdataWithInput();UpdataWithoutInput();}closegraph();getchar();return 0;
}
总结:难点在于设计菜单需要用到多重循环,以及按键效果,数据存储时避免遗漏。
此游戏功能简单,仅供学习参考。(有不足的地方欢迎大家指出,希望能和大家一起学习进步)
有兴趣可以尝试完成其他功能,比如封装、添加ai蛇,速度随着长度增加,障碍物或用链表写一个贪吃蛇等。
easyx图形库资源,音乐资源网上可下载。
用C语言写一个简单的贪吃蛇游戏(用到easyx图形库)相关推荐
- 一个简单的贪吃蛇游戏 c
一个简单的贪吃蛇游戏 #include "pch.h" #include <iostream> #include<stdio.h> #include< ...
- 基于面向对象 来写一个简单的贪吃蛇小游戏(代码可直接用)
分析一下用到的对象(这个案例的地图过于简单,可以不用创建为对象) 食物对象(food) 蛇对象(snake) 游戏对象(game) 1.food对象 属性 :x, y, ...
- 用C语言写一个简单的飞机大战游戏(用到easyx图形库)
学习内容:1.背景的运动 2.飞机爆炸效果 3.透明贴图工具 目录 一.需要用到的头文件.全局变量和一些函数.结构体 二.数据初始化以及图片处理 三.主体 四.物体碰撞 五.游戏运行 六.透明贴图工具 ...
- c语言写一个简单的小游戏-推箱子
在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...
- 一个简单的c 游戏编程语言,编程达人 c语言写一个简单的小游戏-推箱子
在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...
- 用Java写一个简单的回合制游戏
用Java写一个简单的回合制游戏 创建基本属性,血量,名字,技能,技能伤害. 如下: public class One3 {//创建三个属性private String name;private St ...
- 老滚5初始化python失败_五分钟学会怎么用python做一个简单的贪吃蛇
Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发.我们今天将利用它来制作一款大家基本都玩过的小游戏--贪吃蛇. 一.需要导入的包 import pygame ...
- Java语言写一个简单的学生信息管理系统,通过JDBC连接数据库对学生信息进行增删改查,采用三层思想和DBUtils第三方框架。
我把源代码和sql文件放GitHub上了,你们可以自行下载:https://github.com/fenglily1/student. 有问题可以留言或私信,我看到就会回. 进阶版加上页面的管理系统在 ...
- 【超详细C语言】带你吃透贪吃蛇游戏之精髓
文章目录 01. 开发背景 02. 功能介绍 03. 欢迎界面设计 3.1 常用终端控制函数 3.2 设置文本颜色函数 3.3 设置光标位置函数 3.4 绘制字符画(蛇) 3.5 欢迎界面函数 04. ...
最新文章
- php与mysql字符集,php与mysql字符集编码问题
- (0097)iOS开发之应用间的分享系列(2)
- 今天看到这篇新闻之后,决定休息一下咯
- 人脸识别损失函数综述(附开源地址)
- 三家逐鹿,私有化部署能帮神策数据杀出重围么?| 公司调研
- 二进制文件被拒_苹果商店上架,二进制文件被拒绝
- 小程序和android联调,小程序打开APP指定页面
- 通过特性动态获取属性及值
- FX Composer 2 中文版快速教程
- static_cast vs dynamic_cast
- Base64编解码原理以及其和图片之间的互相转换
- 如何设计接口测试用例?(文末送接口测试用例模板)
- C语言实现扩展欧几里得算法
- 红米note9pro刷鸿蒙,红米Note9Pro稳定版刷机包(官方系统固件升级包MIUI11)
- 【电路】电容(三)——耦合、退耦电容
- apex显示服务器连接超时,apex与服务器链接超时
- ssd测试软件寿命查看,铅锤哥:怎么看SSD还能用多久?固态硬盘寿命的检测方法...
- 极域电子教室学生机房管理助手(好好上课)教程
- 奔驰c260语言设置方法图解,奔驰glc260l​中控​按钮图解,glc260l车内按键功能说明...
- FPGA-炼狱传奇-三态门之战
热门文章
- GAMES101现代计算机图形学入门-第一节-图形学导论
- ICG-PEG-NHS,吲哚菁绿PEG活性酯,ICG-PEG2000-NHS
- C++的ostream的用法,输出符符号重载
- 卡巴斯基:微软利用市场主导地位排挤我们
- 局域网内QQ号码的嗅探
- 低版本Mac OS安装合适xcode的方法
- C/C++什么是内存泄露,内存泄露如何避免?
- python物理引擎模拟三体_三体世界的模拟
- 无法修复此计算机蓝屏,计算机蓝屏故障错误代码:0x000000ba的解决办法
- 2023年武汉大学新闻与传播硕士考研上岸前辈备考经验指导