AtCoder ABC 075 B – Minesweeper Python解説

スポンサーリンク

Minesweeper

H×W のマス目が与えられます。
入力において、全てのマスは文字で表されており、.は空きマス、 # は爆弾マスに対応します。

マス目は H 個の文字列 S_1,…,S_Hで表されます。
文字列Sij 文字目は、マス目の上から i 番目、左から j 番目のマスに対応します。

イルカは各空きマスの上下左右および斜めの 8 方向で隣接しているマスに爆弾マスが何個あるか気になっています。
そこで、各空きマスに対応する . を、その空きマスの周囲8方向に隣接するマスにおける爆弾マスの個数を表す数字で置き換えることにしました。

以上の規則で置き換えられた後のマス目を出力してください。

AtCoder Beginner Contest 075 「Minesweeper」

マインスイーパーを遊んだことがあればルールに覚えがあるはず。
今回は、空きマスに隣接(周囲8方向)する爆弾マスの数を出力していく問題です。

#入力例
.....
.#.#.
.....

#出力例
11211
1#2#1
11211

方針としては、与えられたマスをひとつずつ調べていき、爆弾マスだったらスルー、空きマスだったら周囲に爆弾マスがないか更に調べていきます。

h, w = map(int, input().split())
s = [list(input()) for _ in range(h)]

# *1
d_x = [1, 0, -1, 0, 1, -1, -1, 1]
d_y = [0, 1, 0, -1, 1, 1, -1, -1]

for i in range(h):
    for j in range(w):
        if s[i][j] == ".":
            cnt = 0
           
            for k in range(8):
                search_i = i + d_y[k]
                search_j = j + d_x[k]
                # *2
                if 0 <= search_i < h and 0 <= search_j < w and s[search_i][search_j] == "#":
                    cnt += 1
                    
            s[i][j] = cnt
        
for i in range(h):
    for j in range(w):
        print(s[i][j], end = "")
    print()

(*1)ここでは空きマスの周囲を調べるために、配列d_xとd_yを用意しました。for文でこの配列の要素を足すことにより、空きマスの周囲8方向を調べることができます。

(*2)空きマスの周囲を調べる際、調べる場所によっては範囲外エラーになることが予想されます。そのため、元々用意されているマス目に収まる範囲、かつ爆弾マスだったらcnt+1されるように条件文で書いています。