学习内容: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图形库)相关推荐

  1. 一个简单的贪吃蛇游戏 c

    一个简单的贪吃蛇游戏 #include "pch.h" #include <iostream> #include<stdio.h> #include< ...

  2. 基于面向对象 来写一个简单的贪吃蛇小游戏(代码可直接用)

    分析一下用到的对象(这个案例的地图过于简单,可以不用创建为对象)     食物对象(food)     蛇对象(snake)     游戏对象(game) 1.food对象     属性 :x, y, ...

  3. 用C语言写一个简单的飞机大战游戏(用到easyx图形库)

    学习内容:1.背景的运动 2.飞机爆炸效果 3.透明贴图工具 目录 一.需要用到的头文件.全局变量和一些函数.结构体 二.数据初始化以及图片处理 三.主体 四.物体碰撞 五.游戏运行 六.透明贴图工具 ...

  4. c语言写一个简单的小游戏-推箱子

    在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...

  5. 一个简单的c 游戏编程语言,编程达人 c语言写一个简单的小游戏-推箱子

    在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...

  6. 用Java写一个简单的回合制游戏

    用Java写一个简单的回合制游戏 创建基本属性,血量,名字,技能,技能伤害. 如下: public class One3 {//创建三个属性private String name;private St ...

  7. 老滚5初始化python失败_五分钟学会怎么用python做一个简单的贪吃蛇

    Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发.我们今天将利用它来制作一款大家基本都玩过的小游戏--贪吃蛇. 一.需要导入的包 import pygame ...

  8. Java语言写一个简单的学生信息管理系统,通过JDBC连接数据库对学生信息进行增删改查,采用三层思想和DBUtils第三方框架。

    我把源代码和sql文件放GitHub上了,你们可以自行下载:https://github.com/fenglily1/student. 有问题可以留言或私信,我看到就会回. 进阶版加上页面的管理系统在 ...

  9. 【超详细C语言】带你吃透贪吃蛇游戏之精髓

    文章目录 01. 开发背景 02. 功能介绍 03. 欢迎界面设计 3.1 常用终端控制函数 3.2 设置文本颜色函数 3.3 设置光标位置函数 3.4 绘制字符画(蛇) 3.5 欢迎界面函数 04. ...

最新文章

  1. php与mysql字符集,php与mysql字符集编码问题
  2. (0097)iOS开发之应用间的分享系列(2)
  3. 今天看到这篇新闻之后,决定休息一下咯
  4. 人脸识别损失函数综述(附开源地址)
  5. 三家逐鹿,私有化部署能帮神策数据杀出重围么?| 公司调研
  6. 二进制文件被拒_苹果商店上架,二进制文件被拒绝
  7. 小程序和android联调,小程序打开APP指定页面
  8. 通过特性动态获取属性及值
  9. FX Composer 2 中文版快速教程
  10. static_cast vs dynamic_cast
  11. Base64编解码原理以及其和图片之间的互相转换
  12. 如何设计接口测试用例?(文末送接口测试用例模板)
  13. C语言实现扩展欧几里得算法
  14. 红米note9pro刷鸿蒙,红米Note9Pro稳定版刷机包(官方系统固件升级包MIUI11)
  15. 【电路】电容(三)——耦合、退耦电容
  16. apex显示服务器连接超时,apex与服务器链接超时
  17. ssd测试软件寿命查看,铅锤哥:怎么看SSD还能用多久?固态硬盘寿命的检测方法...
  18. 极域电子教室学生机房管理助手(好好上课)教程
  19. 奔驰c260语言设置方法图解,奔驰glc260l​中控​按钮图解,glc260l车内按键功能说明...
  20. FPGA-炼狱传奇-三态门之战

热门文章

  1. GAMES101现代计算机图形学入门-第一节-图形学导论
  2. ICG-PEG-NHS,吲哚菁绿PEG活性酯,ICG-PEG2000-NHS
  3. C++的ostream的用法,输出符符号重载
  4. 卡巴斯基:微软利用市场主导地位排挤我们
  5. 局域网内QQ号码的嗅探
  6. 低版本Mac OS安装合适xcode的方法
  7. C/C++什么是内存泄露,内存泄露如何避免?
  8. python物理引擎模拟三体_三体世界的模拟
  9. 无法修复此计算机蓝屏,计算机蓝屏故障错误代码:0x000000ba的解决办法
  10. 2023年武汉大学新闻与传播硕士考研上岸前辈备考经验指导