Программирование на языке Ruby
Программирование на языке Ruby читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Но природные процессы считаются истинно случайными. Поэтому при розыгрыше призов в лотерее счастливчики определяются лототроном, который хаотично выбрасывает шары. Другие источники случайности — радиоактивный распад или атмосферный шум.
Есть источники случайных чисел и в Web. Один из них — сайт www.random.org, который мы задействуем в следующем примере.
Программа в листинге 18.4 имитирует подбрасывание пяти обычных (шестигранных) костей. Конечно, игровые фанаты могли бы увеличить число граней до 10 или 20, но тогда стало бы сложно рисовать ASCII-картинки.
require 'net/http'
HOST = "www.random.org"
RAND_URL = "/cgi-bin/randnum?col=5&"
def get_random_numbers(count=1, min=0, max=99)
path = RAND_URL + "num=#{count}&min=#{min}&max=#{max}"
connection = Net::HTTP.new(HOST)
response, data = connection.get(path)
if response.code == "200"
data.split.collect { |num| num.to_i }
else
[]
end
end
DICE_LINES = [
"+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ ",
"| | | * | | * | | * * | | * * | | * * | ",
"| * | | | | * | | | | * | | * * | ",
"| | | * | | * | | * * | | * * | | * * | ",
"+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ "
DIE_WIDTH = DICE_LINES[0].length/6
def draw_dice(values)
DICE_LINES.each do | line |
for v in values
print line[(v-1)*DIE_WIDTH, DIE_WIDTH]
print " "
end
puts
end
end
draw_dice(get_random_numbers(5, 1, 6))
Здесь мы воспользовались классом
Net::НТТР
Посмотрим на вариацию этой идеи. Что если вы захотели бы применить случайные числа в каком-нибудь приложении? Поскольку обслуживающая программа на стороне сервера позволяет указать количество возвращаемых чисел, то было бы логично сохранить их в буфере. Учитывая, что при обращении к удаленному серверу задержки неизбежны, следует сразу заполнить буфер во избежание лишних запросов по сети.
В листинге 18.5 эта мысль реализована. Буфер заполняется отдельным потоком и совместно используется всеми экземплярами класса. Размер буфера и «нижняя отметка» (
@slack
require "net/http"
require "thread"
class TrueRandom
def initialize(min=nil,max=nil,buff=nil,slack=nil)
@buffer = []
@site = "www.random.org"
if ! defined? @init_flag
# Принять умолчания, если они не были заданы явно И
# это первый созданный экземпляр класса...
@min = min || 0
@max = max || 1
@bufsize = buff || 1000
@slacksize = slack || 300
@mutex = Mutex.new
@thread = Thread.new { fillbuffer }
@init_flag = TRUE # Значение может быть любым.
else
@min = min || @min
@max = max || @max
@bufsize = buff || @bufsize
@slacksize = slack || @slacksize
end
@url = "/cgi-bin/randnum" +
"?num=#@bufsize&min=#@min&max=#@max&col=1"
end
def fillbuffer
h = Net::HTTP.new(@site, 80)
resp, data = h.get(@url, nil)
@buffer += data.split
end
def rand
num = nil
@mutex.synchronize { num = @buffer.shift }
if @buffer.size < @slacksize
if ! @thread.alive?
@thread = Thread.new { fillbuffer }
end
end
if num == nil
if @thread.alive?
@thread.join
else
@thread = Thread.new { fillbuffer }