【Python】レッスン3-☆2:石取りゲームを作ろう

記事内に商品プロモーションを含む場合があります

この記事の練習問題で使用する知識:
レッスン1の知識比較演算子と論理演算子if文による条件分岐while文による繰り返し処理繰り返しの制御関数の定義と使用戻り値とデフォルト引数

Pythonのゲームコード一覧はこちら

<<前の問題 問題集Top 次の問題>>

練習問題3-☆2:石取りゲームを作ろう

石取りゲームは2人のプレイヤーが交互に石を取るターン制のゲームです。

このゲームでは15個の石を山に置き、プレイヤーが1ターンに取れる石の数は1個から3個までです。

プレイヤーは交互に石を取り、最後の石を取ったプレイヤーが負けとなります。Pythonでこのゲームを実装してみましょう。

この問題の要件

以下の要件に従ってコードを完成させてください。

  • is_valid_move関数: プレイヤーが1ターンに取れる石の数(1〜3個)を判定し、適切かどうかを確認すること。
  • take_turn関数: プレイヤーが石を選んで取るロジックを実装し、プレイヤーが取った石の数を残りの石から減らすこと。
  • play_game関数: ゲームの進行を管理するメインループを作成し、2人のプレイヤーが交互に石を取ること。最後の石を取ったプレイヤーが負けたことを表示すること。
  • 変数の使用: 石の数(stones)、プレイヤーのターン(turn)を変数で管理すること。
  • 入力の使用: input関数を使って、プレイヤーが取る石の数を入力すること。
  • 出力の使用: print関数を使って、ゲームの進行状況や勝敗を表示すること。

ただし、以下のような実行結果となるコードを書くこと。

*****↓↓正解コードの実行結果の例↓↓*****

石取りゲームへようこそ!
プレイヤー1の番です。残りの石は 15 個です。
プレイヤー1, 何個の石を取りますか?(1~3個まで選べます):2
プレイヤー2の番です。残りの石は 13 個です。
プレイヤー2, 何個の石を取りますか?(1~3個まで選べます):3
...
プレイヤー1が最後の石を取りました。プレイヤー1の負けです!

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:関数 is_valid_move の定義
  □ return文でプレイヤーが選択した石の数が有効かどうかを判定し、戻り値として返す
2:関数 take_turn の定義
  □ print関数でプレイヤーの番と残りの石の数を表示
  □ input関数でプレイヤーに石の数を入力させ、int関数で数値に変換し move に代入
  □ while文で is_valid_move 関数を使い、選択された石の数が有効でない場合に再入力させる
  □ □ print関数で無効な選択であることを表示し、再度入力を促す
  □ 石の数を減らし、その結果を返す
3:関数 play_game の定義
  □ print関数でゲームの開始メッセージを表示
  □ 変数 stones に15を代入(石の初期値)
  □ 変数 turn に1を代入(プレイヤー1のターンを示す)
  □ while文で stones が0より大きい間ゲームを続ける
  □ □ if文で turn が1ならプレイヤー1、それ以外ならプレイヤー2とし、current_player に代入
  □ □ take_turn関数を呼び出し、プレイヤーが石を取る操作を行い、残りの石の数を更新
  □ □ if文で残りの石が0ならゲーム終了メッセージを表示し、ループを終了
  □ □ ターンをプレイヤー2に交代し、次のループに進む
4:if __name__ == "__main__": によるメインプログラムの実行
  □ play_game関数を呼び出してゲームを開始

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

# 石取りゲームの開始
def is_valid_move(stones, move):
    """【穴埋め問題1】ここに石の数が有効かどうかを判定して返すコードを書いてください。"""

def take_turn(player, stones):
    # 各プレイヤーのターンを処理する関数
    """【穴埋め問題2】ここにプレイヤーに石の数を入力させ、選択が有効であることを確認するコードを書いてください。"""

    """【穴埋め問題3】ここでプレイヤーが取った石の数を残りの石から引いて返すコードを書いてください。"""

def play_game():
    # 石取りゲームのメイン関数
    print("石取りゲームへようこそ!")
    stones = 15  # ゲーム開始時の石の数
    turn = 1  # 1ならプレイヤー1、2ならプレイヤー2
    
    # 石が残っている限りゲームを続ける
    while stones > 0:
        """【穴埋め問題4】ここにプレイヤーを切り替えるコードを書いてください。"""

        """【穴埋め問題5】ここで現在のプレイヤーのターンを実行し、残りの石の数を更新するコードを書いてください。"""

        """【穴埋め問題6】ここに石が0になった場合、ゲームを終了するコードを書いてください。"""

        """【穴埋め問題7】ここにターンを交代するコードを書いてください。"""

# ゲームの実行
if __name__ == "__main__":
    """【穴埋め問題8】ここにゲームを開始するコードを書いてください。"""

この問題の穴埋めコードは以上です。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

解答例と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

# 石取りゲームの開始
def is_valid_move(stones, move):
    # プレイヤーの選択した石の数が有効かどうかを判定する関数
    return 1 <= move <= 3 and move <= stones

def take_turn(player, stones):
    # 各プレイヤーのターンを処理する関数
    print(f"\n{player}の番です。残りの石は {stones} 個です。")
    
    move = int(input(f"{player}, 何個の石を取りますか?(1~3個まで選べます):"))
    
    # プレイヤーが有効な数を選択するまで繰り返し
    while not is_valid_move(stones, move):
        print("無効な選択です。もう一度選んでください。")
        move = int(input(f"{player}, 何個の石を取りますか?(1~3個まで選べます):"))
    
    # 石を減らす
    stones -= move
    return stones

def play_game():
    # 石取りゲームのメイン関数
    print("石取りゲームへようこそ!")
    stones = 15  # ゲーム開始時の石の数
    turn = 1  # 1ならプレイヤー1、2ならプレイヤー2
    
    # 石が残っている限りゲームを続ける
    while stones > 0:
        # プレイヤーの切り替え
        if turn == 1:
            current_player = "プレイヤー1"
        else:
            current_player = "プレイヤー2"
        
        # 現在のプレイヤーのターンを実行
        stones = take_turn(current_player, stones)
        
        # 石が0になったらゲーム終了
        if stones == 0:
            print(f"\n{current_player}が最後の石を取りました。{current_player}の負けです!")
            break
        
        # ターンを交代
        if turn == 1:
            turn = 2
        else:
            turn = 1

# ゲームの実行
if __name__ == "__main__":
    play_game()

正解コードの解説

この解説では、Pythonの基本構文を使用したシンプルな「石取りゲーム」を、各部分ごとにわかりやすく説明します。

is_valid_move関数の定義

def is_valid_move(stones, move):
    return 1 <= move <= 3 and move <= stones
  • 関数の定義defキーワードでis_valid_moveという関数を定義しています。この関数は、プレイヤーが取る石の数が正しいかどうかを判定する役割を持ちます。
  • 引数stonesmoveという2つの引数を受け取ります。stonesは残りの石の数で、moveはプレイヤーが選んだ石の数です。
  • 条件式return文で「1以上3以下の数で、残りの石より少ないか同じである」ことを確認し、TrueまたはFalseを返します。1 <= move <= 3 and move <= stonesは条件式で、Pythonの基本的な論理演算(and)を使用しています。

take_turn関数の定義

def take_turn(player, stones):
    print(f"\n{player}の番です。残りの石は {stones} 個です。")
    move = int(input(f"{player}, 何個の石を取りますか?(1~3個まで選べます):"))

    while not is_valid_move(stones, move):
        print("無効な選択です。もう一度選んでください。")
        move = int(input(f"{player}, 何個の石を取りますか?(1~3個まで選べます):"))

    stones -= move
    return stones
  • プレイヤーのターン:この関数は、プレイヤーが石の数を選ぶ手順を管理します。
  • inputprintinput関数で入力を受け取り、print関数で残りの石数を表示します。また、f文字列でメッセージの中に変数の値を挿入します。
  • whileループ:条件に合わない数を選んだ場合(例えば、4個以上取ろうとした場合)、無効な選択を表示し、再入力を求めます。
  • 石の数の更新:プレイヤーが選んだ数の石を減らし、残りの石の数を返します。

play_game関数の定義

def play_game():
    print("石取りゲームへようこそ!")
    stones = 15
    turn = 1

    while stones > 0:
        if turn == 1:
            current_player = "プレイヤー1"
        else:
            current_player = "プレイヤー2"

        stones = take_turn(current_player, stones)

        if stones == 0:
            print(f"\n{current_player}が最後の石を取りました。{current_player}の負けです!")
            break

        if turn == 1:
            turn = 2
        else:
            turn = 1
  • ゲームの開始メッセージprint関数でゲームの開始を表示し、石の初期数を15個に設定します。
  • whileループstonesが0より大きい限りゲームを続けます。プレイヤーのターンを管理し、交代させるためにturnという変数を使用しています。
  • プレイヤーの交代if文でターンの管理を行い、turnの値に基づいてプレイヤーを切り替えます。
  • ゲームの終了stonesが0になった場合はゲーム終了のメッセージを表示し、breakでループを抜けます。

メインプログラムの実行

if __name__ == "__main__":
    play_game()

この部分では、play_game関数を呼び出し、ゲームが開始されます。

if __name__ == "__main__":はPythonでよく使われる構文で、直接実行されるときだけプログラムを動かす役割を持ちます。

まとめ

この石取りゲームのコードは、関数、条件分岐、ループ処理、そしてユーザー入力を使ってシンプルなゲームを作る方法を学ぶ良い例です。

Pythonの基本的な文法を実践するための良い練習問題にもなります。

繰り返しコードを読み解き、手を動かしながら理解を深めていくことで、Pythonプログラミングへの自信がついていくでしょう。

Pythonのゲームコード一覧はこちら

<<前の問題 問題集Top 次の問題>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Python記事トップへ戻る
    トップページへ戻る