敬初学者Python基础学完了,该怎么知道自己学的怎么样呢?十个经典实战小项目附源码
Posted 鬼鬼Kimi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了敬初学者Python基础学完了,该怎么知道自己学的怎么样呢?十个经典实战小项目附源码相关的知识,希望对你有一定的参考价值。
前言
前言
初学者要想成功,一句话,大量的实操,大量的练,乍一看我的这个答案似乎有点敷衍,但是这确实是我接触Python以来,总结出的最有价值的经验,接下来分享我自己初学时用来练手的经典实战小项目,适合初学者敲的代码。
1.街霸游戏
1.1 KO街霸
游戏小剧场
特别调查员春丽突然收到了来自中尉查理的一封邮件,邮件里详细地说明了神月家族在美国唐人街举办的街霸挑战赛,挑战的终极boss正是街霸维加。春丽在很小的时候,父亲就被维加残忍地杀害,为报父仇,春丽毅然决然地买好了飞往唐人街的机票。
邪恶的维加正通过催眠术,控制着在擂台上饮败的格斗家们在世界各地执行暗杀计划。
隆远在印度修行,孤身一人的春丽能在擂台上挑战成功吗?
程序完整源码
这是一个针对Python初学者的练手小程序,简单地模拟春丽与维加的格斗过程。有一定开发经验的朋友可以对程序进行扩展,比如利用多进程来模拟春丽同时与多人进行格斗。
Python
# 导入random模块,执行random模块中的choice方法来随机获取列表中的元素
import random
import time
VEGA_STRATEGIES = ["原地蹲防", "失误", "回旋攻击", "失误", "伤害修正", "回血", "超必杀"]
CHUNLI_KUNFU = ["气功拳", "旋转踢", "百裂脚", "霸山天升脚"]
def countdown(seconds=3, message=""):
"""
:param seconds: 倒数的秒数
:param message: 倒计时结束后输出的提示信息
:return:
"""
for _ in range(seconds, 0, -1):
_, _ = print(_), time.sleep(1)
else:
print(message)
def generate_prompts(kunfu):
"""
:param kunfu: 街霸格斗选手的格斗招数,为一个列表对象,例如["气功拳", "旋转踢"]
:return: 返回用户指令输入的提示信息,为一个字符串对象
"""
prompts = "\\n"
for index, value in enumerate(kunfu):
prompts += "<{}>{}".format(index, value)
prompts += "\\n输入<>中的指令来挑战街霸:__\\b\\b"
return prompts
def fight():
# 定义整型变量fighter,用来保存街霸维加的血量
vega = 100
# 定义整型变量chunli,用来保存春丽的血量
chunli = 100
blood = 5
prompts = generate_prompts(CHUNLI_KUNFU)
countdown(message="Fight!")
# 执行while循环,不断重复执行下面的代码
while True:
# 春丽或boss其中一人血量为0时就退出战斗
if vega * chunli == 0:
break
# 执行input函数获得键盘的输入内容
command = input(prompts)
# 对输入的字符串类型转换为整型,读者在输入时必须输入有效的数字,否则会抛出异常
try:
command = int(command)
_ = CHUNLI_KUNFU[command]
except (ValueError, IndexError):
print("春丽,这是在战斗,请输入正确的战斗指令!")
continue
print("春丽对街霸使出了{}".format(CHUNLI_KUNFU[command]))
# 使用random模块中的choice函数,来随机选择列表里的值
vega_strategy = random.choice(VEGA_STRATEGIES)
if vega_strategy == "失误":
print("街霸维加在对战中反击失误!")
else:
print("街霸维加在对战中对你使用了{}".format(vega_strategy))
if vega_strategy in {"原地蹲防", "回血"}:
if vega_strategy == "回血" and vega < 100:
vega += blood
elif vega_strategy == "失误":
vega -= blood*2
elif vega_strategy == "伤害修正":
vega -= blood
elif vega_strategy == "超必杀":
chunli -= blood*2
else:
chunli -= blood
chunli = 0 if chunli <=0 else chunli
vega = 0 if vega <=0 else vega
print("\\n-*- 春丽现在的血量:{} 维加现在的血量:{} -*-".format(chunli, vega))
time.sleep(3)
if chunli == 0:
print("春丽,你战败了!")
else:
print("维加,我今天终于把你打败,父亲泉下有知,可以瞑目了!")
if __name__ == "__main__":
fight()
程序的输出界面
1.2 春丽VS巴洛克
游戏小剧场
虽然美丽的春丽打败了维加,但邪恶的影罗组织并未就此覆灭。许多年以后,春丽站在A号街区,会突然想起打败神月卡琳后的那个下午。当时,身躯高大的巴洛克已将面具摘下,道场中的其他四名影子杀手,形如雕塑,酷似木偶…春丽经过这场残酷的战斗以后,在背部留下了一道很长的月牙形伤痕。
在本节程序实战中,通过多进程的方式来模拟春丽一人对抗影罗组织的五名邪恶杀手。
参考源码
通过多进程+队列来模拟春丽1VS5的街霸游戏挑战赛:
from multiprocessing import Process, Queue
import random
class Fighter:
def __init__(self, name, blood = 100, justice = True, kungfu = None, enemies = 1):
"""
:param name: 表示该fighter的姓名
:param blood: 表示该fighter的血量
:param justice: 布尔类型,表示该fighter是否代表正义的一方
:param kungfu: 表示该fighter的格斗技能
:param enemies: 表示该fighter对抗的敌人数
"""
self.__name = name
self.__blood = blood
self.__justice = justice
self.__kungfu = kungfu
self.__enemies = enemies
def attack(self):
kungfu, harm = None, 0
if self.__blood > 0:
kungfu = random.choice(list(self.__kungfu.keys()))
harm = self.__kungfu[kungfu]
return kungfu, harm
@property
def name(self):
return self.__name
@property
def blood(self):
return self.__blood
@blood.setter
def blood(self, value):
self.__blood = value
@property
def enemies(self):
return self.__enemies
@enemies.setter
def enemies(self, count):
self.__enemies = count
@property
def justice(self):
return self.__justice
def fight(fighter, justice_attacks, injustice_attacks):
"""
:param fighter: Fighter对象
:param justice_attacks: 队列类型,表示春丽的攻击
:param injustice_attacks: 队列类型,表示巴洛克等杀手的攻击
:return:
"""
while True:
kungfu, harm = fighter.attack()
attack = {"name": fighter.name, "kungfu": kungfu,
"harm": harm, "blood": fighter.blood}
if fighter.justice:
# 通过justice_attacks代表的队列,向以巴洛克为首的杀手们发起一个攻击
justice_attacks.put(attack)
if fighter.blood == 0:
break
# 从justice_attacks代表的消息队列中,接收对方的一个攻击
attack = injustice_attacks.get()
# 如果对方攻击时的blood值为0,表示对方已被击败
if attack["blood"] == 0:
# 减去敌人数
fighter.enemies -= 1
if fighter.enemies == 0:
# 敌人已全部被击败, 退出战斗!
break
else:
continue
else:
# 通过justice_attacks代表的队列,向春丽发起一个攻击
injustice_attacks.put(attack)
if fighter.blood == 0:
break
# 从justice_attacks队列中接收春丽发起的攻击
attack = justice_attacks.get()
# 如果春丽攻击时的血量为0,说明春丽已经被击败
if attack["blood"] == 0:
"""
春丽已经战败,通过justice_attacks对列向己方的杀手们进行消息转发,
同时退出战斗
"""
justice_attacks.put({"blood": 0})
break
kungfu, harm = fighter.attack()
"""
如果在回击的过程中反击的伤害大于对方的伤害值,
则加上已有的血量值来实现回血的功能,否则将血量减去对应的伤害值
"""
fighter.blood += harm - attack["harm"]
if fighter.blood <= 0:
fighter.blood = 0
elif fighter.blood > 100:
fighter.blood = 100
if fighter.blood > 0:
print("{} 获得了胜利!!!".format(fighter.name))
if __name__ == "__main__":
# 定义chunli_kungfu来保存春丽的招式及对应的伤害值
chunli_kungfu = {
"失误": 0,
"原地蹲防": 5,
"龙星落": 10,
"气功拳": 15,
"旋转踢": 20,
"百裂脚": 20,
"霸山天升脚": 20,
"超必杀-千翼气功掌": 25
}
# 定义baroque_kungfu来保存杀手巴洛克的招式及对应的伤害值
baroque_kungfu = {
"失误": 0,
"伤疤之恨": 15,
"闪光漩涡": 20,
"飞翔巴塞罗那": 20,
"红色冲击": 20
}
# 定义来shadow_kungfu保存影子杀手的攻击策略及对应的伤害值
shadow_kungfu = {
"失误": 0,
"暗器": 10,
"毒药": 15,
"炸弹": 20
}
processes = []
fighters = [
Fighter(name="春丽", kungfu=chunli_kungfu, enemies=5),
Fighter(name="巴洛克", kungfu=baroque_kungfu, justice=False),
Fighter(name="影子杀手1", kungfu=shadow_kungfu, justice=False),
Fighter(name="影子杀手2", kungfu=shadow_kungfu, justice=False),
Fighter(name="影子杀手3", kungfu=shadow_kungfu, justice=False),
Fighter(name="影子杀手4", kungfu=shadow_kungfu, justice=False)
]
justice_attacks = Queue()
injustice_attacks = Queue()
for fighter in fighters:
process = Process(target=fight, args=(fighter, justice_attacks, injustice_attacks))
processes.append(process)
[process.start() for process in processes]
[process.join() for process in processes]
2.猜谜游戏
2.1简单的猜数字游戏
项目要求
实现一个简单的猜数字游戏:程序启动时获取一个随机值,根据用户的输入提示大了还是小了,如果用户输入的整数与随机值相等,则退出循环。
通过random模块randint方法获取一个随机值,通过input函数获取用户的输入。
代码示例:
# 导入random模块
import random
# 获取从1到100000之间的随机数
random_number = random.randint(1, 1000000)
# 执行input方法获取用户的输入,input的返回值为字符串类型,通过int()将其转换为整型
guess_number = int(input("Please enter the number:____\\b\\b\\b\\b"))
参考源码
import time
import random
def get_random_number(start=0, end=10**3):
return random.randint(start, end)
def countdown(seconds=3, message=""):
"""
:param seconds: 倒数的秒数
:param message: 倒计时结束后输出的提示信息
:return:
"""
for _ in range(seconds, 0, -1):
_, _ = print(_), time.sleep(1)
else:
print(message)
def serve_forever():
random_number = get_random_number()
countdown(message="猜数字游戏开始,Go!!!")
while True:
try:
guess_number = int(input("请输入你猜的数字:"+"_"*4+"\\b"*4))
except ValueError:
print("请输入合法的数字!")
continue
if guess_number != random_number:
_ = print("你输入的数字大了") if guess_number > random_number else print("你输入的数字小了")
continue
print("恭喜你猜对了!!!")
if input("按键盘任意键继续玩猜数字游戏或输入quit退出游戏:____\\b\\b\\b\\b").lower() == "quit":
break
else:
random_number = get_random_number()
print("游戏已被终止,再见!!!")
if __name__ == "__main__":
serve_forever()
程序的输出界面
2.2 进阶的猜姓名游戏
项目要求
定义一个人名集合,例如 {“王祖贤”, “李嘉欣”, “李嘉诚”, “刘德华”, “叶倩文”,“叶倩倩”, “王李丹妮”}。如果用户的输入前缀匹配第一个字,则提示"不错,有点接近了",前缀匹配前面两个字,则提示"厉害,比较接近了",完全匹配则提示"哇塞,你是个猜姓名天才,请收下我的膝盖"。
构造该Trie结构的算法逻辑很简单,以第一次构造为例:
将姓名中的第一个字作为键插入到指针指向的空字典中,键值为一个空字典,然后将指针指向键值所对应的空字典,接着将姓名中的第二个字作为键插入到指针指向的空字典中,键值为一个空字典,同样需要将指针指向键值所对应的空字典,不断重复这样的过程,直到遍历完姓名中的所有字符。
简化的代码实例:
name = "王八蛋"
trie = {}
trie[name[0]] = {}
trie[name[0]][name[1]] = {}
trie[name[0]][name[1]][name[2]] = {}
这样在查找用户的输入是否包含某姓名的前缀时,只需要遍历用户输入的字符,然后在构造好的Trie结构中进行查找。
参考源码
import time
def countdown(seconds=3, message=""):
"""
:param seconds: 倒数的秒数
:param message: 倒计时结束后输出的提示信息
:return:
"""
for _ in range(seconds, 0, -1):
_, _ = print(_), time.sleep(1)
else:
print(message)
def build_lookup_table(data):
"""
:param data: a set of names, e.g: {"王祖贤", "李嘉欣"}
:return: lookup table e.g:{'王': {'祖': {'贤': {}}}, '李': {'嘉': {'欣': {}}}}
"""
lookup_table = {}
for name in data:
lookup_table_ = lookup_table
for char in name:
if char not in lookup_table_:
lookup_table_[char] = {}
lookup_table_ = lookup_table_[char]
return lookup_table
def guess_name():
stars = {"王祖贤", "李嘉欣", "李嘉诚", "刘德华", "叶倩文", "叶倩倩", "王李丹妮"}
# 构造一个查找表
lookup_table = build_lookup_table(stars)
countdown(3, "猜姓名游戏开始,Go!!!")
messages = {0: "不要瞎猜好吗?", 1: "不错,有点接近了", 2: "厉害,比较接近了",
66: "哇塞,你是个猜姓名天才,请收下我的膝盖"}
end = 2
while True:
name = input("请输入你要猜的姓名:____\\b\\b\\b\\b")
if name in stars:
print(messages[66])
if input("按键盘任意键继续玩猜数字游戏或输入quit退出游戏:____\\b\\b\\b\\b").lower() == "quit":
break
else:
lookup_table_ = lookup_table
index = 0
for word in name:
if word in lookup_table_:
lookup_table_ = lookup_table_[word]
index = index+1 if index < end else index
else:
break
print(messages[index])
if __name__ == "__main__":
guess_name()
程序的输出界面
2.3基于英文分词的猜单词游戏
项目要求
① 对某一篇英文文章进行分词,以获取一个英语词典
② 如果用户输入的单词在词典中,则提示"你是个猜单词天才,请收下我的膝盖"
③ 如果用户的输入前缀匹配第一个字母,则提示"不错,有点接近了",前缀匹配前面两个字母,则提示"厉害,比较接近了"
算法逻辑如下:
① 定义一个布尔类型的标记变量,初始情况下为True,表示已完成单词的拆分
② 遍历英文字符串,如果当前字符为分隔符且尚未切分,则开始分词:将起始位置的索引与分隔符位置之前的所有字符进行拆分
③ 如果当前字符不是分隔符且已拆分,则将标记变量更新为False, 同时更新拆分的起始位置
参考源码
import time
def cut(content, language=0):
""以上是关于敬初学者Python基础学完了,该怎么知道自己学的怎么样呢?十个经典实战小项目附源码的主要内容,如果未能解决你的问题,请参考以下文章