我在绞刑架附近见过几个问题。通常情况下,这是一种非常草率的方式,这通常不能进一步推广。我的想法或问题是关于礼服的创造,这是任何绞刑游戏的核心部分。
我想创建下面的ASCII图像
_____
| |
O |
/|\ |
/ \ |
|
---------- 每当提示函数时,棒形的一个“肢体”就会出现。
我也希望能够指定礼服的高度和宽度。然而,相对于礼服的尺寸,我无法缩放棍子的形状。下面提供了代码,我有两个关于它=的简单问题。
from math import ceil
def create_gown(width, height):
gown = []
gown.append('{:>{}s}'.format('_'*int(width/2), 10))
gown.append('{:>{}s} {:>{}s}'.format(
'|', 11 - int(width/2), '|', int(width/2)-2))
for i in range(height-3):
gown.append('{:^{}s}'.format('|', 20))
gown.append('{:^{}s}'.format('-'*width, 20))
return gown
def wrong_answer(gown, attempt=0):
height, width = len(gown), len(gown[-1].strip())
offset1 = int((-width+23)*0.5)+1
offset3 = int(ceil(0.5*(width-7)))
if attempt == 0:
return gown
elif attempt == 1:
new_line = '{:>{}s} {:>{}s}'.format('O', offset1-1, '|', offset3+1)
row = 2
elif attempt == 2:
new_line = '{:>{}s} {:>{}s}'.format('|', offset1-1, '|', offset3+1)
row = 3
elif attempt == 3:
new_line = '{:>{}s} {:>{}s}'.format('/| ', offset1, '|', offset3)
row = 3
elif attempt == 4:
new_line = '{:>{}s} {:>{}s}'.format('/|\\', offset1, '|', offset3)
row = 3
elif attempt == 5:
new_line = '{:>{}s} {:>{}s}'.format('/ ', offset1, '|', offset3)
row = 4
elif attempt == 6:
new_line = '{:>{}s} {:>{}s}'.format('/ \\', offset1, '|', offset3)
row = 4
else:
raise Exception("Ops! The number of attempts must be an integer from 0 to 6.")
gown[row] = new_line
return gown
def print_gown(gown):
for line in gown:
print line
if __name__ == '__main__':
gown = create_gown(10, 7)
print len(gown)
for i in range(7):
gown = wrong_answer(gown, i)
print_gown(gown)发布于 2016-06-07 13:22:33
所有的elif都有相同的结构。您只需要确保插入的模式总是3宽,并且可以删除偏移调整。逻辑的下一步是使用字典来存储每次尝试的模式和行:
_GOWN_MODIFIER = {
1: (' O ', 2),
2: (' | ', 3),
3: ('/| ', 3),
4: ('/|\\', 3),
5: ('/ ', 4),
6: ('/ \\', 4),
}
def wrong_answer(gown, attempt=0):
height, width = len(gown), len(gown[-1].strip())
offset1 = int((-width+23)*0.5)+1
offset3 = int(ceil(0.5*(width-7)))
if not attempt:
return gown
try:
pattern, row = _GOWN_MODIFIER[attempt]
except KeyError:
raise Exception("Ops! The number of attempts must be an integer from 0 to 6.")
else:
gown[row] = '{:>{}s} {:>{}s}'.format(pattern, offset1, '|', offset3)
return gown您不需要ceil或int来执行整数除法2。在Python2中,/已经是您需要的运算符。您还可以使用//,这也是相同的操作。与前者相比,后者的优点是在Python3中的行为是相同的,而/将在Python3中执行十进制除法。
_GOWN_MODIFIER = {
1: (' O ', 2),
2: (' | ', 3),
3: ('/| ', 3),
4: ('/|\\', 3),
5: ('/ ', 4),
6: ('/ \\', 4),
}
def wrong_answer(gown, attempt=0):
if not attempt:
return gown
height, width = len(gown), len(gown[-1].strip())
offset1 = (23 - width) // 2 + 1
offset3 = (width - 6) // 2
try:
pattern, row = _GOWN_MODIFIER[attempt]
except KeyError:
raise Exception("Ops! The number of attempts must be an integer from 0 to 6.")
else:
gown[row] = '{:>{}s} {:>{}s}'.format(pattern, offset1, '|', offset3)
return gown
def create_gown(width, height):
half_width = width // 2
gown = []
gown.append('{:>{}s}'.format('_'*half_width, 10))
gown.append('{:>{}s} {:>{}s}'.format(
'|', 11 - half_width, '|', half_width-2))
for i in range(height-3):
gown.append('{:^{}s}'.format('|', 20))
gown.append('{:^{}s}'.format('-'*width, 20))
return gown您知道可以使用seq(element) * count创建重复元素的序列。您可以使用它来创建gown变量,方法是重复极点,然后修改前两行和最后一行;由于存储列表所需的空间将一次分配给您,所以内存应该更友好:
def create_gown(width, height):
half_width = width // 2
gown = ['{:^{}s}'.format('|', 20)] * height
gown[0] = '{:>{}s}'.format('_' * half_width, 10)
gown[1] = '{:>{}s} {:>{}s}'.format(
'|', 11 - half_width, '|', half_width-2)
gown[-1] = '{:^{}s}'.format('-' * width, 20)
return gown修改位置并返回值
的事情
您的wrong_answer既修改了礼服的位置,又返回了修改后的值。这是不必要的,因为调用方仍然应该保存对值的引用(该值已被修改)。调用代码时,您可以拥有:
gown2 = wrong_answer(gown, attempt=3)但
>>> gown2 is gown
True因此,复制对同一个对象的引用是没有意义的。相反,您可以做的是对打印作业进行预处理,因此您实际上不需要print_gown函数:
def wrong_answer(gown, attempt=0):
height, width = len(gown), len(gown[-1].strip())
offset1 = (23 - width) // 2 + 1
offset3 = (width - 6) // 2
if attempt:
try:
pattern, row = _GOWN_MODIFIER[attempt]
except KeyError:
raise Exception("Ops! The number of attempts must be an integer from 0 to 6.")
else:
gown[row] = '{:>{}s} {:>{}s}'.format(pattern, offset1, '|', offset3)
return '\n'.join(gown)用法:
print(wrong_answer(gown, attempt=3))引发通用用途Exception是一种糟糕的做法,因为它使试图处理代码的except子句能够捕获比它们更多的代码。您至少应该使用更通用的异常(如ValueError)或定义您自己的异常:
class AlreadyHangedError(ValueError):
pass
def wrong_answer(gown, attempt):
...
raise AlreadyHangedError('...')
...但是,您使用wrong_answer的方式有一些奇怪之处:期望调用方使用增加的attempts来调用这个函数。这是发电机的工作。通过将wrong_answer转换为生成器,您可以调用它来创建生成器实例,然后在这个实例上调用next (或者让for循环为您完成),以获得要打印的下一个礼服:
def wrong_answer(width, height):
gown = create_gown(width, height)
offset1 = (23 - width) // 2 + 1
offset3 = (width - 6) // 2
yield '\n'.join(gown)
for attempt in range(1, 7):
pattern, row = _GOWN_MODIFIER[attempt]
gown[row] = '{:>{}s} {:>{}s}'.format(pattern, offset1, '|', offset3)
yield '\n'.join(gown)用法:
for gown in wrong_answer(10, 7):
print(gown)或者,在更真实的情况下:
def hangman_game():
for gown in wrong_answer(10, 7):
while True:
status = manage_user_input()
if status == 'FAILED': # Whatever
break
if status == 'COMPLETED': # Whatever
return
print gown
print 'You lose'create_gown似乎把礼服集中在20条线上,但如果width比那更大呢?首先,您应该定义这个值,并给它一个有意义的名称,对由此派生出来的所有值都是相同的;然后,您可能希望将max(20, width)作为微积分的基础。
https://codereview.stackexchange.com/questions/131314
复制相似问题