Python Learning Diary – KillAliens: Implementing Persistent Read/Write and Computation
Preface
I had put Python aside for half a year. After the midterm exams, we'll soon be covering the basics of algorithms. I believe that thinking in Python significantly helps with learning algorithms, so I spent a few hours writing this little game called KillAliens.
The two most important parts are persistent reading/writing and computation of scores and generation of random events. Next, I'll explain in detail how to implement the entire KillAliens game and these two parts.
Based on
This KillAliens game is inspired by a simple text-based game I wrote long ago called 击杀外星人.py, which was less than 30 lines. In KillAliens, the scoring system is something 击杀外星人.py didn't have. It also uses dictionaries, mapping each type of Alien to its own score via key-value pairs.
You can find 击杀外星人.py in my Python learning repository.
Supplement
This little game was first written on 2022/5/14. After some research, I modified the algorithm on 2022/5/19 to improve thread performance. The old code is named KillAliens.py or KillAliens_NoComment.py in the repository, and the new code is named KillAliens_V2.py or KillAliens_NoComment_V2.py.
Output Preview
Your name:
Magneto
Hello Magneto , let me introduce the Aliens in the game and their corresponding scores!
Killing Big Alien gives you 10 points
Killing Middle Alien gives you 5 points
Killing A Alien gives you 2 points
Killing Small Alien gives you 1 point
Your current score is 0 points
If you want to quit the game, enter 'quit' to exit, or enter any other value to start (continue) the game.
Start
Enter the name of the Alien you want to kill. After a successful kill, you get the specified score.
Name: Big Alien
Score: 10
Name: Middle Alien
Score: 5
Name: A Alien
Score: 2
Name: Small Alien
Score: 1
Please note that you may fail to kill the Alien and the game will end. Also, the higher the score, the lower the kill chance.
Enter the corresponding name:
Small Alien
You chose Small Alien
Congratulations Magneto , kill successful, you get 1 point
Total score: 1 points
Your current score is 1 points
If you want to quit the game, enter 'quit' to exit, or enter any other value to start (continue) the game.
Continue
Enter the name of the Alien you want to kill. After a successful kill, you get the specified score.
Name: Big Alien
Score: 10
Name: Middle Alien
Score: 5
Name: A Alien
Score: 2
Name: Small Alien
Score: 1
Please note that you may fail to kill the Alien and the game will end. Also, the higher the score, the lower the kill chance.
Enter the corresponding name:
Small Alien
You chose Small Alien
Congratulations Magneto , kill successful, you get 1 point
Total score: 2 points
Your current score is 2 points
If you want to quit the game, enter 'quit' to exit, or enter any other value to start (continue) the game.
Continue
Enter the name of the Alien you want to kill. After a successful kill, you get the specified score.
Name: Big Alien
Score: 10
Name: Middle Alien
Score: 5
Name: A Alien
Score: 2
Name: Small Alien
Score: 1
Please note that you may fail to kill the Alien and the game will end. Also, the higher the score, the lower the kill chance.
Enter the corresponding name:
Big Alien
You chose Big Alien
Sorry Magneto , you failed to kill Big Alien. Your score is reset to zero and the game exits.
Process finished with exit code 0
Code Preview
############################
### 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,而不是其它内容。")
Code Analysis
Analysis Notes
The code analysis in this article mainly covers the key syntax used; it won't analyze every line in detail—that's for you to figure out.
Comments
In Python, comments are marked with the hash symbol, i.e., #. Everything after the hash is ignored by the Python interpreter. The code included in this article has no functional comments, only author comments.
Module Imports
Lines 9-10 import the random and time modules.
import random
import time
These two modules are used for random processing and making the Python thread sleep for a specified time, respectively.
The usage of random was covered in Python Learning Diary – Coordinate Movement #random module, so I won't go into it again here.
The time module's function is to make the Python thread sleep for a specified time, measured in seconds. Let's try it:
name = input("你的名字:")
time.sleep(1)
print(f"你好{name}")
Here's the output:
你的名字:Magneto
你好Magneto
In the code above, the first line executes immediately when the Python thread starts, asking for the name. After getting the user's input, the second line executes, and the Python interpreter receives the instruction to sleep for 1 second. After the thread sleeps for 1 second, it continues to the third line and prints the name.
Dictionaries and the for Statement
In Python, a dictionary is enclosed in curly braces { } and contains two parts: keys and values, which we call key-value pairs. Each key corresponds to a value. In KillAliens, lines 12-17 form a dictionary, and line 18 is another dictionary. These two dictionaries are written differently but are both dictionaries with no difference. The format in lines 12-17 is for aesthetics, as we are required to write code in a standardized way in Python—a good habit.
Using a dictionary makes it convenient for the for statement to output. Let's write a dictionary and a for statement to output:
name_and_money = {
'Mark': '10',
'Tom': '20',
}
for name, money in name_and_moneu.items():
print(f"{name} 有 {money} 元。")
For easier viewing and learning, I've written each key-value pair on separate lines. Output:
Mark 有 10 元。
Tome 有 20 元。
In the for statement, there is a strict order: name corresponds to the key, money to the value, and items() is used to loop through until there are no more key-value pairs to print.
The print inside the for loop can use the names assigned to the key-value pairs, i.e., name and money, to read the keys and values in the dictionary.
Besides the for statement, dictionaries can also be read and written directly, but this only applies to reading and writing values.
Let's look at reading first:
# 首先定义字典
name_and_money = {
'Mark': '10',
'Tom': '20',
}
# 让我们读取字典
print(f"他有{name_and_money['Mark']}元")
In print, using { } means reading the content in a specific area, and adding [ ] inside reads a specific value within that area.
In the code above, {name_and_money['Mark']} reads the value 10 corresponding to the key Mark in the name_and_money dictionary. Let's see the output:
他有10元
Now let's look at writing:
# 首先定义字典
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']}元")
Let's see the output:
他原来有10元
但他现在有11元
Note that, unlike the reading part, I didn't put quotes ' ' around the value. This is because quotes indicate a string, which would require conversion to a float for arithmetic, while no quotes mean it's a pure number that can be used directly in calculations.
Of course, this is arithmetic writing; you can also write directly:
# 首先定义字典
name_and_boyfriend = {
'Mark': 'Williams',
'Tom': 'Brown',
}
# 让我们读取原本的字典
print(f"他的前男友是{name_and_boyfriend['Mark']}")
# 覆盖值
name_and_boyfriend['Mark'] = 'Wilson'
# 让我们读取新的的字典
print(f"他现男友是{name_and_boyfriend['Mark']}")
Here we gave an example with a boyfriend, directly overwriting the value associated with the key.
他的前男友是Williams
他现男友是Wilson
The overwrite uses a string, but numbers work the same way.
Note that such overwrites are permanent.
Let's see what that means:
# 首先定义字典
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}')
Output:
Mark曾经的男朋友是Williams
Tom曾经的男朋友是Brown
他的前男友是Williams
他现男友是Wilson
Mark现在的男朋友是Wilson
Tom现在的男朋友是Brown
Tom serves as a control group; his boyfriend remains Brown. After Mark's change, the for loop reads the updated value.
Advanced if-elif-else
KillAliens uses an advanced form of the if statement, nesting if statements and using the in syntax. Let's take a snippet from KillAliens and modify it for explanation.
# 引入 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("您需要输入的是指定名称而不是其它内容。")
To show different results, I ran it multiple times.
# 第一次
请输入对应名称:
Small Alien
你选择了 Small Alien
恭喜你,击杀成功,获得 1 分
# 第二次运行
请输入对应名称:
A Alien
你选择了 A Alien
很遗憾 ,你尝试击杀 A Alien 失败了
# 第三次运行
请输入对应名称:
Magneto
您需要输入的是指定名称而不是其它内容。
In the first run, we went through the if branch, and the randomly picked number was in the control group state_one, so we got success. In the second run, we went through the elif branch, and the random number was not in state_one, so we got failure. In the third run, we entered Magneto, which didn't match any if or elif condition, so it went to else and returned a prompt.
In KillAliens, this effectively prevents the program from crashing when non-existent input is entered.
While Loop
The While loop in KillAliens is used simply; I won't explain it in detail. You can refer to Python3 Loop Statements | Runoob Tutorial for learning.
Conclusion
KillAliens is a relatively complex program I wrote—a simple text-based mini-game. The scoring system, judgment system, and kill system are all implemented purely in Python and are quite complete yet simple. However, these data only exist within the thread, and there's still a lot of room for improvement.