import random
twoDimMap = [["H", "-", "-", "-", "-", "-"], ["-", "-", "-", "-", "-", "-"],
["-", "-", "-", "-", "-", "-"], ["-", "-", "-", "-", "-", "-"],
["-", "-", "-", "-", "-", "-"], ["-", "-", "-", "-", "-", "-"]]
items = 0
while items <= 4:
test = random.randrange(0, 3)
if test == 0:
twoDimMap[random.randrange(0, 5)][random.randrange(0, 5)] = "S"
if test == 1:
twoDimMap[random.randrange(0, 5)][random.randrange(0, 5)] = "R"
if test == 2:
twoDimMap[random.randrange(0, 5)][random.randrange(0, 5)] = "*"
# I couldn't think of an easier way to do this
if twoDimMap[0][0] != "H":
twoDimMap[0][0] = "H"
items -= 1
items += 1
print(twoDimMap)
标题几乎解释了所有这一切(即使我知道它不是太描述性的:/),我正在尝试制作一款游戏,其中英雄在地图上的位置[0],[0]开始。我不知道为什么有时候我会比其他时候生成更少的项目。
编辑:感谢您的所有反馈,对于由于我的愚蠢错误:/浪费您的时间而感到抱歉。我要把原因归咎于缺乏咖啡。
答案 0 :(得分:4)
您只检查播放器是否被覆盖,而不是对象是否被覆盖,您应该首先获取随机坐标,然后检查是否有物体。
while items <= 4:
test = random.randrange(0,3)
x = random.randrange(0, 5)
y = random.randrange(0, 5)
if twoDimMap[x][y] == '-':
if test == 0:
twoDimMap[x][y] = "S"
if test ==1:
twoDimMap[x][y] = "R"
if test == 2:
twoDimMap[x][y] = "*"
items += 1
评论中建议的更紧凑的解决方案是
while items <= 4:
x = random.randrange(0, 5)
y = random.randrange(0, 5)
if twoDimMap[x][y] == '-':
twoDimMap[x][y] = random.choice('SR*')
items += 1
答案 1 :(得分:3)
由于问题空间很小,仅生成三个保证唯一的问题可能不是一个可怕的想法。
valid_locations = (tup for tup in itertools.product(range(5), repeat=2) if tup != (0, 0))
items = ["S", "R", "*"]
choices = [(random.choice(items), loc) for loc in random.sample(valid_locations, 3)]
for item, (x, y) in choices:
twoDimMap[y][x] = item
random.sample(collection, n)
保证n
的{{1}}个无重复的随机结果。 collection
为您提供了random.choice(collection)
中的一个随机元素。
答案 2 :(得分:1)
有时randrange(0, 5)
多次返回同一事物,因此重新分配了某个点。
这可以通过生成坐标以及类型并仅在当前未占用该点的情况下执行循环的其余部分来解决。这也将消除对单独(0,0)测试用例的需要。
答案 3 :(得分:1)
为避免覆盖先前放置的项目,可以使用random.sample
,它将从输入样本中随机选择项目,而无需替换。
random
模块中还有其他方便的functions for sequences。
我已经重写了您的代码,并将其转换为可以生成任何大小,数量和类型的项目的矩形地图的函数。
import random
def make_map(width, height, number_of_items, items='SR*'):
"""Create a map with the Hero in top left corner
and random items spread around"""
# build an empty map using a nested list comprehension
game_map = [['-' for x in range(width)] for y in range(height)]
# place the hero at coordinates 0, 0
game_map[0][0] = 'H'
# possible item positions, excluding 0, where the hero is.
positions = range(1, width * height)
# loop over n random choices from the available positions
for pos in random.sample(positions, number_of_items):
# convert pos to x, y coordinates using modular arithmetic
x, y = pos % width, pos // width
# select a random item to and place it at coordinates x, y
game_map[y][x] = random.choice(items)
return game_map
# generate a map. You can change the input arguments to vary size and items
game_map = make_map(6, 6, 5)
# convert the nested list to one string and print
print('\n'.join(''.join(line) for line in game_map))
我们使用模块化算法将位置值(范围为1到36的数字)转换为6×6网格上的x,y坐标。这是计算机图形学中非常常见且有用的操作。
x, y = pos % width, pos // width
这是一种非常常见的操作,python具有可用于此确切功能的内置函数。
y, x = divmod(pos, width)
我不会解释所有代码,但我鼓励您通读答案并尝试理解每一行的工作方式。通过阅读别人对自己已经解决的问题的解决方案,您可以学到很多东西。
答案 4 :(得分:0)
生成较少的项目是因为有时会再次生成相同的坐标。避免这种情况的一种方法是在分配位置之前检查该位置是否已经有一个项目。这样,您也将解决替换英雄的问题。
import random
twoDimMap = [["H","-","-","-","-","-"],["-","-","-","-","-","-"],["-","-","-","-","-","-"],["-","-","-","-","-","-"],["-","-","-","-","-","-"],["-","-","-","-","-","-"]]
items = 0
item_list = ['S', 'R', '*']
while items <= 4:
x = random.randrange(0,5)
y = random.randrange(0,5)
if twoDimMap[x][y] == '-':
twoDimMap[x][y] = item_list[random.randrange(0,3)]
items += 1
答案 5 :(得分:0)
如果地图不太大,则可以使用random.sample
至Choose at random from combinations。
twoDimMap = [list(line) for line in """\
H-----
------
------
------
------
------""".split("\n")]
width, height = len(twoDimMap[0]), len(twoDimMap)
allLocations = [(x, y) for x in range(width) for y in range(height) if (x, y) != (0, 0)]
for x, y in random.sample(allLocations, 5):
case = random.randrange(3)
twoDimMap[y][x] = "SR*"[case]