2025.07.31(更新日: 2025.08.26)
      再び、Pythonで作るビンゴゲーム
はじめに
以前、以下のような記事を書いた。
今読み返してみると、わかりにくかったので、Pythonの実務経験を経た今の私が解説していこう。
今日も指と腕の痛みを理由にして会社を休んでいる。
もちろん実際に痛みが残っている。
しかし、家だと休憩の時間をたっぷりとれる。
そのため、腕と指を労わりながらブログを書いていこう。
全ソースコード
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
    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 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
    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()
def play_bingo():
    card = BingoCard()
    card.display_card()
    drawn_numbers = set()
    while True:
        input("Enterで次の番号を引きます...")
        number = random.randint(1, 75)
        while number in drawn_numbers:  # 重複しないようにする
            number = random.randint(1, 75)
        drawn_numbers.add(number)
        print(f"引かれた番号: {number}")
        card.mark_number(number)
        card.display_card()
        if card.check_bingo():
            print("ビンゴ!おめでとうございます!")
            break
# ゲームを開始
play_bingo()実行結果
hiroki@shibatahiroshitakanoiMac python %  cd /Users/hiroki/Downloads/python ; /usr/bin/env /usr/local/bin/python3.12 /Users/hiroki/.vscode/extensions/ms-python.debugpy-2025.10.0-darwin-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher 58612 -- /Users/
hiroki/Downloads/python/bingo.py 
B  I  N  G  O
 8 29 43 59 75 
 7 18 40 60 62 
 5 17 FREE 58 67 
11 24 41 49 69 
 4 21 35 51 64 
Enterで次の番号を引きます...引かれた番号: 57
B  I  N  G  O
 8 29 43 59 75 
 7 18 40 60 62 
 5 17 FREE 58 67 
11 24 41 49 69 
 4 21 35 51 64 
Enterで次の番号を引きます...途中省略
引かれた番号: 29
B  I  N  G  O
 8 29 43 59 75 
 7 18 40 60 62 
 5 17 FREE 58 67 
11 24 41 49 69 
 4 21 35 51 64 
ビンゴ!おめでとうございます!
hiroki@shibatahiroshitakanoiMac python % 仕様

BINGOの各列に指定範囲内のランダムな数値を5つずつ配置(B : 1~15、I : 16~30、N : 31~45、G : 46~60、O : 61~75)
中央マスは、「FREE」
引かれた番号がカード上にあればマーク
横、縦、斜めのいずれか一列すべてがマーク済みでビンゴ!
Enterキー押下でランダムに番号を引き、ビンゴになるまで繰り返す
同じ番号が2回引かれないように制御
フローチャート
スタート→カードとマーク状態の初期化

カードの表示

プレイヤーにカードを引いてもらう→引かれた番号をマークする→カードを表示


ビンゴ判定

ビンゴの場合

ビンゴではない場合


スタート→カードとマーク状態の初期化
play_bingo関数を実行
# ゲームを開始
play_bingo()BingoCardクラスのインスタンス生成
def play_bingo():
    card = BingoCard()cardの初期化
class BingoCard:
    def __init__(self):
        self.card = self.generate_card()    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 cardrandomモジュール使用
import randomsampleメソッド
random.sample(range(1, 15), 5)
[1, 2, 7, 12, 3]
random.sample(range(1, 15), 3)
[2, 7, 13]戻り値のcard
import pprint 
pprint.pprint(card)
[[5, 13, 12, 3, 14],
 [23, 20, 26, 25, 30],
 [38, 33, 'FREE', 42, 44],
 [56, 54, 49, 57, 59],
 [70, 67, 63, 68, 62]]毎回異なる
import pprint 
pprint.pprint(card)
[[1, 2, 12, 11, 6],
 [19, 21, 30, 20, 29],
 [35, 40, 'FREE', 37, 43],
 [53, 59, 49, 58, 57],
 [68, 65, 75, 66, 72]]cardインスタンスを生成すると、cardが初期化されている
card = BingoCard()
card.card
[[15, 10, 4, 7, 6], [23, 21, 22, 26, 27], [36, 32, 'FREE', 39, 45], [57, 46, 52, 60, 49], [75, 72, 73, 74, 69]]こちらも毎回異なる
card = BingoCard()
card.card
[[6, 14, 7, 9, 3], [19, 21, 25, 22, 18], [39, 43, 'FREE', 37, 32], [57, 49, 56, 46, 60], [71, 75, 73, 64, 72]]数字のマーク状態を保持
self.marked = [[False] * 5 for _ in range(5)]リスト内包表記
import pprint 
pprint.pprint([[False] * 5 for _ in range(5)] )
[[False, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False]]pprint.pprint([[False] * 3 for _ in range(5)] )
[[False, False, False],
 [False, False, False],
 [False, False, False],
 [False, False, False],
 [False, False, False]]pprint.pprint([[a] * 3 for a in range(5)] ) 
[[0, 0, 0], [1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]pprint.pprint([_ * 3 for _ in range(5)] ) 
[0, 3, 6, 9, 12]カードの表示
    card.display_card()    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()BINGO
        print("\nB  I  N  G  O")hiroki@shibatahiroshitakanoiMac python %  cd /Users/hiroki/Downloads/python ; /usr/bin/env /usr/local/bin/python3.12 /Users/hiroki/.vscode/extensions/ms-python.debugpy-2025.10.0-darwin-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher 58870 -- /Users/hiroki/Downloads/
python/bingo.py 
B  I  N  G  O外側for文
        for i in range(5):内側for文
            for j in range(5):value
                value = self.card[j][i]self.card
import pprint
pprint.pprint(self.card)
[[3, 9, 8, 2, 7],
 [27, 29, 30, 20, 18],
 [38, 44, 'FREE', 34, 39],
 [50, 55, 53, 46, 54],
 [65, 67, 66, 70, 69]]self.card[4][0]
self.card[4][0]
65数値の場合、右寄せ、右に空白を開けて表示
                if isinstance(value, int):
                    print(f"{value:2d}", end=" ")print(f"{self.card[0][0]:2d}", end=" ")
 3 
print(self.card[0][0])
3

数値以外(FREE)の場合、右寄せ(右寄せしなくても結果は変わらない)
                else:
                    print(f"{value:>2}", end=" ")
プレイヤーにカードを引いてもらう→引かれた番号をマークする→カードを表示
    while True:
        input("Enterで次の番号を引きます...")
        number = random.randint(1, 75)
        while number in drawn_numbers:  # 重複しないようにする
            number = random.randint(1, 75)
        drawn_numbers.add(number)
        print(f"引かれた番号: {number}")hiroki@shibatahiroshitakanoiMac python %  cd /Users/hiroki/Downloads/python ; /usr/bin/env /usr/local/bin/python3.12 /Users/hiroki/.vscode/extensions/ms-python.debugpy-2025.10.0-darwin-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher 59249 -- /Users/hiroki/Downloads/
python/bingo.py 
B  I  N  G  O
 9 28 42 53 67 
 8 16 40 54 61 
 5 25 FREE 46 70 
 2 30 43 57 69 
13 29 32 51 75 
Enterで次の番号を引きます...Enterを押す

B  I  N  G  O
 9 28 42 53 67 
 8 16 40 54 61 
 5 25 FREE 46 70 
 2 30 43 57 69 
13 29 32 51 75 
Enterで次の番号を引きます...
引かれた番号: 9引かれた番号をマークする
        card.mark_number(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
import pprint
pprint.pprint(self.marked)
[[False, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False]]↓

pprint.pprint(self.marked)
[[True, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False],
 [False, False, False, False, False]]カードを表示
        card.display_card()B  I  N  G  O
 9 28 42 53 67 
 8 16 40 54 61 
 5 25 FREE 46 70 
 2 30 43 57 69 
13 29 32 51 75 ビンゴ判定
        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 Falseallで判定
all([True, True])
True
all([True, True, False])
Falseall(self.marked[i])
Falseself.marked[i] # i = 0(初回ループ)
[True, False, False, False, False]ビンゴではない

card.check_bingo()
FalseWhile文の最初に戻る

ビンゴの場合は、「ビンゴ!おめでとうございます!」を出力
B  I  N  G  O
 2 18 38 48 69 
 5 29 37 59 62 
 7 19 FREE 52 73 
 8 24 34 51 64 
14 22 42 53 72 
ビンゴ!おめでとうございます!
hiroki@shibatahiroshitakanoiMac python % 
コメントを残す