C++学习(二十二)(C语言部分)之 扫雷项目实例
程序员文章站
2022-06-26 09:58:33
一、新建项目 二、新建源文件 main.cpp和mining,cpp 三、新建头文件 mining.h 四、图片资源添加 添加完成后会在头文件里面生成一个.h头文件,用来调用资源 打开之后可以看到,对每一个资源文件进行了定义 这里面的顺序和你添加文件时的顺序是一样的,是根据你添加资源的先后顺序进行排 ......
一、新建项目
二、新建源文件
main.cpp和mining,cpp
三、新建头文件
mining.h
四、图片资源添加
添加完成后会在头文件里面生成一个.h头文件,用来调用资源
打开之后可以看到,对每一个资源文件进行了定义
这里面的顺序和你添加文件时的顺序是一样的,是根据你添加资源的先后顺序进行排列定义的
在资源文件夹下回显示添加的资源
五、vs安装图形库
安装完成后重启vs之后就可以在项目中调用图形库的头文件-----> #include<graphics.h> //图形库的头文件
接下来是相关代码:
头文件部分:
mining.h文件
1 #include<time.h> //该种方式引用的头文件是c自带的头文件 2 #include<stdlib.h> 3 #include<graphics.h> //图形库的头文件 4 5 #define map_width 500 //定义地图宽度 宏定义方式 即map_width就等于550 6 7 #define map_height 550 //定义地图的高度 8 9 #define each_size 50 //每一个格子的大小 10 11 #define max_x (map_width/each_size) //计算每一行有多少个 12 13 #define max_y (map_height/each_size) //计算每一列有多少个 14 15 #define mine_count 20 //雷的个数 16 17 //1.初始化地图 18 void initmap(); //定义一个函数 是一个模块 只做属于自己的事情 19 20 //2.实现雷的周围加一 21 void changestate(int x,int y); 22 23 //3.判断是否越界 24 int isposok(int x, int y); 25 26 //4.贴图 27 void drawmap(); 28 29 //5.显示信息 30 void showinfo(); 31 32 //6.实现鼠标点击 ** 还未实现 33 int isopenmine(); 34 35 //7.进行递归翻开格子 ** 还未实现 36 void openzerorecursively(int x,int y); 37 38 //8.翻开所有格子 39 void openall(); 40 41 //9.判断输赢 点击到地雷就输了 ** 还未实现 42 void rengame();
源文件部分:
main.cpp
1 #include"mining.h" 2 #include<stdio.h> 3 4 int main() 5 { 6 initgraph(map_width, map_height);//画出地图窗口 7 8 initmap();//初始换函数 9 10 drawmap();//贴图函数 11 getchar(); 12 13 openall();//翻开所有格子 14 drawmap();//贴图 15 16 getchar(); 17 return 0; 18 getchar();//防止结果闪退 19 }
mining.cpp
1 #include"mining.h" //这种方式引用的头文件是我们自己定义的 2 #include"resource.h" 3 4 int map[max_x][max_y]; //定义一个二维数组 制作地图 5 6 int ncountopen; //打开格子的个数 7 8 int ncountflag; //标记的个数 9 10 void initmap() //第一个函数 初始化函数 11 { 12 //1.初始化数组 13 for (int i = 0; i < max_x; i++) 14 { 15 for (int j = 0; j < max_y; j++) 16 { 17 map[i][j] = 0; 18 } 19 } 20 21 ncountopen = 0; //初始化 22 23 ncountflag = 0; //初始化 24 25 //2.埋地雷---> 地雷是随机的 26 27 srand((unsigned int)time(0)); // 种下随机数种子 28 29 int x, y; 30 31 int ncount=0; //统计埋雷的个数 32 33 //开始埋雷 34 while (ncount<mine_count) //当前埋雷的个数 小于埋雷的最大个数 就一直循环 35 { 36 x = rand() % max_x; // ? %10==0~9 rand 获取随机数 37 38 y = rand() % (max_y - 1) + 1; // 39 40 if (-1 == map[x][y]) //-1 表示地雷 41 {//随机下标是一个地雷 42 continue; //跳过本次循环 不是结束循环(break) 43 } 44 map[x][y] = -1; // 埋雷 45 46 ncount++; //埋雷的个数加一 47 } 48 49 //实现地雷九宫格周围加一 50 for (int i = 0; i < max_x; i++) 51 { 52 for (int j = 1; j < max_y; j++) //因为第一行没有雷 我们是用来显示信息的 所以不能从0开始 53 { 54 if (-1 == map[i][j]) //判断是不是一颗地雷 -1写在左边的原因-->左值 map[i][j]=-1这种形式是错误的 55 { 56 changestate(i, j); //下标 57 } 58 } 59 } 60 } 61 62 void changestate(int x, int y) //第二个函数 实现雷的周围加一 九宫格范围 63 { 64 for (int i = x - 1; i <= x + 1; i++) 65 { 66 for (int j = y - 1; j <= y + 1; j++) 67 { 68 if (-1 == map[i][j]||isposok(i,j)==0 ) //这个位置是一颗地雷并且判断是否越界 69 { 70 continue; //跳出本次循环 71 } 72 map[i][j]+=1; //和map[i][j]++;是一样的 73 } 74 } 75 } 76 77 int isposok(int x, int y) //第三个函数 判断当前的下标是不是越界了 78 { 79 //逻辑表达式的值 0和1 80 return (x >= 0 && x <= max_x&&y <= 1 && y < max_y); //越界返回0 没越界返回1 81 } 82 83 void drawmap() //第四个函数 对地图贴图贴图 84 { 85 image img; 86 87 for (int i = 0; i < max_x; i++) 88 { 89 for (int j = 1; j < max_y; j++) 90 { 91 if (map[i][j] < 9) //雷的周围1最大是8个不会超过九 小于9 说明格子没有被翻开 92 { 93 loadimage(&img, l"jpg", makeintresource(idr_jpg13), each_size, each_size); //l宽字节 jpg13是没有翻开的情况的图片 94 } 95 else //已经被翻开 96 { //翻开一个格子 让这个格子+10 表示已经被翻开 97 if (map[i][j] >= 11 && map[i][j] <= 18) //11~18表示1~8 98 { 99 loadimage(&img, l"jpg", makeintresource(idr_jpg1 + map[i][j] - 11, each_size, each_size)); //通过这个算法 判断贴哪一张图片 100 } 101 else if (map[i][j] == 9) //9-10==-1 -1是地雷 102 { 103 loadimage(&img, l"jpg", makeintresource(idr_jpg10), each_size, each_size); //贴地雷图片 104 } 105 else if (map[i][j] == 10) //10-10==0 0表示空白 106 { 107 loadimage(&img, l"jpg", makeintresource(idr_jpg11), each_size, each_size); //贴空地图片 108 } 109 else 110 { 111 loadimage(&img, l"jpg", makeintresource(idr_jpg9), each_size, each_size); //贴标记图片 112 } 113 } 114 putimage(i*each_size, j*each_size, &img); 115 } 116 } 117 showinfo(); 118 } 119 120 void showinfo() //第五个函数 显示信息 121 { 122 //埋雷的个数 打开的个数 标记的个数 123 //设置字体的样式 124 settextstyle(20, 20, l"wingding.ttf"); //字体样式标号 125 126 //背景颜色 127 setbkmode(transparent); 128 129 //字体颜色 130 settextcolor(yellow); 131 132 //设置字体的位置 133 wchar szopen[32]; 134 wchar szflag[32]; 135 wchar szallmine[32]; 136 137 //字符串格式化 138 //与printf scanf类似 139 wsprintf(szallmine, l"埋雷:%d", mine_count);//埋雷:20 把“埋雷”这个字符串放到szallmine里面 格式化成字符串类型 140 wsprintf(szopen, l"打开:%d", ncountopen); 141 wsprintf(szflag, l"标记:%d", ncountflag); 142 143 //调整坐标 144 outtextxy(20, 20, szallmine); 145 outtextxy(190, 20, szopen); 146 outtextxy(350, 20, szflag); 147 148 } 149 150 151 152 153 154 155 void openzerorecursively(int x, int y) //第七个函数 进行递归翻开格子 156 { 157 158 } 159 160 void openall() //第八个函数 翻开所有格子 161 { 162 for (int i = 0; i < max_x; i++) 163 { 164 for (int j=1;j<max_y;j++) 165 { 166 if (map[i][j] < 9) 167 { 168 map[i][j] += 10; 169 } 170 } 171 } 172 } 173 174 void rengame() //第九个函数 判断输赢 175 { 176 177 }
注:
设置字体样式:
目前实现的结果如下:
之后的以后有机会写好之后再补充
2019-03-20 13:09:47
之前写的代码并不完整,而且还有一些错误,在经过一番学习添加修改后,
最终添加修改完善后的代码如下所示:
1 mining.h文件 2 #include<time.h> //该种方式引用的头文件是c自带的头文件 3 #include<stdlib.h> 4 #include<graphics.h> //图形库的头文件 5 6 #define map_width 500 //定义地图宽度 宏定义方式 即map_width就等于550 7 8 #define map_height 550 //定义地图的高度 9 10 #define each_size 50 //每一个格子的大小 11 12 #define max_x (map_width/each_size) //计算每一行有多少个 13 14 #define max_y (map_height/each_size) //计算每一列有多少个 15 16 #define mine_count 5//雷的个数 17 18 //1.初始化地图 19 void initmap(); //定义一个函数 是一个模块 只做属于自己的事情 20 21 //2.实现雷的周围加一 22 void changestate(int x,int y); 23 24 //3.判断是否越界 25 int isposok(int x, int y); 26 27 //4.贴图 28 void drawmap(); 29 30 //5.显示信息 31 void showinfo(); 32 33 //6.实现鼠标点击 34 int isopenmine(); 35 36 //7.进行递归翻开格子 37 void openzerorecursively(int x,int y); 38 39 //8.翻开所有格子 40 void openall(); 41 42 //9.判断输赢 点击到地雷就输了 43 void rengame(); 44 45 //以上是对使用函数的一个声明 46 47 48 mining.cpp文件 49 #include"mining.h" //这种方式引用的头文件是我们自己定义的 50 #include"resource.h" 51 52 int map[max_x][max_y]; //定义一个二维数组 制作地图 53 54 int ncountopen; //打开格子的个数 55 56 int ncountflag; //标记的个数 57 58 void initmap() //第一个函数 初始化函数 59 { 60 //1.初始化数组 61 for (int i = 0; i < max_x; i++) 62 { 63 for (int j = 0; j < max_y; j++) 64 { 65 map[i][j] = 0; 66 } 67 } 68 69 ncountopen = 0; //初始化 70 71 ncountflag = 0; //初始化 72 73 //2.埋地雷---> 地雷是随机的 74 75 srand((unsigned int)time(0)); // 种下随机数种子 76 77 int x, y; 78 79 int ncount=0; //统计埋雷的个数 80 81 //开始埋雷 82 while (ncount<mine_count) //当前埋雷的个数 小于埋雷的最大个数 就一直循环 83 { 84 x = rand() % max_x; // ? %10==0~9 rand 获取随机数 85 86 y = rand() % (max_y - 1) + 1; // 87 88 if (-1 == map[x][y]) //-1 表示地雷 89 {//随机下标是一个地雷 90 continue; //跳过本次循环 不是结束循环(break) 91 } 92 map[x][y] = -1; // 埋雷 93 94 ncount++; //埋雷的个数加一 95 } 96 97 //实现地雷九宫格周围加一 98 for (int i = 0; i < max_x; i++) 99 { 100 for (int j = 1; j < max_y; j++) //因为第一行没有雷 我们是用来显示信息的 所以不能从0开始 101 { 102 if (-1 == map[i][j]) //判断是不是一颗地雷 -1写在左边的原因-->左值 map[i][j]=-1这种形式是错误的 103 { 104 changestate(i, j); //下标 105 } 106 } 107 } 108 } 109 110 void changestate(int x, int y) //第二个函数 实现雷的周围加一 九宫格范围 111 { 112 for (int i = x - 1; i <= x + 1; i++) 113 { 114 for (int j = y - 1; j <= y + 1; j++) 115 { 116 if (-1 == map[i][j]||isposok(i,j)==0 ) //这个位置是一颗地雷并且判断是否越界 117 { 118 continue; //跳出本次循环 119 } 120 map[i][j]+=1; //和map[i][j]++;是一样的 121 } 122 } 123 } 124 125 int isposok(int x, int y) //第三个函数 判断当前的下标是不是越界了 126 { 127 //逻辑表达式的值 0和1 128 return (x >= 0 && x < max_x &&y >= 1 && y < max_y); //越界返回0 没越界返回1 129 } 130 131 void drawmap() //第四个函数 对地图贴图贴图 132 { 133 image img; 134 beginbatchdraw(); //批量绘图 解决闪屏问题 135 136 cleardevice(); 137 138 139 for (int i = 0; i < max_x; i++) 140 { 141 for (int j = 1; j < max_y; j++) 142 { 143 if (map[i][j] < 9) //雷的周围1最大是8个不会超过九 小于9 说明格子没有被翻开 144 { 145 loadimage(&img, l"jpg", makeintresource(idr_jpg13), each_size, each_size); //l宽字节 jpg13是没有翻开的情况的图片 146 } 147 else //已经被翻开 148 { //翻开一个格子 让这个格子+10 表示已经被翻开 149 if (map[i][j] >= 11 && map[i][j] <= 18) //11~18表示1~8 150 { 151 loadimage(&img, l"jpg", makeintresource(idr_jpg1 + map[i][j] - 11), each_size, each_size); //通过这个算法 判断贴哪一张图片 152 } 153 else if (map[i][j] == 9) //9-10==-1 -1是地雷 154 { 155 loadimage(&img, l"jpg", makeintresource(idr_jpg10), each_size, each_size); //贴地雷图片 156 } 157 else if (map[i][j] == 10) //10-10==0 0表示空白 158 { 159 loadimage(&img, l"jpg", makeintresource(idr_jpg12), each_size, each_size); //贴空地图片 160 } 161 else 162 { 163 loadimage(&img, l"jpg", makeintresource(idr_jpg9), each_size, each_size); //贴标记图片 164 } 165 } 166 putimage(i*each_size, j*each_size, &img); 167 } 168 } 169 showinfo(); 170 endbatchdraw(); 171 } 172 173 void showinfo() //第五个函数 显示信息 174 { 175 //埋雷的个数 打开的个数 标记的个数 176 //设置字体的样式 177 settextstyle(20, 20, l"wingding.ttf"); //字体样式标号 178 179 //背景颜色 180 setbkmode(transparent); 181 182 //字体颜色 183 settextcolor(yellow); 184 185 //设置字体的位置 186 wchar szopen[32]; 187 wchar szflag[32]; 188 wchar szallmine[32]; 189 190 //字符串格式化 191 //与printf scanf类似 192 wsprintf(szallmine, l"埋雷:%d", mine_count);//埋雷:20 把“埋雷”这个字符串放到szallmine里面 格式化成字符串类型 193 wsprintf(szopen, l"打开:%d", ncountopen); 194 wsprintf(szflag, l"标记:%d", ncountflag); 195 196 //调整坐标 197 outtextxy(20, 20, szallmine); 198 outtextxy(190, 20, szopen); 199 outtextxy(350, 20, szflag); 200 201 } 202 203 int isopenmine() 204 { 205 mousemsg m = { 0 };//保存鼠标消息 206 207 while (1) //死循环 208 { 209 m = getmousemsg();//获取鼠标消息 210 switch (m.umsg) 211 { 212 case wm_lbuttondown: //鼠标左键按下 213 if (map[m.x / each_size][m.y / each_size] == -1) //点击到了地雷 214 { 215 map[m.x / each_size][m.y / each_size] += 10; //int a=5; a+=10 a=a+10 翻开格子+10 表示已经翻开 216 return 0; //返回0说明点击的是一颗雷 217 } 218 else if (map[m.x / each_size][m.y / each_size] == 0) //点击到的是一个空地 219 { 220 openzerorecursively(m.x / each_size, m.y / each_size); 221 return 1; 222 } 223 else if (map[m.x / each_size][m.y / each_size] > 0 && map[m.x / each_size][m.y / each_size] < 9) //表示 点击的位置的值是1~8 9表示的是已经被翻开的 224 { 225 map[m.x / each_size][m.y / each_size] += 10; 226 ncountopen++; 227 return 1; 228 } 229 230 break; 231 case wm_rbuttondown: 232 if (map[m.x / each_size][m.y / each_size] < 9) 233 { 234 map[m.x / each_size][m.y / each_size ]+= 100; //加多少都可以 只是一个标记 235 ncountflag++; 236 } 237 else if (map[m.x / each_size][m.y / each_size]>19) 238 { 239 map[m.x / each_size][m.y / each_size] -= 100; 240 ncountflag--; 241 } 242 return 1; 243 } 244 } 245 } 246 247 void openzerorecursively(int x, int y) //第七个函数 进行递归翻开格子 248 { 249 map[x][y] += 10; 250 ncountopen++; 251 for (int i = x - 1; i <= x + 1; i++) 252 { 253 for (int j = y - 1; j <= y + 1; j++) 254 { 255 if (isposok(i, j)==0) 256 { 257 continue; 258 } 259 if (0==map[i][j]) 260 { 261 openzerorecursively(i, j); 262 } 263 if (map[i][j] < 9) 264 { 265 map[i][j] += 10; 266 ncountopen++; 267 } 268 } 269 } 270 } 271 272 void openall() //第八个函数 翻开所有格子 游戏结束 273 { 274 for (int i = 0; i < max_x; i++) 275 { 276 for (int j=1;j<max_y;j++) 277 { 278 if (map[i][j] < 9) 279 { 280 map[i][j] += 10; 281 } 282 } 283 } 284 } 285 286 void rengame() //第九个函数 判断输赢 287 { 288 while (ncountopen<((max_x*(max_y-1))-mine_count)) //100个格子 有20个地雷 10*111=110 10*10 289 { 290 if (isopenmine()==0) 291 { 292 openall(); 293 drawmap(); 294 messagebox(gethwnd(), l"你太菜了!再去修炼吧!", l"提示",mb_ok); 295 return ; //结束函数 296 } 297 drawmap(); 298 } 299 drawmap(); 300 messagebox(gethwnd(), l"恭喜你,你赢了", l"提示", mb_ok); 301 } 302 303 304 305 main.cpp文件 306 #include"mining.h" 307 #include<stdio.h> 308 309 int main() 310 { 311 initgraph(map_width, map_height);//画出地图窗口 312 313 initmap();//初始换函数 314 drawmap();//贴图 315 316 while (true) //循环游戏 317 { 318 rengame(); 319 initmap(); 320 drawmap(); 321 } 322 getchar(); 323 return 0; 324 }
2019-03-20 23:57:46