穴を開ける

はじめに

前回、Python製のビンゴゲームについて解説した。

現状、番号を引いてもカードに穴が開かない。

カードに穴を空けるには

処理の流れを追う。

1. ゲームスタートから以下の画面が表示されるまで

1-1. play_bingo関数が発火

# ゲームを開始
play_bingo()

1-2. BingoCardクラスのインスタンス生成

def play_bingo():
    card = BingoCard()

1-3. カードとマークの初期化

import random

class BingoCard:
    def __init__(self):
        self.card = self.generate_card()
        self.marked = [[False] * 5 for _ in range(5)]  # 数字のマーク状態を保持

    def generate_card(self):
        # 各列 (B, I, N, G, O) ごとに範囲内のランダムな数字を選ぶ
        card = []
        ranges = [(1, 15), (16, 30), (31, 45), (46, 60), (61, 75)]
        for start, end in ranges:
            column = random.sample(range(start, end + 1), 5)
            card.append(column)

        card[2][2] = "FREE"  # 中央のフリー枠
        return card

1-4. カードを表示

def play_bingo():
    card.display_card()
class BingoCard:
    def display_card(self):
        print("\nB  I  N  G  O")
        for i in range(5):
            for j in range(5):
                value = self.card[j][i]  # 列ごとに表示
                if isinstance(value, int):
                    print(f"{value:2d}", end=" ")
                else:
                    print(f"{value:>2}", end=" ")
            print()

1-5. すでに引いたカードの集合を作成

def play_bingo():
    drawn_numbers = set()

1-6. 無限ループ突入→番号を引かせる

    while True:
        input("Enterで次の番号を引きます...")

2. ユーザが番号を引く → その番号が表示される

2-1. 数字をランダム生成

import random

def play_bingo():
    while True:
        number = random.randint(1, 75)

2-2. 重複防止処理

        while number in drawn_numbers:  # 重複しないようにする
            number = random.randint(1, 75)

2-3. 集合に追加

def play_bingo():
    drawn_numbers = set()
    while True:
        drawn_numbers.add(number)

2-4. 引かれた番号を出力

        print(f"引かれた番号: {number}")

3. マークに穴を開ける処理

3-1. mark_number関数の発火

        card.mark_number(number)

3-2. 二重for文で引いた数字があるかカードのすべての番号を確認

    def mark_number(self, number):
        for i in range(5):
            for j in range(5):
                if self.card[i][j] == number:
                    self.marked[i][j] = True

3-3. 一致していれば、markedの該当箇所をTrueにする

    def mark_number(self, number):
        for i in range(5):
            for j in range(5):
                if self.card[i][j] == number:
                    self.marked[i][j] = True

変更する箇所は、mark_numberメソッド

以下の赤字部分を変更する。

    def mark_number(self, number):
        for i in range(5):
            for j in range(5):
                if self.card[i][j] == number:
                    self.marked[i][j] = True

以下の赤字部分を変更した。

    def mark_number(self, number):
        for i in range(5):
            for j in range(5):
                if self.card[i][j] == number:
                    self.card[i][j] = "✖️"

引かれた番号のカードが「✖️」になった。

問題点発生 – ビンゴにならない –

先程の画像を見てもらえればわかるが、Bの縦列が揃っているのにビンゴにならない。

最終的には、1 ~ 75までの一意の番号がなくなってしまった。

今の処理がどうなっているのか?

1. mark_numberメソッドで引かれた番号がカードにあれば「✖️」にする。

def play_bingo():
    card = BingoCard()
        card.mark_number(number)
class BingoCard:
    def mark_number(self, number):
        for i in range(5):
            for j in range(5):
                if self.card[i][j] == number:
                    self.card[i][j] = "✖️"
        card.display_card()

2. check_bingoメソッドでビンゴ判定

        if card.check_bingo():
            print("ビンゴ!おめでとうございます!")
            break
    def check_bingo(self):
        # 行と列でビンゴかどうかをチェック
        for i in range(5):
            if all(self.marked[i]):  # 行のビンゴ
                return True
            if all([self.marked[j][i] for j in range(5)]):  # 列のビンゴ
                return True

        # 対角線のビンゴをチェック
        if all([self.marked[i][i] for i in range(5)]):  # 左上から右下
            return True
        if all([self.marked[i][4 - i] for i in range(5)]):  # 右上から左下
            return True

        return False

ここで判定条件をmarkedにしているのが原因。

解決方法

check_bingoメソッドの中身を「marked → card」に変更する。

もしくは、mark_numberメソッドでmarkedの状態を変更できるようにする。

後者の方が簡単。

以下の太字部分を追加した(元々あった)

    def mark_number(self, number):
        for i in range(5):
            for j in range(5):
                if self.card[i][j] == number:
                    self.card[i][j] = "✖️"
                    self.marked[i][j] = True

ビンゴ!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です