2025.08.01(更新日: 2025.08.26)
      穴を開ける
はじめに
前回、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 card1-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] = True3-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ビンゴ!

コメントを残す