北理工49. 【游戏】扫雷

49. 【游戏】扫雷

 

背景

你玩儿过扫雷游戏吧?有个操作系统中带了这个小游戏,那个系统叫什么来着?;-)在游戏中要想过关,就必须要在一个 NxM 的区域上找出所有的地雷。游戏过程中,计算机会在地图上显示一些数字从而帮助你确定哪里有地雷。例如,在下面这个有两颗地雷的 4x4 的地图(*表示地雷):

*...
....
.*..
.... 

根据上面的地图,可以计算出应该提供给游戏者的数字如下所示:

*100
2210
1*10
1110 

每个数字表示了该方格周围到底有几个地雷,当然,一个方格周围最多的时候只会有八个。

输入

输入中将包括一系列的地图,每个地图的第一行有两个整数 n 和 m(0 <n,m <= 100),它们表示了地图的行数和列数。下面的 n 行每行都有 m 个字符,其中 "." 表示安全而 "*" 表示地雷。如果地图的 n 和 m 都为 0,则表示输入结束。

输出

针对每一个地图,首先输出一行:

Field #x:

其中 x 是当前地图的编号(从 1 开始)。下面的 n 行则将地图中的 "." 以数字表示,该数字表示该方格周围有多少颗地雷。

 

来源

http://acm.uva.es/problemset/v101/10189.html

  测试输入 期待的输出 时间限制 内存限制 额外进程
测试用例 1 以文本方式显示
  1. 4 4↵
  2. *...↵
  3. ....↵
  4. .*..↵
  5. ....↵
  6. 3 5↵
  7. **...↵
  8. .....↵
  9. .*...↵
  10. 0 0↵
以文本方式显示
  1. Field #1:↵
  2. *100↵
  3. 2210↵
  4. 1*10↵
  5. 1110↵
  6. Field #2:↵
  7. **100↵
  8. 33200↵
  9. 1*100↵
1秒 64M 0
测试用例 2 以文本方式显示
  1. 3 3↵
  2. ...↵
  3. ...↵
  4. ...↵
  5. 3 3↵
  6. ***↵
  7. ***↵
  8. ***↵
  9. 0 0↵
以文本方式显示
  1. Field #1:↵
  2. 000↵
  3. 000↵
  4. 000↵
  5. Field #2:↵
  6. ***↵
  7. ***↵
  8. ***↵
1秒 64M 0

 


这道题很难,至少我做这题的感觉是这样。第一感觉是要用到二维数组,但是二维数组我忘记了!我还是太菜了……这题做的还是比较艰辛的,花了两天(流泪)

#include <stdio.h>
int row, col;
char landmine_number(const char point[][100], int x, int y);
int main(void) 
{
    /*首先创立一个大小为100*100的char数组读入row,col,还要有一个counter来记录次数
    * 读入row,col
    * 对于一个坐标x,y;它的周围 [x-1][y-1]~[x-1][y+1];[x][y-1]~[x][y+1];[x+1][y-1]~[x+1][y+1]
    * landmine_counter来记录坐标周围地雷数量
    */
    char table[100][100] = { '.'};
    int counter = 0, landmine_counter = 0;
    scanf("%d %d", &row, &col);
    getchar();
    do {
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++)
                table[i][j] = getchar();
            getchar();
        }
        counter++;
        putchar(counter > 1 ? '\n' : '\0');
        printf("Field #%d:\n", counter);        
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++)
                printf("%c", landmine_number(table, i, j));
            putchar('\n');
        }
        scanf("%d %d", &row, &col);
        getchar();
    } while (row != 0 && col != 0);
    return 0;
}
char landmine_number(const char point[][100], int x, int y)
{
    int landmine_counter = 0;

    for (int i = x - 1; i <= x + 1 && i < row ; i++)
        for (int j = y - 1; j <= y + 1 && j < col; j++)
            if(j>=0 && i >= 0)
                if (point[i][j] == '*' && (i != x || j != y)) landmine_counter++;    
    char ret[2] = {0};
    if (point[x][y] == '*') ret[0] = '*';
    else  sprintf(ret, "%d", landmine_counter);
    return ret[0];
}

 

原本这道题已经被我弃之脑后了,但是一次偶然与丁助教的聊天,又让我萌发了新的灵感,代码还可以改进!

1. 数据的读入可以采用字符串%s,或者一些专门的字符串读入函数。这样可以看上去更赏心悦目

2. 我采取的输出地雷方法是最容易想到的,但是还可以有另外一种想法。那就是把每个地雷周围的八个位置都++,然后输出

3. 关于边界问题,我自认为采取了一个很巧妙的方法,也就是下述代码!(我的脑子思考了两天才想出来)

for (int i = x - 1; i <= x + 1 && i < row ; i++)
        for (int j = y - 1; j <= y + 1 && j < col; j++)
            if(j>=0 && i >= 0)
                if (point[i][j] == '*' && (i != x || j != y)) landmine_counter++;    

但是还有一个新的想法就是,通过将数组扩大来避免边界问题。这样说很抽象,所以还是看代码

 

#include<stdio.h>
#include<string.h>
static int row, col;
void mark_mines(char table[][110], char mines[][110]);
int main(void) {
	int counter = 0;
	char table[110][110],mines[110][110];
	scanf("%d %d", &row, &col);
	getchar();
	do {
		memset(table, 0, sizeof(table));
		memset(mines, '0', sizeof mines);		
		for (int i = 1; i < row + 1; i++)
			gets(&table[i][1]);
		/*only two rows, the whole data was read completely,wonderful*/
		putchar(counter++ > 0 ? '\n' : '\0');
		printf("Field #%d\n", counter);
		mark_mines(table, mines);
		for (int i = 1; i < row + 1; i++)
			puts(&mines[i][1]);
		scanf("%d %d", &row, &col);
		getchar();
	} while (row != 0 && col != 0);
	return 0;
}
void mark_mines(char table[][110], char mines[][110])
{
	for (int x = 1; x < row + 1; x++) 
		for (int y = 1; y < col + 1; y++) 
			if (table[x][y] == '*') {
				for (int i = -1; i < 2; i++)
					for (int j = -1; j < 2; j++)
						if (mines[x + i][y + j] != '*') mines[x + i][y + j]++;
				mines[x][y] = '*';
			}
	for (int i = 1; i < row + 1; i++)
		mines[i][col + 1] = '\0';
}

 

 

posted @ 2022-12-14 21:46  我千五可以  阅读(139)  评论(0)    收藏  举报