Optimized pick-random-elements-from-list method.

This commit is contained in:
Niels Serup 2012-08-10 11:27:36 +02:00
parent 9860036860
commit 1f552640e5
4 changed files with 31 additions and 22 deletions

View File

@ -30,6 +30,7 @@ import random
import re import re
import itertools import itertools
import misc
import level import level
import player import player
import tile import tile
@ -52,10 +53,8 @@ class Level(level.Level):
self.draw_background() self.draw_background()
emptys = list(itertools.product(range(2, 20), range(2, 20))) for x, y in misc.pick_random_elements(
for _ in range(150): list(itertools.product(range(2, 20), range(2, 20))), 150):
x, y = random.choice(emptys)
emptys.remove((x, y))
self.objects.append(block.Block(self, 64 * x, 48 * y, self.objects.append(block.Block(self, 64 * x, 48 * y,
self.imgs['block1'], movable=True)) self.imgs['block1'], movable=True))

View File

@ -33,6 +33,7 @@ import random
import itertools import itertools
from robotgame.logic.direction import * from robotgame.logic.direction import *
import robotgame.logic.rollingstone as rstone import robotgame.logic.rollingstone as rstone
import robotgame.misc as misc
class Mirror(object): class Mirror(object):
pass pass
@ -81,18 +82,16 @@ def generate_simple_playfield(nmirrors):
succs = (lambda s: lambda d: succ(s(d)))(succs) succs = (lambda s: lambda d: succ(s(d)))(succs)
source_direc = succ(source_direc) source_direc = succ(source_direc)
emptys = set(itertools.product(range(12), range(12))) \ emptys = list(
- set(playfield.keys()) set([(0, y) for y in range(12)]
emptys = set([(0, y) for y in range(12)] + [(11, y) for y in range(12)]
+ [(11, y) for y in range(12)] + [(x, 0) for x in range(12)]
+ [(x, 0) for x in range(12)] + [(x, 11) for x in range(12)])
+ [(x, 11) for x in range(12)]) - set(playfield.keys()))
for _ in range(nlevers): if len(emptys) < nlevers:
if not emptys: raise Exception("Not enough space for all levers!")
raise Exception("Not enough space for all levers!") for pos in misc.pick_random_elements(emptys, nlevers):
pos = random.choice(list(emptys))
playfield[pos] = Lever playfield[pos] = Lever
emptys.remove(pos)
return playfield return playfield
def _adjust(source_direc, w, h, x, y): def _adjust(source_direc, w, h, x, y):

View File

@ -32,7 +32,9 @@ from __future__ import print_function
import math import math
import random import random
import itertools import itertools
from robotgame.logic.direction import * from robotgame.logic.direction import *
import robotgame.misc as misc
class Blocker(object): class Blocker(object):
pass pass
@ -89,6 +91,9 @@ def generate_simple_playfield(width, height, nturns, nstones,
'steps' is the number of steps used by the generated solution. It is not 'steps' is the number of steps used by the generated solution. It is not
necessarily the lowest number of steps the playfield can be completed in. necessarily the lowest number of steps the playfield can be completed in.
This generator favours increasing the turn density the closer to the goal
it gets.
""" """
min_width, min_height = _min_play_size(nturns) min_width, min_height = _min_play_size(nturns)
@ -151,13 +156,10 @@ def generate_simple_playfield(width, height, nturns, nstones,
del turns[-1] del turns[-1]
for p, d in turns: for p, d in turns:
playfield[p] = d playfield[p] = d
emptys = set(itertools.product(range(width),
range(height))) - set(used_fields) for pos in misc.pick_random_elements(
for _ in range(nstones): list(set(itertools.product(range(width), range(height)))
if not emptys: - set(used_fields)), nstones):
break
pos = random.choice(list(emptys))
emptys.remove(pos)
playfield[pos] = Blocker playfield[pos] = Blocker
return playfield, len(used_fields) - 1 return playfield, len(used_fields) - 1

9
robotgame/misc.py Normal file
View File

@ -0,0 +1,9 @@
from __future__ import print_function
import random
def pick_random_elements(xs, n):
for i in range(min(n, len(xs))):
i1 = random.randrange(i, len(xs))
yield xs[i1]
xs[i1] = xs[i]