在python中生成超出范围的随机数 [英] Generate random number outside of range in python

查看:336
本文介绍了在python中生成超出范围的随机数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发一个pygame游戏,我需要将对象随机放置在屏幕上,除非它们不能位于指定的矩形内.有没有一种简单的方法来执行此操作,而不是连续生成随机的坐标对,直到它位于矩形之外?

I'm currently working on a pygame game and I need to place objects randomly on the screen, except they cannot be within a designated rectangle. Is there an easy way to do this rather than continuously generating a random pair of coordinates until it's outside of the rectangle?

这是屏幕和矩形外观的大致示例.

Here's a rough example of what the screen and the rectangle look like.

 ______________
|      __      |
|     |__|     |
|              |
|              |
|______________|

屏幕尺寸为1000x800,矩形为[x:500,y:250,宽度:100,高度:75]

Where the screen size is 1000x800 and the rectangle is [x: 500, y: 250, width: 100, height: 75]

一种更加面向代码的查看方式

A more code oriented way of looking at it would be

x = random_int
0 <= x <= 1000
    and
500 > x or 600 < x

y = random_int
0 <= y <= 800
    and
250 > y or 325 < y

推荐答案

要生成具有这些约束条件的均匀随机点,需要一些思想.我能想到的最简单的暴力方式是生成所有有效点的列表,并使用random.choice()从该列表中进行选择.这会为列表使用几MB的内存,但是生成一个点非常快:

It requires a bit of thought to generate a uniformly random point with these constraints. The simplest brute force way I can think of is to generate a list of all valid points and use random.choice() to select from this list. This uses a few MB of memory for the list, but generating a point is very fast:

import random

screen_width = 1000
screen_height = 800
rect_x = 500
rect_y = 250
rect_width = 100
rect_height = 75

valid_points = []
for x in range(screen_width):
    if rect_x <= x < (rect_x + rect_width):
        for y in range(rect_y):
            valid_points.append( (x, y) )
        for y in range(rect_y + rect_height, screen_height):
            valid_points.append( (x, y) )
    else:
        for y in range(screen_height):
            valid_points.append( (x, y) )

for i in range(10):
    rand_point = random.choice(valid_points)
    print(rand_point)

可以生成一个随机数,并将其映射到屏幕上的有效点,这会占用较少的内存,但是有点混乱,并且会花费更多的时间来生成该点.可能有一种更简洁的方法来执行此操作,但是此处使用与上述相同的屏幕尺寸变量的一种方法是:

It is possible to generate a random number and map it to a valid point on the screen, which uses less memory, but it is a bit messy and takes more time to generate the point. There might be a cleaner way to do this, but one approach using the same screen size variables as above is here:

rand_max = (screen_width * screen_height) - (rect_width * rect_height) 
def rand_point():
    rand_raw = random.randint(0, rand_max-1)
    x = rand_raw % screen_width
    y = rand_raw // screen_width
    if rect_y <= y < rect_y+rect_height and rect_x <= x < rect_x+rect_width:
        rand_raw = rand_max + (y-rect_y) * rect_width + (x-rect_x)
        x = rand_raw % screen_width
        y = rand_raw // screen_width
    return (x, y)

此处的逻辑类似于在旧的8位和16位微处理器上根据x和y坐标计算屏幕地址的方式的逆过程.变量rand_max等于有效屏幕坐标的数量.计算像素的x和y坐标,如果像素在矩形内,则将像素推到rand_max上方,进入第一个调用无法生成的区域.

The logic here is similar to the inverse of the way that screen addresses are calculated from x and y coordinates on old 8 and 16 bit microprocessors. The variable rand_max is equal to the number of valid screen coordinates. The x and y co-ordinates of the pixel are calculated, and if it is within the rectangle the pixel is pushed above rand_max, into the region that couldn't be generated with the first call.

如果您不太关心均匀随机点,则此解决方案易于实现且非常快速. x值是随机的,但如果选择的X在带有矩形的列中,则Y值会受到限制,因此与矩形左右两侧的像素相比,矩形上方和下方的像素被选择的可能性更高. :

If you don't care too much about the point being uniformly random, this solution is easy to implement and very quick. The x values are random, but the Y value is constrained if the chosen X is in the column with the rectangle, so the pixels above and below the rectangle will have a higher probability of being chosen than pizels to the left and right of the rectangle:

def pseudo_rand_point():        
    x = random.randint(0, screen_width-1)
    if rect_x <= x < rect_x + rect_width: 
        y = random.randint(0, screen_height-rect_height-1)
        if y >= rect_y:
            y += rect_height
    else:
        y = random.randint(0, screen_height-1)
    return (x, y)

另一个答案是计算像素在屏幕某些区域的概率,但是他们的答案还不是很正确.这是使用类似想法的版本,计算像素在给定区域中的概率,然后计算像素在该区域中的位置:

Another answer was calculating the probability that the pixel is in certain regions of the screen, but their answer isn't quite correct yet. Here's a version using a similar idea, calculate the probability that the pixel is in a given region and then calculate where it is within that region:

valid_screen_pixels = screen_width*screen_height - rect_width * rect_height
prob_left = float(rect_x * screen_height) / valid_screen_pixels
prob_right = float((screen_width - rect_x - rect_width) * screen_height) / valid_screen_pixels
prob_above_rect = float(rect_y) / (screen_height-rect_height)
def generate_rand():
    ymin, ymax = 0, screen_height-1
    xrand = random.random()
    if xrand < prob_left:
        xmin, xmax = 0, rect_x-1
    elif xrand > (1-prob_right):
        xmin, xmax = rect_x+rect_width, screen_width-1
    else:
        xmin, xmax = rect_x, rect_x+rect_width-1
        yrand = random.random()
        if yrand < prob_above_rect:
            ymax = rect_y-1
        else:
            ymin=rect_y+rect_height
    x = random.randrange(xmin, xmax)
    y = random.randrange(ymin, ymax)
    return (x, y)

这篇关于在python中生成超出范围的随机数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆