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

View File

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

View File

@ -32,7 +32,9 @@ from __future__ import print_function
import math
import random
import itertools
from robotgame.logic.direction import *
import robotgame.misc as misc
class Blocker(object):
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
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)
@ -151,13 +156,10 @@ def generate_simple_playfield(width, height, nturns, nstones,
del turns[-1]
for p, d in turns:
playfield[p] = d
emptys = set(itertools.product(range(width),
range(height))) - set(used_fields)
for _ in range(nstones):
if not emptys:
break
pos = random.choice(list(emptys))
emptys.remove(pos)
for pos in misc.pick_random_elements(
list(set(itertools.product(range(width), range(height)))
- set(used_fields)), nstones):
playfield[pos] = Blocker
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]