4

我想知道哪种语言最适合模拟 Chutes and Ladders(某些国家的蛇和梯子)游戏。我希望收集基本统计数据,例如游戏长度的平均和标准偏差(轮流),基于轮流顺序的获胜概率(谁先玩,谁玩第二等),以及您能想到的任何其他感兴趣的东西。具体来说,我正在寻找最具可读性、可维护性和可修改性的实现。它也需要非常简短。

如果你是一个成年人并且没有花太多时间和小孩在一起,那么你可能不太记得这个游戏。我会提醒你:

  • 棋盘上有 100 个方格。
  • 每个玩家轮流旋转 1-6 的随机数(或掷骰子)。
  • 然后玩家前进那么多格。
  • 一些方块位于梯子的底部;降落在这些方格之一意味着玩家可以爬上梯子,将玩家的位置推进到预定的方格。
  • 一些方块位于滑梯的顶部(滑槽或蛇形);降落在其中一个方格上意味着玩家必须向下滑动,将玩家的位置移回预定方格。
  • 无论哪个玩家首先到达 100 位,都是获胜者。
4

7 回答 7

24

这有点粗糙,但它应该可以工作:

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!"
于 2009-07-03T07:23:34.063 回答
14

您应该查看一些类似 Ruby 或 Python 的东西。两者基本上都是可执行的伪代码。

你也许可以用 Haskell 得到一个更短、更出色的程序,但我想 Ruby 或 Python 可能实际上是可以理解的。

于 2009-07-03T07:09:50.933 回答
5

对于许多统计数据,您不需要模拟。使用马尔可夫链,您可以将许多问题减少到 100x100 矩阵上的矩阵运算,计算只需大约 1 毫秒。

于 2009-07-03T18:46:32.820 回答
4

我将不同意早期的一些海报,并说面向对象的方法在这里是错误的,因为它使事情变得更加复杂。

您所需要的只是跟踪每个玩家的位置,以及一个代表棋盘的向量。如果棋盘位置没有滑槽或梯子,则为 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)
于 2009-07-04T14:25:41.613 回答
2

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"
于 2009-07-06T08:20:03.380 回答
1

选择任何面向对象的语言,它们是为模拟而发明的。

既然您希望它简短(为什么?),请选择一种动态类型的语言,例如 Smalltalk、Ruby 或 Python。

于 2009-07-03T08:39:55.230 回答
1

我记得大约 4 年前这是一场顶级编码员比赛,问题是玩家 1 在蛇和梯子上获胜的概率是多少。

有一篇非常好的文章写了如何在比赛结束后发布拼图。现在找不到了,不过这个文笔不错

C/C++ 似乎足以很好地解决问题。

于 2009-07-03T08:05:32.973 回答