Pythonサイコロゲームで学ぶ!基礎からオブジェクト指向プログラミング (2/3)

この資料は、Pythonプログラミングの初学者を対象とし、サイコロゲームを題材に基礎からオブジェクト指向プログラミング(OOP)までを段階的に理解してもらうことを目的としています。 ___や日本語になっている部分を埋めてください

ステップ8: コンピュータと1回だけ対戦してみよう

これまでは一人でサイコロを振るゲームでしたが、ここからはコンピュータと対戦する機能を追加していきます。 まずは、1回だけコンピュータとサイコロの出目を比べて勝敗を決めるプログラムを作成しましょう。

考えてみよう(コードの穴埋め):

import random

# サイコロを1個振って、出た目を返す関数
def roll_die()->int:
    return random.randint(1, 6)

# 「もう一度振りますか?」と聞いて、"y"ならTrue、"n"ならFalseを返す関数
def ask_and_check_if_continue()->bool:
    while True:
        y_or_n = input("もう一度振りますか? (y/n): ")
        if y_or_n == "y":
            return True
        elif y_or_n == "n":
            return False
        else:
            print("無効な入力です。'y' または 'n' を入力してください。")

# 出た目の履歴リストを受け取って、見やすく表示する関数
def print_history(history_list):
    print("---これまでの出た目---")
    for i, roll in enumerate(history_list, start=1):
        print(f"{i}回目: {roll}")
    print("--------------------")
    print(f"合計: {sum(history_list)}")

# サイコロゲームのソロプレイを実行する関数
def solo_play():
    roll_history_list = []
    while True:
        roll = roll_die()
        roll_history_list.append(roll)
        print(f"出た目は {roll} です。")
        if not ask_and_check_if_continue():
            print("ゲームを終了します。")
            break
    print_history(roll_history_list)

# コンピュータと1回だけ対戦する関数
def one_match():
    # プレイヤーのサイコロを振る
    player_die = ___
    # コンピュータのサイコロを振る
    computer_die = ___

    # それぞれの出目を表示する
    print(f"あなたの出た目は {player_die} です。コンピュータの出た目は {computer_die} です。")

    # プレイヤーの出目とコンピュータの出目を比較して勝敗を判定する
    もしプレイヤーが勝ちの場合:
        # プレイヤーの勝ちの場合のメッセージを表示
        print("あなたの勝ち!")
    もしプレイヤーが負け、コンピュータが勝った場合:
        # コンピュータの勝ちの場合のメッセージを表示
        print("コンピュータの勝ち!")
    else:
        # 引き分けの場合のメッセージを表示
        print("引き分け!")

# このスクリプトが直接実行されたときに、one_match関数を呼び出す
if __name__ == "__main__":
    # one_match関数を実行する
    ___

ヒント:

解答例:

import random

# サイコロを1個振って、出た目を返す関数
def roll_die():
    return random.randint(1, 6)

# 「もう一度振りますか?」と聞いて、"y"ならTrue、"n"ならFalseを返す関数
def ask_and_check_if_continue():
    while True:
        y_or_n = input("もう一度振りますか? (y/n): ")
        if y_or_n == "y":
            return True
        elif y_or_n == "n":
            return False
        else:
            print("無効な入力です。'y' または 'n' を入力してください。")

# 出た目の履歴リストを受け取って、見やすく表示する関数
def print_history(history_list):
    print("---これまでの出た目---")
    for i, roll in enumerate(history_list, start=1):
        print(f"{i}回目: {roll}")
    print("--------------------")
    print(f"合計: {sum(history_list)}")

# サイコロゲームのソロプレイを実行する関数
def solo_play():
    roll_history_list = []
    while True:
        roll = roll_die()
        roll_history_list.append(roll)
        print(f"出た目は {roll} です。")
        if not ask_and_check_if_continue():
            print("ゲームを終了します。")
            break
    print_history(roll_history_list)

# コンピュータと1回だけ対戦する関数
def one_match():
    # プレイヤーのサイコロを振る
    player_die = roll_die()
    # コンピュータのサイコロを振る
    computer_die = roll_die()

    # それぞれの出目を表示する
    print(f"あなたの出た目は {player_die} です。コンピュータの出た目は {computer_die} です。")

    # プレイヤーの出目とコンピュータの出目を比較して勝敗を判定する
    if player_die > computer_die:
        # プレイヤーの勝ちの場合のメッセージを表示
        print("あなたの勝ち!")
    elif player_die < computer_die:
        # コンピュータの勝ちの場合のメッセージを表示
        print("コンピュータの勝ち!")
    else:
        # 引き分けの場合のメッセージを表示
        print("引き分け!")

# このスクリプトが直接実行されたときに、one_match関数を呼び出す
if __name__ == "__main__":
    # one_match関数を実行する
    one_match()

ポイント:

コラム 今回はコンピュータもプレイヤーも同じ roll_die() 関数を使っています。もし将来的に「コンピュータは少しイカサマをする」といった特別なルールを加えたくなった場合、コンピュータ専用のサイコロを振る関数を別途作成することも考えられますね。


ステップ9: コンピュータと連続対戦できるようにしよう

これまでのステップでは、1回だけコンピュータと対戦する機能を作成しました。 このステップでは、複数回対戦できるように機能を拡張します。

考えてみよう(コードの穴埋め):

import random

# サイコロを振って目を返す
def roll_die(sides=6):
    return random.randint(1, sides)

# 続行確認
def ask_and_check_if_continue(prompt="もう一度振りますか? (y/n): ")-> bool:
    while True:
        ans = input(prompt).lower()
        if ans in ("y", "n"):
            return ans == "y"
        print("無効な入力です。'y' または 'n' を入力してください。")

def print_history(history):
    ...

def solo_play():
    ...

def one_match()->[int,int, str]:
    """コンピュータとの対戦"""
    player_die = roll_die()
    computer_die = roll_die()
    print(f"あなたの出た目は {player_die} です。コンピュータの出た目は {computer_die} です。")
    winner = ""
    if player_die > computer_die:
        print("あなたの勝ち!")
        winner = "player"
    elif player_die < computer_die:
        print("コンピュータの勝ち!")
        winner = "computer"
    else:
        print("引き分け!")
        winner = "draw"
    return ___, ___, ___

# コンピュータとの対戦
def play_vs_computer():

    player_win_count = 0
    computer_win_count = 0
    draw_count = 0

    while True:
        player_die, computer_die, winner = ___()

        if winner == "player":
            ___
        elif: winner =="computer"":
            ___
        else:
            ___

        if not ask_and_check_if_continue("もう一度対戦しますか? (y/n): "):
            print("対戦を終了します。")
            break

    print("対戦結果:")
    print("あなたの勝利数:", player_win_count)
    print("コンピュータの勝利数:", computer_win_count)
    print("引き分け数:", draw_count)


# メイン処理
if __name__ == "__main__":
    print("モードを選択してください:\n 1: ソロプレイ\n 2: コンピュータと対戦")
    mode = input("選択 (1/2): ")
    if mode == "1":
        ___()
    elif mode == "2":
        ___()
    else:
        print("無効な選択です。")

ヒント:

解答例:

import random

# サイコロを振って目を返す
def roll_die(sides=6):
    return random.randint(1, sides)

# 続行確認
def ask_and_check_if_continue(prompt="もう一度振りますか? (y/n): ")-> bool:
    while True:
        ans = input(prompt).lower()
        if ans in ("y", "n"):
            return ans == "y"
        print("無効な入力です。'y' または 'n' を入力してください。")

# 出た目の履歴リストを受け取って、見やすく表示する関数
def print_history(history_list):
    print("---これまでの出た目---")
    for i, roll in enumerate(history_list, start=1):
        print(f"{i}回目: {roll}")
    print("--------------------")
    print(f"合計: {sum(history_list)}")

# サイコロゲームのソロプレイを実行する関数
def solo_play():
    roll_history_list = []
    while True:
        roll = roll_die()
        roll_history_list.append(roll)
        print(f"出た目は {roll} です。")
        if not ask_and_check_if_continue():
            print("ゲームを終了します。")
            break
    print_history(roll_history_list)


def one_match()->[int, int, str]:
    """コンピュータとの対戦"""
    player_die = roll_die()
    computer_die = roll_die()
    print(f"あなたの出た目は {player_die} です。コンピュータの出た目は {computer_die} です。")
    winner = ""
    if player_die > computer_die:
        print("あなたの勝ち!")
        winner = "player"
    elif player_die < computer_die:
        print("コンピュータの勝ち!")
        winner = "computer"
    else:
        print("引き分け!")
        winner = "draw"
    return player_die, computer_die, winner

# コンピュータとの対戦
def play_vs_computer():

    player_win_count = 0
    computer_win_count = 0
    draw_count = 0

    while True:
        player_die, computer_die, winner = one_match()

        if winner == "player":
            player_win_count += 1
        elif winner == "computer":
            computer_win_count += 1
        else:
            draw_count += 1

        if not ask_and_check_if_continue("もう一度対戦しますか? (y/n): "):
            print("対戦を終了します。")
            break

    print("対戦結果:")
    print("あなたの勝利数:", player_win_count)
    print("コンピュータの勝利数:", computer_win_count)
    print("引き分け数:", draw_count)


# メイン処理
if __name__ == "__main__":
    print("モードを選択してください:\n 1: ソロプレイ\n 2: コンピュータと対戦")
    mode = input("選択 (1/2): ")
    if mode == "1":
        solo_play()
    elif mode == "2":
        play_vs_computer()
    else:
        print("無効な選択です。")

ポイント:


ステップ10: リストを使って対戦履歴をもっと充実させよう

ステップ9では対戦の勝敗数を記録しました。 このステップでは、リストをより効果的に活用して、対戦履歴をもっと詳細に記録し、統計情報も表示できるようにしましょう。

考えてみよう(コードの穴埋め):

import random

# サイコロを振って目を返す
def roll_die(sides=6):
    return random.randint(1, sides)

# 続行確認
def ask_and_check_if_continue(prompt="もう一度振りますか? (y/n): "):
    while True:
        ans = input(prompt).lower()
        if ans in ("y", "n"):
            return ans == "y"
        print("無効な入力です。'y' または 'n' を入力してください。")

# 出た目の履歴リストを受け取って、見やすく表示する関数
def print_history(history_list):
    print("---これまでの出た目---")
    for i, roll in enumerate(history_list, start=1):
        print(f"{i}回目: {roll}")
    print("--------------------")
    print(f"合計: {sum(history_list)}")

# サイコロゲームのソロプレイを実行する関数
def solo_play():
    roll_history_list = []
    while True:
        roll = roll_die()
        roll_history_list.append(roll)
        print(f"出た目は {roll} です。")
        if not ask_and_check_if_continue():
            print("ゲームを終了します。")
            break
    print_history(roll_history_list)

def one_match():
    """コンピュータとの対戦"""
    player_die = roll_die()
    computer_die = roll_die()
    print(f"あなたの出た目は {player_die} です。コンピュータの出た目は {computer_die} です。")
    
    winner = ""
    if player_die > computer_die:
        print("あなたの勝ち!")
        winner = "player"
    elif player_die < computer_die:
        print("コンピュータの勝ち!")
        winner = "computer"
    else:
        print("引き分け!")
        winner = "draw"
    
    return player_die, computer_die, winner

# 対戦履歴の詳細統計を表示する関数
def print_match_statistics(match_history:list[int,int,str]):
    """
    match_history: 各要素が [プレイヤー出目, コンピュータ出目, 勝者] のリスト
    """
    if not match_history:
        print("対戦履歴がありません。")
        return
    
    print("\n---詳細な対戦履歴---")

    for i, match in ___(match_history, start=1): # iには0,1,2,3... matchにはmatch_historyの一つの要素である、[player_dice, computer_dice, winner]のリストが入る
        player_roll, computer_roll, result = ___ # matchの要素を取り出す
        print(f"{i}戦目: あなた:{player_roll}, コンピュータ:{computer_roll}, 結果:{result}")
    
    print("\n---統計情報---")
    
    # プレイヤーの出目だけを抽出してリストにする
    player_rolls = ___  # match_historyから各matchの0番目の要素(プレイヤーの出目)を取り出してリストにする
    # コンピュータの出目だけを抽出してリストにする  
    computer_rolls = ___  # match_historyから各matchの1番目の要素(コンピュータの出目)を取り出してリストにする
    
    # プレイヤーの統計情報を表示
    print(f"あなたの出目統計:")
    print(f"  最高出目: {___(player_rolls)}")
    print(f"  最低出目: {___(player_rolls)}")
    print(f"  平均出目: {sum(player_rolls) / ___(player_rolls):.2f}")
    
    # コンピュータの統計情報を表示
    print(f"コンピュータの出目統計:")
    print(f"  最高出目: {___(computer_rolls)}")
    print(f"  最低出目: {___(computer_rolls)}")
    print(f"  平均出目: {sum(computer_rolls) / ___(computer_rolls):.2f}")
    
    # 勝敗数を集計
    player_win_count = 0
    computer_win_count = 0
    draw_count = 0
    
    # match_historyの各要素をループして勝敗数をカウント
    for match in match_history:
        _, _, winner = match
        if winner == "player":
            ___  # player_win_countを1増やす
        elif winner == "computer":
            ___  # computer_win_countを1増やす
        else:
            ___  # draw_countを1増やす
    
    print(f"\n最終結果:")
    print(f"  あなたの勝利: {player_win_count}回")
    print(f"  コンピュータの勝利: {computer_win_count}回") 
    print(f"  引き分け: {draw_count}回")

# コンピュータとの対戦(履歴記録機能付き)
def play_vs_computer():
    match_history = []  # 各対戦の詳細情報を保存するリスト
    
    while True:
        player_die, computer_die, winner = one_match()
        
        # 対戦結果を詳細履歴に追加(リストの形で)
        ___  # match_historyに [player_die, computer_die, winner] を追加
        
        if not ask_and_check_if_continue("もう一度対戦しますか? (y/n): "):
            print("対戦を終了します。")
            break
    
    # 詳細統計を表示
    ___))

# メイン処理
if __name__ == "__main__":
    print("モードを選択してください:\n 1: ソロプレイ\n 2: コンピュータと対戦")
    mode = input("選択 (1/2): ")
    if mode == "1":
        solo_play()
    elif mode == "2":
        play_vs_computer()
    else:
        print("無効な選択です。")

ヒント:

解答例:

import random

# サイコロを振って目を返す
def roll_die(sides=6):
    return random.randint(1, sides)

# 続行確認
def ask_and_check_if_continue(prompt="もう一度振りますか? (y/n): "):
    while True:
        ans = input(prompt).lower()
        if ans in ("y", "n"):
            return ans == "y"
        print("無効な入力です。'y' または 'n' を入力してください。")

# 出た目の履歴リストを受け取って、見やすく表示する関数
def print_history(history_list):
    print("---これまでの出た目---")
    for i, roll in enumerate(history_list, start=1):
        print(f"{i}回目: {roll}")
    print("--------------------")
    print(f"合計: {sum(history_list)}")

# サイコロゲームのソロプレイを実行する関数
def solo_play():
    roll_history_list = []
    while True:
        roll = roll_die()
        roll_history_list.append(roll)
        print(f"出た目は {roll} です。")
        if not ask_and_check_if_continue():
            print("ゲームを終了します。")
            break
    print_history(roll_history_list)

def one_match():
    """コンピュータとの対戦"""
    player_die = roll_die()
    computer_die = roll_die()
    print(f"あなたの出た目は {player_die} です。コンピュータの出た目は {computer_die} です。")
    
    winner = ""
    if player_die > computer_die:
        print("あなたの勝ち!")
        winner = "player"
    elif player_die < computer_die:
        print("コンピュータの勝ち!")
        winner = "computer"
    else:
        print("引き分け!")
        winner = "draw"
    
    return player_die, computer_die, winner

# 対戦履歴の詳細統計を表示する関数
def print_match_statistics(match_history):
    """
    match_history: 各要素が [プレイヤー出目, コンピュータ出目, 勝者] のリスト
    """
    if not match_history:
        print("対戦履歴がありません。")
        return
    
    print("\n---詳細な対戦履歴---")
    # enumerateを使って各対戦の詳細を表示
    for i, match in enumerate(match_history, start=1):
        player_roll, computer_roll, result = match
        print(f"{i}戦目: あなた:{player_roll}, コンピュータ:{computer_roll}, 結果:{result}")
    
    print("\n---統計情報---")
    
    # プレイヤーの出目だけを抽出してリストにする
    player_rolls = [match[0] for match in match_history]
    # コンピュータの出目だけを抽出してリストにする  
    computer_rolls = [match[1] for match in match_history]
    
    # プレイヤーの統計情報を表示
    print(f"あなたの出目統計:")
    print(f"  最高出目: {max(player_rolls)}")
    print(f"  最低出目: {min(player_rolls)}")
    print(f"  平均出目: {sum(player_rolls) / len(player_rolls):.2f}")
    
    # コンピュータの統計情報を表示
    print(f"コンピュータの出目統計:")
    print(f"  最高出目: {max(computer_rolls)}")
    print(f"  最低出目: {min(computer_rolls)}")
    print(f"  平均出目: {sum(computer_rolls) / len(computer_rolls):.2f}")
    
    # 勝敗数を集計
    player_win_count = 0
    computer_win_count = 0
    draw_count = 0
    
    # match_historyの各要素をループして勝敗数をカウント
    for match in match_history:
        _, _, winner = match
        if winner == "player":
            player_win_count += 1
        elif winner == "computer":
            computer_win_count += 1
        else:
            draw_count += 1
    
    print(f"\n最終結果:")
    print(f"  あなたの勝利: {player_win_count}回")
    print(f"  コンピュータの勝利: {computer_win_count}回") 
    print(f"  引き分け: {draw_count}回")

# コンピュータとの対戦(履歴記録機能付き)
def play_vs_computer():
    match_history = []  # 各対戦の詳細情報を保存するリスト
    
    while True:
        player_die, computer_die, winner = one_match()
        
        # 対戦結果を詳細履歴に追加(リストの形で)
        match_history.append([player_die, computer_die, winner])
        
        if not ask_and_check_if_continue("もう一度対戦しますか? (y/n): "):
            print("対戦を終了します。")
            break
    
    # 詳細統計を表示
    print_match_statistics(match_history)

# メイン処理
if __name__ == "__main__":
    print("モードを選択してください:\n 1: ソロプレイ\n 2: コンピュータと対戦")
    mode = input("選択 (1/2): ")
    if mode == "1":
        solo_play()
    elif mode == "2":
        play_vs_computer()
    else:
        print("無効な選択です。")

ポイント:


ステップ11: 辞書(dict)を使ってゲーム設定を一元管理しよう

これまでのプログラムでは、サイコロの面数(6)やメッセージ("あなたの勝ち!"など)がコード内に直接書かれていました。 このステップでは、辞書(dictionary) を使ってこれらの設定を一元管理し、より保守しやすいコードに改良しましょう。

考えてみよう(コードの穴埋め):

import random

# 結果の定数を定義
PLAYER_WIN = "player"
COMPUTER_WIN = "computer"
DRAW = "draw"

# ゲーム設定を辞書で一元管理
game_config = {
    "sides": ___,  # サイコロの面数
    "messages": {
        ___: "あなたの勝ち!",
        ___: "コンピュータの勝ち!", 
        ___: "引き分け!"
    }
}

# サイコロを振って目を返す(面数は設定から取得)
def roll_die(sides=None):
    if sides is None:
        # game_configから面数を取得
        sides = ___
    return random.randint(1, sides)

# 続行確認
def ask_and_check_if_continue(prompt="もう一度振りますか? (y/n): "):
    while True:
        ans = input(prompt).lower()
        if ans in ("y", "n"):
            return ans == "y"
        print("無効な入力です。'y' または 'n' を入力してください。")

# 出た目の履歴リストを受け取って、見やすく表示する関数
def print_history(history_list):
    print("---これまでの出た目---")
    for i, roll in enumerate(history_list, start=1):
        print(f"{i}回目: {roll}")
    print("--------------------")
    print(f"合計: {sum(history_list)}")

# サイコロゲームのソロプレイを実行する関数
def solo_play():
    roll_history_list = []
    while True:
        roll = roll_die()
        roll_history_list.append(roll)
        print(f"出た目は {roll} です。")
        if not ask_and_check_if_continue():
            print("ゲームを終了します。")
            break
    print_history(roll_history_list)

# 一回の対戦を実行して結果を返す
def one_match():
    player_die = roll_die()
    computer_die = roll_die()
    print(f"あなたの出た目は {player_die} です。コンピュータの出た目は {computer_die} です。")
    
    if player_die > computer_die:
        result = ___  # PLAYER_WINを設定
    elif player_die < computer_die:
        result = ___  # COMPUTER_WINを設定
    else:
        result = ___  # DRAWを設定
    
    # 結果メッセージをgame_configから取得して表示
    message = ___
    print(message)
    
    return player_die, computer_die, result

# 対戦履歴の詳細統計を表示する関数
def print_match_statistics(match_history):
    if not match_history:
        print("対戦履歴がありません。")
        return
    
    print("\n---詳細な対戦履歴---")
    for i, match in enumerate(match_history, start=1):
        player_roll, computer_roll, result = match
        print(f"{i}戦目: あなた:{player_roll}, コンピュータ:{computer_roll}, 結果:{result}")
    
    print("\n---統計情報---")
    
    player_rolls = [match[0] for match in match_history]
    computer_rolls = [match[1] for match in match_history]
    
    print(f"あなたの出目統計:")
    print(f"  最高出目: {max(player_rolls)}")
    print(f"  最低出目: {min(player_rolls)}")
    print(f"  平均出目: {sum(player_rolls) / len(player_rolls):.2f}")
    
    print(f"コンピュータの出目統計:")
    print(f"  最高出目: {max(computer_rolls)}")
    print(f"  最低出目: {min(computer_rolls)}")
    print(f"  平均出目: {sum(computer_rolls) / len(computer_rolls):.2f}")
    
    # 勝敗数を辞書で管理
    win_counts = {___: 0, ___: 0, ___: 0}  # PLAYER_WIN, COMPUTER_WIN, DRAWのキーで初期化
    
    for match in match_history:
        winner = match[2]
        ___  # win_counts[winner] を1増やす
    
    print(f"\n最終結果:")
    print(f"  あなたの勝利: {win_counts[___]}回")      # PLAYER_WINのカウントを表示
    print(f"  コンピュータの勝利: {win_counts[___]}回")  # COMPUTER_WINのカウントを表示
    print(f"  引き分け: {win_counts[___]}回")         # DRAWのカウントを表示

# コンピュータとの対戦(辞書による設定管理版)
def play_vs_computer():
    match_history = []
    
    while True:
        player_die, computer_die, winner = one_match()
        match_history.append([player_die, computer_die, winner])
        
        if not ask_and_check_if_continue("もう一度対戦しますか? (y/n): "):
            print("対戦を終了します。")
            break
    
    print_match_statistics(match_history)

# メイン処理
if __name__ == "__main__":
    print("モードを選択してください:\n 1: ソロプレイ\n 2: コンピュータと対戦")
    mode = input("選択 (1/2): ")
    if mode == "1":
        solo_play()
    elif mode == "2":
        play_vs_computer()
    else:
        print("無効な選択です。")

ヒント:

解答例:

import random

# 結果の定数を定義
PLAYER_WIN = "player"
COMPUTER_WIN = "computer"
DRAW = "draw"

# ゲーム設定を辞書で一元管理
game_config = {
    "sides": 6,  # サイコロの面数
    "messages": {
        PLAYER_WIN: "あなたの勝ち!",
        COMPUTER_WIN: "コンピュータの勝ち!", 
        DRAW: "引き分け!"
    }
}

# サイコロを振って目を返す(面数は設定から取得)
def roll_die(sides=None):
    if sides is None:
        # game_configから面数を取得
        sides = game_config["sides"]
    return random.randint(1, sides)

# 続行確認
def ask_and_check_if_continue(prompt="もう一度振りますか? (y/n): "):
    while True:
        ans = input(prompt).lower()
        if ans in ("y", "n"):
            return ans == "y"
        print("無効な入力です。'y' または 'n' を入力してください。")

# 出た目の履歴リストを受け取って、見やすく表示する関数
def print_history(history_list):
    print("---これまでの出た目---")
    for i, roll in enumerate(history_list, start=1):
        print(f"{i}回目: {roll}")
    print("--------------------")
    print(f"合計: {sum(history_list)}")

# サイコロゲームのソロプレイを実行する関数
def solo_play():
    roll_history_list = []
    while True:
        roll = roll_die()
        roll_history_list.append(roll)
        print(f"出た目は {roll} です。")
        if not ask_and_check_if_continue():
            print("ゲームを終了します。")
            break
    print_history(roll_history_list)

# 一回の対戦を実行して結果を返す
def one_match():
    player_die = roll_die()
    computer_die = roll_die()
    print(f"あなたの出た目は {player_die} です。コンピュータの出た目は {computer_die} です。")
    
    if player_die > computer_die:
        result = PLAYER_WIN
    elif player_die < computer_die:
        result = COMPUTER_WIN
    else:
        result = DRAW
    
    # 結果メッセージをgame_configから取得して表示
    message = game_config["messages"][result]
    print(message)
    
    return player_die, computer_die, result

# 対戦履歴の詳細統計を表示する関数
def print_match_statistics(match_history):
    if not match_history:
        print("対戦履歴がありません。")
        return
    
    print("\n---詳細な対戦履歴---")
    for i, match in enumerate(match_history, start=1):
        player_roll, computer_roll, result = match
        print(f"{i}戦目: あなた:{player_roll}, コンピュータ:{computer_roll}, 結果:{result}")
    
    print("\n---統計情報---")
    
    player_rolls = [match[0] for match in match_history]
    computer_rolls = [match[1] for match in match_history]
    
    print(f"あなたの出目統計:")
    print(f"  最高出目: {max(player_rolls)}")
    print(f"  最低出目: {min(player_rolls)}")
    print(f"  平均出目: {sum(player_rolls) / len(player_rolls):.2f}")
    
    print(f"コンピュータの出目統計:")
    print(f"  最高出目: {max(computer_rolls)}")
    print(f"  最低出目: {min(computer_rolls)}")
    print(f"  平均出目: {sum(computer_rolls) / len(computer_rolls):.2f}")
    
    # 勝敗数を辞書で管理
    win_counts = {PLAYER_WIN: 0, COMPUTER_WIN: 0, DRAW: 0}
    
    for match in match_history:
        _, _, winner = match
        win_counts[winner] += 1
    
    print(f"\n最終結果:")
    print(f"  あなたの勝利: {win_counts[PLAYER_WIN]}回")
    print(f"  コンピュータの勝利: {win_counts[COMPUTER_WIN]}回")
    print(f"  引き分け: {win_counts[DRAW]}回")

# コンピュータとの対戦(辞書による設定管理版)
def play_vs_computer():
    match_history = []
    
    while True:
        player_die, computer_die, winner = one_match()
        match_history.append([player_die, computer_die, winner])
        
        if not ask_and_check_if_continue("もう一度対戦しますか? (y/n): "):
            print("対戦を終了します。")
            break
    
    print_match_statistics(match_history)

# メイン処理
if __name__ == "__main__":
    print("モードを選択してください:\n 1: ソロプレイ\n 2: コンピュータと対戦")
    mode = input("選択 (1/2): ")
    if mode == "1":
        solo_play()
    elif mode == "2":
        play_vs_computer()
    else:
        print("無効な選択です。")

ポイント:

コラム 設定を変更してみよう!

# 10面サイコロに変更
game_config["sides"] = 10

# メッセージをカスタマイズ
game_config["messages"][PLAYER_WIN] = "やったね!君の勝ちだ!"

このように、辞書を使うことで、コードの他の部分を変更することなく、簡単に設定を変更できます。これが「設定の一元管理」の威力です!

コラム zip関数での履歴表示

2つのリストを同時にループしたい場合、zip() 関数が便利です:

# 従来の方法
for i in range(len(player_history)):
    print(f"{i+1}回戦: あなた {player_history[i]} - コンピュータ {comp_history[i]}")

# zipとenumerateを組み合わせた方法
for i, (p, c) in enumerate(zip(player_history, comp_history), start=1):
    print(f"{i}回戦: あなた {p} - コンピュータ {c}")

より簡潔で読みやすいコードになります!