Python学習日記 – KillAliens でスコアの継続読み書きと計算を実装
はじめに
Pythonから半年ほど離れていましたが、中間試験が終わるとすぐにアルゴリズムの初歩に触れることになります。Python的な考え方がアルゴリズムの学習に非常に役立つと感じたので、数時間かけてこのKillAliensという小さなゲームを書きました。
その中で最も重要な2つの部分は、スコアの継続的な読み書きと計算とランダムイベントの生成です。これから、KillAliensというゲーム全体の実装方法と、この2つの部分の実装プロセスについて詳しく説明します。
このKillAliensという小さなゲームは、ずいぶん前に書いた30行にも満たないシンプルなテキストベースのゲーム击杀外星人.pyから着想を得ています。KillAliensでは、击杀外星人.pyにはなかったスコアリングシステムを追加し、辞書を使って、各エイリアンの種類に対応するスコアをキーと値のペアで管理しています。
击杀外星人.pyは私のPython学習リポジトリで見つけることができます。
補足
この小さなゲームは2022年5月14日に初めて書かれました。研究の結果、2022年5月19日にアルゴリズムを修正し、スレッドのパフォーマンスを向上させました。旧コードはリポジトリ内でKillAliens.pyまたはKillAliens_NoComment.pyという名前で、新コードはKillAliens_V2.pyまたはKillAliens_NoComment_V2.pyという名前です。
出力プレビュー
あなたの名前:
Magneto
こんにちは Magneto 、次にゲーム内のAlienとそのスコアを紹介します!
Big Alienを倒すと10点獲得できます
Middle Alienを倒すと5点獲得できます
A Alienを倒すと2点獲得できます
Small Alienを倒すと1点獲得できます
現在のあなたのスコアは 0 点です
ゲームを終了したい場合は、'quit' と入力してください。ゲームを終了するか、他の任意の値を入力してゲームを開始(続行)します。
開始
倒したいAlienの 名前 を入力してください。倒すことに成功すると、指定されたスコアを獲得できます
名前:Big Alien
対応スコア:10
名前:Middle Alien
対応スコア:5
名前:A Alien
対応スコア:2
名前:Small Alien
対応スコア:1
注意:Alienを倒せず、ゲームが終了する可能性があります。また、対応するスコアが高いほど、倒せる確率は低くなります。
対応する名前を入力してください:
Small Alien
あなたはSmall Alienを選択しました
おめでとうございます Magneto 、倒すことに成功し、1点獲得しました
現在の合計スコア: 1 点
現在のあなたのスコアは 1 点です
ゲームを終了したい場合は、'quit' と入力してください。ゲームを終了するか、他の任意の値を入力してゲームを開始(続行)します。
続行
倒したいAlienの 名前 を入力してください。倒すことに成功すると、指定されたスコアを獲得できます
名前:Big Alien
対応スコア:10
名前:Middle Alien
対応スコア:5
名前:A Alien
対応スコア:2
名前:Small Alien
対応スコア:1
注意:Alienを倒せず、ゲームが終了する可能性があります。また、対応するスコアが高いほど、倒せる確率は低くなります。
対応する名前を入力してください:
Small Alien
あなたはSmall Alienを選択しました
おめでとうございます Magneto 、倒すことに成功し、1点獲得しました
現在の合計スコア: 2 点
現在のあなたのスコアは 2 点です
ゲームを終了したい場合は、'quit' と入力してください。ゲームを終了するか、他の任意の値を入力してゲームを開始(続行)します。
続行
倒したいAlienの 名前 を入力してください。倒すことに成功すると、指定されたスコアを獲得できます
名前:Big Alien
対応スコア:10
名前:Middle Alien
対応スコア:5
名前:A Alien
対応スコア:2
名前:Small Alien
対応スコア:1
注意:Alienを倒せず、ゲームが終了する可能性があります。また、対応するスコアが高いほど、倒せる確率は低くなります。
対応する名前を入力してください:
Big Alien
あなたはBig Alienを選択しました
残念ながら Magneto 、Big Alienを倒す試みは失敗しました。スコアはリセットされ、ゲームを終了します。
プロセスは終了しました。終了コード0
コードプレビュー
############################
### Date 2022 May 14 ###
### Author Magneto ###
### Name KillAliens <——>
### Facility Windows 11 ###
### Language Python ###
############################
import random
import time
aliens_name_and_mark = {
'Big Alien': 10,
'Middle Alien': 5,
'A Alien': 2,
'Small Alien': 1
}
Data = {'The_name': '', 'The_marks': 0}
state_one = ['1', '2', '3', '4', '5']
print("KillAliens ミニゲームへようこそ。辞書は初期化済みです\n次に内容を入力してください\n")
Data['The_name'] = input("あなたの名前:\n\t")
print(f"こんにちは \033[94m{Data['The_name']}\033[0m 、次にゲーム内のAlienとそのスコアを紹介します!\n")
time.sleep(1)
for name, marks in aliens_name_and_mark.items():
print(f"\t{name}を倒すと {marks} 点獲得できます")
time.sleep(1)
while True:
print(f"\n現在のあなたのスコアは \033[35m{Data['The_marks']}\033[0m 点です")
exit_the_game = input("\nゲームを終了したい場合は、'quit' と入力してください。ゲームを終了するか、他の任意の値を入力してゲームを開始(続行)します。\n\t")
if exit_the_game == 'quit':
break
print("倒したいAlienの \033[94m 名前 \033[0m を入力してください。倒すことに成功すると、指定されたスコアを獲得できます")
for name, marks in aliens_name_and_mark.items():
print(f"\t名前:{name}\n\t\t対応スコア:{marks}")
print("注意:Alienを倒せず、ゲームが終了する可能性があります。また、対応するスコアが高いほど、倒せる確率は低くなります。")
time.sleep(1)
ChoiseAliens = input("対応する名前を入力してください:\n\t")
if ChoiseAliens == 'Small Alien':
state_two = ['1', '2', '3', '4', '5', '6', '7', '8']
The_Random = random.choice(state_two)
print("あなたはSmall Alienを選択しました")
if The_Random in state_one:
print(f"おめでとうございます \033[94m{Data['The_name']}\033[0m 、倒すことに成功し、1点獲得しました")
Data['The_marks'] += aliens_name_and_mark['Small Alien']
print(f"現在の合計スコア:\033[35m{Data['The_marks']}\033[0m 点\n\n\n")
else:
print(f"残念ながら \033[94m {Data['The_name']} \033[0m 、Small Alienを倒す試みは失敗しました。スコアはリセットされ、ゲームを終了します。")
break
elif ChoiseAliens == 'A Alien':
state_two = ['1', '2', '3', '6', '7', '8']
The_Random = random.choice(state_two)
print("あなたはA Alienを選択しました")
if The_Random in state_one:
print(f"おめでとうございます \033[94m{Data['The_name']}\033[0m 、倒すことに成功し、2点獲得しました")
Data['The_marks'] += aliens_name_and_mark['A Alien']
print(f"現在の合計スコア:\033[35m{Data['The_marks']}\033[0m 点\n\n\n")
else:
print(f"残念ながら \033[94m{Data['The_name']}\033[0m 、A Alienを倒す試みは失敗しました。スコアはリセットされ、ゲームを終了します。")
break
elif ChoiseAliens == 'Middle Alien':
state_two = ['1', '2', '6', '7', '8']
The_Random = random.choice(state_two)
print("あなたはMiddle Alienを選択しました")
if The_Random in state_one:
print(f"おめでとうございます \033[94m {Data['The_name']} \033[0m 、倒すことに成功し、5点獲得しました")
Data['The_marks'] += aliens_name_and_mark['Middle Alien']
print(f"現在の合計スコア:\033[35m{Data['The_marks']}\033[0m 点\n\n\n")
else:
print(f"残念ながら \033[94m{Data['The_name']}\033[0m 、Middle Alienを倒す試みは失敗しました。スコアはリセットされ、ゲームを終了します。")
break
elif ChoiseAliens == 'Big Alien':
state_two = ['1', '6', '7', '8']
The_Random = random.choice(state_two)
print("あなたはBig Alienを選択しました")
if The_Random in state_one:
print(f"おめでとうございます \033[94m{Data['The_name']}\033[0m 、倒すことに成功し、10点獲得しました")
Data['The_marks'] += aliens_name_and_mark['Big Alien']
print(f"現在の合計スコア:\033[35m{Data['The_marks']}\033[0m 点\n\n\n")
else:
print(f"残念ながら \033[94m{Data['The_name']}\033[0m 、Big Alienを倒す試みは失敗しました。スコアはリセットされ、ゲームを終了します。")
break
else:
print("対応する\033[94m名前\033[0mを入力してください。他の内容ではありません。")
コード分析
分析の説明
この記事のコード分析では、主に使用されている主要な構文について説明します。各行のコードの役割を具体的に分析することはせず、ご自身で理解する必要があります。
コメント
Pythonでは、コメントは井桁、つまり#で識別します。井桁の後の内容はPythonインタープリタによって無視されます。この記事に添付されているコードには機能的なコメントはなく、作者によるコメントのみです。
モジュールのインポート
コードの9-10行目で、それぞれrandomモジュールとtimeモジュールをインポートしています。
import random
import time
これら2つのモジュールの役割は、それぞれランダム処理と、Pythonスレッドを指定時間スリープさせることです。
randomの使い方は、Python学習日記 – 座標移動 #random モジュールで説明したので、ここでは詳しく説明しません。
timeの役割は、Pythonスレッドを指定時間スリープさせることで、この時間は秒単位です。試してみましょう:
name = input("あなたの名前:")
time.sleep(1)
print(f"こんにちは{name}")
これが実行結果です
あなたの名前:Magneto
こんにちはMagneto
上記のコードの最初の行は、Pythonスレッドの実行開始後、すぐに実行され、名前を尋ねます。ユーザーの入力値を受け取った後、2行目のコードが実行されます。Pythonインタープリタは2行目で命令を受け取り、1秒間スリープするよう要求され、スリープします。Pythonスレッドが1秒間スリープした後、ようやく3行目のコードが実行され、名前が出力されます。
辞書とfor文
Pythonでは、辞書は{ }の波括弧で囲まれた内容で、キー(key)と値(value)の2つの要素で構成され、これをキーと値のペアと呼びます。各キーは1つの値に対応します。KillAliensでは、12-17行目が1つの辞書で、18行目が1つの辞書です。これら2つの辞書は記述形式が異なりますが、どちらも辞書であり、違いはありません。12-17行目の記述形式は、見た目の問題を解決するためのものです。つまり、Pythonではコードを規範的に書くことが求められており、これは良い習慣です。
辞書を使用するのは、for文での出力を容易にするためです。辞書とfor文を使った出力を書いて試してみましょう:
name_and_money = {
'Mark': '10',
'Tom': '20',
}
for name, money in name_and_moneu.items():
print(f"{name} は {money} 元持っています。")
学習しやすいように、各キーと値のペアを分けて書きました。実行結果:
Mark は 10 元持っています。
Tome は 20 元持っています。
for文では、厳密な順序の対応があります。nameはキーに対応し、moneyは値に対応します。そしてitems()は、辞書に出力できるキーと値のペアがなくなるまでループ出力するためのものです。
また、for文内のprintでは、上記のキーと値のペアの命名を使用できます。つまり、nameとmoneyを使って辞書内のキーと値に対応し、読み取ることができます。
for文以外にも、辞書は直接読み書きできますが、これは値の読み書きに限ります。
まず読み取りを見てみましょう
# まず辞書を定義します
name_and_money = {
'Mark': '10',
'Tom': '20',
}
# 辞書を読み取りましょう
print(f"彼は{name_and_money['Mark']}元持っています")
print内で{ }を使用すると、特定の領域の内容を読み取ることを意味し、その中に[ ]を追加すると、特定の領域内の特定の値を読み取ることを意味します。
上記のコードでは、{name_and_money['Mark']}を使用して、name_and_money辞書のMarkというキーに対応する値10を読み取っています。出力結果を見てみましょう
彼は10元持っています
次に書き込みを見てみましょう
# まず辞書を定義します
name_and_money = {
'Mark': 10,
'Tom': 20,
}
# 元の辞書を読み取りましょう
print(f"彼は元々{name_and_money['Mark']}元持っていました")
# 数字+1、つまり計算を行います
name_and_money['Mark'] += 1
# 新しい辞書を読み取りましょう
print(f"しかし彼は今{name_and_money['Mark']}元持っています")
出力結果を見てみましょう
彼は元々10元持っていました
しかし彼は今11元持っています
注意すべき点として、読み取りの部分とは異なり、この値に引用符' 'を付けていません。これは、引用符を付けると文字列を意味し、計算を続行するには浮動小数点数に変換する必要があるためです。一方、引用符を付けない場合は、純粋な数字を意味し、直接計算できます。
もちろん、これは計算を伴う書き込みですが、直接書き込むこともできます
# まず辞書を定義します
name_and_boyfriend = {
'Mark': 'Williams',
'Tom': 'Brown',
}
# 元の辞書を読み取りましょう
print(f"彼の元彼氏は{name_and_boyfriend['Mark']}")
# 値を上書きします
name_and_boyfriend['Mark'] = 'Wilson'
# 新しい辞書を読み取りましょう
print(f"彼の今彼氏は{name_and_boyfriend['Mark']}")
ここでは彼氏の例を挙げて、キーに対応する値を直接上書きして置き換えました。
彼の元彼氏はWilliams
彼の今彼氏はWilson
ここでの上書きは文字列を使用していますが、数字も同様の考え方です。
注意すべき点として、このような上書きによる変更は永続的です。
どういう意味か見てみましょう
# まず辞書を定義します
name_and_boyfriend = {
'Mark': 'Williams',
'Tom': 'Brown',
}
# for文ループ
for name, boyfriend in name_and_boyfriend.items():
print(f'{name}のかつての彼氏は{boyfriend}')
# 元の辞書を読み取りましょう
print(f"彼の元彼氏は{name_and_boyfriend['Mark']}")
# 値を上書きします
name_and_boyfriend['Mark'] = 'Wilson'
# 新しい辞書を読み取りましょう
print(f"彼の今彼氏は{name_and_boyfriend['Mark']}")
# for文ループ
for name, boyfriend in name_and_boyfriend.items():
print(f'{name}の今の彼氏は{boyfriend}')
出力結果
Markのかつての彼氏はWilliams
Tomのかつての彼氏はBrown
彼の元彼氏はWilliams
彼の今彼氏はWilson
Markの今の彼氏はWilson
Tomの今の彼氏はBrown
Tomは対照群として、変更されていません。彼の彼氏は常にBrownです。一方、Markは変更後、for文で辞書を読み取る際も、変更後の値を読み取ります。
if-elif-else の発展
KillAliensでは、if文の発展形を使用しています。if文の中にif文をネストし、in構文を使用しています。KillAliensから抜粋したコードを修正して説明しましょう。
# random ランダムモジュールをインポート
import random
# 対照群の数字
state_one = ['1', '2', '3', '4', '5']
# 対応する名前を入力します。ここでは下の if 文に対応する名前を書きます
ChoiseAliens = input("対応する名前を入力してください:\n\t")
# if 文で判断し、ChoiseAliens の値が Small Alien の場合、if 文内の内容を実行します
if ChoiseAliens == 'Small Alien':
# 実験群、The_Random にランダム処理を委ねます。
state_two = ['1', '2', '3', '4', '5', '6', '7', '8']
The_Random = random.choice(state_two)
print("あなたはSmall Alienを選択しました")
# ネストした if 文、生成された乱数が対照群にあれば、以下の値を返します
if The_Random in state_one:
print(f"おめでとうございます、倒すことに成功し、1点獲得しました")
# ネストした if 文、子文、生成された乱数が対照群になければ、以下の値を返します
else:
print(f"残念ながら、Small Alienを倒す試みは失敗しました")
# if 文、子文で判断し、ChoiseAliens の値が A Alien の場合に実行します
elif ChoiseAliens == 'A Alien':
# 実験群、The_Random にランダム処理を委ねます。
state_two = ['1', '2', '3', '6', '7', '8']
The_Random = random.choice(state_two)
print("あなたはA Alienを選択しました")
# ネストした if 文、生成された乱数が対照群にあれば、以下の値を返します
if The_Random in state_one:
print(f"おめでとうございます、倒すことに成功し、2点獲得しました")
else:
# ネストした if 文、子文、生成された乱数が対照群になければ、以下の値を返します
print(f"残念ながら、A Alienを倒す試みは失敗しました")
# if 文、子文で判断し、入力された内容が if と elif のどちらにも該当しない場合、以下の値を返します
else:
print("入力する必要があるのは、指定された名前であり、他の内容ではありません。")
異なる結果を示すために、複数回実行しました。
# 1回目
対応する名前を入力してください:
Small Alien
あなたはSmall Alienを選択しました
おめでとうございます、倒すことに成功し、1点獲得しました
# 2回目の実行
対応する名前を入力してください:
A Alien
あなたはA Alienを選択しました
残念ながら、A Alienを倒す試みは失敗しました
# 3回目の実行
対応する名前を入力してください:
Magneto
入力する必要があるのは、指定された名前であり、他の内容ではありません。
1回目の実行では、ifの判断を通過し、ランダムに選ばれた数が対照群state_oneにあったため、成功を返しました。2回目の実行では、elifの判断を通過し、ランダムに選ばれた数が対照群state_oneになかったため、失敗を返しました。3回目の実行では、Magnetoと入力したため、ifとelifの判断のどちらにも適合せず、elseに委ねられ、プロンプトが返されました。
KillAliensでは、これにより、存在しない内容を入力してプログラムがエラーになることを効果的に回避しています。
Whileループ
WhileループはKillAliensでは単純に使用されているだけなので、詳しい説明はしません。Python3 ループ文 | 菜鳥教程 を参照して学習できます。
終わりに
KillAliensは私が書いた比較的複雑なプログラムで、シンプルなテキストベースのミニゲームです。Pythonだけで実装されたスコアリングシステム、判断システム、撃破システムは、どれも完成度が高く比較的シンプルですが、これらのデータはスレッド内にのみ存在するため、まだ大きな