マインスイーパ作った

pythonでマインスイーパのコードを作ってみました。

## コード

```py
import random

class Minesweeper:
    def __init__(self, size=8, mines=10):
        self.size = size
        self.mines = mines
        self.board = [[' ' for _ in range(size)] for _ in range(size)]
        self.mines_positions = set()
        self.generate_mines()
        self.populate_board()

    def generate_mines(self):
        while len(self.mines_positions) < self.mines:
            x = random.randint(0, self.size - 1)
            y = random.randint(0, self.size - 1)
            self.mines_positions.add((x, y))

    def populate_board(self):
        for x, y in self.mines_positions:
            self.board[x][y] = 'M'
        for i in range(self.size):
            for j in range(self.size):
                if self.board[i][j] != 'M':
                    self.board[i][j] = self.count_adjacent_mines(i, j)

    def count_adjacent_mines(self, x, y):
        count = 0
        for i in range(max(0, x-1), min(self.size, x+2)):
            for j in range(max(0, y-1), min(self.size, y+2)):
                if (i, j) != (x, y) and self.board[i][j] == 'M':
                    count += 1
        return str(count) if count > 0 else ' '

    def print_board(self):
        print('  ' + ' '.join([str(i+1) for i in range(self.size)]))
        for i in range(self.size):
            print(str(i+1) + ' ' + ' '.join(self.board[i]))

    def reveal_cell(self, x, y):
        if self.board[x][y] == 'M':
            return False
        self.flood_fill(x, y)
        return True

    def flood_fill(self, x, y):
        if self.board[x][y] != ' ':
            return
        self.board[x][y] = '.'
        for i in range(max(0, x-1), min(self.size, x+2)):
            for j in range(max(0, y-1), min(self.size, y+2)):
                if (i, j) != (x, y) and self.board[i][j] == ' ':
                    self.flood_fill(i, j)

    def is_win(self):
        for i in range(self.size):
            for j in range(self.size):
                if self.board[i][j] == ' ':
                    return False
        return True

    def play(self):
        while True:
            self.print_board()
            move = input("Enter your move (e.g., 3 4): ")
            try:
                x, y = map(int, move.split())
                x -= 1
                y -= 1
                if not (0 <= x < self.size and 0 <= y < self.size):
                    print("Invalid move. Try again.")
                    continue
                if not self.reveal_cell(x, y):
                    print("Game Over! You hit a mine.")
                    break
                if self.is_win():
                    print("Congratulations! You cleared the board.")
                    break
            except ValueError:
                print("Invalid input. Enter row and column numbers separated by a space.")
            except Exception as e:
                print(f"An error occurred: {e}")

if __name__ == "__main__":
    game = Minesweeper()
    game.play()


```

## 実行

```
$ python minesweeper.py
```

## プレイ画面
入力は `数字 数字` で指定する。
最初の数字が左の1〜8の位置に対応して、後の数字が上の1〜８に対応しています。
逆にしないように注意してください。
地雷のマスを指定するとその時点でゲームオーバーになります。

```
  1 2 3 4 5 6 7 8
1         2 M 2
2 1 1 2 1 3 M 3 1
3 1 M 2 M 2 1 2 M
4 1 1 2 1 1 1 2 2
5           1 M 2
6 1 1   1 1 2 2 M
7 M 1   1 M 2 2 1
8 1 1   1 2 M 1
Enter your move (e.g., 3 4): 1 8
```

地雷を踏まないと、「・」でそのエリアが埋まります。
ここはもう指定しなくていいです。

```
  1 2 3 4 5 6 7 8
1         2 M 2 .
2 1 1 2 1 3 M 3 1
3 1 M 2 M 2 1 2 M
4 1 1 2 1 1 1 2 2
5           1 M 2
6 1 1   1 1 2 2 M
7 M 1   1 M 2 2 1
8 1 1   1 2 M 1
```

## 終了画面

全部「・」で埋まると勝利です。

```
  1 2 3 4 5 6 7 8
1 . . . . 2 M 2 .
2 1 1 2 1 3 M 3 1
3 1 M 2 M 2 1 2 M
4 1 1 2 1 1 1 2 2
5 . . . . . 1 M 2
6 1 1 . 1 1 2 2 M
7 M 1 . 1 M 2 2 1
8 1 1 . 1 2 M 1
Enter your move (e.g., 3 4): 8 8
Congratulations! You cleared the board.
```