偶然看到一段很有意思的代码,模拟武侠小说中两派的遭遇战,拿来和大家分享一下。
原文出自:https://blog.csdn.net/yutu75/article/details/109035351
效果展示:
先看一下效果:
场景设置:
两个互为仇敌的派系偶然相见分外眼红,开始战斗,因为只是偶然遇见并没有提前预知,所以每个帮派人数不确定。战斗采用回合制的方式进行,比如少林派阵营的一个人随机选择逍遥派阵营的一个人进行攻击,逍遥派阵营被选择的这个人所受到的伤害值即为攻击他的人随机选择的技能输出值加上20%标准正态分布生成的随机数值(具体后面再说),结束一次攻击后开始下一会合,即逍遥派阵营的一个人随机选择少林派阵营的一个人进行攻击,计算方式同前面的形式一致,以此类推,直到其中某一门派参与战斗的所有人都阵亡(即血量HP=0)则战斗结束。
程序解析:
首先,我们需要编写一个叫做“武林人士”的父类,两派人(自己命名)均继承自武林人士这个父类,但有各个门派都有各自的技能包及对应的输出值(面向对象继承概念)。参与战斗的每个人都有名字、血量(HP) 、一系列技能及技能对应的攻击输出值,所有人的攻击方式一致,即随机从自己的技能包中抽取一个技能进行攻击,门派下每个人拥有的技能包都是在实例化对象的时候随机赋予的。
开始遭遇战的时候,每个帮派的人数不确定,战斗采用回合制的方式进行,即帮派A中的一个人随机选择帮派B中的一个人进行攻击,B受到的伤害值为A随机选择的技能的输出值加上20%的标准正态分布生成的随机数向下取整,即伤害值=输出值(1+0.2*N( 0,1)),技能被选择的概率和其对应的输出值成反比,如某人拥有两个技能,输出值分别为10、30,则技能1的被选择概率为 (1/10)/(1/10 + 1/30)。其中某一门派参与战斗的所有人都则阵亡(既HP降为0)则战斗结束。
几个随机数生成函数:
首先引入random包, import random; random.random()生成一个0-1的均匀分布随机数; random.randint(a,b)生成取值范围为[a.b]的随机整数。
代码展示:
import random # 导入库
import numpy as np
import math
from matplotlib import pyplot as plt
shaolin = {"玄难": 135, "玄寂": 132, "玄奘": 136, "玄苦": 137, "玄渡": 131} # 人 及其 HP
carefree = {"康广陵": 91, "范百龄": 93, "薛慕华": 108} # 人 及其 HP
s_skill = {"大金刚掌": 20, "如来千手": 30, "擒龙功": 25, "金刚指": 30, "少林长拳": 35} # 技能及其输出值
c_skill = {"小无相功": 20, "天山折梅手": 30, "八荒六合唯我独尊功": 25, "天上六阳掌": 30} # 技能及其输出值
d_sname = {}
d_cname = {}
s_suiji = {}
c_suiji = {}
class Wulinpeople():
def __init__(self):
self.s_name = random.sample(list(s_skill), random.randrange(1, len(s_skill) + 1))
self.c_name = random.sample(list(c_skill), random.randrange(1, len(c_skill) + 1))
def Shaolin_Temple(self):
s_name = random.sample(list(shaolin), 1)[0] # 随机选取攻击方的人物
s_hp = shaolin[s_name] # 随机选取攻击方人物的hp
c_name = random.sample(list(carefree), 1)[0] # 随机选取被攻击方的人物
c_hp = carefree[c_name] # 随机选取被攻击方人物的hp
pt = d_sname[s_name] # 随机分配的技能包
qwq = random.random()
for x in pt: # 随机分配的技能包的输出值
s_suiji[x] = s_skill[x]
a = list(s_suiji.values())
c = 0
key = 0
s_kill_name = "" # 定义随机技能名的变量
for i in s_suiji:
i_1 = s_skill[i]
b = 0
for j in a:
b += 1 / j
key += 1 / i_1 / b
# print("c的值:{} key的值{}".format(c,key))
if c < qwq < key:
s_kill_name = i # 根据输出值成反比的概率 分配的技能名
# print('随机值:{},技能名:{},技能输出值{}'.format(qwq,i,i_1))
c = key
# s_kill_name = random.sample(pt, 1)[0] # 随机分配的技能
s_kill_hp = int(s_skill[s_kill_name]) # 随机分配的技能输出值
random3 = np.random.randn() # 随机生成1个服从正态分布的随机数
hurt = math.floor(s_kill_hp * (1 + 0.2 * random3)) # 向下取整的伤害值
# print("伤害是{:0.1f}".format(hurt))
print("少林僧人{}使出了一招伤害为{}的{}".format(s_name, s_kill_hp, s_kill_name))
c_kill_hp = c_hp - hurt
if c_kill_hp <= 0:
del carefree[c_name] # 删除键 'shaolin'
print("逍遥派{}受到{}点伤害,剩余HP{}".format(c_name, hurt, 0))
print("逍遥派{}阵亡!!!!".format(c_name))
else:
carefree[c_name] = c_kill_hp
print("逍遥派{}受到{}点伤害,剩余HP{}".format(c_name, hurt, c_kill_hp))
def Carefree(self):
c_name = random.sample(list(carefree), 1)[0] # 随机选取攻击方的人物
c_hp = carefree[c_name] # 随机选取攻击方人物的hp
s_name = random.sample(list(shaolin), 1)[0] # 随机选取被攻击方的人物
s_hp = shaolin[s_name] # 随机选取被攻击方人物的hp
pt = d_sname[c_name] # 随机分配的技能包
qwq = random.random()
for x in pt: # 随机分配的技能包的输出值
c_suiji[x] = c_skill[x]
a = list(c_suiji.values())
c = 0
key = 0
c_kill_name = "" # 定义随机技能名的变量
for i in c_suiji:
i_1 = c_skill[i]
b = 0
for j in a:
b += 1 / j
key += 1 / i_1 / b
# print("c的值:{} key的值{}".format(c,key))
if c < qwq < key:
c_kill_name = i # 根据输出值成反比的概率 分配的技能名
# print('随机值:{},技能名:{},技能输出值{}'.format(qwq,i,i_1))
c = key
# s_kill_name = random.sample(pt, 1)[0] # 随机分配的技能
c_kill_hp = int(c_skill[c_kill_name]) # 随机分配的技能输出值
random3 = np.random.randn() # 随机生成1个服从正态分布的随机数
hurt = math.floor(c_kill_hp * (1 + 0.2 * random3)) # 向下取整的伤害值
# print("伤害是{:0.1f}".format(hurt))
print("逍遥派{}使出了一招伤害为{}的{}".format(c_name, c_kill_hp, c_kill_name))
s_kill_hp = s_hp - hurt
if s_kill_hp <= 0:
del shaolin[s_name] # 删除键 'shaolin'
print("少林僧人{}受到{}点伤害,剩余HP{}".format(s_name, hurt, 0))
print("少林僧人{}阵亡!!!!".format(s_name))
else:
shaolin[s_name] = s_kill_hp
print("少林僧人{}受到{}点伤害,剩余HP{}".format(s_name, hurt, s_kill_hp))
pass
def Battle():
sign = True
while sign:
# 少林寺
Wulinpeople.Shaolin_Temple(Wulinpeople)
if not shaolin or not carefree: # 判断双方是否完全阵亡
if shaolin:
print("战斗结束,少林寺获胜!留在战场的是:")
for i in shaolin:
print("少林僧人{}剩余血量{}".format(i, shaolin[i]))
sign = False
else:
print("战斗结束,逍遥派获胜!留在战场的是:")
for i in carefree:
print("逍遥派人{}剩余血量{}".format(i, carefree[i]))
sign = False
if not sign: # 结束程序
break
# 逍遥派
Wulinpeople.Carefree(Wulinpeople)
def main():
print("战斗开始了!出场人物是:")
for i in range(len(shaolin) + len(carefree)):
a = Wulinpeople()
if i < len(shaolin):
kill = ",".join(a.s_name)
d_sname[list(shaolin)[i]] = a.s_name
print("少林寺的少林僧人{},HP{},招数为{}"
.format(list(shaolin)[i], shaolin[list(shaolin)[i]], kill))
else:
i = i - len(shaolin)
kill = ",".join(a.c_name)
d_sname[list(carefree)[i]] = a.c_name
print("逍遥派的逍遥派{},HP{},招数为{}"
.format(list(carefree)[i], carefree[list(carefree)[i]], kill))
Battle()
main()
# 1)生成随机数
rdm = np.random.randn(10000) # 随机生成10000个服从正态分布的随机数
# 2)结果验证
import seaborn as sns # 使用seaborn 库画直方图验证结果
sns.set_palette("hls") # 设置所有图的颜色,使用hls色彩空间
sns.distplot(rdm, color="r", bins=1000, kde=True) # 绘制直方图,color设置颜色,bins设置直方图的划分数
plt.show()
验证随机数:
代码最后一部分是生成了一张直方图来验证所生成的随机数是否服从正态分布,运行结果如下:
可看到随机数所呈现的中间高、两边低的钟型曲线服从标准正态分布。
以上为本文全部内容,全篇代码融合了Python基础部分多种知识,非常适合初学者在学完基础部分语法之后的实践练习,给作者的创意点赞!