• C++学习(二十二)(C语言部分)之 项目扫雷实例


    一、新建项目

     

     

     

     二、新建源文件

    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

  • 相关阅读:
    KVC该机制
    JS多语种方式
    面试经典(1)---翻转字的顺序在一个句子
    正确Linux新手很实用20命令
    代码添加背景音乐的日记
    什么是比特币(Bitcoin)?
    李开复:该算法的重要性
    javascript推断的浏览器类型
    libyuv编
    Linux下将UTF8编码批量转换成GB2312编码的方法
  • 原文地址:https://www.cnblogs.com/Yuuki-/p/10564281.html
Copyright © 2020-2023  润新知