самый читаемый язык программирования для имитации 10 000 игр с лотками и лестницами?

Мне интересно, какой язык больше всего подходит для моделирования игры Желоба и Лестницы (Змеи и Лестницы в некоторых странах). Я хочу собрать базовую статистику, такую ​​как среднее и стандартное отклонение продолжительности игры (по ходам), вероятность выигрыша в зависимости от порядка хода (кто играет первым, вторым и т. Д.) И все остальное, что может вас заинтересовать. В частности, я ищу наиболее читаемую, удобную в обслуживании и модифицируемую реализацию. Он также должен быть очень кратким.

Если вы взрослый и не проводите много времени с маленькими детьми, вы, вероятно, плохо помните игру. Напомню:

  • На доске 100 квадратов.
  • Каждый игрок по очереди вращает случайное число от 1 до 6 (или бросает кости).
  • Затем игрок продвигается на столько клеток.
  • Некоторые квадраты находятся у основания лестницы; приземление на один из этих квадратов означает, что игрок может подняться по лестнице, продвигая его позицию до заранее определенного квадрата.
  • Некоторые квадраты находятся в верхней части горки (желоб или змейка); приземление на один из этих квадратов означает, что игрок должен соскользнуть вниз, перемещая позицию игрока обратно в заранее определенный квадрат.
  • Тот игрок, который первым попадет на позицию 100, становится победителем.

person Landon Kuhn    schedule 03.07.2009    source источник
comment
Что касается змей и лестниц, вам действительно нужно спросить? Это должен быть Python!   -  person    schedule 04.07.2009
comment
Мне любопытно, есть ли у вас свои выводы и данные и готовы ли вы ими поделиться? То есть статистика. Я бы использовал Руби. Сложно обыграть по читабельности.   -  person Mohamad    schedule 20.11.2014


Ответы (7)


Это немного грубо, но должно работать:

class Board
  attr_accessor :winner

  def initialize(players, &blk)
    @chutes, @ladders = {}, {}
    @players = players
    @move = 0
    @player_locations = Hash.new(0)
    self.instance_eval(&blk)
  end

  def chute(location)
    @chutes[location[:from]] = location[:to]
  end

  def ladder(location)
    @ladders[location[:from]] = location[:to]
  end

  def spin
    player = @move % @players
    die = rand(6) + 1
    location = (@player_locations[player] += die)

    if endpoint = @chutes[location] || endpoint = @ladders[location]
      @player_locations[player] = endpoint
    end

    if @player_locations[player] >= 100
      @winner = player
    end

    @move += 1
  end
end

num_players = 4

board = Board.new num_players, do
  ladder :from => 4, :to => 14
  ladder :from => 9, :to => 31
  # etc.
  chute :from => 16, :to => 6
  # etc.
end

until board.winner
  board.spin
end

puts "Player #{board.winner} is the winner!"
person Yehuda Katz    schedule 03.07.2009
comment
как я получил баллы за простой общий ответ use ruby ​​или python, в то время как этот парень действительно пошел дальше и сделал это? На самом деле это не кажется справедливым. - person Ben Hughes; 03.07.2009
comment
@Ben: Добро пожаловать в систему голосования StackOverflow, где быстро лучше, чем полезно, правильно выглядящий лучше, чем правильный, и люди голосуют, чтобы сказать, что мне нравится этот ответ, а не Этот ответ полезен. :-) - person ShreevatsaR; 04.07.2009
comment
Поскольку вопрос был конкретно в том, какой язык наиболее читабелен? Пожалуйста, не делайте это за меня :-) - person paxdiablo; 04.07.2009
comment
@Ben: Как только я увидел этот ответ, я подумал о том, чтобы убрать свой голос за ваш, но я передумал, вспомнив вашу заметку на Haskell. - person Domenic; 04.07.2009

Вам следует попробовать что-нибудь вроде Ruby или Python. Оба в основном являются исполняемым псевдокодом.

Вы могли бы получить более короткую и более блестящую программу с Haskell, но я полагаю, что Ruby или Python, вероятно, действительно будут понятны.

person Ben Hughes    schedule 03.07.2009
comment
Если вашу программу на Haskell непросто понять, значит, вы делаете это неправильно. (Это либо кодирование, либо обучение.) - person ShreevatsaR; 03.07.2009

Для многих статистических данных моделирование не требуется. Используя цепи Маркова, вы можете свести многие проблемы к матричным операциям с матрицей 100x100, вычисление которых занимает всего около 1 миллисекунды.

person mattiast    schedule 03.07.2009
comment
Не могли бы вы предоставить немного дополнительной информации или ссылки на источники? Звучит очень интересно. - person Landon Kuhn; 04.07.2009
comment
en.wikipedia.org/wiki/Examples_of_Markov_chains ‹- Есть пример с двумя состояниями, вы потребуется 100 состояний (что соответствует 100 квадратам). По сути, из каждого состояния всегда есть 1/6 вероятность перейти в шесть разных состояний. Не читайте настоящую статью в Википедии о цепях Маркова, это только запутает вас! - person mattiast; 04.07.2009
comment
Эта идея должна была получить больше голосов. Но имейте в виду, что если вы хотите иметь дело с двумя игроками, вам придется либо перейти к матрице (100x100) x (100x100), либо быть намного умнее. - person othercriteria; 09.07.2009
comment
Я немного опоздал на вечеринку, но для всех, кто гулит, вот сообщение в блоге, описывающее, как выразить эту проблему в виде цепочки Маркова с матрицей перехода. Очевидно, что это лучший способ решить его проблему, поскольку вы получаете определенное аналитическое решение. - person David Marx; 08.01.2013
comment
@DavidMarx, вы забыли предоставить ссылку. Будет ли оно у вас по-прежнему? - person Mohamad; 25.11.2014

Я собираюсь не согласиться с некоторыми из более ранних постов и сказать, что объектно-ориентированный подход здесь не подходит, поскольку он усложняет ситуацию.

Все, что вам нужно, это отслеживать позицию каждого игрока и вектор для представления доски. Если на позиции доски нет желоба или лестницы, она равна 0. Если она содержит лестницу, доска содержит положительное число, указывающее, на сколько позиций нужно продвинуться вперед. Если он содержит желоб, он содержит отрицательное число, чтобы переместить вас назад. Просто отслеживайте количество поворотов и позиций каждого игрока.

Фактическое моделирование с помощью этого метода довольно просто, и вы можете сделать это практически на любом языке программирования. Я бы посоветовал R или python, но только потому, что сегодня я использую именно их.

У меня нет копии желобов и лестниц, поэтому я сделал небольшую доску. Вам нужно будет вставить правую доску:

#!/usr/bin/python

import random, numpy

board = [0, 0, 0, 3, 0, -3, 0, 1, 0, 0]
numplayers = 2
numruns = 100

def simgame(numplayers, board):
    winner = -1
    winpos = len(board)
    pos = [0] * numplayers
    turns = 0
    while max(pos) < winpos:
        turns += 1
        for i in range(0, numplayers):
            pos[i] += random.randint(1,6)
            if pos[i] < winpos:
                pos[i] += board[pos[i]]
            if pos[i] >= winpos and winner == -1:
                winner = i
    return (turns, winner)

# simulate games, then extract turns and winners
games = [simgame(numplayers, board) for x in range(numruns)]
turns = [n for (n, w) in games]
winner = [w for (t, w) in games]
pwins = [len([p for p in winner if p == i]) for i in range(numplayers)]

print "runs:", numruns
print "mean(turns):", numpy.mean(turns)
print "sd(turns):", numpy.std(turns)
for i in range(numplayers):
    print "Player", (i+1), "won with proportion:", (float(pwins[i])/numruns)
person leif    schedule 04.07.2009
comment
Тройной цикл с условным оператором. Это наиболее читабельно? Бьюсь об заклад, что питон может добиться большего успеха. - person Arnis Lapsa; 04.07.2009
comment
Бьюсь об заклад, это тоже может. К сожалению, я не лучший специалист в python, я трачу слишком много времени на написание кода R. Я избавился от условного цикла, отслеживая победителя, и я избавился от некоторых циклов (вероятно, неудачная попытка), используя понимание списков. - person leif; 04.07.2009

F # тоже не слишком уродлив, его сложно превзойти функциональный язык по краткости:

#light
open System 

let snakes_and_ladders = dict [(1,30);(2,5);(20,10);(50,11)]

let roll_dice(sides) =  
    Random().Next(sides) + 1

let turn(starting_position) =
    let new_pos = starting_position + roll_dice(6)   
    let found, after_snake_or_ladder = snakes_and_ladders.TryGetValue(new_pos)
    if found then after_snake_or_ladder else new_pos 

let mutable player_positions = [0;0]

while List.max player_positions < 100 do
    player_positions <- List.map turn player_positions 

if player_positions.Head > 100 then printfn "Player 1 wins" else printf "Player 2 wins"
person Sam Saffron    schedule 06.07.2009

Я помню, как около 4 лет назад это было соревнование Top Coders, где вопрос заключался в том, какова вероятность того, что игрок 1 выиграет в змейках и лестницах.

После матча была опубликована действительно хорошая статья о том, как решать головоломку. Не могу найти сейчас, но эта статья вполне хорошо

C / C ++ казалось достаточно, чтобы хорошо решить проблему.

person Simeon Pilgrim    schedule 03.07.2009
comment
Достаточно любого языка. - person Osama Al-Maadeed; 06.07.2009
comment
Да, согласен, я указывал, что даже язык старой школы хорош в этой области. - person Simeon Pilgrim; 06.07.2009

Выберите любой объектно-ориентированный язык, они были придуманы для моделирования.

Поскольку вы хотите, чтобы он был кратким (почему?), Выберите язык с динамической типизацией, такой как Smalltalk, Ruby или Python.

person starblue    schedule 03.07.2009
comment
Читаемость подразумевает краткость. При прочих равных легче прочитать одну страницу, чем две. - person David Thornley; 01.12.2009
comment
За исключением того, что в остальном нет равных. Явная запись типов дает вам дополнительную информацию, которая может облегчить понимание кода. - person starblue; 02.12.2009