You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用R语言闭包为5个玩家实现计时器及相关函数?解决代码报错

问题分析与解决方案

首先,你遇到的Error: attempt to apply non-function错误,根源在于定义StopWatch函数时,list()里的内容是赋值表达式的结果,而非函数本身。比如strt<-function(Name = "name") Start <<- Sys.time()这行代码,执行后返回的是赋值后的函数,但你在list里的写法其实是把赋值操作的结果(函数)作为元素,语法逻辑有误;另外你误用了全局赋值<<-,这会导致多个玩家的时间互相覆盖,完全违背了闭包的封装性。

接下来我们重新实现支持5位玩家的计时器闭包,完整满足你需要的四个功能:

完整实现代码

StopWatch <- function() {
  # 内部环境存储玩家数据:每个玩家包含start_time和end_time
  players <- list()
  
  # 1. 开始计时函数:记录指定玩家的开始时间,最多支持5位玩家
  start_timer <- function(player_name) {
    if (length(players) >= 5) {
      stop("最多支持5位玩家,请先结束已有玩家的计时")
    }
    if (player_name %in% names(players)) {
      warning(paste("玩家", player_name, "已经开始计时,将覆盖之前的开始时间"))
    }
    players[[player_name]] <- list(start_time = Sys.time(), end_time = NULL)
    invisible()
  }
  
  # 2. 结束计时函数:记录指定玩家的结束时间
  stop_timer <- function(player_name) {
    if (!(player_name %in% names(players))) {
      stop(paste("玩家", player_name, "未开始计时"))
    }
    if (!is.null(players[[player_name]]$end_time)) {
      warning(paste("玩家", player_name, "已经结束计时,将覆盖之前的结束时间"))
    }
    players[[player_name]]$end_time <- Sys.time()
    invisible()
  }
  
  # 3. 获取单个玩家的时长
  get_duration <- function(player_name) {
    if (!(player_name %in% names(players))) {
      stop(paste("玩家", player_name, "不存在"))
    }
    player_data <- players[[player_name]]
    if (is.null(player_data$end_time)) {
      stop(paste("玩家", player_name, "尚未结束计时"))
    }
    duration <- player_data$end_time - player_data$start_time
    cat(paste("玩家", player_name, "的时长:"), duration, "\n")
    return(duration)
  }
  
  # 4. 按降序显示所有已结束计时玩家的时长
  show_results_desc <- function() {
    # 筛选出已结束计时的玩家
    finished_players <- Filter(function(x) !is.null(x$end_time), players)
    if (length(finished_players) == 0) {
      cat("暂无已结束计时的玩家\n")
      return(invisible(NULL))
    }
    # 计算每个玩家的时长
    durations <- sapply(finished_players, function(x) x$end_time - x$start_time)
    # 按降序排序
    sorted_durations <- sort(durations, decreasing = TRUE)
    # 打印结果
    cat("玩家时长排名(降序):\n")
    for (i in seq_along(sorted_durations)) {
      cat(paste0(i, ". ", names(sorted_durations)[i], ": ", sorted_durations[i], "\n"))
    }
    return(invisible(sorted_durations))
  }
  
  # 返回包含四个函数的列表
  list(
    start = start_timer,
    stop = stop_timer,
    get_duration = get_duration,
    show_results = show_results_desc
  )
}

代码解释与使用示例

核心改进点

  • 用闭包内部的players列表存储每个玩家的时间数据,避免全局变量污染,保证数据的封装性
  • 每个函数都是命名的,调用时逻辑更清晰(比如w$start("player1"))
  • 增加了边界检查:限制最多5位玩家、检查玩家是否存在、是否已开始/结束计时,避免无效操作
  • 完整实现了你要求的四个独立函数

使用示例

# 创建计时器实例
w <- StopWatch()

# 开始玩家1的计时
w$start("player1")
# 模拟耗时操作(这里用Sys.sleep代替你的sleep_for_a_minute)
Sys.sleep(2)
# 结束玩家1的计时
w$stop("player1")

# 开始玩家2的计时
w$start("player2")
Sys.sleep(1)
w$stop("player2")

# 获取玩家1的时长
w$get_duration("player1")

# 按降序显示所有已结束玩家的时长
w$show_results()

运行结果示例

玩家 player1 的时长: Time difference of 2.001 secs
玩家时长排名(降序):
1. player1: Time difference of 2.001 secs
2. player2: Time difference of 1.000 secs

内容的提问来源于stack exchange,提问作者New_to_ML

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:32:23