【Python】レッスン4-☆1:宝探しゲームを作ろう

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

この記事の練習問題で使用する知識:
1.基礎文法、2.制御構造、3.関数とスコープ、4.データ構造、5.オブジェクト指向

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

<<前のページ Python記事一覧
次のページ>>

練習問題4-☆1:Pythonで宝探しゲームを作ろう

ランダムな位置にある宝を探し当てるゲームを作成しましょう。

プレイヤーは1から25までの番号が振られた5×5のグリッドから、宝が隠された場所を3回以内に見つける必要があります。

プレイヤーが選んだマスに基づいてヒントを表示し、宝に近づいているかどうかを知らせます。宝を見つけるか、チャンスを使い切るとゲームが終了します。

問題の詳細条件

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

  • 5×5のグリッドを用意し、マス目には01から25までの番号を振ること。
  • プレイヤーは1から25の数字を入力し、宝が隠されたマスを3回以内に当てることを目指す。
  • 宝の位置はゲーム開始時にランダムに決定されること。
  • プレイヤーがマスを選ぶと、そのマスを選択済みとして印を付けること。
  • 宝が見つからない場合、プレイヤーに「上」「下」「左」「右」などのヒントを表示すること。
  • 宝を見つけた場合、グリッド上で宝の場所を特別な記号(☆)で表示すること。
  • ゲームが終了した際、宝を見つけたか、全てのチャンスを使い切ったことを知らせること。

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

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

宝探しゲームへようこそ!1から25までの数字で宝を探し当ててください。
宝を探すチャンスは3回です。
現在のグリッド:
01 02 03 04 05
06 07 08 09 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

1から25のマス番号を入力してください: 13
下 に宝があります。
残りのチャンス: 2回
現在のグリッド:
01 02 03 04 05
06 07 08 09 10
11 12 * 14 15
16 17 18 19 20
21 22 23 24 25

1から25のマス番号を入力してください: 23
おめでとうございます!宝を見つけました!
現在のグリッド:
01 02 03 04 05
06 07 08 09 10
11 12 * 14 15
16 17 18 19 20
21 22 ☆ 24 25

【ヒント】難しいと感じる人だけ見よう

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

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

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

1:randomモジュールのインポート
2:定数GRID_SIZEに5を代入
3:関数initialize_gridの定義
  □ gridの初期化
  □ 変数countに1を代入
  □ forループにて0からGRID_SIZEまでを繰り返す
  □ □ rowの初期化
  □ □ forループにて0からGRID_SIZEまでを繰り返す
  □ □ □ rowに01, 02, 03の形式でcountを追加
  □ □ □ countを1増やす
  □ □ rowをgridに追加
  □ gridを返す
4:関数display_gridの定義
  □ ”現在のグリッド:”と出力
  □ forループにてgrid内の各rowを表示
  □ 空行を出力
5:関数give_hintの定義
  □ hintの初期化
  □ if文にてplayer_xがtreasure_xより小さいか判定
  □ □ 真の場合、hintに”右”を追加
  □ elif文にてplayer_xがtreasure_xより大きいか判定
  □ □ 真の場合、hintに”左”を追加
  □ if文にてplayer_yがtreasure_yより小さいか判定
  □ □ 真の場合、hintに”下”を追加
  □ elif文にてplayer_yがtreasure_yより大きいか判定
  □ □ 真の場合、hintに”上”を追加
  □ hintと”に宝があります。”を結合して返す
6:関数treasure_hunt_gameの定義
  □ gridにinitialize_gridの戻り値を代入
  □ treasure_xとtreasure_yにランダムな位置を代入
  □ ”宝探しゲームへようこそ…”と出力
  □ display_gridを呼び出す
  □ attemptsに0を代入
  □ found_treasureにFalseを代入
  □ whileループにてattemptsが3未満かつfound_treasureがFalseの間繰り返す
  □ □ try文の開始
  □ □ □ ユーザーから1から25の数値を取得し、choiceに代入
  □ □ □ if文にてchoiceが無効な番号か判定
  □ □ □ □ 真の場合、”無効な番号です…”と出力しcontinue
  □ □ □ player_xにchoice % GRID_SIZEを代入
  □ □ □ player_yにchoice // GRID_SIZEを代入
  □ □ □ if文にてgridの選んだ場所が”*”か判定
  □ □ □ □ 真の場合、”そのマスは既に選択されています…”と出力しcontinue
  □ □ □ if文にてplayer_xとtreasure_x, player_yとtreasure_yが一致するか判定
  □ □ □ □ 真の場合、”おめでとうございます!…”と出力
  □ □ □ □ gridの選んだ場所を”☆”に変更しfound_treasureをTrueに
  □ □ □ else文
  □ □ □ □ gridの選んだ場所を”*”に変更
  □ □ □ □ give_hintを呼び出してヒントを出力
  □ □ □ □ attemptsに1を加算
  □ □ □ □ 残りのチャンスを出力
  □ □ □ □ display_gridを呼び出す
  □ □ except文にてValueErrorの場合エラーメッセージを出力
  □ if文にてfound_treasureがFalseの場合、”残念ながら…”と出力
7:treasure_hunt_gameの呼び出し

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

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

import random

# グリッドサイズを定義
GRID_SIZE = 5

# グリッドを初期化する関数
def initialize_grid():
    grid = []
    count = 1
    for i in range(GRID_SIZE):
        row = []
        for j in range(GRID_SIZE):
            """【穴埋め問題1】
            ここにグリッドの各セルに番号を振るコードを書いてください。
            """
            count += 1
        grid.append(row)
    return grid

# グリッドを表示する関数
def display_grid(grid):
    print("現在のグリッド:")
    for row in grid:
        print(" ".join(row))
    print()

# ヒントを提供する関数
def give_hint(player_x, player_y, treasure_x, treasure_y):
    hint = []
    """【穴埋め問題2】
    ここに宝物の方向に応じてヒントを作成するコードを書いてください。
    """
    return " ".join(hint) + " に宝があります。"

# 宝探しゲームを実行する関数
def treasure_hunt_game():
    # グリッドと宝の位置を初期化
    grid = initialize_grid()
    treasure_x = random.randint(0, GRID_SIZE - 1)
    treasure_y = random.randint(0, GRID_SIZE - 1)

    print("宝探しゲームへようこそ!1から25までの数字で宝を探し当ててください。")
    print("宝を探すチャンスは3回です。")
    display_grid(grid)

    attempts = 0
    found_treasure = False

    while attempts < 3 and not found_treasure:
        try:
            choice = int(input("1から25のマス番号を入力してください: ")) - 1
            """【穴埋め問題3】
            ここにユーザーの選択したマスを計算し、選ばれた位置をgridに反映させるコードを書いてください。
            """
            # 宝を見つけた場合
            if player_x == treasure_x and player_y == treasure_y:
                print("おめでとうございます!宝を見つけました!")
                grid[player_y][player_x] = "☆"  # 宝の位置を☆で表示
                found_treasure = True
            else:
                """【穴埋め問題4】
                ここに選択したマスを*でマークし、ヒントを表示し、試行回数を増やすコードを書いてください。
                """

            display_grid(grid)
        except ValueError:
            print("無効な入力です。1から25までの数字を入力してください。")

    if not found_treasure:
        print("残念ながら、チャンスを使い切りました。宝は見つかりませんでした。")

# ゲームを実行
treasure_hunt_game()

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

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

問題の答え合わせと解説

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

一つの正解例

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

import random

# グリッドサイズを定義
GRID_SIZE = 5

# グリッドを初期化する関数
def initialize_grid():
    grid = []
    count = 1
    for i in range(GRID_SIZE):
        row = []
        for j in range(GRID_SIZE):
            row.append(f"{count:02d}")  # 01, 02, 03...の形式で初期化
            count += 1
        grid.append(row)
    return grid

# グリッドを表示する関数
def display_grid(grid):
    print("現在のグリッド:")
    for row in grid:
        print(" ".join(row))
    print()

# ヒントを提供する関数
def give_hint(player_x, player_y, treasure_x, treasure_y):
    hint = []
    if player_x < treasure_x:
        hint.append("右")
    elif player_x > treasure_x:
        hint.append("左")

    if player_y < treasure_y:
        hint.append("下")
    elif player_y > treasure_y:
        hint.append("上")

    return " ".join(hint) + " に宝があります。"

# 宝探しゲームを実行する関数
def treasure_hunt_game():
    # グリッドと宝の位置を初期化
    grid = initialize_grid()
    treasure_x = random.randint(0, GRID_SIZE - 1)
    treasure_y = random.randint(0, GRID_SIZE - 1)

    print("宝探しゲームへようこそ!1から25までの数字で宝を探し当ててください。")
    print("宝を探すチャンスは3回です。")
    display_grid(grid)

    attempts = 0
    found_treasure = False

    while attempts < 3 and not found_treasure:
        try:
            choice = int(input("1から25のマス番号を入力してください: ")) - 1
            if choice < 0 or choice >= GRID_SIZE * GRID_SIZE:
                print("無効な番号です。1から25までの数字を入力してください。")
                continue

            player_x = choice % GRID_SIZE
            player_y = choice // GRID_SIZE

            # 既に選択した場所は選べないようにする
            if grid[player_y][player_x] == "*":
                print("そのマスは既に選択されています。別のマスを選んでください。")
                continue

            # 宝を見つけた場合
            if player_x == treasure_x and player_y == treasure_y:
                print("おめでとうございます!宝を見つけました!")
                grid[player_y][player_x] = "☆"  # 宝の位置を☆で表示
                found_treasure = True
            else:
                # 選んだ場所を*でマークし、ヒントを出す
                grid[player_y][player_x] = "*"
                print(give_hint(player_x, player_y, treasure_x, treasure_y))
                attempts += 1
                print(f"残りのチャンス: {3 - attempts}回")

            display_grid(grid)
        except ValueError:
            print("無効な入力です。1から25までの数字を入力してください。")

    if not found_treasure:
        print("残念ながら、チャンスを使い切りました。宝は見つかりませんでした。")

# ゲームを実行
treasure_hunt_game()

正解例の詳細解説

コードの各部分の解説を以下に示します。

グリッドサイズの定義

GRID_SIZE = 5

このコードでは宝探しゲームのグリッドのサイズを定義しています。5×5のグリッドが生成され、宝を探す場所が25箇所用意されます。

グリッドを初期化する関数

def initialize_grid():
    grid = []
    count = 1
    for i in range(GRID_SIZE):
        row = []
        for j in range(GRID_SIZE):
            row.append(f"{count:02d}")  # 01, 02, 03...の形式で初期化
            count += 1
        grid.append(row)
    return grid

この関数は5×5のグリッドを作成します。

各セルには01から25までの数字が割り当てられ、これにより宝探しを行う範囲がわかるようになっています。

f"{count:02d}" は、数字を2桁で表示するフォーマットです。

グリッドを表示する関数

def display_grid(grid):
    print("現在のグリッド:")
    for row in grid:
        print(" ".join(row))
    print()

この関数はグリッドの状態を画面に表示します。

リスト内の各行をループで処理し、プレイヤーが選択可能な位置や既に選択された場所が視覚的に確認できるようにしています。

ヒントを提供する関数

def give_hint(player_x, player_y, treasure_x, treasure_y):
    hint = []
    if player_x < treasure_x:
        hint.append("右")
    elif player_x > treasure_x:
        hint.append("左")

    if player_y < treasure_y:
        hint.append("下")
    elif player_y > treasure_y:
        hint.append("上")

    return " ".join(hint) + " に宝があります。"

プレイヤーが宝の位置を予測できるように宝の方向を示すヒントを提供する関数です。

宝がプレイヤーから見てどの方向にあるかを教えてくれます。方向のリストを結合し、ヒントを表示します。

宝探しゲームを実行する関数

def treasure_hunt_game():
    grid = initialize_grid()
    treasure_x = random.randint(0, GRID_SIZE - 1)
    treasure_y = random.randint(0, GRID_SIZE - 1)

ゲームを開始するために最初にグリッドを初期化し、宝の位置をランダムに決定します。

random.randint()を使用して宝の位置をランダムに決定します。

プレイヤーの選択処理

choice = int(input("1から25のマス番号を入力してください: ")) - 1
player_x = choice % GRID_SIZE
player_y = choice // GRID_SIZE

プレイヤーが1から25の範囲で数字を入力し、それをグリッド上の位置に変換します。

player_xplayer_y は選択された位置を計算するために使用されます。

選択したマスに印をつけ、ヒントを表示する

grid[player_y][player_x] = "*"
print(give_hint(player_x, player_y, treasure_x, treasure_y))
attempts += 1
print(f"残りのチャンス: {3 - attempts}回")

プレイヤーが選んだマスには「*」を表示し、既に選ばれたことを示します。

また、ヒントが表示され、残りのチャンスが更新されます。

宝を見つけた場合の処理

if player_x == treasure_x and player_y == treasure_y:
    print("おめでとうございます!宝を見つけました!")
    grid[player_y][player_x] = "☆"
    found_treasure = True

プレイヤーが宝を見つけた場合、画面に「おめでとうございます!」と表示し、宝の場所に「☆」が表示されます。

これでゲームは終了します。

チャンスを使い切った場合の処理

if not found_treasure:
    print("残念ながら、チャンスを使い切りました。宝は見つかりませんでした。")

レイヤーが3回のチャンスを使い切った場合、宝が見つからなかったことを通知します。

まとめ

この宝探しゲームではythonの基本的な制御構造(ループや条件分岐)、関数、リスト操作を学びました。

また乱数を使ってゲームのランダム性を実現しており、Pythonの基本的な文法を体験しながら楽しめる構成になっています。

このようなゲームを作ることで、プログラミングの楽しさを感じ、さらに複雑なプログラムに挑戦する自信をつけてください。

引き続き、練習を重ねていきましょう!

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

<<前のページ Python記事一覧
次のページ>>

質問用コンタクトフォーム

この記事はAIを用いて書いた記事です。

人間の目による確認も行っていますが、もし間違い等ありましたらご指摘頂けると大変助かります。






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