项目:C语言实现扫雷的小游戏

扫雷这个经典的游戏大家都应该玩过,今天我们就将用C语言来实现扫雷这个游戏,我的这个扫雷游戏主要有三个功能:

  • 第一次扫雷,一定不会点到雷
  • 第一次扫雷,可以大片的展开
  • 会显示所选位置周围的雷数
下面讲述一下我这个扫雷的思想:
  1. 我们需要两个棋盘,一个用来给用户展示,一个用来自己内部使用
  2. 布雷:在自己使用的棋盘随机布雷
  3. 保证第一步不会踩到雷。首先判断所选位置是否为雷,如果是,将其改掉,并在其他随机不为雷的位置设置雷
  4. 计算所选位置周围雷的个数
  5. 将第一步所选位置周围展开
  6. 判断输赢
但你会发现,在计算周围雷个数的时候,在边边的和在中间位置的计算还不一样,我们可以让数组周围都在加一行或者一列,比如,需要打印出来的是9*9的表格,我们在设置的时候,可以弄成11*11的,只要我们知道就行了,方便计算。
    #define ROW 9
    #define COL 9

    #define ROWS ROW+2
    #define COLS COL+2

话不多说,上代码:

头文件:

这段代码是放在game.h中,函数声明
    #ifndef __GAME_H__
    #define __GAME_H__

    #define ROW 9
    #define COL 9

    #define ROWS ROW+2
    #define COLS COL+2
    #define EASY_COUNT 10 //设置雷数

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>

    void InitBoard(char board[ROWS][COLS], int row, int col, char c);//初始化棋盘
    void SetBoard(char board[ROWS][COLS], int row, int col);//布雷
    void PrintBoard(char board[ROWS][COLS], int row, int col);//打印棋盘
    int AroundCount(char board[ROWS][COLS], int x, int y);//计算周围雷数
    int IfWin(char board[ROWS][COLS], int row, int col);//判断输赢
    void Minesweeper(char MineBoard[ROWS][COLS], char PlayBoard[ROWS][COLS], int row, int col);//扫雷过程
    void FirstStep(char MineBoard[ROWS][COLS], char PlayBoard[ROWS][COLS], int row, int col, int x, int y);//第一步
    void OpenBoard(char MineBoard[ROWS][COLS], char PlayBoard[ROWS][COLS], int x, int y);//第一步展开

    #endif
下面的代码是放在game.c中的:

初始化棋盘:

我们有两个棋盘,自己使用的全部初始化为‘0’(不是雷),用户使用的,全部初始化为‘*’

    void InitBoard(char board[ROWS][COLS], int row, int col, char c)
    {
        memset(board, c, sizeof(board[0][0]) * row * col);
    }

打印棋盘:

    void PrintBoard(char board[ROWS][COLS], int row, int col)
{
    for (int i = 1; i < row - 1; i++)
    {
        if (i == 1)
        {
            printf("  %d", i);
        }
        else
        {
            printf(" %d", i);
        }
    }
    printf("\n");
    for (int i = 1; i < row - 1; i++)
    {
        printf("%d ", i);
        for (int j = 1; j < col - 1; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

这里写图片描述

布雷:

    void SetBoard(char board[ROWS][COLS], int row, int col)
    {
        int x = 0;
        int y = 0;
        int i = 0;
        while (i < EASY_COUNT)
        {
            while (1)
            {
                x = rand() % 9 + 1;
                y = rand() % 9 + 1;
                if (board[x][y] == '0')
                {
                    board[x][y] = '1';
                    break;
                }
            }
            i++;
        }
    }

计算周围雷的个数:

    int AroundCount(char board[ROWS][COLS], int x, int y)
    {
        return board[x - 1][y] + board[x - 1][y - 1] + 
               board[x][y - 1] + board[x + 1][y - 1] + 
               board[x + 1][y] + board[x + 1][y + 1] + 
               board[x][y + 1] + board[x - 1][y + 1] - 8 * '0';
    }

判断输赢:

当最后所剩余棋盘上的 * 就是雷时,则胜利

    int IfWin(char board[ROWS][COLS], int row, int col)
    {
        int count = 0;
        for (int i = 1; i <= row; i++)
        {
            for (int j = 1; j <= col; j++)
            {
                if (board[i][j] == '*')
                {
                    count++;
                }
            }
        }
        return count;
    }

第一步为雷时:

    void FirstStep(char MineBoard[ROWS][COLS], char PlayBoard[ROWS][COLS], int row, int col, int x, int y)
    {
            MineBoard[x][y] = '0';
            int i = 0;
            int j = 0;
            while (1)
            {
                i = rand() % 9 + 1;
                j = rand() % 9 + 1;
                if (MineBoard[i][j] == '0')
                {
                    MineBoard[i][j] = '1';
                    break;
                }
            }
            int ret = AroundCount(MineBoard, x, y);
            PlayBoard[x][y] = ret + '0';
            OpenBoard(MineBoard, PlayBoard, x, y);
            PrintBoard(PlayBoard, ROWS, COLS);
            PrintBoard(MineBoard, ROWS, COLS);
    }

这里写图片描述
这里写图片描述

扫雷过程:

当第一步所选位置不是雷时,正常走,如若是雷,就将其改变

void Minesweeper(char MineBoard[ROWS][COLS], char PlayBoard[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int step = 1;
    while (1)
    {
        printf("请输入坐标:\n");
        scanf("%d%d", &x, &y);
        if (MineBoard[x][y] == '1' && step == 1)
        {
            FirstStep(MineBoard, PlayBoard, ROW, COL, x, y);
            step++;
            if (IfWin(PlayBoard, ROW, COL) == EASY_COUNT)
            {
                printf("恭喜你,YOU WIN!\n");
                PrintBoard(MineBoard, ROWS, COLS);
                break;
            }
            continue;
        }
        if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
        {
            if (MineBoard[x][y] == '1')
            {
                printf("BOOM!你被炸飞了\n");
                PrintBoard(MineBoard, ROWS, COLS);
                break;
            }
            else
            {
                int ret = AroundCount(MineBoard, x, y);
                PlayBoard[x][y] = ret + '0';
                OpenBoard(MineBoard, PlayBoard, x, y);
                PrintBoard(PlayBoard, ROWS, COLS);
            }
        }
        else
        {
            printf("输入坐标非法,请重新输入\n");
        }
        if (IfWin(PlayBoard, ROW, COL) == EASY_COUNT)
        {
            printf("恭喜你,YOU WIN!\n");
            PrintBoard(MineBoard, ROWS, COLS);
            break;
        }
    }
}

展开:

该过程使用的是递归,如若周围一直没有雷,就会一直扩展下去

    void OpenBoard(char MineBoard[ROWS][COLS], char PlayBoard[ROWS][COLS], int x, int y)
    {
        if (MineBoard[x][y] == '0' && PlayBoard[x][y] == '*')
        {
            PlayBoard[x][y] = AroundCount(MineBoard, x, y) + '0';
        }
        if (MineBoard[x - 1][y] == '0' && PlayBoard[x - 1][y] == '*')
        {
            PlayBoard[x - 1][y] = AroundCount(MineBoard, x - 1, y) + '0';
            if (AroundCount(MineBoard, x - 1, y) == 0)
            {
                OpenBoard(MineBoard, PlayBoard, x - 1, y);
            }
        }
        if (MineBoard[x - 1][y - 1] == '0' && PlayBoard[x - 1][y - 1] == '*')
        {
            PlayBoard[x - 1][y - 1] = AroundCount(MineBoard, x - 1, y - 1) + '0';
            if (AroundCount(MineBoard, x - 1, y - 1) == 0)
            {
                OpenBoard(MineBoard, PlayBoard, x - 1, y - 1);
            }
        }
        if (MineBoard[x][y - 1] == '0' && PlayBoard[x][y - 1] == '*')
        {
            PlayBoard[x][y - 1] = AroundCount(MineBoard, x, y - 1) + '0';
            if (AroundCount(MineBoard, x, y - 1) == 0)
            {
                OpenBoard(MineBoard, PlayBoard, x, y - 1);
            }
        }
        if (MineBoard[x + 1][y - 1] == '0' && PlayBoard[x + 1][y - 1] == '*')
        {
            PlayBoard[x + 1][y - 1] = AroundCount(MineBoard, x + 1, y - 1) + '0';
            if (AroundCount(MineBoard, x + 1, y - 1) == 0)
            {
                OpenBoard(MineBoard, PlayBoard, x + 1, y - 1);
            }
        }
        if (MineBoard[x + 1][y] == '0' && PlayBoard[x + 1][y] == '*')
        {
            PlayBoard[x + 1][y] = AroundCount(MineBoard, x + 1, y) + '0';
            if (AroundCount(MineBoard, x + 1, y) == 0)
            {
                OpenBoard(MineBoard, PlayBoard, x + 1, y);
            }
        }
        if (MineBoard[x + 1][y + 1] == '0' && PlayBoard[x + 1][y + 1] == '*')
        {
            PlayBoard[x + 1][y + 1] = AroundCount(MineBoard, x + 1, y + 1) + '0';
            if (AroundCount(MineBoard, x + 1, y + 1) == 0)
            {
                OpenBoard(MineBoard, PlayBoard, x + 1, y + 1);
            }
        }
        if (MineBoard[x][y + 1] == '0' && PlayBoard[x][y + 1] == '*')
        {
            PlayBoard[x][y + 1] = AroundCount(MineBoard, x, y + 1) + '0';
            if (AroundCount(MineBoard, x, y + 1) == 0)
            {
                OpenBoard(MineBoard, PlayBoard, x, y + 1);
            }
        }
        if (MineBoard[x - 1][y + 1] == '0' && PlayBoard[x - 1][y + 1] == '*')
        {
            PlayBoard[x - 1][y + 1] = AroundCount(MineBoard, x - 1, y + 1) + '0';
            if (AroundCount(MineBoard, x - 1, y + 1) == 0)
            {
                OpenBoard(MineBoard, PlayBoard, x - 1, y + 1);
            }
        }
    }

这里写图片描述

下面的代码是放在test.c中的:

游戏模块:

    #pragma warning(disable:4996)
    #include "game.h"

    void menu()
    {
        printf("*********************************\n");
        printf("****          1.play         ****\n");
        printf("****          0.exit         ****\n");
        printf("*********************************\n");
    }

    void game()
    {
        char MineBoard[ROWS][COLS];
        char PlayBoard[ROWS][COLS];
        InitBoard(MineBoard, ROWS, COLS, '0');
        InitBoard(PlayBoard, ROWS, COLS, '*');
        SetBoard(MineBoard, ROWS, COLS);
        //PrintBoard(MineBoard, ROWS, COLS);
        PrintBoard(PlayBoard, ROWS, COLS);
        Minesweeper(MineBoard, PlayBoard, ROW, COL);
    }

    void test()
    {
        srand((unsigned int)time(NULL));
        int input = 0;
        do
        {
            menu();
            printf("请选择:\n");
            scanf("%d", &input);
            switch (input)
            {
            case 1:
                game();
                break;
            case 0:
                printf("退出游戏\n");
                break;
            default:
                printf("请重新选择:\n");
                break;
            }
        } while (input);
    }

    int main()
    {
        test();
        system("pause");
        return 0;
    }
当选到雷时:

这里写图片描述

最终排除所有雷时:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/aixiaodeshushu/article/details/81120448