PTA.h0038. 扫雷游戏(C语言实现)

题目:

       扫雷游戏是在n * n的网格上进行的。在这个网格中隐藏着m个地雷,每个地雷都位于不同的网格位置。玩家反复触碰网格位置。如果触碰到一个有地雷的位置,地雷就会爆炸,玩家就输了。如果触及不包含地雷的位置,则会出现0到8之间的整数,表示包含地雷的相邻或对角线相邻网格位置的数量。部分博弈中的一系列走法如下图所示。

       这里,n是8,m是10,空白方块代表整数0,凸起的方块代表未发挥的位置,类似星号的数字代表地雷。最左边的图像代表部分游戏。从第一张图像到第二张图像,玩家已经走了两步,每次都选择了一个安全的网格位置。从第二个图像到第三个图像,玩家就没那么幸运了;他选了一个有地雷的位置,因此输了。如果玩家继续采取安全的行动,直到剩下的位置都没有了,他就赢了;这些必须遏制地雷。
       你的工作是阅读部分游戏的信息,并打印相应的网格。

输入格式:

       输入的第一行包含一个正整数n(n<=10)。接下来的n行表示地雷的位置。每一行用n个字符表示一行的内容: 句号表示未挖掘的位置,星号表示已挖掘的位置。接下来的n行每n个字符长: 触及的位置用x表示,未触及的位置用句点表示。示例输入对应于上面的中间图。

输出格式:

        输出网格,并适当地填写每个位置。被触碰过且不包含地雷的位置应该包含0到8之间的整数。如果地雷被触碰,所有有地雷的位置都应加星号。所有其他位置都应该包含一个句号。

输入样例:

输出样例:

上思路:

       这题要求我们输出一张表显示触碰到的区域(x)有没有地雷,没踩到地雷就输出0~8的数字,踩到地雷要把全屏的地雷打印出来,没触碰到的区域用(.)表示。

       我先在输入的时候对地雷进行处理,只要有地雷,那该地雷周围的八个格子应该加一,如何表示出来呢?我是用数组实现的,创建一个整型二维数组,当我输入地雷时,该地雷的坐标对应的周围八个格子的坐标的值就从0变成1,那么这个时候就会出现一个问题,可能会出现arr[0][0]是地雷,那么出现arr[-1][-1],这是不对的,怎么解决这个问题呢?很简单,我从下标为1的时候开始输入,这样就避免了数组下标小于0的情况,完成上述操作后,我们就能得到一张数字表。那么接下来的工作就很简单了,上代码。

#include<stdio.h>
int main()
{
    int n, i, j, arr[15][15] = {0};//arr是数字扫雷模拟版,保存绘制出来的数字图像,用于输出数字
    char special, ch[15][15], ch1[15][15];//special用不上,ch是扫雷初始版(用于借用地雷输出,本来想从arr借,后发现没必要),ch1是用户输入版(接收探查范围x)
    scanf("%d", &n);//确定是n*n
    getchar();//至关重要,包括下面的若干个getchar(),用于吸收回车
    if (n >10) return 0;//这里已经实测不是一个测试点,可写可不写
    for (i = 1; i <= n; i++) {//为什么从i=1,j=1开始?因为无需考虑越界,若从0开始,那么下面的if语句里的数组可能会越界变成-1,我这么做避免了越界
        for (j = 1; j <= n; j++) {
            scanf("%c",&ch[i][j]);
            if (ch[i][j] == '*') {
                arr[i][j] = 10;//标记地雷的值是10,这里我也不打算删了,从一开始写的时候就想利用这个点做事,后来发现没必要,因为ch里有
                arr[i-1][j-1]++;//从这行开始的八行,意味着地雷周围的八个点必须强制加一
                arr[i-1][j+1]++;
                arr[i+1][j-1]++;
                arr[i+1][j+1]++;
                arr[i][j-1]++;
                arr[i][j+1]++;
                arr[i-1][j]++;
                arr[i+1][j]++;
            }
        }
        getchar();
    }
//上面代码的作用就是根据输入的符号绘制数字图像arr,只要出现地雷那么就会自动扫描当前地雷的周围八个格子并加一
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            scanf("%c",&ch1[i][j]);
        }
        getchar();
    }
//上面代码的作用是输入探查的范围
    int flag=0;//此开关是用来控制是否恢复出厂设置,当开关为1,就说明踩到了地雷,必须把所有ch2数组里对应地雷数字ij的元素改为*,强制输出
    for (i = 1; i <= n; i++) {//在这里我们先强制转换跟地雷对应的数字所在的位置全部改为*,并判断是否探查到了地雷,若没有则恢复出厂设置,若有则无需操作
        for (j = 1; j <= n; j++) {
            if (ch[i][j] == '*') {
                if (ch1[i][j] == 'x') {//判断是否探查到
                    flag =1;
                }
                ch1[i][j] = '*';//强制转换
            }
        }
    }
    if (flag == 0) {//当开关为0,则说明没有踩到地雷,必须恢复出厂设置,按照原先的字符输出即可
        for (i = 1; i <= n; i++) {
            for (j = 1; j <= n; j++) {
                if (ch1[i][j] == '*') {
                    ch1[i][j] = '.';//恢复出厂设置
                }
            }
        }
    }
    for (i = 1; i <= n; i++) {//这里就是常规打印,因为在上面我们已经决定了是否打印地雷,所以只需判断当前的位置是不是输入的探查范围,如果是就打印对应的数字,否则输出点.
        for (j = 1; j <= n; j++) {
            if (ch1[i][j] == 'x') {
                printf("%d", arr[i][j]);
            }
            else {
                printf("%c", ch1[i][j]);
            }
        }
        if(i != n) printf("\n");//注意换行,不确定这里有没有测试点,还是要严谨
    }
    return 0;
}

       这题的有一个测试点大家不容易发现,解决方式就是我在代码里设置的开关。问题出现的原因是因为如果前面的地雷没有触及到,自然不会打印,有可能会错过打印,为什么这么说?因为有可能在之后的某行某列触及到了地雷,那么这个时候就需要打印所有地雷,但是前面的地雷已经被错过了,理应打印地雷的(*)变成了(.)那就不符合题意了.

        相信大家可以看懂的,如果有不懂的可以在评论区提问哦~

——人生自古谁无死,留篇题解帮萌新——
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值