当前位置:   article > 正文

C++实现扫雷_扫雷c++

扫雷c++

目录

        前言

一、引入游戏所需文件

二、游戏界面初始化

     1.宏定义游戏行列数,图片的尺寸以及雷的数量

     2.InitGame函数,实现游戏初始化功能

三、PaintGame函数打印游戏界面

四、Expand函数实现游戏机制

五、PlayGame函数实现玩家与游戏的互动

六、JudgeMent函数实现游戏运行以及胜负的判定

七、主函数

        总结

前言

要实现扫雷,我们可以将其分为这样几个不同的部分来一一实现:

  1. 引入游戏所需文件
  2. 游戏界面的初始化
  3. 打印游戏界面
  4. 游戏机制的实现
  5. 玩家与游戏之间的互动
  6. 游戏运行以及胜负判定

一、引入游戏所需文件

扫雷中我们需要用到EasyX绘图库中包含的部分功能

附上官网链接:https://easyx.cn/

下面列出需要包含的头文件:

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<ctime>
  4. #include<graphics.h>
  5. #include<windows.h>
  6. #include<Mmsystem.h>
  7. #pragma comment(lib,"winmm.lib")

初始化需要用到的图片以及声音资源(我的资源是从别的博主那里下载来的,就是一二三四五和红旗的等,故不附上):

  1. int o = 0;
  2. int init[row + 2][col + 2];
  3. IMAGE img[11];
  4. void load()
  5. {
  6. loadimage(&img[0], L"0.jpg", size, size);
  7. loadimage(&img[1], L"1.jpg", size, size);
  8. loadimage(&img[2], L"2.jpg", size, size);
  9. loadimage(&img[3], L"3.jpg", size, size);
  10. loadimage(&img[4], L"4.jpg", size, size);
  11. loadimage(&img[5], L"5.jpg", size, size);
  12. loadimage(&img[6], L"6.jpg", size, size);
  13. loadimage(&img[7], L"7.jpg", size, size);
  14. loadimage(&img[8], L"8.jpg", size, size);
  15. loadimage(&img[9], L"9.jpg", size * row, size * col);
  16. loadimage(&img[10], L"10.jpg", size * row, size * col);
  17. }

二、游戏界面初始化

1.宏定义游戏行列数,图片的尺寸以及雷的数量

  1. #define row 10 //定义行数
  2. #define col 10 //定义列数
  3. #define boom 10 //定义炸弹数
  4. #define size 50 //定义图片长宽

2.InitGame函数,实现游戏初始化功能

  1. int init[row + 2][col + 2];
  2. void InitGame()//初始化游戏、
  3. {
  4. for (int i = 0; i < row + 2; i++) //设置缓冲区,并使缓冲区内全为0,缓冲区是指在游戏界面外一圈区域,不设置缓冲区的话会有一些麻烦
  5. {
  6. for (int j = 0; j < col + 2; j++)
  7. {
  8. init[i][j] = 0;
  9. }
  10. }
  11. srand((int)time(0));
  12. int a = boom;//初始化雷的数量
  13. while (a > 0)//设置循环,初始化雷的位置,雷的位置是随机出现的
  14. {
  15. int row1 = rand() % row + 1; //缓冲区不可出现雷,rand%10是指[0,10),加一使得雷在界面内出现
  16. int col1 = rand() % col + 1;
  17. if (init[row1][col1] == 0)
  18. {
  19. init[row1][col1] = 6;//将雷所在数组元素设为6
  20. a--;
  21. }
  22. }
  23. for (int i = 1; i <= row; i++)
  24. {
  25. for (int j = 1; j <= col; j++)
  26. {
  27. if (init[i][j] == 0)
  28. {
  29. for (int m = i - 1; m <= i + 1; m++)//设置两个循环,获取某一位置周围雷的数量
  30. {
  31. for (int n = j - 1; n <= j + 1; n++)
  32. {
  33. if (init[m][n] == 6)
  34. {
  35. init[i][j]++;
  36. }
  37. }
  38. }
  39. }
  40. }
  41. }
  42. for (int i = 1; i <= row ; i++)//把数组的每个元素都+100,通过加载图片成为初始状态
  43. {
  44. for (int j = 1; j <= col ; j++)
  45. {
  46. init[i][j] = init[i][j] + 100;
  47. }
  48. }
  49. }

三、PaintGame函数打印游戏界面

当二维数组元素值处于不同区间时,我们打印不同的图片,就可以实现每个格子不同的状态,注意一定要控制好值和范围的关系,否则可能会出现插了棋子却又可以左键点击出炸弹等尴尬的Bug,我所定义的范围肯定没有问题,可以放心用

  1. void PaintGame()
  2. {
  3. for (int i = 1; i <= row ; i++)
  4. {
  5. for (int j = 1; j <= col; j++)
  6. {
  7. if (init[i][j] >= 0 && init[i][j] <= 6)
  8. {
  9. putimage((i - 1) * size, (j - 1) * size, &img[init[i][j]]);
  10. }
  11. if (init[i][j] >= 100 && init[i][j] <= 106 || init[i][j] >= 300 && init[i][j] % 200 > 10)//初始时为100到106,大于300以后有插旗与取消状态,除以200取余大于10,则为插旗后取消旗子
  12. {
  13. putimage((i - 1) * size, (j - 1) * size, &img[8]);
  14. }
  15. if (init[i][j] >= 200 && init[i][j] <= 206 || init[i][j] >= 300 && init[i][j] % 200 < 10)//同上,小于10则为插旗
  16. {
  17. putimage((i - 1) * size, (j - 1) * size, &img[7]);
  18. }
  19. if (init[i][j] == -101)
  20. {
  21. putimage((i - 1) * size, (j - 1) * size, &img[0]);
  22. }
  23. }
  24. }
  25. }

四、Expand函数实现游戏机制

玩扫雷时我们发现,当点击目标周围没有炸弹时,我们点击一下会点开一片,可以称之为游戏独特的机制,用Expand函数来实现

  1. void Expand(int m, int n)
  2. {
  3. if (m >= 1 && n >= 1 && m <= row && n <= col)//设置好,小心超出范围
  4. {
  5. for (int i = m - 1; i <= m + 1; i++)
  6. {
  7. for (int j = n - 1; j <= n + 1; j++)
  8. {
  9. if (init[i][j] % 100 == 0)
  10. {
  11. init[i][j] = -101; //换一个新的独特的值,避免套娃造成bug
  12. Expand(i, j); //逢0递归
  13. }
  14. if (init[i][j] % 100 >= 1 && init[i][j] % 100 <= 5)
  15. {
  16. init[i][j] = init[i][j] % 100;
  17. }
  18. else
  19. {
  20. init[i][j] = init[i][j];
  21. }
  22. }
  23. }
  24. }
  25. else
  26. {
  27. init[m][n] = init[m][n];
  28. }
  29. }

五、PlayGame函数实现玩家与游戏的互动

总体来看很好理解,通过鼠标的点击,来改变点击位置对应数组元素的值,点击方式的不同,即左键点击和右键点击,值的改变也不同,一定要设置好改变的值,否则会出现插了棋子却又可以左键点击等Bug

  1. void PlayGame()
  2. {
  3. MOUSEMSG msg = { 0 };
  4. msg = GetMouseMsg();
  5. int m, n;
  6. m = msg.x / size + 1; //加一使该函数的操作作用于init[1][1]及之后的元素,因为打印时外圈的全为0的行列不打印
  7. n = msg.y / size + 1;
  8. if (msg.uMsg == WM_LBUTTONDOWN)
  9. {
  10. PlaySound(TEXT("b.wav"), NULL, SND_FILENAME | SND_ASYNC);
  11. if ( init[m][n] >= 100 && init[m][n] <= 106 || init[m][n] >= 300 && init[m][n] % 200 > 10)//当前格子赋值为100到106(初始),或者300以上并且除以200余数小于10时,因为旗子状态不能变为数
  12. {
  13. init[m][n] = init[m][n] % 100;//取除以10的余数,即可得原值
  14. if (init[m][n] == 0)//当选中位置元素为0时,扩散
  15. {
  16. Expand(m, n);
  17. }
  18. }
  19. else
  20. {
  21. init[m][n] = init[m][n];
  22. }
  23. }
  24. if (msg.uMsg == WM_RBUTTONDOWN)
  25. {
  26. PlaySound(TEXT("b.wav"), NULL, SND_FILENAME | SND_ASYNC);
  27. if (init[m][n] > 6)//因为所有值都大于0,所以小于等于6时是12345和炸
  28. {
  29. init[m][n] = init[m][n] + 100;
  30. }
  31. else
  32. {
  33. init[m][n] = init[m][n];
  34. }
  35. }
  36. }

六、JudgeMent函数实现游戏运行以及胜负的判定

  1. void JudgeMent()
  2. {
  3. while (1)
  4. {
  5. PaintGame();
  6. PlayGame();
  7. int boomnum = 0;//初始化踩中炸弹数量
  8. int boomleft = boom;//初始化剩余炸弹数量
  9. for (int i = 1; i <= row; i++)
  10. {
  11. for (int j = 1; j <= col; j++)
  12. {
  13. if (init[i][j] == 6)
  14. {
  15. boomnum++;//踩中炸弹
  16. }
  17. if (init[i][j] == 206 || init[i][j] >= 300 && init[i][j] % 200 == 6)
  18. {
  19. boomleft--;
  20. }
  21. }
  22. }
  23. if (boomnum == 1)//踩中炸弹即为失败
  24. {
  25. PlaySound(TEXT("a.wav"), NULL, SND_FILENAME | SND_ASYNC);
  26. putimage(0, 0, &img[9]);
  27. break;
  28. }
  29. if (boomleft == 0)
  30. {
  31. PlaySound(TEXT("c.wav"), NULL, SND_FILENAME | SND_ASYNC);
  32. putimage(0, 0, &img[10]);
  33. break;
  34. }
  35. }
  36. }

七、主函数

  1. int main()
  2. {
  3. load();
  4. initgraph(row * size, col * size);
  5. InitGame();
  6. JudgeMent();
  7. getchar();
  8. return 0;
  9. }

总结

以上即为扫雷小游戏的全部实现过程,难点在于选择的值范围对格子状态的影响以及递归函数的构造,总体难度不大。

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