当前位置:   article > 正文

c++小游戏之扫雷篇_c++小游戏扫雷 总结

c++小游戏扫雷 总结

寒假的时候作为一个接触C语言一个学期的咸鱼,学习了c++,
属于啥都不会的那种(っ ̯ -。) 

那时周末了,很突然的,自己就决定编写扫雷小游戏,并且全程尝试按照自己的设计思路来编写
虽然过程经常遇阻,最终设计也存有大量优化空间
历时一个月终于肝出了扫雷小游戏
在独立的编程中(当然有各位大佬的代码)也还是有了很多收获

以下尝试从头解析自己的程序,希望也能对大家有帮助(滑稽)
先上一张效果图

 代码段

  1. #include<stdio.h>
  2. #include<windows.h>
  3. #include<stdlib.h>
  4. #include<time.h>
  5. #include<conio.h>
  6. #include<queue>
  7. #include<ctype.h>
  8. #define A 17 //地图的高
  9. #define B 17 //地图的宽
  10. #define C 30 //雷的总数
  11. using namespace std;
  12. //全局变量
  13. DWORD a,b;
  14. char map[A][B],news,spare;
  15. int BoomTotalNum,floatx,floaty,flag[A][B],flagnum,mode,slect[A][B],game;
  16. //颜色属性
  17. const WORD FORE_BLUE = FOREGROUND_BLUE; //蓝色文本属性
  18. const WORD FORE_GREEN = FOREGROUND_GREEN; //绿色文本属性
  19. const WORD FORE_RED = FOREGROUND_RED; //红色文本属性
  20. //开垦地图结构体
  21. struct node {
  22. int x;
  23. int y;
  24. };
  25. queue <node> dui;
  26. //打印位置
  27. void position(int x,int y) {
  28. COORD pos={x,y};
  29. HANDLE Out=GetStdHandle(STD_OUTPUT_HANDLE);
  30. SetConsoleCursorPosition(Out,pos);
  31. }
  32. //隐藏光标
  33. void Hide() {
  34. HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  35. CONSOLE_CURSOR_INFO CursorInfo;
  36. GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
  37. CursorInfo.bVisible = false; //隐藏控制台光标
  38. SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态
  39. }
  40. //初始化
  41. void Beginning() {
  42. while(!dui.empty()) {
  43. dui.pop();
  44. }
  45. game=1;
  46. //BoomTotalNum=C;
  47. floatx=A/2;
  48. floaty=B/2;
  49. flagnum=0;
  50. BoomTotalNum=C;
  51. mode=0;
  52. HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
  53. CONSOLE_SCREEN_BUFFER_INFO csbi; //定义窗口缓冲区信息结构体
  54. GetConsoleScreenBufferInfo(handle_out, &csbi); //获得窗口缓冲区信息
  55. int x,y;
  56. srand((unsigned)time(0));
  57. for(int i=0;i<A;i++) for(int j=0;j<B;j++) {
  58. map[i][j]=' ';
  59. flag[i][j]=0;
  60. slect[i][j]=0;
  61. }
  62. while(BoomTotalNum) {
  63. x=rand()%A;
  64. y=rand()%B;
  65. if(map[x][y]==' ') {
  66. map[x][y]='@';
  67. BoomTotalNum--;
  68. }
  69. }
  70. SetConsoleTextAttribute(handle_out, FORE_GREEN);
  71. for(int i=0;i<A;i++) {
  72. for(int j=0;j<B;j++) printf("█");
  73. printf("\n");
  74. }
  75. position(floaty*2,floatx);
  76. SetConsoleTextAttribute(handle_out, FORE_RED);
  77. printf(""); //光标位置
  78. position(44,9);
  79. printf("扫雷模式");
  80. position(44,5);
  81. printf("剩余雷数:%d ",C-flagnum);
  82. SetConsoleTextAttribute(handle_out, FORE_GREEN);
  83. position(5,22);
  84. printf("按“空格”切换模式");
  85. position(5,23);
  86. printf("按“Enter”确认");
  87. position(5,24);
  88. printf("按“方向键”选择方块");
  89. }
  90. //打印地图的一块儿
  91. void Lump(int xx,int yy) {
  92. switch(map[xx][yy]) {
  93. case '1' : printf("①");break; //周围雷的数量(下同)
  94. case '2' : printf("②");break;
  95. case '3' : printf("③");break;
  96. case '4' : printf("④");break;
  97. case '5' : printf("⑤");break;
  98. case '6' : printf("⑥");break;
  99. case '7' : printf("⑦");break;
  100. case '8' : printf("⑧");break;
  101. case ' ' :
  102. if(xx==floatx&&yy==floaty) {
  103. if(flag[xx][yy]==0) {
  104. if(mode%2==0) printf("");
  105. else printf("");
  106. }
  107. else printf("");
  108. }
  109. else {
  110. if(flag[xx][yy]==0) printf("█");
  111. else printf("");
  112. }
  113. break;
  114. case '@' :
  115. if(xx==floatx&&yy==floaty) {
  116. if(flag[xx][yy]==0) {
  117. if(mode%2==0) printf("");
  118. else printf("");
  119. }
  120. else printf("");
  121. }
  122. else {
  123. if(flag[xx][yy]==0) printf("█");
  124. else printf("");
  125. }
  126. break;
  127. case 'x' : if(floatx==xx&&floaty==yy) printf(""); else printf(" ");break; //已经挖开的空白
  128. }
  129. }
  130. //移动光标
  131. void Move() {
  132. HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
  133. CONSOLE_SCREEN_BUFFER_INFO csbi; //定义窗口缓冲区信息结构体
  134. GetConsoleScreenBufferInfo(handle_out, &csbi); //获得窗口缓冲区信息
  135. int xxx,yyy;
  136. xxx=floatx;
  137. yyy=floaty;
  138. switch(news) {
  139. case 72 : floatx--;break; //
  140. case 80 : floatx++;break; //
  141. case 75 : floaty--;break; //
  142. case 77 : floaty++;break; //
  143. }
  144. if(floatx==-1) floatx=A-1; floatx%=A; //两端穿模处理
  145. if(floaty==-1) floaty=B-1; floaty%=B;
  146. position(yyy*2,xxx);
  147. SetConsoleTextAttribute(handle_out, FORE_GREEN);
  148. Lump(xxx,yyy); //删除原位置
  149. if(map[floatx][floaty]=='x') {
  150. position(floaty*2,floatx);
  151. printf(" ");
  152. }
  153. position(floaty*2,floatx);
  154. SetConsoleTextAttribute(handle_out, FORE_BLUE);
  155. Lump(floatx,floaty); //更新新位置
  156. }
  157. //插旗和排雷模式切换
  158. void Mode() {
  159. HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
  160. CONSOLE_SCREEN_BUFFER_INFO csbi; //定义窗口缓冲区信息结构体
  161. GetConsoleScreenBufferInfo(handle_out, &csbi); //获得窗口缓冲区信息
  162. mode++;
  163. SetConsoleTextAttribute(handle_out, FORE_BLUE);
  164. position(floaty*2,floatx);
  165. if(mode%2==0) printf("");
  166. else printf("");
  167. position(44,9);
  168. if(mode%2==0) {
  169. SetConsoleTextAttribute(handle_out, FORE_BLUE);
  170. printf("扫雷模式");
  171. }
  172. else {
  173. SetConsoleTextAttribute(handle_out, FORE_RED);
  174. printf("插旗模式");
  175. }
  176. }
  177. //该点周围地雷数
  178. int Boomnum(int xx,int yy) {
  179. int num=0;
  180. if((xx-1>=0)&&(yy-1>=0)&&(map[xx-1][yy-1]=='@')) num++;
  181. if((xx-1>=0)&&(yy+0>=0)&&(map[xx-1][yy]=='@')) num++;
  182. if((xx-1>=0)&&(yy+1<B) &&(map[xx-1][yy+1]=='@')) num++;
  183. if((xx+0>=0)&&(yy-1>=0)&&(map[xx][yy-1]=='@')) num++;
  184. if((xx+0>=0)&&(yy+1<B) &&(map[xx][yy+1]=='@')) num++;
  185. if((xx+1<A)&&(yy-1>=0) &&(map[xx+1][yy-1]=='@')) num++;
  186. if((xx+1<A)&&(yy+0>=0) &&(map[xx+1][yy]=='@')) num++;
  187. if((xx+1<A)&&(yy+1<B) &&(map[xx+1][yy+1]=='@')) num++;
  188. return num;
  189. }
  190. //更新地图
  191. void Open() {
  192. node c;
  193. node d;
  194. while(!dui.empty()) {
  195. dui.pop();
  196. }
  197. c.x=floatx;
  198. c.y=floaty;
  199. dui.push(c);
  200. slect[c.x][c.y]=1;
  201. while(!dui.empty()) {
  202. c=dui.front();
  203. dui.pop();
  204. if(Boomnum(c.x,c.y)!=0) {
  205. map[c.x][c.y]=(Boomnum(c.x,c.y)+48);
  206. continue;
  207. }
  208. else {
  209. map[c.x][c.y]='x';
  210. if((c.x-1>=0)&&(c.y-1>=0)&&(map[c.x-1][c.y-1]==' ')&&(slect[c.x-1][c.y-1]==0)) {
  211. d.x=c.x-1;
  212. d.y=c.y-1;
  213. dui.push(d);
  214. slect[d.x][d.y]=1;
  215. }
  216. if((c.x-1>=0)&&(c.y-0>=0)&&(map[c.x-1][c.y]==' ')&&(slect[c.x-1][c.y]==0)) {
  217. d.x=c.x-1;
  218. d.y=c.y-0;
  219. dui.push(d);
  220. slect[d.x][d.y]=1;
  221. }
  222. if((c.x-1>=0)&&(c.y+1<B)&&(map[c.x-1][c.y+1]==' ')&&(slect[c.x-1][c.y+1]==0)) {
  223. d.x=c.x-1;
  224. d.y=c.y+1;
  225. dui.push(d);
  226. slect[d.x][d.y]=1;
  227. }
  228. if((c.x-0>=0)&&(c.y-1>=0)&&(map[c.x][c.y-1]==' ')&&(slect[c.x][c.y-1]==0)) {
  229. d.x=c.x-0;
  230. d.y=c.y-1;
  231. dui.push(d);
  232. slect[d.x][d.y]=1;
  233. }
  234. if((c.x-0>=0)&&(c.y+1<B)&&(map[c.x][c.y+1]==' ')&&(slect[c.x][c.y+1]==0)) {
  235. d.x=c.x-0;
  236. d.y=c.y+1;
  237. dui.push(d);
  238. slect[d.x][d.y]=1;
  239. }
  240. if((c.x+1<A)&&(c.y-1>=0)&&(map[c.x+1][c.y-1]==' ')&&(slect[c.x+1][c.y-1]==0)) {
  241. d.x=c.x+1;
  242. d.y=c.y-1;
  243. dui.push(d);
  244. slect[d.x][d.y]=1;
  245. }
  246. if((c.x+1<A)&&(c.y-0>=0)&&(map[c.x+1][c.y]==' ')&&(slect[c.x+1][c.y]==0)) {
  247. d.x=c.x+1;
  248. d.y=c.y-0;
  249. dui.push(d);
  250. slect[d.x][d.y]=1;
  251. }
  252. if((c.x+1<A)&&(c.y+1<B)&&(map[c.x+1][c.y+1]==' ')&&(slect[c.x+1][c.y+1]==0)) {
  253. d.x=c.x+1;
  254. d.y=c.y+1;
  255. dui.push(d);
  256. slect[d.x][d.y]=1;
  257. }
  258. }
  259. }
  260. }
  261. int main() {
  262. freopen("排名.txt","r",stdin);
  263. Relife: //重玩处
  264. HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
  265. CONSOLE_SCREEN_BUFFER_INFO csbi; //定义窗口缓冲区信息结构体
  266. GetConsoleScreenBufferInfo(handle_out, &csbi); //获得窗口缓冲区信息
  267. Hide();
  268. Beginning();
  269. a=GetTickCount();
  270. while(1) {
  271. if(kbhit()!=0) {
  272. spare=getch();
  273. if((spare!=(-32))&&(spare!=13)&&(spare!=' ')) continue;
  274. if(spare==13) {;
  275. if(mode%2==0) {
  276. if(map[floatx][floaty]=='@'&&flag[floatx][floaty]==0) {
  277. break;
  278. game=0;
  279. }
  280. if(flag[floatx][floaty]==1) continue;
  281. Open();
  282. position(0,0);
  283. SetConsoleTextAttribute(handle_out, FORE_GREEN);
  284. for(int i=0;i<A;i++) {
  285. for(int j=0;j<B;j++) Lump(i,j);
  286. printf("\n");
  287. }
  288. position(floaty*2,floatx);
  289. SetConsoleTextAttribute(handle_out, FORE_BLUE);
  290. Lump(floatx,floaty);
  291. }
  292. else {
  293. if(map[floatx][floaty]=='x'||(map[floatx][floaty]>'0'&&map[floatx][floaty]<'9'))
  294. continue;
  295. if(flag[floatx][floaty]==0) {
  296. flagnum++;
  297. flag[floatx][floaty]=1;
  298. position(floaty*2,floatx);
  299. SetConsoleTextAttribute(handle_out, FORE_BLUE);
  300. Lump(floatx,floaty);
  301. }
  302. else {
  303. flagnum--;
  304. flag[floatx][floaty]=0;
  305. position(floaty*2,floatx);
  306. SetConsoleTextAttribute(handle_out, FORE_BLUE);
  307. Lump(floatx,floaty);
  308. }
  309. }
  310. }
  311. if(spare==' ') Mode();
  312. //按方向键
  313. if(spare==-32) {
  314. news=getch();
  315. Move();
  316. }
  317. for(int i=0;i<A;i++) for(int j=0;j<B;j++) if(map[i][j]=='x'||(map[i][j]>'0'&&map[i][j]<'9')) game++;
  318. if(game==A*B-C+1) break;
  319. else game=1;
  320. SetConsoleTextAttribute(handle_out, FORE_RED);
  321. position(44,5);
  322. printf("剩余雷数:%d ",C-flagnum);
  323. }
  324. else Sleep(10);
  325. b=GetTickCount();
  326. SetConsoleTextAttribute(handle_out, FORE_RED);
  327. position(44,7);
  328. printf("用时:");
  329. if((b-a)/60000<10) printf("0");
  330. printf("%d:",(b-a)/60000);
  331. if(((b-a)/1000)%60<10) printf("0");
  332. printf("%d:",((b-a)/1000)%60);
  333. if(((b-a)/10)%100<10) printf("0");
  334. printf("%d",((b-a)/10)%100);
  335. }
  336. SetConsoleTextAttribute(handle_out, FORE_RED);
  337. position(5,5);
  338. if(game==1) printf("游戏结束!");
  339. else printf("恭喜通关!");
  340. position(5,8);
  341. printf("任意键重玩");
  342. scanf("%c%c",&spare,&spare);
  343. system("cls");
  344. position(0,0);
  345. goto Relife;
  346. }

第一次写博客,写的不好,请多多指教  ~( ̄▽ ̄)~*

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/90885
推荐阅读
相关标签
  

闽ICP备14008679号