4

我正在尝试模拟一个简单的游戏,您旋转一个标有 1-5 的旋转器,然后继续前进,直到您通过终点线(点 50)。我对 R 有点陌生,并且一直在努力寻找答案。当我运行下面的代码时,它不会按顺序添加数字,它会返回我的 50 次随机旋转及其值​​的列表。我怎样才能让它相互叠加旋转,然后停止一次 => 50?

SpacesOnSpinner<-(seq(1,5,by=1))
N<-50
L1<-integer(N)

for (i in 1:N){
takeaspin<-sample(SpacesOnSpinner,1,replace=TRUE)
L1[i]<-L1[i]+takeaspin
} 
4

3 回答 3

4

这是一个很好的用例replicate。我不确定你是否必须使用for循环,但你可以这样做(replicate也是一个循环):

SpacesOnSpinner<-(seq(1,5,by=1))
N<-10
cumsum( replicate( N , sample(SpacesOnSpinner,1,replace=TRUE) ) )
#[1]  5 10 14 19 22 25 27 29 30 33

然而,既然你有一个你想要的条件,那么在这种情况下break,也许另一个while有条件的答案正是你所需要的(人们会告诉你他们在 R 中不好,但他们有他们的用途)。使用此方法,您可以通过一个简单的子集查看经过 50 次之后的旋转次数(但您不会事先知道需要旋转多少次,但最多为 50 次!):

N<-50
x <- cumsum( replicate( N , sample(5,1) ) )

# Value of accumulator at each round until <= 50
x[ x < 50 ]
#[1]  5  6  7  8 12 16 21 24 25 29 33 34 36 38 39 41 42 44 45 49

# Number of spins before total <= 50
length(x[x < 50])
[1] 20
于 2013-04-29T16:34:35.717 回答
3

这是使用递归函数模拟游戏的另一种有趣方式。

spin <- function(outcomes = 1:5, start = 0L, end = 50L)
   if (start <= end)
      c(got <- sample(outcomes, 1), Recall(outcomes, start + got, end))

spin()
# [1] 5 4 4 5 1 5 3 2 3 4 4 1 5 4 3

虽然很优雅,但它不会像sample@Viktor 所建议的那样进行一次调用的@Simon 解决方案的改进版本那么快:

spin <- function(outcomes = 1:5, end = 50L) {
   max.spins <- ceiling(end / min(outcomes))
   x <- sample(outcomes, max.spins, replace = TRUE)
   head(x, match(TRUE, cumsum(x) >= end))
}

spin()
# [1] 3 5 2 3 5 2 2 5 1 2 1 5 5 5 2 4

对于您的最终目标(找出一个人在整个游戏中处于领先地位的概率),是否while会更有效率是值得商榷的:while 循环肯定会更慢,但您可能会受益于提前退出的可能性领先者从一名球员切换到另一名球员。这两种方法都值得测试。

于 2013-04-29T17:40:13.447 回答
2

您可以使用 while 语句和变量total来跟踪总和:

total <- 0
while(total <= 50){
   takeaspin<-sample(SpacesOnSpinner,1,replace=TRUE)
   total <- takeaspin + total
} 

print (total)
于 2013-04-29T16:30:09.520 回答