C语言 | 扫雷游戏-优化

C语言实现扫雷游戏

本文接上篇:C语言实现扫雷游戏-简单版

为了添加扫出一片的效果,本文对扫雷部分函数做出修改如下:

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

static void clean_around(char show[ROWS][COLS], char mine[ROWS][COLS], char tag[ROWS][COLS], int x, int y)
{
    //屏蔽掉边缘部分
    if (x == 0 || x == ROWS - 1 || y == 0 || y == COLS - 1)
    {
        //
    }
    else
    {
        int i;
        for (i = x - 1; i <= x + 1; i++)
        {
            int j;
            for (j = y - 1; j <= y + 1; j++)
            {
                if (tag[i][j] == '0') //0表示未被访问过
                {
                    tag[i][j] = '1';//标记为1,表示排查过,下次不再排查
                    int ret  = get_mine(mine, i, j);
                    if (ret == 0)
                    {
                        show[i][j] = ' ';
                        clean_around(show, mine, tag, i, j);
                    }else
                    {
                        show[i][j] = ret + '0';
                    }
                }
            }
        }
    }

}

static int CountMine(char show[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    int count = 0;
    for (i = 1; i <= row; i++)
    {
        for (j = 1; j <=col; j++)
        {
            if (show[i][j] == '*' || show[i][j] == '#')
            {
                count++;
            }
        }
    }
    return count;
}

void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], char tag[ROWS][COLS], int row, int col)
{
    int count = 0;//记录找出的雷的个数
    while(count != EASY_COUNT)
    {
        //玩家输入
        printf("Please enter x and y:>");
        int x, y;
        scanf("%d %d", &x, &y);
        //检查输入合法性,不合法重新输入
        if (x < 1 || y < 1 || x > ROW || y > COL)
        {
            printf("Invalid input, please re-enter.\n");
            continue;
        }

        //点击or标记
        printf("1 CLICK\n2 TAG\n\n");
        int z;
        scanf("%d", &z);
        if (z == 1) //点击
        {
            if (mine[x][y] == '1') //炸死了
            {
                printf("Oops, here is a bomb, you out!\n");
                PrintBoard(mine, row, col);
                printf("\n\n\n");
                break;
            }else //安全
            {
                //查询周围一圈雷的个数
                int ret = get_mine(mine, x, y);
                tag[x][y] = '1';
                
                if (ret == 0)
                {
                    show[x][y] = ' ';
                    clean_around(show, mine, tag, x, y);

                }else
                {
                    show[x][y] = ret + '0';
                }

                PrintBoard(show, row, col);
                printf("\n\n");
            }
        }else if (z == 2) //标记
        {
            show[x][y] = '#';
            PrintBoard(show, row, col);
            printf("\n\n");
        }
        //检查雷是否排完
        count = CountMine(show, ROW, COL);
        if (count == EASY_COUNT)
        {
            printf("Congratulations, you successfully cleared all the mines!\n");
            PrintBoard(mine, row, col);
            printf("\n\n\n");
        }
        
    }
    
}

效果测试

//设置一个雷
//show数组展示如下
0 1 2 3 4 5 6 7 8 9 
1 0 0 0 0 0 0 0 0 0 
2 0 0 0 0 0 0 0 0 0 
3 0 0 0 0 0 0 0 0 0 
4 1 0 0 0 0 0 0 0 0 
5 0 0 0 0 0 0 0 0 0 
6 0 0 0 0 0 0 0 0 0 
7 0 0 0 0 0 0 0 0 0 
8 0 0 0 0 0 0 0 0 0 
9 0 0 0 0 0 0 0 0 0 
//可见只有(4,1)处是雷

//玩游戏测试
*********************
****  1. Play  ******
****  0. Exit  ******
*********************
Please enter your choice(1/0):> 1
Welcome to Minesweeper!
0 1 2 3 4 5 6 7 8 9 
1 * * * * * * * * * 
2 * * * * * * * * * 
3 * * * * * * * * * 
4 * * * * * * * * * 
5 * * * * * * * * * 
6 * * * * * * * * * 
7 * * * * * * * * * 
8 * * * * * * * * * 
9 * * * * * * * * * 

Please enter x and y:>4 3
1 CLICK
2 TAG

1
0 1 2 3 4 5 6 7 8 9 
1                   
2                   
3 1 1               
4 * 1               
5 1 1               
6                   
7                   
8                   
9                   


Congratulations, you successfully cleared all the mines!
0 1 2 3 4 5 6 7 8 9 
1 0 0 0 0 0 0 0 0 0 
2 0 0 0 0 0 0 0 0 0 
3 0 0 0 0 0 0 0 0 0 
4 1 0 0 0 0 0 0 0 0 
5 0 0 0 0 0 0 0 0 0 
6 0 0 0 0 0 0 0 0 0 
7 0 0 0 0 0 0 0 0 0 
8 0 0 0 0 0 0 0 0 0 
9 0 0 0 0 0 0 0 0 0 



*********************
****  1. Play  ******
****  0. Exit  ******
*********************
Please enter your choice(1/0):> 0
Bye bye ~

完整版代码,欢迎各位网友复制测试

1-game.h
//库函数
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//定义字符
#define ROW 9 //排雷区域
#define COL 9 //排雷区域
#define EASY_COUNT 1 //雷的个数
#define ROWS ROW+2 //显示区域
#define COLS COL+2 //显示区域

//定义函数

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void PrintBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], char tag[ROWS][COLS], int row, int col);

2-game.c
#include "game.h"

void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
    int i;
    for(i = 0; i < ROWS; i++)
    {
        int j;
        for(j = 0; j < COLS; j++)
        {
            board[i][j] = set;
        }
    }
}

void PrintBoard(char board[ROWS][COLS], int row, int col)
{
    int i;
    for(i = 0; i <= col; i++)
    {
        printf("%c ", i + '0');
    }
    printf("\n");

    for(i = 1; i <= row; i++)
    {
        printf("%c ", i + '0');
        int j;
        for(j = 1; j <= col; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
}

void SetMine(char board[ROWS][COLS], int row, int col)
{
    //某座标的值设为'1'代表设置雷
    int count = 0;
    while(count < EASY_COUNT)
    {
        int x = rand() % row + 1;
        int y = rand() % col + 1;
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (board[x][y] == '0')
            {
                board[x][y] = '1'; //布置雷
                count++;
            }
        }       
    }
    
}

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

static void clean_around(char show[ROWS][COLS], char mine[ROWS][COLS], char tag[ROWS][COLS], int x, int y)
{
    //屏蔽掉边缘部分
    if (x == 0 || x == ROWS - 1 || y == 0 || y == COLS - 1)
    {
        //
    }
    else
    {
        int i;
        for (i = x - 1; i <= x + 1; i++)
        {
            int j;
            for (j = y - 1; j <= y + 1; j++)
            {
                if (tag[i][j] == '0') //0表示未被访问过
                {
                    tag[i][j] = '1';//标记为1,表示排查过,下次不再排查
                    int ret  = get_mine(mine, i, j);
                    if (ret == 0)
                    {
                        show[i][j] = ' ';
                        clean_around(show, mine, tag, i, j);
                    }else
                    {
                        show[i][j] = ret + '0';
                    }
                }
            }
        }
    }

}

static int CountMine(char show[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    int count = 0;
    for (i = 1; i <= row; i++)
    {
        for (j = 1; j <=col; j++)
        {
            if (show[i][j] == '*' || show[i][j] == '#')
            {
                count++;
            }
        }
    }
    return count;
}

void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], char tag[ROWS][COLS], int row, int col)
{
    int count = 0;//记录找出的雷的个数
    while(count != EASY_COUNT)
    {
        //玩家输入
        printf("Please enter x and y:>");
        int x, y;
        scanf("%d %d", &x, &y);
        //检查输入合法性,不合法重新输入
        if (x < 1 || y < 1 || x > ROW || y > COL)
        {
            printf("Invalid input, please re-enter.\n");
            continue;
        }

        //点击or标记
        printf("1 CLICK\n2 TAG\n\n");
        int z;
        scanf("%d", &z);
        if (z == 1) //点击
        {
            if (mine[x][y] == '1') //炸死了
            {
                printf("Oops, here is a bomb, you out!\n");
                PrintBoard(mine, row, col);
                printf("\n\n\n");
                break;
            }else //安全
            {
                //查询周围一圈雷的个数
                int ret = get_mine(mine, x, y);
                tag[x][y] = '1';
                
                if (ret == 0)
                {
                    show[x][y] = ' ';
                    clean_around(show, mine, tag, x, y);

                }else
                {
                    show[x][y] = ret + '0';
                }

                PrintBoard(show, row, col);
                printf("\n\n");
            }
        }else if (z == 2) //标记
        {
            show[x][y] = '#';
            PrintBoard(show, row, col);
            printf("\n\n");
        }
        //检查雷是否排完
        count = CountMine(show, ROW, COL);
        if (count == EASY_COUNT)
        {
            printf("Congratulations, you successfully cleared all the mines!\n");
            PrintBoard(mine, row, col);
            printf("\n\n\n");
        }
        
    }
    
}
3-test.c
#include "game.h"

void menu()
{
    printf("*********************\n");
    printf("****  1. Play  ******\n");
    printf("****  0. Exit  ******\n");
    printf("*********************\n");
}

void game()
{
    //二维数组存储棋盘
    char mine[ROWS][COLS] = {0}; //存放布置好的雷的信息
    char show[ROWS][COLS] = {0}; //存放排查出的雷的信息
    char tag[ROWS][COLS] = {0}; //用于标记被排查过的坐标
    //初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');
    InitBoard(tag, ROWS, COLS, '0');
    //打印棋盘
    // PrintBoard(mine, ROW, COL);
    PrintBoard(show, ROW, COL);
    //布置雷
    SetMine(mine, ROW, COL);
    // PrintBoard(mine, ROW, COL);
    //扫雷
    FindMine(show, mine, tag, ROW, COL);

}

int main(int argc, char **argv)
{
    srand((unsigned int)time(NULL));
    int input;
    do
    {
        menu();
        printf("Please enter your choice(1/0):> ");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            printf("Welcome to Minesweeper!\n");
            game();
            break;

        case 0:
            printf("Bye bye ~\n\n\n");
            break; 

        default:
            printf("Invalid input, please re-enter.\n");
            break;
        }
    } while (input);
    
    return 0;
}
posted @ 2022-12-08 18:15  万国码aaa  阅读(58)  评论(0编辑  收藏  举报