Python 中的双骰图形
Double dice graphics in Python
我是编程新手,在我的项目中,我正在尝试打印基本的骰子图形。
我正在尝试制作一个函数,它接受从 1 到 6 的两个数字,并打印相应的两个相邻的骰子面。我尝试了几种方法,但这是唯一有效的方法,而且它很笨拙:
s="+ - - - - + + - - - - +"
m1="| o o |"
m2="| o |"
m3="| o |"
m4="| o |"
m5="| |"
def dice(a,b):
if a == 1:
str1=m5
str2=m3
str3=m5
elif a == 2:
str1=m2
str2=m5
str3=m4
elif a == 3:
str1=m2
str2=m3
str3=m4
elif a == 4:
str1=m1
str2=m5
str3=m1
elif a == 5:
str1=m1
str2=m3
str3=m1
elif a == 6:
str1=m1
str2=m1
str3=m1
if b == 1:
str1=str1+" "+m5
str2=str2+" "+m3
str3=str3+" "+m5
elif b == 2:
str1=str1+" "+m2
str2=str2+" "+m5
str3=str3+" "+m4
elif b == 3:
str1=str1+" "+m2
str2=str2+" "+m3
str3=str3+" "+m4
elif b == 4:
str1=str1+" "+m1
str2=str2+" "+m5
str3=str3+" "+m1
elif b == 5:
str1=str1+" "+m1
str2=str2+" "+m3
str3=str3+" "+m1
elif b == 6:
str1=str1+" "+m1
str2=str2+" "+m1
str3=str3+" "+m1
print(s)
print(str1)
print(str2)
print(str3)
print(s)
有没有更简洁优雅的方式来做到这一点?
你的尝试已经展示了一些好的部分:找到共同的部分,并将它们存储在单独的变量中。
但我们可以通过实现一个 单个 函数来生成 一个 骰子来做得更好。例如:
s ="+ - - - - +"
m1="| o o |"
m2="| o |"
m3="| o |"
m4="| o |"
m5="| |"
dice = [
[m5, m3, m5],
[m2, m5, m4],
[m2, m3, m4],
[m1, m5, m1],
[m1, m3, m1],
[m1, m1, m1]
]
所以现在我们可以为 one 创建一个函数:
def die(i):
return [s, *dice[i-1], s]
对于范围内给定的 i
,这将是一个包含三个字符串的列表 return。
然后我们可以创建将行连接在一起的函数,例如:
def join_row(*rows):
return [' '.join(r) for r in zip(*rows)]
所以现在对于两个骰子,我们可以定义一个函数:
def twodice(a, b):
for line in join_row(die(a), die(b)):
print(line)
好消息是我们可以将此概括为任意数量的骰子,例如:
def ndice(*ns):
for line in join_row(*map(die, ns)):
print(line)
例如:
>>> ndice(3, 2, 5, 1)
+ - - - - + + - - - - + + - - - - + + - - - - +
| o | | o | | o o | | |
| o | | | | o | | o |
| o | | o | | o o | | |
+ - - - - + + - - - - + + - - - - + + - - - - +
>>> ndice(1)
+ - - - - +
| |
| o |
| |
+ - - - - +
>>> ndice(1, 4)
+ - - - - + + - - - - +
| | | o o |
| o | | |
| | | o o |
+ - - - - + + - - - - +
>>> ndice(1, 4, 2)
+ - - - - + + - - - - + + - - - - +
| | | o o | | o |
| o | | | | |
| | | o o | | o |
+ - - - - + + - - - - + + - - - - +
>>> ndice(1, 4, 2, 5)
+ - - - - + + - - - - + + - - - - + + - - - - +
| | | o o | | o | | o o |
| o | | | | | | o |
| | | o o | | o | | o o |
+ - - - - + + - - - - + + - - - - + + - - - - +
这种方法的一个好处是,您可以获得很多 实用函数 ,您可以将它们重复用于类似的问题。此外,每个函数都做一些简单的事情,因此其中一个函数出现大问题的几率相当 "low"。如果出现问题,通常很容易解决这些问题。
您可以将所有骰子的字符串表示形式写成字典,键从 1 到 6。作为值,您可以使用字符串列表来组成骰子。
打印时,根据键从每组值中选择行。
关于如何创建字典,方法可以像您在那里采用的方法,但它是一次创建的,没有所有 if
s -
s= "+ - - - - +"
m1="| o o |"
m2="| o |"
m3="| o |"
m4="| o |"
m5="| |"
die = {
1: [s, m5, m3, m5, s],
2: ...,
...
6: [s, m2, m2, m2, s]
}
def print_dice(a, b):
for part1, part2 in zip(die[a], die[b)):
print (part1, part2)
zip
负责给定两个或多个序列或迭代器,从每个序列或迭代器中选择一个元素,并为每个元素生成一个元组。打印函数本身可以打印骰子的两个部分。
如果你想要任意数量的两个骰子,你只需要在 Python 中使用“*”语法,它在函数参数、zip 调用中都有效,并调用打印:
def print_n_dice(*args):
for parts in zip(*(die[x] for x in args)):
print(*parts)
这是主题的另一个变体。我将面部图案编码为数字字符串。
rows = (
"+ - - - - +",
"| o o |",
"| o |",
"| o |",
"| o |",
"| |",
)
faces = ['555', '535', '254', '234', '151', '131', '111']
def dice(n):
out = [rows[0]]
for u in faces[n]:
out.append(rows[int(u)])
out.append(rows[0])
return out
def multi_dice(*nums):
buf = [[] for _ in range(5)]
for row, seg in zip(buf, zip(*[dice(n) for n in nums])):
row.extend(seg)
return '\n'.join(map(' '.join, buf))
# Test showing all 6 faces
print(multi_dice(1, 2, 3, 4, 5, 6))
输出
+ - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - +
| | | o | | o | | o o | | o o | | o o |
| o | | | | o | | | | o | | o o |
| | | o | | o | | o o | | o o | | o o |
+ - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - +
我们可以使用列表理解将 dice
函数减少到一行:
def dice(n):
return [rows[0]] + [rows[int(u)] for u in faces[n]] + [rows[0]]
作为奖励,如果你将 n=0 传递给 dice
,你会得到一张空白的脸。
虽然你可以做一些非常奇特的事情,但对于这样一个相对简单的情况,使用一些硬编码数据可能会很好(并且改变它们的外观也很容易做到):
DICE_DATA = """\
+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +
| |,| o |,| o |,| o o |,| o o |,| o o |
| o |,| |,| o |,| |,| o |,| o o |
| |,| o |,| o |,| o o |,| o o |,| o o |
+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +
"""
faces = [[] for _ in range(6)]
for line in DICE_DATA.splitlines():
for i, section in enumerate(line.split(',')):
faces[i].append(section)
for face in faces:
print('\n'.join(face)) # Print a single face.
输出:
+ - - - - +
| |
| o |
| |
+ - - - - +
+ - - - - +
| o |
| |
| o |
+ - - - - +
+ - - - - +
| o |
| o |
| o |
+ - - - - +
+ - - - - +
| o o |
| |
| o o |
+ - - - - +
+ - - - - +
| o o |
| o |
| o o |
+ - - - - +
+ - - - - +
| o o |
| o o |
| o o |
+ - - - - +
不要尝试同时生成两个骰子的线条; Python 字符串处理足够强大,可以将两个行块连接在一起,使它们并排工作。专注于高效地生成骰子面。
您不需要在骰子中生成每一行。骰子是对称的;下半部分是上半部分的旋转。您可以纯粹通过一些布尔测试来创建一半,以决定是一只眼睛还是一只眼睛;这是当三只眼睛在一半(忽略中间的眼睛)时的骰子值 on:
+ - - - - - - - - - - +
| {2,3,4,5,6} {4,5,6} |
|
| {6}
中眼是奇数的时候。因此,您可以分别用 value > 1
、value > 3
和 value > 5
来确定是否存在眼睛。
下面的版本生成这样一个没有中心眼的一半,然后将两半组合起来('rotating'后半部分通过反转字符串),并在它们之间插入中间眼:
def ascii_dice(v, e=' o'):
half = f'+ - - - - +\n| {e[v > 1]} {e[v > 3]} |\n| {e[v > 5]} '
return f'{half}{e[v & 1]}{half[::-1]}'
这会根据需要生成 6 个骰子面中的任何一个:
>>> for i in range(1, 7):
... print(ascii_dice(i))
...
+ - - - - +
| |
| o |
| |
+ - - - - +
+ - - - - +
| o |
| |
| o |
+ - - - - +
+ - - - - +
| o |
| o |
| o |
+ - - - - +
+ - - - - +
| o o |
| |
| o o |
+ - - - - +
+ - - - - +
| o o |
| o |
| o o |
+ - - - - +
+ - - - - +
| o o |
| o o |
| o o |
+ - - - - +
接下来,将多个骰子并排组合,简单来说就是拆分多个线块,并将每个块的线分组的功能;所有第一行放在一起,第二行放在一起,依此类推,然后用 space 重新加入它们。这是 zip()
和 str.join()
非常擅长的工作;以下函数可以连续生成任意数量的骰子:
def multi_dice(*d, sep=' '):
zipped = zip(*(ascii_dice(v).splitlines() for v in d))
return '\n'.join([sep.join(l) for l in zipped])
zip(*(...))
函数在这里完成所有工作,它将每个骰子面的线(作为不带换行符的字符串列表)作为单独的参数传递,并完成第一行的所有配对,第二行等。然后我们将骰子面的这些部分与 sep
变量(默认情况下为 3 spaces)连接起来,并用换行符连接所有结果行。
现在您可以打印尽可能多的相邻骰子:
>>> print(multi_dice(*random.sample(range(1, 7), 6)))
+ - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - +
| o | | o o | | o o | | o | | | | o o |
| | | o o | | o | | o | | o | | |
| o | | o o | | o o | | o | | | | o o |
+ - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - +
对于您的用例,只需传入 2 个骰子值,然后打印函数 returns:
>>> print(multi_dice(4, 5))
+ - - - - + + - - - - +
| o o | | o o |
| | | o |
| o o | | o o |
+ - - - - + + - - - - +
这是一种绝对更紧凑的方法:
print("\u2680\u2681\u2682\u2683\u2684\u2685")
打印:
⚀⚁⚂⚃⚄⚅
已经有 Unicode 符号了!只需将它们保存在一个字符串中,当要求给出第 i
个骰子时,return 第 i-1
个字符:
def die(i):
return "\u2680\u2681\u2682\u2683\u2684\u2685"[i - 1]
def dice(i, j):
print(f"{die(i)}{die(j)}")
示例:
>>> dice(2, 3)
⚁⚂
我是编程新手,在我的项目中,我正在尝试打印基本的骰子图形。
我正在尝试制作一个函数,它接受从 1 到 6 的两个数字,并打印相应的两个相邻的骰子面。我尝试了几种方法,但这是唯一有效的方法,而且它很笨拙:
s="+ - - - - + + - - - - +"
m1="| o o |"
m2="| o |"
m3="| o |"
m4="| o |"
m5="| |"
def dice(a,b):
if a == 1:
str1=m5
str2=m3
str3=m5
elif a == 2:
str1=m2
str2=m5
str3=m4
elif a == 3:
str1=m2
str2=m3
str3=m4
elif a == 4:
str1=m1
str2=m5
str3=m1
elif a == 5:
str1=m1
str2=m3
str3=m1
elif a == 6:
str1=m1
str2=m1
str3=m1
if b == 1:
str1=str1+" "+m5
str2=str2+" "+m3
str3=str3+" "+m5
elif b == 2:
str1=str1+" "+m2
str2=str2+" "+m5
str3=str3+" "+m4
elif b == 3:
str1=str1+" "+m2
str2=str2+" "+m3
str3=str3+" "+m4
elif b == 4:
str1=str1+" "+m1
str2=str2+" "+m5
str3=str3+" "+m1
elif b == 5:
str1=str1+" "+m1
str2=str2+" "+m3
str3=str3+" "+m1
elif b == 6:
str1=str1+" "+m1
str2=str2+" "+m1
str3=str3+" "+m1
print(s)
print(str1)
print(str2)
print(str3)
print(s)
有没有更简洁优雅的方式来做到这一点?
你的尝试已经展示了一些好的部分:找到共同的部分,并将它们存储在单独的变量中。
但我们可以通过实现一个 单个 函数来生成 一个 骰子来做得更好。例如:
s ="+ - - - - +"
m1="| o o |"
m2="| o |"
m3="| o |"
m4="| o |"
m5="| |"
dice = [
[m5, m3, m5],
[m2, m5, m4],
[m2, m3, m4],
[m1, m5, m1],
[m1, m3, m1],
[m1, m1, m1]
]
所以现在我们可以为 one 创建一个函数:
def die(i):
return [s, *dice[i-1], s]
对于范围内给定的 i
,这将是一个包含三个字符串的列表 return。
然后我们可以创建将行连接在一起的函数,例如:
def join_row(*rows):
return [' '.join(r) for r in zip(*rows)]
所以现在对于两个骰子,我们可以定义一个函数:
def twodice(a, b):
for line in join_row(die(a), die(b)):
print(line)
好消息是我们可以将此概括为任意数量的骰子,例如:
def ndice(*ns):
for line in join_row(*map(die, ns)):
print(line)
例如:
>>> ndice(3, 2, 5, 1)
+ - - - - + + - - - - + + - - - - + + - - - - +
| o | | o | | o o | | |
| o | | | | o | | o |
| o | | o | | o o | | |
+ - - - - + + - - - - + + - - - - + + - - - - +
>>> ndice(1)
+ - - - - +
| |
| o |
| |
+ - - - - +
>>> ndice(1, 4)
+ - - - - + + - - - - +
| | | o o |
| o | | |
| | | o o |
+ - - - - + + - - - - +
>>> ndice(1, 4, 2)
+ - - - - + + - - - - + + - - - - +
| | | o o | | o |
| o | | | | |
| | | o o | | o |
+ - - - - + + - - - - + + - - - - +
>>> ndice(1, 4, 2, 5)
+ - - - - + + - - - - + + - - - - + + - - - - +
| | | o o | | o | | o o |
| o | | | | | | o |
| | | o o | | o | | o o |
+ - - - - + + - - - - + + - - - - + + - - - - +
这种方法的一个好处是,您可以获得很多 实用函数 ,您可以将它们重复用于类似的问题。此外,每个函数都做一些简单的事情,因此其中一个函数出现大问题的几率相当 "low"。如果出现问题,通常很容易解决这些问题。
您可以将所有骰子的字符串表示形式写成字典,键从 1 到 6。作为值,您可以使用字符串列表来组成骰子。
打印时,根据键从每组值中选择行。
关于如何创建字典,方法可以像您在那里采用的方法,但它是一次创建的,没有所有 if
s -
s= "+ - - - - +"
m1="| o o |"
m2="| o |"
m3="| o |"
m4="| o |"
m5="| |"
die = {
1: [s, m5, m3, m5, s],
2: ...,
...
6: [s, m2, m2, m2, s]
}
def print_dice(a, b):
for part1, part2 in zip(die[a], die[b)):
print (part1, part2)
zip
负责给定两个或多个序列或迭代器,从每个序列或迭代器中选择一个元素,并为每个元素生成一个元组。打印函数本身可以打印骰子的两个部分。
如果你想要任意数量的两个骰子,你只需要在 Python 中使用“*”语法,它在函数参数、zip 调用中都有效,并调用打印:
def print_n_dice(*args):
for parts in zip(*(die[x] for x in args)):
print(*parts)
这是主题的另一个变体。我将面部图案编码为数字字符串。
rows = (
"+ - - - - +",
"| o o |",
"| o |",
"| o |",
"| o |",
"| |",
)
faces = ['555', '535', '254', '234', '151', '131', '111']
def dice(n):
out = [rows[0]]
for u in faces[n]:
out.append(rows[int(u)])
out.append(rows[0])
return out
def multi_dice(*nums):
buf = [[] for _ in range(5)]
for row, seg in zip(buf, zip(*[dice(n) for n in nums])):
row.extend(seg)
return '\n'.join(map(' '.join, buf))
# Test showing all 6 faces
print(multi_dice(1, 2, 3, 4, 5, 6))
输出
+ - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - +
| | | o | | o | | o o | | o o | | o o |
| o | | | | o | | | | o | | o o |
| | | o | | o | | o o | | o o | | o o |
+ - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - +
我们可以使用列表理解将 dice
函数减少到一行:
def dice(n):
return [rows[0]] + [rows[int(u)] for u in faces[n]] + [rows[0]]
作为奖励,如果你将 n=0 传递给 dice
,你会得到一张空白的脸。
虽然你可以做一些非常奇特的事情,但对于这样一个相对简单的情况,使用一些硬编码数据可能会很好(并且改变它们的外观也很容易做到):
DICE_DATA = """\
+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +
| |,| o |,| o |,| o o |,| o o |,| o o |
| o |,| |,| o |,| |,| o |,| o o |
| |,| o |,| o |,| o o |,| o o |,| o o |
+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +,+ - - - - +
"""
faces = [[] for _ in range(6)]
for line in DICE_DATA.splitlines():
for i, section in enumerate(line.split(',')):
faces[i].append(section)
for face in faces:
print('\n'.join(face)) # Print a single face.
输出:
+ - - - - +
| |
| o |
| |
+ - - - - +
+ - - - - +
| o |
| |
| o |
+ - - - - +
+ - - - - +
| o |
| o |
| o |
+ - - - - +
+ - - - - +
| o o |
| |
| o o |
+ - - - - +
+ - - - - +
| o o |
| o |
| o o |
+ - - - - +
+ - - - - +
| o o |
| o o |
| o o |
+ - - - - +
不要尝试同时生成两个骰子的线条; Python 字符串处理足够强大,可以将两个行块连接在一起,使它们并排工作。专注于高效地生成骰子面。
您不需要在骰子中生成每一行。骰子是对称的;下半部分是上半部分的旋转。您可以纯粹通过一些布尔测试来创建一半,以决定是一只眼睛还是一只眼睛;这是当三只眼睛在一半(忽略中间的眼睛)时的骰子值 on:
+ - - - - - - - - - - +
| {2,3,4,5,6} {4,5,6} |
|
| {6}
中眼是奇数的时候。因此,您可以分别用 value > 1
、value > 3
和 value > 5
来确定是否存在眼睛。
下面的版本生成这样一个没有中心眼的一半,然后将两半组合起来('rotating'后半部分通过反转字符串),并在它们之间插入中间眼:
def ascii_dice(v, e=' o'):
half = f'+ - - - - +\n| {e[v > 1]} {e[v > 3]} |\n| {e[v > 5]} '
return f'{half}{e[v & 1]}{half[::-1]}'
这会根据需要生成 6 个骰子面中的任何一个:
>>> for i in range(1, 7):
... print(ascii_dice(i))
...
+ - - - - +
| |
| o |
| |
+ - - - - +
+ - - - - +
| o |
| |
| o |
+ - - - - +
+ - - - - +
| o |
| o |
| o |
+ - - - - +
+ - - - - +
| o o |
| |
| o o |
+ - - - - +
+ - - - - +
| o o |
| o |
| o o |
+ - - - - +
+ - - - - +
| o o |
| o o |
| o o |
+ - - - - +
接下来,将多个骰子并排组合,简单来说就是拆分多个线块,并将每个块的线分组的功能;所有第一行放在一起,第二行放在一起,依此类推,然后用 space 重新加入它们。这是 zip()
和 str.join()
非常擅长的工作;以下函数可以连续生成任意数量的骰子:
def multi_dice(*d, sep=' '):
zipped = zip(*(ascii_dice(v).splitlines() for v in d))
return '\n'.join([sep.join(l) for l in zipped])
zip(*(...))
函数在这里完成所有工作,它将每个骰子面的线(作为不带换行符的字符串列表)作为单独的参数传递,并完成第一行的所有配对,第二行等。然后我们将骰子面的这些部分与 sep
变量(默认情况下为 3 spaces)连接起来,并用换行符连接所有结果行。
现在您可以打印尽可能多的相邻骰子:
>>> print(multi_dice(*random.sample(range(1, 7), 6)))
+ - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - +
| o | | o o | | o o | | o | | | | o o |
| | | o o | | o | | o | | o | | |
| o | | o o | | o o | | o | | | | o o |
+ - - - - + + - - - - + + - - - - + + - - - - + + - - - - + + - - - - +
对于您的用例,只需传入 2 个骰子值,然后打印函数 returns:
>>> print(multi_dice(4, 5))
+ - - - - + + - - - - +
| o o | | o o |
| | | o |
| o o | | o o |
+ - - - - + + - - - - +
这是一种绝对更紧凑的方法:
print("\u2680\u2681\u2682\u2683\u2684\u2685")
打印:
⚀⚁⚂⚃⚄⚅
已经有 Unicode 符号了!只需将它们保存在一个字符串中,当要求给出第 i
个骰子时,return 第 i-1
个字符:
def die(i):
return "\u2680\u2681\u2682\u2683\u2684\u2685"[i - 1]
def dice(i, j):
print(f"{die(i)}{die(j)}")
示例:
>>> dice(2, 3)
⚁⚂