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

Kotlin实现按钮指令匹配胜率计数功能代码异常求解

原有代码的核心问题
  • 语法错误:Kotlin中if/else不加大括号时,仅对紧随其后的第一行代码生效。你写的判断逻辑里,counter +=20、发送下一条指令的代码根本不在匹配成功的分支内,else也只会匹配到最内层的if,分支逻辑完全错乱。
  • 逻辑缺陷:用固定delay(3000)傻等3秒,完全没有监听「按住中途松手」「按错其他按钮」的异常场景,也没有做状态记录,根本无法判断用户是不是真的按住正确按钮满了时长。
  • 结构问题:硬编码嵌套四层按钮判断,扩展性极差,错误后重启的逻辑没有闭环,也没有实现顺序解锁(x→y→z→w)的状态管理,计数规则也没落地。
  • 协程使用错误:直接用GlobalScope启动协程没有结构化并发约束,容易内存泄漏,也没法在出错时取消无效的等待任务。
实现思路
  • 把四个按钮按解锁顺序存在列表里,用一个索引变量记录当前需要验证的关卡,不用硬写嵌套判断,出错重置索引即可回到x按钮的初始环节。
  • 单独维护按压状态:监听按钮的按下、松开两个事件,按下时先校验是否匹配当前指令按钮,匹配才开始计时,不匹配直接触发重置。
  • 计时过程中持续校验按压状态:只要中途松开、或者按了别的按钮,立刻取消计时、计数器归零、回到初始关卡。
  • 按住满3秒后才给计数器加20,进入下一关,发送对应按钮的操作提示。
参考实现代码
import kotlinx.coroutines.*

// 按验证顺序定义按钮标签
private val buttonOrder = listOf("x", "y", "z", "w")
private var currentStep = 0
var counter = 0
// 保存计时任务,出错/切换关卡时可以直接取消
private var countDownJob: Job? = null
// 实际项目中替换为页面/业务自身的协程作用域,禁止直接使用GlobalScope
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())

/**
 * 发送操作提示,保留原有函数结构,实际场景中可在这里更新UI提示用户
 */
fun sendInstruction(buttonLabel: String): String {
    println("请按住按钮 $buttonLabel 保持3秒")
    return buttonLabel
}

/**
 * 按钮按下事件回调,在按钮的按下监听里调用
 * @param pressedLabel 用户按下的按钮标签
 */
fun onButtonPress(pressedLabel: String) {
    // 先取消上一轮没完成的计时任务
    countDownJob?.cancel()
    val targetLabel = buttonOrder[currentStep]
    if (pressedLabel != targetLabel) {
        // 按错按钮,直接重置流程
        resetFlow()
        return
    }
    // 按对当前按钮,开始3秒计时校验
    countDownJob = scope.launch {
        var heldTime = 0L
        val checkInterval = 100L
        while (heldTime < 3000) {
            delay(checkInterval)
            heldTime += checkInterval
            // 每次轮询校验用户是否持续按住正确按钮,实际项目替换为自己的按压状态判断逻辑
            if (!isUserHoldingButton(pressedLabel)) {
                resetFlow()
                return@launch
            }
        }
        // 按住满3秒,验证通过
        counter += 20
        currentStep++
        if (currentStep >= buttonOrder.size) {
            println("全部按钮验证通过,当前得分:$counter")
            return@launch
        }
        // 发送下一个按钮的操作指令
        sendInstruction(buttonOrder[currentStep])
    }
}

/**
 * 按钮松开事件回调,在按钮的松开监听里调用
 */
fun onButtonRelease() {
    // 计时未完成就松开按钮,直接重置流程
    if (countDownJob?.isActive == true) {
        resetFlow()
    }
}

/**
 * 重置流程:计数器归零,回到x按钮验证环节
 */
fun resetFlow() {
    countDownJob?.cancel()
    counter = 0
    currentStep = 0
    sendInstruction(buttonOrder[currentStep])
}

// 示例方法,实际项目替换为你自己的按压状态判断逻辑
fun isUserHoldingButton(label: String): Boolean {
    return true
}

// 业务初始化时调用,启动第一个验证指令
fun initFlow() {
    resetFlow()
}
补充说明
  • 代码没有用固定delay(3000)等待,而是每隔100ms检查一次按压状态,只要中途松手、按错键都会立刻触发重置,符合校验逻辑要求。
  • 所有状态统一管理,不管在哪一步出错都直接调用resetFlow()回到初始状态,不用写重复的重启逻辑。
  • 协程用结构化作用域管理,计时任务可随时取消,不会出现内存泄漏、无效等待的问题。
  • 如果要落地「不匹配则计数器递减」的胜率统计逻辑,只需要在按错分支、中途松手分支的重置逻辑前,加上counter = (counter - 1).coerceAtLeast(0)即可,避免计数器出现负数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 07:24:28