首页 > 其他分享 >C语言 | 扫雷游戏-优化

C语言 | 扫雷游戏-优化

时间:2022-12-08 18:35:02浏览次数:57  
标签:COLS ROWS 游戏 show int mine C语言 扫雷 printf

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;
}

标签:COLS,ROWS,游戏,show,int,mine,C语言,扫雷,printf
From: https://www.cnblogs.com/ljdsbfj/p/16966932.html

相关文章

  • 举例: 在C语言 使用结构体和联合体,设计应用全局变量
    /*举例:在C语言使用结构体和联合体,设计应用全局变量*/#include"stm32f1xx_hal.h"typedefstruct/*定义GSP结构体*/{uint8_tgps_year_time;/*,单位年,......
  • 飞机游戏三 JSBSim介绍
    飞机游戏三JSBSim介绍目录飞机游戏三JSBSim介绍1介绍2xml配置文件解析3气动力模型4基本状态和动作1简易demo2获取状态空间(状态空间)3直接设置初始状态4控制指......
  • 飞机游戏四 飞机作战场景
    飞机游戏四飞机作战场景目录飞机游戏四飞机作战场景感谢视距空战超视距空战感谢浅谈作战飞机机动性-知乎(zhihu.com)视距空战浅谈作战飞机机动性-知乎(zhih......
  • C语言-求1!+2!+3!+4!+5!...+10!
    #include<stdio.h>intmain{inta=0;intb=1;intsum+0;for(a=1;a<11;a++){b=b*a;sum=sum+b;}printf("%d",sum);return0;}......
  • 虹桥滨海新区游戏网站高防BGP物理机
    服务器认定都能从三种方面聊一聊:神泣的无视任何GJ高防服务器、英雄王座的奇特、问道的一条龙高防服务器。在WM世界中真封神专用流量清洗高防服务器是去看看市场上、连合利......
  • 有效解决游戏出海难题,茄子科技为合作伙伴提供专业的本地化营销落地经验
    面对变幻莫测、内卷严重的海外市场,尽管相比国内游戏市场环境有着更多的增量红利,能够支撑行业高速发展,但随着入局者数量上涨,海外用户对出海产品的内容和质量要求越来越高。如......
  • 虹桥滨海新区游戏网站高防物理机租用
    些一样也以优良的任事和以人为本的准则,专注、用情,用极特殊的一些的职业为每三位男性做千年需求分析,江湖界面设计,英雄王座最终研究不行笑傲江湖责任心标记表明引导。为每一......
  • 游戏玩法分析 I
    SQL架构活动表 Activity:+--------------+---------+|ColumnName|Type|+--------------+---------+|player_id|int||device_id|int......
  • 游戏引擎MiniEngine开发记录(一)
    游戏引擎MiniEngine开发记录(一)最近看了Youtube大神TheCherno的GameEngine系列,学习到了很多知识,但是作者前期做的很多工作后期都推翻重构了,很多地方写的也很乱,因此想从自......
  • c语言分支与循环pta练习题
    7-7高空坠球皮球从某给定高度自由落下,触地后反弹到原高度的一半,再落下,再反弹,……,如此反复。问皮球在第n次落地时,在空中一共经过多少距离?第n次反弹的高度是多少?输入格......