2026.09.18(金) / 09:31

Pythonで作るビンゴゲーム

最終更新
2026.09.18
タグ
import random


class BingoCard:
    def __init__(self):
        self.card = self.generate_card()

        # 各マスがマークされているかを管理する
        self.marked = [[False] * 5 for _ in range(5)]

        # 中央のFREE枠は最初からマーク済みにする
        self.marked[2][2] = True

    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 column in range(5):
            for row in range(5):
                if self.card[column][row] == number:
                    self.marked[column][row] = True

    def check_bingo(self):
        for i in range(5):
            # 列のビンゴ
            if all(self.marked[i]):
                return True

            # 行のビンゴ
            if all(self.marked[column][i] for column 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()
        for header in "BINGO":
            print(f"{header:>6}", end="")
        print()

        # カード
        for row in range(5):
            for column in range(5):
                value = self.card[column][row]

                if value == "FREE":
                    print(f"{'FREE':>6}", end="")
                elif self.marked[column][row]:
                    print(f"{'XX':>6}", end="")
                else:
                    print(f"{value:>6}", 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()

処理の流れ

最初にビンゴカードを生成して画面に表示します。

Enterキーを押すたびに1〜75の数字をランダムに1つ選びます。

すでに引かれた数字だった場合は、まだ引かれていない数字が出るまで再抽選します。

引かれた数字がビンゴカードに存在する場合は、そのマスをマークします。

その後、縦・横・対角線のいずれかがすべてマークされているかを確認します。ビンゴが成立したらゲーム終了です。

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

初期化

class BingoCard:
    def __init__(self):
        self.card = self.generate_card()

        self.marked = [[False] * 5 for _ in range(5)]

        self.marked[2][2] = True

BingoCardクラスでは、cardmarkedの2つのデータを管理しています。

cardには、それぞれのマスに書かれている数字を保存します。

markedには、それぞれのマスがマーク済みかどうかをTrueまたはFalseで保存します。

つまり、「マスに何が書かれているか」と「そのマスが現在どの状態か」を分けて管理しています。

また、ビンゴの中央はFREE枠なので、最初からTrueにしています。

ビンゴカードを生成する

def generate_card(self):
    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

ビンゴでは、B・I・N・G・Oの各列で使用する数字の範囲が決まっています。

random.sample()を使って、それぞれの範囲から重複しない数字を5個選びます。

このプログラムでは、カードを「列ごとの配列」として管理しています。

self.card[列][行]

という順番で各マスにアクセスします。

カードを表示する

def display_card(self):
    # 見出し
    print()
    for header in "BINGO":
        print(f"{header:>6}", end="")
    print()

    # カード
    for row in range(5):
        for column in range(5):
            value = self.card[column][row]

            if value == "FREE":
                print(f"{'FREE':>6}", end="")
            elif self.marked[column][row]:
                print(f"{'XX':>6}", end="")
            else:
                print(f"{value:>6}", end="")

        print()

display_card()でビンゴカードを画面に表示します。

マーク済みの数字はXXとして表示します。

中央のFREE枠は最初からマーク済みですが、画面上ではFREEと表示します。

if 文でマスの状態を確認し、中央のFREE枠ならFREE、マーク済みならXX、それ以外なら元の数字を表示します。

:>6で6文字分の幅を確保して右寄せし、end=""を指定することで、各マスを横並びに表示しています。

ランダムに数字を選ぶ

number = random.randint(1, 75)

random.randint(1, 75)で、1〜75の整数からランダムに1つ選びます。

同じ数字が重複しないようにする

drawn_numbers = set()

number = random.randint(1, 75)

while number in drawn_numbers:
    number = random.randint(1, 75)

drawn_numbers.add(number)

setを使って、すでに引いた数字を記録します。

新しく引いた数字がdrawn_numbersの中に存在していた場合は、存在しない数字が出るまでwhile文で再抽選します。

そして、まだ引かれていない数字が出たらdrawn_numbers.add(number)で集合に追加します。

数字が一致したマスをマークする

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

カード内の数字と、引かれた数字が一致しているかを確認します。

一致した場合は、対応するmarkedの値をTrueにします。

このように、TrueFalseを使って各マスの状態をシンプルに管理しています。

ビンゴかどうかをチェックする

def check_bingo(self):
    for i in range(5):
        # 列のビンゴ
        if all(self.marked[i]):
            return True

        # 行のビンゴ
        if all(self.marked[column][i] for column 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

all()を使って、縦・横・対角線のすべてのマスがTrueになっているかを確認します。

all()は、渡された値がすべてTrueの場合にTrueを返します。

縦・横・2本の対角線のいずれかがすべてマーク済みになれば、ビンゴ成立です。

まとめ

今回のビンゴゲームでは、カードに書かれている数字とマーク状態を別々の二次元配列で管理しました。

randomによる乱数生成、setによる抽選済み数字の管理、all()によるビンゴ判定など、Pythonの基本的な機能を組み合わせてゲームを作ることができました。