Python の勉強 スロットゲーム編 〜その10:while による繰り返し〜

プログラミング

Python における while での繰り返しについて勉強していきます。

for と違って書き方のパターンが少ないので、こちらの方が理解はしやすいかも知れません。しかし、ちょっとしたことで “無限ループ” になってしまいますのでご注意下さい。
(”無限ループ” と言えば、スーパーマリオブラザーズ「-1」面のあれです)

n = 0

while n < 10:           # while {条件式}: という形で記載します
    print(n)            # {条件式} の結果が True の場合、内部の処理を実行します
    n += 1              # 最後まできたら、また while {条件式}: に戻ります
print(f'{n}. 終わり')    # これは while ループの外です

上記プログラム内にもコメントで記載した通り、「while {条件式}:」という形でループを下記始めます。処理の内容はインデント(字下げ)して記載します。 6 行目の print() のように、たとえ繋げてかいたとしてもインデント(字下げ)が元通りなら、それは while 繰り返し処理の対象ではありませんので、ご注意下さい。

無限ループについても書き方を見ておきます。プログラムを途中で止めたくなった際には「Ctrl + c」を 2 回ほど押しましょう。

import time


# 一番簡単な無限ループ
n = 0
while True:             # {条件式} のところが常に True なので、永遠に内部の処理を繰り返します...
    print(n)
    time.sleep(1)       # 1秒間停止。これを入れておかないと、画面がブワーってなるので……
    n += 1
import time


# うっかりした無限ループ(1)
n = 1
while n > 0:            # (同上)
    print(n)
    time.sleep(1)       # (同上)
    n += 1
import time


# うっかりした無限ループ(2)
n = 0
while n < 10:           # (同上)
    print(n)
    time.sleep(1)       # (同上)
n += 1                  # while の処理対象の外にあるため、一度も使われることがない……。

スロットゲームに適用する

今までは for を使って規定回数、ゲームに挑戦できるようにしていました。今後は while を使って “所持コイン数が 0 より多い” 間はゲームが続くように修正してみましょう。いつもと同じ様に前回(009.py)をコピペして「010.py」を作成します。

修正する箇所は前回と同じ場所になります。while に続く “条件式” を正しく掛けるかどうかがポイントとなります。今回はその他にも、前回の修正方法によって気をつけないといけないポイントがありますので、合わせて下記いたします。

  • while の条件式にプレーヤーの所持コイン数(player_coin)が 0 より大きいことを適用する
  • 使えなくなる変数がある
    • VS Code が下線で警告を出してくれるので分かりやすいと思います
      • リストで繰り返し回数を増やした人は message が使えなくなってます
      • range() で繰り返し回数を増やした人は r(等)が使えなくなってます
    • 重要ではないので思い切って「○回目」等のメッセージは削除しましょう
  • ゲーム終了時に表示していたメッセージを、所持コイン数が 0 枚以下になったことを通知するように修正する

結果

私はゲーム終了時のメッセージを「ゲームオーバーです」「さようなら ○○○ さん」にしました。結果、プログラム全体は以下のようになりました。

"""スロットゲーム

簡単なスロットゲームです。ゲームスタート時に保有しているコインを増やしましょう。
掛けコイン数を入力すると、スロットの結果が表示されます。
絵柄が揃うと、そのパターンに応じた配当倍率でコインを獲得することができます。
"""


import random   # "乱数" を生成するために必要なライブラリをメモリ上に読み込む(標準ライブラリ)


# スロット(リール)の中身を "定数" で定義する
# 配列のインデックスは 0 から始まるので、0 〜 9 番目に格納されている
# 定数は全て大文字で記載する
REEL_MARK_LIST = ('♠', '♥', '♥', '◆', '◆', '◆', '♣', '♣', '♣', '♣')

# 特別なプレーヤーの名前と、その名前を使用した際のボーナスコイン数
BONUS_PLAYER_AND_COINS = {'king': 100, 'queen': 150}

# スペシャルサンクスの対象者名
# ボーナスコインは一律 50 枚とする
SPECIAL_THANKS = {'akira',      # 弊社社長。詳細は社長が作成最多ブログ記事のプロフィール欄をご確認下さい。
                  'hurry',      # 詳細はプロフィール欄から twitter をご確認下さい。
                  'shachi',     # https://shachi-web.com/
                  }
SPECIAL_THANKS_COIN = 50


# ============================================================
# ゲームに必要な関数を定義する
# ============================================================

def show_start_message():
    """ゲーム開始のメッセージを表示する
    (This function is to be called to show the start message.)
    """
    print('--------------')
    print('スロットゲーム')
    print('--------------')

def ask_player_name():
    """プレーヤーの名前を尋ねる
    (This function is to be called to ask player's name.)

    プレーヤーの名前を入力(input)してもらい、挨拶を表示(print)する
    入力されたプレーヤーの名前を返す(return)

    Returns:
        str: プレーヤーの名前
    """
    player_name = input('あなたの名前を入力して下さい: ')
    print(f'こんにちは {player_name} さん')
    return player_name

def ask_bets(player_coin):
    """現在の所持コイン数を表示した後、掛けるコイン数(bets)を尋ねる
    (This function is to be called to ask bets.)

    所持コイン数(player_coin)は数値なので、文字列に含めたい場合は文字列(string)に変換する必要がある ==> str() 関数
    input() 関数で入力した値は文字列(string)になるので整数(integer)に変換する ==> int() 関数

    Args:
        player_coin (int): プレーヤーの所持コイン数

    Returns:
        int: 掛けコイン数
    """
    print('------------------------------')
    print(f'現在の所持コイン数は {player_coin:,} 枚です。')
    str_bets = input('掛けコイン数を入力して下さい: ')
    bets = int(str_bets)
    return bets

def show_and_get_result():
    """スロットの結果(絵柄)を表示し、結果を取得する
    (This function is to be called to show and get result.)

    Returns:
        str: スロットの結果(絵柄)
    """
    result_list = []
    for _ in range(3):
        index = random.randint(0, 9)
        result = REEL_MARK_LIST[index]
        result_list.append(result)
    result_all = ''.join(result_list)
    print(result_all)
    return result_all

def get_division(marks):
    """絵柄に応じた配当倍率を取得する
    (This function is to be called to get division.)

    Args:
        marks (str): スロットの結果(絵柄)

    Returns:
        int: 配当倍率
    """
    if marks == '♠♠♠':
        print('超大当たり!!')
        return 15
    elif marks == '♥♥♥':
        print('大当たり!')
        return 12
    elif marks == '◆◆◆':
        print('大当たり!')
        return 10
    elif marks == '♣♣♣':
        print('大当たり!')
        return 8
    elif marks[0:2] == '♠♠':
        print('当たり!')
        return 5
    else:
        print('ハズレ...')
        return -1

def calculate_coin(coin, bets, division):
    """掛けたコイン数(bets)と、配当倍率(division)を使用してプレーヤーの所持コイン数を精算する
    (This function is to be called to calculate (players's) coin.)

    Args:
        coin (int): プレーヤーの精算前の所持コイン数
        bets (int): 掛けコイン数
        division (int): 配当倍率

    Returns:
        int: 精算後のプレーヤーの所持コイン数
    """
    coin = coin + bets * division
    return coin


# ============================================================
# 実際にゲームを実行する
# ============================================================

# プレーヤーの所持コイン数
player_coin = 123

show_start_message()
player_name = ask_player_name()

if player_name in BONUS_PLAYER_AND_COINS:
    player_coin = player_coin + BONUS_PLAYER_AND_COINS[player_name]
elif player_name in SPECIAL_THANKS:
    player_coin = player_coin + SPECIAL_THANKS_COIN

while player_coin > 0:
    bets = ask_bets(player_coin)
    marks = show_and_get_result()
    division = get_division(marks)
    player_coin = calculate_coin(player_coin, bets, division)

print('ゲームオーバーです')
print(f'さようなら {player_name} さん')

次回は一度、forwhile のループを途中で抜ける方法について勉強します。

コメント

タイトルとURLをコピーしました