Bootstrap

自写扫雷小程序

一:头文件部分 

#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<Windows.h>
#include<errno.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9   // 行  扫雷以及布雷的时候用
#define COL   9   //列
#define ROWS ROW+2   //创建棋盘考虑判断时候用
#define COLS    COL+2
#define bomb 10 //地雷的数量


//菜单
void menu();

//游戏主体
void game();

//初始化
void lnitboard(char board[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void displayboard(char board[ROWS][COLS], int row, int col);//board只是数组名在这段函数中的名称而已 不影响数据


//设置雷区
//因为传输的rows cols的棋盘 所以自然也用同样的规格接收
void setmine(char board[ROWS][COLS], int row, int col, char set);//set是雷的代号

//计算选中坐标周围的雷区
int count(char board[ROWS][COLS], int i, int j);


//爆破棋盘
void Bombboard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int n, int m);


//排雷
void playmove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

二:函数实现部分

#define _CRT_SECURE_NO_WARNINGS 1 
#include"zhk.h"

//菜单
void menu()
{
    printf("*********************欢迎来到征氏扫雷游戏!************************\n");
    printf("*********************祝你游玩愉快!********************************\n");
    printf("**********************1. play  0.exit********************************\n");
}

//初始化
void lnitboard(char board[ROWS][COLS], int rows, int cols, char set)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] = set;
        }
    }
}
//设置雷区
void setmine(char board[ROWS][COLS], int row, int col, char set)
{
    int i, j;//i j是行标和列标 c代表要布置多少地雷
    int c = 0;
    while (1)
    {
        //行标与列标的范围是1-9
        i = rand() % row + 1;//一个数的余数只能是0~被除数-1 否则进一了
        j = rand() % col + 1;
        if (i <= row && j <= col && board[i][j] == '0')//需要此区域并没有布过雷 而且坐标的输入在规定的区域
        {
            board[i][j] = set;//如果符合这个规范则将随机的坐标变为雷区
            c++;
        }
        if (c== bomb)
        {
            break;
        }
    }
}


//打印棋盘
void displayboard(char board[ROWS][COLS], int row, int col)
{
    int i, j;
    printf("*******************扫雷游戏***********************\n");
    for (j = 0; j<= col; j++)//打印每一行的列标
    {
        printf("%d ", j);//就用列标j 反正会重新赋值为0
    }
    printf("\n");//打印完列标换行
    for (i = 1; i <= row; i++)//i为行标 j为列标
    {
        printf("%d ", i);//打印每一行的行标 行标从1开始就行
        for (j = 1; j <= col; j++)//打印每一行的数据
        {
            printf("%c ", board[i][j]);//打印每一行的数据 数据内容由所传输的数组决定
        }
        printf("\n");//一行打印完换下一行
    }
    printf("*******************扫雷游戏***********************\n");
}
//显示选中坐标周围雷的数量
int count(char board[ROWS][COLS], int i, int j)
{
    int a = 0, b = 0,c=0;//创建变量用于作为坐标 与 计算雷区
    for (a = i - 1; a < i + 2; a++)//行
    {
        for (b = j - 1; b < j + 2; b++)//列
        {
            if (board[a][b] == '$')//如果附近有雷就加一 没有就还是0
            {
                c++;
            }
        }
    }
    return c;//将附近雷的数量返回
}


//爆破棋盘
void Bombboard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int n,int m)
{
    int z = count(mine, n, m);//计算坐标附近雷区数量并赋值
    if (mine[n][m] == '0')//想要爆破首先自己这边就不能是雷;
    {
        //只有周围没有雷的时候才会将周围的数目变成空格 同理只有周围没有雷的时候才会进入下一层递归 否则返回上一层递归
        if (z== 0)//如果附近没有雷 则将附近包括自己3*3的区域赋值为空格
        {
            for (int a = n - 1; a < n + 2; a++)//a n为行标 b m为列标
            {//然后确定自己这一圈有没有雷 否则不爆破
                int b = 0;
                for (b = m - 1; b < m + 2; b++)
                {
                    if (mine[a][b] == '0')
                    {
                        if (show[a][b] == '*')//被展开变为空格的不递归 直接跳过
                        {
                            show[a][b] = ' ';//如果被选中区域不是雷区 那么在显示棋盘上改为空格
                            Bombboard(mine, show, row, col, a, b);
                        }
                    }
                }
            }
        }
        else
        {
            show[n][m] = z + '0';//整型数字+数字字符可将整型数字转换为数字字符 反之同理
        }
    }
    else 
    {
            printf("gameover 游戏结束!\n");
            printf("运气不好,下次努力哦\n");
            printf("你共排雷:0颗\n");
            displayboard(mine, row, col);
    }
}

//显示爆破之后排雷的数量 然后计入到总进度中
int showwin(char board[ROWS][COLS], int row, int col)
{
    int i = 0,z=0;//i为行标 j为列标 z表示空格的数量在棋盘中
    for (i = 1; i <= row; i++)//每一行的个数
    {
        int j = 0;
        for (j = 1; j <= col; j++)
        {
            if (board[i][j] != '*')//计算排除的数量 
            {
                z++;//z代表排除的数量
            }
        }
    }
    return z;
}

//排雷
void  playmove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//因是扫雷 正常的规格
{
    int i = 0, j = 0;
    int win = 0;//i j表示坐标 win表示剩余空格数
    int z = 0;//表示周围有几个雷
    printf("请输入你要爆破的区域(如1空格1 然后回车) 如果选中区域不是雷区 将展开棋盘上临近位置不是雷的棋子\n");
    int n = 0, m = 0;
    scanf("%d%d", &n, &m);
    Bombboard(mine, show, ROW, COL, n, m);//传输棋盘基本数据以及需要爆破的区域  将空格数传输爆破一次加一次
    displayboard(show, row, col);//爆破完成 打印棋盘
    win = showwin(show, row, col);
    while (win < row * col - bomb)//如果不符合规定就一直处于输入状态
     {
        if (win == 0)//第一次进入时提示输入样例
        {
            printf("输入的坐标 一般为0 0 第一个0表示行 第二个0表示列 中间空格隔开\n");
        }
        printf("请输入坐标>?:");
        scanf("%d%d", &i, &j);//输入坐标
        if (show[i][j] == '*' && (i >= 1 && i <= row) && (j >= 1 && j <= col))
        {
            if (mine[i][j] == '0')//如果输入的坐标有雷 就返回@结束循环
            {
                z = count(mine, i, j);//因为是计算雷的数量 自然要传输雷区的数据
            win++;//代表排雷一颗
            show[i][j] = z + '0';//探查完之后再赋值给相应显示棋盘的坐标 将整型数组 转换为字符数字
            displayboard(show, row, col);
            printf("恭喜你排雷成功,你离成功又进了%d步\n", win);
            }
            else
            {
                if (win < 10)
                {
                    printf("gameover 游戏结束!\n");
                    printf("运气不好,下次努力哦\n");
                    printf("你共排雷:% d颗\n", win);
                    displayboard(mine, row, col);
                    break;
                }
                if (win <= 30)
                {
                    printf("还可以,再接再厉吧!\n");
                    printf("你共排雷:% d颗\n", win);
                    displayboard(mine, row, col);
                    break;
                }
                if (win <= 50)
                {
                    printf("太可惜了,下次一定成功!加油!\n");
                    printf("你共排雷:% d颗\n", win);
                    displayboard(mine, row, col);
                    break;
                }
                break;
            }

        }
        else
        {
            printf("输入坐标非法,请重新输入\n");
        }
     }
    if (win == ROW * COL - bomb)
    {
        printf("恭喜这位勇士,排雷成功\n");
        displayboard(mine, row, col);
    };
}

//游戏主体
void game()
{
    srand((unsigned int)time(NULL));
    char mine[ROWS][COLS] = { 0 };//布置雷区
    char show[ROWS][COLS] = { 0 };//扫雷使用
    lnitboard(mine, ROWS, COLS, '0');//初始化布雷区
    lnitboard(show, ROWS, COLS, '*');//初始化扫雷区
    setmine(mine, ROW, COL,'$');//设置雷区 用$来表示雷
    displayboard(show, ROW, COL);
    playmove(mine,show,ROW,COL);//因为同时要用到所以两个都传输

}

三:测试部分

#define _CRT_SECURE_NO_WARNINGS 
#include "zhk.h"


int main()
{
    menu();//显示菜单
    int n = 0;//创建变量以便于选择项目
    do
    {
        printf("请输入>?:");
        scanf("%d", &n);//输入选择数值
        switch (n)
        {
        case 0:
        {
            printf("正在退出游戏请稍后,欢迎下次再来!\n");
            Sleep(250);//250微秒后执行
            printf("游戏退出完成\n");
            break;
        }
        case 1:
        {
            printf("欢迎游玩本游戏!\n"); \
            game();//运行游戏主体
            break;
        }
        default :
        {
            printf("输入错误,请重新输入\n");
            break;
        }
        }
    } while (n);
}

;