(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)
今天我们来尝试用easyx图形库实现c语言的扫雷小游戏,相关图片我已经在文中给出
首先就是引用相关头文件
#include<stdio.h> #include<graphics.h>//图形库文件,便于生成新的窗口 #include<stdlib.h> #include<time.h>//用于生成随机函数
接着绘制地图,我们定义的扫雷为十行十列, 规定-1为雷,0表示为空白,1,2,3就是对应的数字
#define row 10//行 #define col 10//列 int map[row][col] = { 0 };//定义地图 void drawmap()//绘制地图 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf(" %2d ", map[i][j]); //2d表示每个字符占两位,使-1与0等齐 } printf("\n"); } }
然后就是埋雷的,因为是随机埋雷,所以需要用到随机函数rand();因此我们先在主函数中创建一个随机函数种子
srand((unsigned int)time(0));//生成随机数种子
然后就是用rand随机生成雷(-1),而且还要防止雷在同一个地方重复出现
//给数组随机埋雷,雷用-1表示,只要10个雷 for (int i = 0; i < 10;) { //雷的行列 int a = rand()%row; int b = rand()%col; if (map[a][b] == 0)//防止重复 { map[a][b] = -1; i++;//只有当-1赋值成功以后,才去遍历下一个雷 } }
有了雷以后,就要对雷周围的数据进行修改,每个雷周围的九宫格都要在0的基础上加一 ,越界问题是扫雷的一个细节,要确保数据在界面以内
//雷周围的九宫格数字都加1,(雷自己除外) for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (map[i][j] == -1) { for (int a = i - 1; a <= i + 1; a++) { for (int b = j - 1; b <= j + 1; b++) { if ((a>=0&&a<row&&b>=0&&b<col)&&map[a][b] != -1)//防止越界且不能为雷 { map[a][b]++; } } } } } }
基本数据已经搭建好了,接下来就是图形的绘制,我们可以在主函数上面先定义一个图形库窗口,且定义每一个图片大小为40
#define imagesize 40//定义图片大小 initgraph(row * imagesize, col * imagesize); //创建窗口
绘制图片分为三步:图片变量定义--图片加载--图片输出(图片如何输出问题在我之前的博客中有提及http://t.csdn.cn/PcJiP)
首先定义图片
IMAGE img[12];//定义图形
接着就是加载图片,这里为了方便,我运用了sprintf
void load()//加载图片 { for (int i = 0; i < 12; i++) { //字符串格式化 char imagename[50]; sprintf(imagename, "./图片库/%d.jpg", i); loadimage(img + i,imagename, imagesize, imagesize); } }
如果大家不了解sprintf,就可以使用常规方法,将图片逐一加载出来
void load() { loadimage(img + 0, "./图片库/0.jpg", imagesize, imagesize); loadimage(img + 1, "./图片库/1.jpg", imagesize, imagesize); loadimage(img + 2, "./图片库/2.jpg", imagesize, imagesize); loadimage(img + 3, "./图片库/3.jpg", imagesize, imagesize); loadimage(img + 4, "./图片库/4.jpg", imagesize, imagesize); loadimage(img + 5, "./图片库/5.jpg", imagesize, imagesize); loadimage(img + 6, "./图片库/6.jpg", imagesize, imagesize); loadimage(img + 7, "./图片库/7.jpg", imagesize, imagesize); loadimage(img + 8, "./图片库/8.jpg", imagesize, imagesize); loadimage(img + 9, "./图片库/9.jpg", imagesize, imagesize); loadimage(img + 10, "./图片库/10.jpg", imagesize, imagesize); loadimage(img + 11, "./图片库/11.jpg", imagesize, imagesize); }
接下来就是输出图片
for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (map[i][j] >= 0 && map[i][j] <= 8) { putimage(j * imagesize, i * imagesize, img + map[i][j]); } else if(map[i][j]==-1)//贴雷 { putimage(j * imagesize, i * imagesize, img + 9); } } }
这样我们的数据原型就做好了,接下来就是对其进行加密,也就是将雷和数字遮起来,我们这里的思路就是将每一个数字的结果加上date,然后使加上date后的数字对应改为第10号图形
#define date 20//定义date的值 //加密数据 for (int m = 0; m < row; m++) { for (int n = 0; n < col; n++) { map[m][n] += date; } }
然后就是对新的数字定义图形
//加密 if (map[i][j] >= -1 + date && map[i][j] <= 8 + date) { putimage(j * imagesize, i * imagesize, img + 10); }
然后我们就需要通过鼠标点击对数据进行修改,我们定义鼠标每次点击后原数据减去date (对于鼠标如何操作,在我之前的博客中有提及http://t.csdn.cn/B7pwW)
if (MouseHit())//判断是否有鼠标操作 { MOUSEMSG msg = GetMouseMsg(); //鼠标变量msg里面有x,y,但是没有行和列,需要自己求 int r = msg.y / imagesize; int c = msg.x / imagesize; //鼠标左键点击打开对应格子,让数组元素-date if (msg.uMsg == WM_LBUTTONDOWN) { //避免越界 if (map[r][c] >= -1 + date && map[r][c] <=8 + date) { map[r][c] -= date; gameover(r,c); draw();//每次鼠标点完以后重新贴图 } } }
插旗子也是如此
//右键按下插旗 if (msg.uMsg == WM_RBUTTONDOWN) { if (map[r][c] >= -1 + date && map[r][c] <= 8 + date)//标记 { map[r][c] += date; draw();//每次鼠标点完以后重新贴图 } else if (map[r][c] > 8 + date)//再次点击取消标记 { map[r][c] -= date; draw(); }
然后就是输出旗子图片
else if(map[i][j]>8+date) { putimage(j * imagesize, i * imagesize, img + 11); }
最后就是游戏结束的相关数据
void gameover(int x, int y) { //如果点到雷,就结束 if (map[x][y] == -1) { //打开所有的雷 for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { //没标记的要打开 if (map[i][j] == -1 + date) { map[i][j] -= date; } //被标记的也要打开 else if (map[i][j] == -1 + date + date) { map[i][j] -= 2 * date; } } } draw(); //弹窗 int ret = MessageBox(GetHWnd(), "游戏结束", "提示", MB_OK); if (ret == IDOK) { exit(0);//退出 } } }
将其汇总到主函数中即可
int main() { srand((unsigned int)time(0));//生成随机数种子 initgraph(row * imagesize, col * imagesize); load(); initmap(); draw(); drawmap(); while (1) { mouse(); } closegraph(); return 0; }
总体代码就是这样,如果大家发现bug或者有更好的方法 ,欢迎大家一起来讨论呀,一起加油
#define _CRT_SECURE_NO_WARNINGS 1//忽略安全检测 #include<stdio.h> #include<graphics.h> #include<stdlib.h> #include<time.h> #define row 10//行 #define col 10//列 #define imagesize 40//定义图片大小 int map[row][col] = { 0 };//定义地图 #define date 20 IMAGE img[12];//定义图形 void drawmap()//绘制地图 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf(" %2d ", map[i][j]); //2d表示每个字符占两位 } printf("\n"); } } //初始化数据 void initmap() { //给数组随机埋雷,雷用-1表示,只要10个雷 for (int i = 0; i < 10;) { //雷的行列 int a = rand()%row; int b = rand()%col; if (map[a][b] == 0)//防止重复 { map[a][b] = -1; i++;//只有当-1赋值成功以后,才去遍历下一个雷 } } //雷周围的九宫格数字都加1,(雷自己除外) for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (map[i][j] == -1) { for (int a = i - 1; a <= i + 1; a++) { for (int b = j - 1; b <= j + 1; b++) { if ((a>=0&&a<row&&b>=0&&b<col)&&map[a][b] != -1)//防止越界且不能为雷 { map[a][b]++; } } } } } } //加密数据 for (int m = 0; m < row; m++) { for (int n = 0; n < col; n++) { map[m][n] += date; } } } //void load()//加载图片 //{ // for (int i = 0; i < 12; i++) // { // //字符串格式化 // char imagename[50]; // sprintf(imagename, "./图片库/%d.jpg", i); // loadimage(img + i,imagename, imagesize, imagesize); // } //} void load() { loadimage(img + 0, "./图片库/0.jpg", imagesize, imagesize); loadimage(img + 1, "./图片库/1.jpg", imagesize, imagesize); loadimage(img + 2, "./图片库/2.jpg", imagesize, imagesize); loadimage(img + 3, "./图片库/3.jpg", imagesize, imagesize); loadimage(img + 4, "./图片库/4.jpg", imagesize, imagesize); loadimage(img + 5, "./图片库/5.jpg", imagesize, imagesize); loadimage(img + 6, "./图片库/6.jpg", imagesize, imagesize); loadimage(img + 7, "./图片库/7.jpg", imagesize, imagesize); loadimage(img + 8, "./图片库/8.jpg", imagesize, imagesize); loadimage(img + 9, "./图片库/9.jpg", imagesize, imagesize); loadimage(img + 10, "./图片库/10.jpg", imagesize, imagesize); loadimage(img + 11, "./图片库/11.jpg", imagesize, imagesize); } //输出图片 void draw() { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (map[i][j] >= 0 && map[i][j] <= 8) { putimage(j * imagesize, i * imagesize, img + map[i][j]); } else if(map[i][j]==-1)//贴雷 { putimage(j * imagesize, i * imagesize, img + 9); } //加密 else if (map[i][j] >= -1 + date && map[i][j] <= 8 + date) { putimage(j * imagesize, i * imagesize, img + 10); } //插旗子 else if(map[i][j]>8+date) { putimage(j * imagesize, i * imagesize, img + 11); } } } } //结束游戏 void gameover(int x, int y) { //如果点到雷,就结束 if (map[x][y] == -1) { //打开所有的雷 for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { //没标记的要打开 if (map[i][j] == -1 + date) { map[i][j] -= date; } //被标记的也要打开 else if (map[i][j] == -1 + date + date) { map[i][j] -= 2 * date; } } } draw(); //弹窗 int ret = MessageBox(GetHWnd(), "游戏结束", "提示", MB_OK); if (ret == IDOK) { exit(0);//退出 } } } //鼠标操作 void mouse() { if (MouseHit())//判断是否有鼠标操作 { MOUSEMSG msg = GetMouseMsg(); //鼠标变量msg里面有x,y,但是没有行和列,需要自己求 int r = msg.y / imagesize; int c = msg.x / imagesize; //鼠标左键点击打开对应格子,让数组元素-date if (msg.uMsg == WM_LBUTTONDOWN) { //避免越界 if (map[r][c] >= -1 + date && map[r][c] <=8 + date) { map[r][c] -= date; gameover(r,c); draw();//每次鼠标点完以后重新贴图 } } //右键按下插旗 if (msg.uMsg == WM_RBUTTONDOWN) { if (map[r][c] >= -1 + date && map[r][c] <= 8 + date)//标记 { map[r][c] += date; draw();//每次鼠标点完以后重新贴图 } else if (map[r][c] > 8 + date)//取消标记 { map[r][c] -= date; draw(); } } } } int main() { srand((unsigned int)time(0));//生成随机数种子 initgraph(row * imagesize, col * imagesize); load(); initmap(); draw(); drawmap(); while (1) { mouse(); } closegraph(); return 0; }