假设我正在尝试用Python制作BattleShip游戏。 我有一个名为board的列表列表。板中的每个列表都是板的那一行中的空格列表,对于这个例子,它将是5x5:
[['clear', 'clear', 'clear', 'clear', 'clear'],
['clear', 'clear', 'clear', 'clear', 'clear'],
['clear', 'clear', 'clear', 'clear', 'clear'],
['clear', 'clear', 'clear', 'clear', 'clear'],
['clear', 'clear', 'clear', 'clear', 'clear']]
我想创建一个函数来在板中返回一个随机的空白区域。
def pl_point(board):
place = [randrange(0,5),randrange(0,5)] #heh, found out these aren't inclusive.
if board[place[0]][place[1]] == "clear": return place
else:
return pl_point() #calls itself until a clear place is found
以下是我的问题:在获得所需的值之前,让函数调用本身是否效率低(即使电路板几乎完全填满)?我有更好的方法来做这件事吗?
我无法弄清楚如何使用while语句,因为语句在分配之前总是会引用'place',而我想不出任何不引用out的地方的值 - 范围或未指定的“董事会”价值。
如果这是一个重复的主题,我很抱歉,我试图找到一个类似的但不能。这也是我第一次使用这个网站提问而不是回答问题。
答案 0 :(得分:5)
在获得函数调用之前它是否效率低,直到获得它想要的值(即使电路板几乎完全填满)?我有更好的方法来做这件事吗?
是的,是的。但问题并不是效率低下,而是如果你不幸需要尝试1000次,你的程序就会因递归错误而失败。
我无法弄清楚如何使用while语句,因为语句在分配之前总是会引用'place',而我想不出任何不引用out的地方的值 - 范围或未指定的“董事会”价值。
只需使用while True:
,您就可以break
或return
退出循环:
while True:
place = [randrange(0,4),randrange(0,4)] #randrange is inclusive
if board[place[0]][place[1]] == "clear":
return place
作为旁注,正如检查员G4dget在评论中指出的那样,randrange
不包含在内;这只会返回数字0
,1
,2
和3
。
此外,将x和y坐标放入列表只是为了让您可以反复使用[0]
和[1]
,这会让事情变得更难以阅读。只需使用x, y = [randrange(5), randrange(5)]
(也可以修复其他问题),然后使用board[x][y]
和return x, y
。
如果这个太慢,那么是的,有更好的方法来做到这一点。首先列出所有清空槽,然后随机选择一个:
clearslots = [(x, y) for x in range(5) for y in range(5) if board[x][y] == "clear"]
return random.choice(clearslots)
当电路板大部分为空时,这可能会慢一些,但随着电路板的填满,它不会变得更糟。此外,与您的方法不同,它保证了最坏情况下的恒定时间;这不是不可能的常规需要多年,这是不可能的。
如果您不理解列表理解,请让我更明确地写出来:
clearslots = []
for x in range(5):
for y in range(5):
if board[x][y] == "clear":
clearslots.append((x, y))
答案 1 :(得分:1)
当然有更好的方法。试试这个:
def pl_point(board):
for y,row in enumerate(board):
for x,col in row:
if col == 'clear':
return (x,y)
它有必要是随机的吗?如果是的话......
def pl_point_random(board):
places = {(x,y) for x in range(len(board)) for y in range(len(board[0]))}
# the above is a set comprehension of every spot on the board
# (assuming the board is rectangular...)
while True:
point = random.choice(places)
# choose a random spot in places
x,y = point
if board[x][y] != 'clear':
return point
else:
places.remove(point)
甚至更好:
def pl_point_random_v2(board):
places = [(x,y) for y,row in enumerate(board) for x,col in rows if col=='clear']
return random.choice(places)
答案 2 :(得分:0)
生成器是一个非常好的Pythonic工具,可以让您解决问题。基本上你想要查看一组随机的空格,一次返回一个项目,对吗?
您创建一个函数,首先获取所有空格的单个列表,就像已经提供的一些答案一样,并从该列表中返回一个随机选择。但是,通过在您创建的函数上调用next(),您可以根据需要继续选择。
import random
def board_randomizer():
clear_spaces = [...] # list comprehension or your method of choosing
while clear_spaces:
coord = random.choice(clear_spaces)
clear_spaces.remove(coord)
yield coord # returns a random location, one item at a time
clear_positions = board_randomizer() # initialize a generator
# keeps picking random locations until a StopIteration error is raised
clear_positions.next()
clear_positions.next()