DND掷骰器
掷骰表达式
在DND游戏中,常用“掷骰表示法”(Dice Notation)来表示随机数,如:
- “1d6”:表示掷一次6面骰子
- “2d8”:表示掷两次8面骰子
- “1d6+10”:表示掷一次6面骰子,并在结果上加常数10
- “2d6+1d20”:表示掷两次6面骰子和一次20面骰子
关于掷骰器的一些思考:
- 掷骰是为了体现现实世界中的随机性
- 假设我们用数值来表示战士的长剑伤害,当他是个新人的时候,可能是从1d4开始,逐步到1d6/1d8,然后随着他的熟练程度增加,开始增加固定保底伤害数值,如5+1d6,9+1d6
- 为何要一直保留随机性呢?因为对敌人造成的伤害不仅取决于你的武器和熟练程度,还取决于敌人的应对
- 而一把菜刀,其伤害可能是1d4,对应不小心切到手指还是砍在敌人的头上。而一把制造精良的长剑,其伤害可能是1d20,对应擦过敌人到把敌人捅个透心凉。
- 显然的,我们利用掷骰表达式可以相对客观的来表示各类技能和装备的特性
代码
下列源代码内含2个函数,一个是掷骰子,另一个是拆解表达式并组合骰子结果:
from random import randint
def dice(CMD='1d6'):
result = 0
if CMD.find('d')==-1:
result = int(CMD)
else:
list_cmd = CMD.split('d')
for _ in range(int(list_cmd[0])):
result += randint(1,int(list_cmd[1]))
return result
def dice_expression(CMD='1d6'):
result = 0
list_cmd = CMD.split('+')
for i in list_cmd:
a = dice(i)
print(a)
result += a
return result
if __name__ == '__main__':
CMD = '1d6+1d20+10'
print('掷骰结果:',dice_expression(CMD))
加上GUI后的成品软件
from random import randint
import tkinter as tk
# 函数
def dice(CMD='1d6',results=[]):
'''掷骰,多次掷同一种骰子,或保持常量'''
result = 0
if CMD.find('d')==-1:
# 处理常数
result = int(CMD)
results.append(result)
else:
# 处理掷骰式
list_cmd = CMD.split('d')
for _ in range(int(list_cmd[0])):
num = randint(1,int(list_cmd[1]))
result += num
results.append(num)
return result,results
def dice_expression(CMD='1d6'):
'''掷骰表达式,参考DND规则,用+号隔开'''
result = 0
results = []
list_cmd = CMD.split('+')
for i in list_cmd:
num,nums = dice(i,results)
result += num
# 因为results既是自变量又是因变量,所以无需额外加总
return result,results
# GUI配置
def GUI_ini():
# 初始化窗口
win = tk.Tk()
win.title('DND Roller')
win.geometry('400x300') # 注意此处为小写字母x
# 容器变量
pad_x = 2
pad_y = 2
# 容器设置
frame_0 = tk.Frame(win)
frame_1 = tk.Frame(frame_0)
frame_2 = tk.Frame(frame_0)
frame_3 = tk.Frame(frame_0)
frame_4 = tk.Frame(frame_0)
# 容器摆放
frame_0.pack(padx=pad_x,pady=pad_y,expand=True,fill='both')
frame_1.pack(padx=pad_x,pady=pad_y,fill='x')
frame_2.pack(padx=pad_x,pady=pad_y,fill='x')
frame_3.pack(padx=pad_x,pady=pad_y,fill='x')
frame_4.pack(padx=pad_x,pady=pad_y,fill='x')
# 创建变量
varbox = []
varbox.append(tk.Variable())
varbox.append(tk.Variable())
varbox.append(tk.Variable())
# 变量初始化
varbox[0].set('2d6+1d20+10')
varbox[1].set('')
varbox[2].set('')
# 动作
def on_click(event=0):
result,results = dice_expression(varbox[0].get())
varbox[1].set(result)
varbox[2].set(f'{results}')
# 控件设置
label_1 = tk.Label(frame_1,background='lightgrey',text='DND掷骰器',height=2)
label_2 = tk.Label(frame_2,background='lightgrey',text='表达式',width=10,height=2)
label_3 = tk.Label(frame_3,background='lightgrey',text='结果',width=10,height=2)
label_4 = tk.Label(frame_4,background='lightgrey',text='列表',width=10,height=2)
entry_1 = tk.Entry(frame_2,textvariable=varbox[0])
entry_2 = tk.Entry(frame_3,textvariable=varbox[1])
entry_3 = tk.Entry(frame_4,textvariable=varbox[2])
button_1 = tk.Button(frame_2,text='掷骰 Enter',command=on_click,width=10)
# 控件摆放
label_1.pack(fill='x')
label_2.pack(side='left',fill='y')
button_1.pack(side='right',fill='y')
entry_1.pack(side='left',fill='both',expand=True)
label_3.pack(side='left',fill='y')
entry_2.pack(side='left',fill='both',expand=True)
label_4.pack(side='left',fill='y')
entry_3.pack(side='left',fill='both',expand=True)
# 绑定键盘事件
win.bind('<KeyRelease-Return>',on_click)
# 返还win对象
return win
# 启动循环
GUI_ini().mainloop()