python中的自调用函数

时间:2014-08-15 01:10:41

标签: python python-2.7

假设我正在尝试用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的地方的值 - 范围或未指定的“董事会”价值。

如果这是一个重复的主题,我很抱歉,我试图找到一个类似的但不能。这也是我第一次使用这个网站提问而不是回答问题。

3 个答案:

答案 0 :(得分:5)

  

在获得函数调用之前它是否效率低,直到获得它想要的值(即使电路板几乎完全填满)?我有更好的方法来做这件事吗?

是的,是的。但问题并不是效率低下,而是如果你不幸需要尝试1000次,你的程序就会因递归错误而失败。

  

我无法弄清楚如何使用while语句,因为语句在分配之前总是会引用'place',而我想不出任何不引用out的地方的值 - 范围或未指定的“董事会”价值。

只需使用while True:,您就可以breakreturn退出循环:

while True:
    place = [randrange(0,4),randrange(0,4)] #randrange is inclusive
    if board[place[0]][place[1]] == "clear":
        return place

作为旁注,正如检查员G4dget在评论中指出的那样,randrange 包含在内;这只会返回数字0123

此外,将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()