控制台小游戏MineSweeper

2018-06-27 10:05:22来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

控制台扫雷游戏。

材料:EasyX图形库

  1 #include<set>
  2 #include<array>
  3 #include<string>
  4 #include<time.h>
  5 #include<graphics.h>
  6 
  7 using namespace std;
  8 #define    Num    20                                       //小方块数量Num*Num //rand()使得Num数值太小进入死循环
  9 #define   Size    25                                       //每个小方块大小
 10 using    UInt16 = unsigned short int;
 11 using    TheMap = array<array<UInt16, Num + 2>, Num + 2>;  //引索地图
 12 #define    Trap   (UInt16)0X0000                           //地雷
 13 #define InitMap   (UInt16)0X0001                           //表示无地雷,每次X2表示周围地雷数+1
 14 #define   Asked   (UInt16)0XFFFF                           //标志已询问
 15 
 16 void Init(TheMap &Map);                                    //生成Map、地雷,绘制窗口
 17 bool MainLoop(TheMap &Map);                                //游戏循环
 18 void DisplayEmpty(TheMap &Map, int i, int j);              //对提示区0的绘制
 19 void DisplayNum(TheMap &Map, int i, int j);                //对提示区1-8的绘制
 20 int DisplayFlag(TheMap &Map, int i, int j);                //对标志的绘制
 21 
 22 int main() {
 23     auto hwnd = initgraph(Num * Size, Num * Size);
 24     //游戏的实现
 25     TheMap Map;
 26     Init(Map);
 27     if (MainLoop(Map))
 28         MessageBox(hwnd, L"Win", L"Mine Clerance", MB_OK);
 29     else
 30         MessageBox(hwnd, L"Defeated", L"Mine Clerance", MB_OK);
 31     //离开游戏
 32     closegraph();
 33     return 0;
 34 }
 35 void Init(TheMap &Map) {
 36     //初始化Map
 37     for (auto &It : Map)
 38         It.assign(InitMap);
 39     //随机生成地雷
 40     srand((unsigned)time(NULL));
 41     for (UInt16 k = 0; k < 2 * Num;) {
 42         auto i = rand() % Num + 1;
 43         auto j = rand() % Num + 1;
 44         if (Map[i][j] == InitMap) {
 45             Map[i][j] = Trap;
 46             for (int m = -1; m <= 1; ++m)
 47                 for (int n = -1; n <= 1; ++n)
 48                     Map[i + m][j + n] <<= 1;
 49             ++k;
 50         }
 51     }
 52     //赋值Asked,防止越界
 53     for (size_t i = 0; i < Num + 2; ++i) {
 54         Map[i][0] = Asked;
 55         Map[i][Num + 1] = Asked;
 56         Map[0][i] = Asked;
 57         Map[Num + 1][i] = Asked;
 58     }
 59     //绘制可视地图
 60     setlinecolor(LIGHTGREEN);
 61     for (size_t i = Size; i < Size * Num; i += Size) {
 62         line(i, 0, i, Size * Num);
 63         line(0, i, Size * Num, i);
 64     }
 65 }
 66 bool MainLoop(TheMap &Map) {
 67     int Ret = 0;
 68     MOUSEMSG Point;
 69     while (Ret != 1) {
 70         Point = GetMouseMsg();
 71         if (Point.mkLButton) { //鼠标左键--点开小方块
 72             Point = GetMouseMsg();
 73             size_t i = Point.x / Size + 1;
 74             size_t j = Point.y / Size + 1;
 75             switch (Map[i][j]) {
 76             case Trap: //按到地雷
 77                 for (size_t i = 1; i < Num + 1; ++i)
 78                     for (size_t j = 1; j < Num + 1; ++j)
 79                         if (Map[i][j] == Trap)
 80                             outtextxy(i*Size - Size / 2, j*Size - 3 * Size / 4, L"X");
 81                 return false;
 82             case InitMap: //按到0
 83                 DisplayEmpty(Map, i, j);
 84                 break;
 85             case InitMap << 1:
 86             case InitMap << 2:
 87             case InitMap << 3:
 88             case InitMap << 4:
 89             case InitMap << 5:
 90             case InitMap << 6:
 91             case InitMap << 7:
 92             case InitMap << 8:
 93                 DisplayNum(Map, i, j); //按到1-8
 94                 break;
 95             }
 96         }
 97         else if (Point.mkRButton) { //鼠标右键--标记
 98             Point = GetMouseMsg();
 99             auto i = Point.x / Size + 1;
100             auto j = Point.y / Size + 1;
101             Ret = DisplayFlag(Map, i, j);
102             if (Ret == -1) {
103                 DisplayFlag(Map, i, j);
104                 MessageBox(GetHWnd(), L"NO More Mark", L"MineSweeper", MB_OK);
105             }
106         }
107     }
108     return true;
109 }
110 void DisplayEmpty(TheMap &Map, int i, int j) {
111     //九宫格历遍,递归
112     for (int m = i - 1; m <= i + 1; ++m)
113         for (int n = j - 1; n <= j + 1; ++n) {
114             if (Map[m][n] == InitMap) {
115                 Map[m][n] = Asked;
116                 outtextxy(m*Size - Size / 2, n*Size - 3 * Size / 4, wstring(to_wstring(0)).c_str());
117                 DisplayEmpty(Map, m, n);
118             }
119             else if (Map[m][n] != Asked)
120                 DisplayNum(Map, m, n);
121         }
122 }
123 void DisplayNum(TheMap &Map, int i, int j) {
124     UInt16 num = 8;
125     switch (Map[i][j]) {
126     case 2:--num;
127     case 4:--num;
128     case 8:--num;
129     case 16:--num;
130     case 32:--num;
131     case 64:--num;
132     case 128:--num;
133     case 256:num;
134         Map[i][j] = Asked;
135         outtextxy(i*Size - Size / 2, j*Size - 3 * Size / 4, wstring(to_wstring(num)).c_str());
136         break;
137     }
138 }
139 int DisplayFlag(TheMap &Map, int i, int j) {
140     static UInt16 TrueFlags = 0;     //定义被正确标志的地雷的数量
141     static UInt16 FlagTimes = 0;     //定义被用户标志的地雷的数量
142     static set<UInt16> Record;       //定义容器,用于记录标记点
143     if (Map[i][j] == Asked)          //对已经访问点不做操作
144         return 0;
145     UInt16 ret = i << 8 | j;         //适用:Map下标最大0XFFFF
146     auto Iter = Record.insert(ret);
147     if (Iter.second) {//标记
148         outtextxy(i*Size - Size / 2, j*Size - 3 * Size / 4, L"\?");
149         if (Map[i][j] == Trap)
150             ++TrueFlags;
151         ++FlagTimes;
152     }
153     else {//清除标记
154         Record.erase(ret);
155         setfillcolor(BLACK);
156         fillrectangle(i*Size - Size, j*Size - Size, i*Size, j*Size);
157         if (Map[i][j] == Trap)
158             --TrueFlags;
159         --FlagTimes;
160     }
161     if (TrueFlags == 2 * Num)
162         return 1;
163     if (FlagTimes > 2 * Num) //控制标记数
164 return -1; 165 return 0; 166 }

2018-02-26

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:BZOJ 1188: [HNOI2007]分裂游戏(multi-nim)

下一篇:模板大集合