在R中模拟蛇和梯子

发布于 2025-01-24 08:50:33 字数 1310 浏览 1 评论 0原文

我是R的初学者,我必须在R中模拟蛇和梯子游戏进行作业。董事会有100个正方形。唯一的获胜广场是100,例如,如果您在Square 98上并滚动一个6,您将向前2到100,然后将4个空间反弹到96。矩阵,并编码获胜条件。这是我到目前为止的代码:

snakesNladders <-
  function()
  {
    transitions <- rbind(   
      c(40, 3),
      c(4, 25),
      c(27, 5),
      c(13, 46),
      c(43, 18),
      c(54, 31),
      c(33, 49),
      c(99, 41),
      c(42, 63),
      c(66, 45),
      c(50, 69),
      c(89, 53),
      c(76, 58),
      c(62, 81),
      c(74, 92))
     
    transmat <- 1:100
    names(transmat) <- as.character(1:100)
    transmat[transitions[,1]] <- transitions[,2]    

    firstpos <- 0
    curpos_player1 <- NULL
    curpos_player2 <- NULL
    while(curpos_player1 & curpos_player2 < 100) {
      curpos_player1 <- firstpos + curpos_player1 + sample(1:6, 1, replace=TRUE)
      curpos_player2 <- firstpos + curpos_player2 + sample(1:6, 1, replace = TRUE)
      curpos_player1 <- transmat[curpos_player1]
      curpos_player2 <- transmat[curpos_player2]
      if(curpos_player1 | curpos_player2 == 100){
        print(win)
        }else if(curpos_player1 > 100){
        return()
        }else if(curpos_player2 > 100){
          return()
        }
       }     
    }
  }
}

不确定我应该在返回括号中放置什么来模拟获胜条件。另外,如果代码的其余部分似乎还可以。我真的很感谢任何帮助。

I am a beginner in R and I have to simulate a snakes and ladders game in R for an assignment. The board has 100 squares. The only winning square is 100, for example if you’re on square 98 and roll a 6 you would go forward 2 spaces to 100 and then bounce back 4 spaces to 96. My difficulty is insterting the snakes/ladders transitions in the complete transition matrix, and coding the winning condition. Here is my code so far:

snakesNladders <-
  function()
  {
    transitions <- rbind(   
      c(40, 3),
      c(4, 25),
      c(27, 5),
      c(13, 46),
      c(43, 18),
      c(54, 31),
      c(33, 49),
      c(99, 41),
      c(42, 63),
      c(66, 45),
      c(50, 69),
      c(89, 53),
      c(76, 58),
      c(62, 81),
      c(74, 92))
     
    transmat <- 1:100
    names(transmat) <- as.character(1:100)
    transmat[transitions[,1]] <- transitions[,2]    

    firstpos <- 0
    curpos_player1 <- NULL
    curpos_player2 <- NULL
    while(curpos_player1 & curpos_player2 < 100) {
      curpos_player1 <- firstpos + curpos_player1 + sample(1:6, 1, replace=TRUE)
      curpos_player2 <- firstpos + curpos_player2 + sample(1:6, 1, replace = TRUE)
      curpos_player1 <- transmat[curpos_player1]
      curpos_player2 <- transmat[curpos_player2]
      if(curpos_player1 | curpos_player2 == 100){
        print(win)
        }else if(curpos_player1 > 100){
        return()
        }else if(curpos_player2 > 100){
          return()
        }
       }     
    }
  }
}

Not sure what I should put in the return brackets to simulate the winning condition. Also if the rest of the code seems ok. I would really appreciate any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小巷里的女流氓 2025-01-31 08:50:33

这就是我可能会如何处理的。也许您可以通过浏览代码来获得一些想法。

library(data.table)
set.seed(1633654196) # for reproducibility
# for the transitions, position 1 is the start position, position 2 is the
# square at the bottom left of the board, position 101 is the winning position

# get a vector of snake/ladder transitions (where a player moves after
# landing on each square)
trans <- 1:101
trans[c(40,  4, 27, 13, 43, 54, 33, 99, 42, 66, 50, 89, 76, 62, 74) + 1] <-
      c( 3, 25,  5, 46, 18, 31, 49, 41, 63, 45, 69, 53, 58, 81, 92) + 1
# get a matrix of all possible starting/ending positions (based on die
# roll 1 through 6)
m <- c(sequence(rep(6L, 100), 2:101), rep(101L, 6))
# handle overshooting the winning square
blnBounce <- m > 101
m[blnBounce] <- 202 - m[blnBounce]
# add in the snake/ladder transitions
# (faster to index moves as a list of vectors than as a matrix)
to <- asplit(m <- matrix(trans[m], 6), 2)

simgame <- function(nplayers = 1, to, blnPrint = TRUE, turns = 50L, start = rep(1L, nplayers)) {
  # turn 1 is the starting position, and won't be retained in the output, so
  # add 1 to turns
  turns <- as.integer(turns) + 1L
  # sample the rolls for all players up front
  rolls <- matrix(sample(6, nplayers*turns, TRUE), ncol = 2)
  # initialize the output matrix
  out <- matrix(0, turns, nplayers)
  out[1,] <- start
  
  for (j in 1:nplayers) {
    for (i in 2:turns) {
      out[i, j] <- to[[out[i - 1L]]][rolls[i, j]]
      if (out[i, j] == 101L) {
        turns <- i
        break
      }
    }
  }
  # subtract 1 so "1" corresponds to square 1 and "100" corresponds to the
  # winning square
  out <- out[2:turns,,drop = FALSE] - 1L
  turns <- turns - 1L
  winner <- match(100L, out[turns,], 0L)
  if (winner) {
    if (blnPrint) print(paste("Player", winner, "wins"))
    out
  } else {
    # no winner yet, recursively call simgame
    rbind(out, Recall(nplayers, to, blnPrint, turns, out[turns,]))
  }
}
# simulate a 2-player game
(game <- simgame(2, to))
#> [1] "Player 2 wins"
#>       [,1] [,2]
#>  [1,]   25    6
#>  [2,]   31   30
#>  [3,]   32   32
#>  [4,]   34   34
#>  [5,]    3   36
#>  [6,]   25    6
#>  [7,]    5   28
#>  [8,]   11   10
#>  [9,]   46   14
#> [10,]   52   51
#> [11,]   31   31
#> [12,]   35   37
#> [13,]   39   38
#> [14,]    3   41
#> [15,]    8    7
#> [16,]   12   12
#> [17,]   46   17
#> [18,]   69   48
#> [19,]   75   71
#> [20,]   78   77
#> [21,]   84   83
#> [22,]   87   53
#> [23,]   93   92
#> [24,]   96   94
#> [25,]   41  100
# simulate the number of rounds for 15k games
system.time(turns <- replicate(15e3, nrow(simgame(2, to, FALSE))))
#>    user  system elapsed 
#>    1.18    0.01    1.06
hist(turns)


# Probability of single player finishing by turn
dt <- data.table(from = c(col(m)), to = c(m))[, .(prob = .N/6), from:to]
# full transition matrix
m1 <- matrix(0L, 101, 101)
m1[as.matrix(dt[, 1:2])] <- dt$prob
# calculate the probabilities for 300 turns
mm <- m1
prob1 <- numeric(300)
for (i in 1:300) {
  mm <- mm %*% m1
  prob1[i] <- mm[1, 101]
}
plot(prob1, xlab = "Roll number", main = "Probability of winning by turn")


# for a 3-player game:
prob3 <- 1 - (1 - prob1)^3

Here's how I might approach it. Maybe you can get some ideas by walking through the code.

library(data.table)
set.seed(1633654196) # for reproducibility
# for the transitions, position 1 is the start position, position 2 is the
# square at the bottom left of the board, position 101 is the winning position

# get a vector of snake/ladder transitions (where a player moves after
# landing on each square)
trans <- 1:101
trans[c(40,  4, 27, 13, 43, 54, 33, 99, 42, 66, 50, 89, 76, 62, 74) + 1] <-
      c( 3, 25,  5, 46, 18, 31, 49, 41, 63, 45, 69, 53, 58, 81, 92) + 1
# get a matrix of all possible starting/ending positions (based on die
# roll 1 through 6)
m <- c(sequence(rep(6L, 100), 2:101), rep(101L, 6))
# handle overshooting the winning square
blnBounce <- m > 101
m[blnBounce] <- 202 - m[blnBounce]
# add in the snake/ladder transitions
# (faster to index moves as a list of vectors than as a matrix)
to <- asplit(m <- matrix(trans[m], 6), 2)

simgame <- function(nplayers = 1, to, blnPrint = TRUE, turns = 50L, start = rep(1L, nplayers)) {
  # turn 1 is the starting position, and won't be retained in the output, so
  # add 1 to turns
  turns <- as.integer(turns) + 1L
  # sample the rolls for all players up front
  rolls <- matrix(sample(6, nplayers*turns, TRUE), ncol = 2)
  # initialize the output matrix
  out <- matrix(0, turns, nplayers)
  out[1,] <- start
  
  for (j in 1:nplayers) {
    for (i in 2:turns) {
      out[i, j] <- to[[out[i - 1L]]][rolls[i, j]]
      if (out[i, j] == 101L) {
        turns <- i
        break
      }
    }
  }
  # subtract 1 so "1" corresponds to square 1 and "100" corresponds to the
  # winning square
  out <- out[2:turns,,drop = FALSE] - 1L
  turns <- turns - 1L
  winner <- match(100L, out[turns,], 0L)
  if (winner) {
    if (blnPrint) print(paste("Player", winner, "wins"))
    out
  } else {
    # no winner yet, recursively call simgame
    rbind(out, Recall(nplayers, to, blnPrint, turns, out[turns,]))
  }
}
# simulate a 2-player game
(game <- simgame(2, to))
#> [1] "Player 2 wins"
#>       [,1] [,2]
#>  [1,]   25    6
#>  [2,]   31   30
#>  [3,]   32   32
#>  [4,]   34   34
#>  [5,]    3   36
#>  [6,]   25    6
#>  [7,]    5   28
#>  [8,]   11   10
#>  [9,]   46   14
#> [10,]   52   51
#> [11,]   31   31
#> [12,]   35   37
#> [13,]   39   38
#> [14,]    3   41
#> [15,]    8    7
#> [16,]   12   12
#> [17,]   46   17
#> [18,]   69   48
#> [19,]   75   71
#> [20,]   78   77
#> [21,]   84   83
#> [22,]   87   53
#> [23,]   93   92
#> [24,]   96   94
#> [25,]   41  100
# simulate the number of rounds for 15k games
system.time(turns <- replicate(15e3, nrow(simgame(2, to, FALSE))))
#>    user  system elapsed 
#>    1.18    0.01    1.06
hist(turns)


# Probability of single player finishing by turn
dt <- data.table(from = c(col(m)), to = c(m))[, .(prob = .N/6), from:to]
# full transition matrix
m1 <- matrix(0L, 101, 101)
m1[as.matrix(dt[, 1:2])] <- dt$prob
# calculate the probabilities for 300 turns
mm <- m1
prob1 <- numeric(300)
for (i in 1:300) {
  mm <- mm %*% m1
  prob1[i] <- mm[1, 101]
}
plot(prob1, xlab = "Roll number", main = "Probability of winning by turn")


# for a 3-player game:
prob3 <- 1 - (1 - prob1)^3
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文