硬币翻转游戏的获胜者判定与重复模拟可视化需求
公平硬币翻转游戏模拟与问题解答
游戏规则
- 1000人参与公平硬币翻转游戏
- 第1轮:掷出反面(tails)的玩家被淘汰
- 第2轮:剩余玩家再次掷硬币,掷出反面的玩家被淘汰
- 以此类推,直到所有玩家都被淘汰
R模拟实现代码
# 游戏初始化 num_players <- 1000 results <- data.frame(player = paste0("player", 1:num_players)) status <- rep("playing", num_players) round <- 1 # 模拟循环 while (any(status == "playing")) { # 生成硬币翻转结果 coin_flips <- ifelse(runif(num_players) > 0.5, "heads", "tails") # 记录当前轮次状态:未淘汰玩家显示翻转结果,已淘汰显示"eliminated" current_round <- ifelse(status == "playing", coin_flips, "eliminated") # 更新玩家状态:未淘汰且掷出反面的玩家被淘汰 status <- ifelse(status == "playing" & coin_flips == "tails", "eliminated", status) # 将当前轮次结果合并到总结果中 results <- cbind(results, current_round) colnames(results)[ncol(results)] <- paste0("round_", round) round <- round + 1 }
模拟结果示例
> head(results) player round_1 round_2 round_3 round_4 round_5 round_6 round_7 round_8 round_9 round_10 1 player1 heads heads heads heads heads heads tails eliminated eliminated eliminated 2 player2 tails eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated 3 player3 tails eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated 4 player4 tails eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated 5 player5 tails eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated 6 player6 heads tails eliminated eliminated eliminated eliminated eliminated eliminated eliminated eliminated
问题解答
1. 判断单次模拟是否存在唯一获胜者
唯一获胜者的判定标准是:游戏过程中存在某一时刻,其余999名玩家均已被淘汰,仅剩下1名玩家仍在游戏中。
实现方法
方法1:模拟过程中实时检查
修改原模拟代码,在每轮结束后检查剩余玩家数,一旦出现剩余1人的情况,即可标记存在唯一获胜者:
num_players <- 1000 status <- rep("playing", num_players) has_unique_winner <- FALSE round <- 1 while (any(status == "playing")) { coin_flips <- ifelse(runif(num_players) > 0.5, "heads", "tails") status <- ifelse(status == "playing" & coin_flips == "tails", "eliminated", status) # 检查当前剩余玩家数 remaining <- sum(status == "playing") if (remaining == 1) { has_unique_winner <- TRUE # 可提前终止循环,无需继续模拟 break } round <- round + 1 } # 输出结果 cat("是否存在唯一获胜者:", ifelse(has_unique_winner, "是", "否"), "\n")
方法2:事后处理模拟结果
从已生成的results数据框中提取每轮的玩家状态,计算每轮剩余的活跃玩家数,检查是否有轮次剩余数为1:
# 提取所有轮次的状态数据(排除player列) round_status <- results[, -1] # 计算每轮剩余的活跃玩家数(即该轮掷出heads的玩家数) remaining_players <- apply(round_status, 2, function(x) sum(x == "heads")) # 判断是否存在剩余1人的轮次 has_unique_winner <- any(remaining_players == 1) cat("是否存在唯一获胜者:", ifelse(has_unique_winner, "是", "否"), "\n")
2. 重复模拟1000次并绘制获胜者数量分布
以下提供两种常见需求的实现方案:
方案1:统计是否存在唯一获胜者的分布
# 封装单次模拟函数,返回是否存在唯一获胜者(1=是,0=否) simulate_game <- function(num_players = 1000) { status <- rep("playing", num_players) has_unique_winner <- FALSE while (any(status == "playing")) { coin_flips <- ifelse(runif(num_players) > 0.5, "heads", "tails") status <- ifelse(status == "playing" & coin_flips == "tails", "eliminated", status) remaining <- sum(status == "playing") if (remaining == 1) { has_unique_winner <- TRUE break } if (remaining == 0) break } return(ifelse(has_unique_winner, 1, 0)) } # 重复模拟1000次 set.seed(123) # 设置随机种子保证结果可重复 sim_results <- replicate(1000, simulate_game()) # 绘制柱状图 library(ggplot2) ggplot(data.frame(winner_count = factor(sim_results, labels = c("无唯一获胜者", "存在唯一获胜者"))), aes(x = winner_count)) + geom_bar(fill = "steelblue", width = 0.6) + labs(title = "1000次模拟的获胜者情况分布", x = "模拟结果", y = "模拟次数") + theme_minimal()
方案2:统计最终剩余玩家数的分布
如果需要展示每次模拟最后一轮淘汰前的剩余玩家数(即最多同时存活的玩家数),可以使用以下代码:
# 封装单次模拟函数,返回最后一轮淘汰前的剩余玩家数 simulate_game <- function(num_players = 1000) { status <- rep("playing", num_players) last_remaining <- num_players while (any(status == "playing")) { coin_flips <- ifelse(runif(num_players) > 0.5, "heads", "tails") status <- ifelse(status == "playing" & coin_flips == "tails", "eliminated", status) current_remaining <- sum(status == "playing") if (current_remaining > 0) { last_remaining <- current_remaining } else { break } } return(last_remaining) } # 重复模拟1000次 set.seed(123) sim_results <- replicate(1000, simulate_game()) # 绘制直方图 ggplot(data.frame(remaining_players = sim_results), aes(x = remaining_players)) + geom_histogram(binwidth = 1, fill = "steelblue", color = "black") + labs(title = "1000次模拟的最终剩余玩家数分布", x = "最终剩余玩家数", y = "模拟次数") + theme_minimal()
内容的提问来源于stack exchange,提问作者konofoso
相关产品推荐
相关产品推荐

