拼棋派对开发实战系列封面

在一组图形中找到亮点,再尽快作出操作,反应抢点用很少的元素就能形成一场短比赛。《拼棋派对》提供入门、标准和挑战三档,分别增加点位数量与比赛轮数。实现的核心是当前目标、双方得分、轮次和结束状态怎样一起推进。

本文分析主应用1.0.19的实际实现,在HarmonyOS7 API26手机模拟器上完成入门8轮。当前玩法没有等待随机信号的倒计时,也没有抢跑判罚;这里聚焦已有的目标切换和计分,不把它描述成精确反应时间测量工具。

本文目录

用一个索引表示当前亮点

reactionTarget 是当前亮点索引,页面遍历所有格子,通过index是否等于目标决定背景和文字颜色。目标背景为绿色,文字用明确的深色,其他格子采用非激活背景。

.backgroundColor(index === this.reactionTarget
  ? '#92F536' : this.inactiveControlBg())
.border({
  width: index === this.reactionTarget ? 3 : 1,
  color: index === this.reactionTarget ? '#2E7600' : this.strokeColor()
})
.onClick(() => this.handleReactionCell(index))

这是当前 ReactionCell 的样式与事件节选。一个目标索引比每格保存一个独立“是否亮起”状态更容易维持唯一目标:索引变化后,旧目标自动变暗,新目标自动变亮。

图形符号只帮助区分格子,不决定分数。命中依赖索引而不是符号内容,避免同样图形重复出现时混淆目标。

点击点位与玩家抢答是两个入口

handleReactionCell 比较点击索引与reactionTarget。命中时调用 hitReaction('A'),未命中只给反馈,不加分、不推进轮次。因此直接点击棋盘亮点,当前归属玩家A。

页面另外提供“玩家A抢”和“玩家B抢”按钮,分别直接调用hitReaction。它们没有传入点位索引,也没有再验证是否点击了亮点。两个人使用按钮时,实际上是人工认定谁先抢到,而不是每人选择正确格子后由程序判定。

private handleReactionCell(index: number): void {
  if (index === this.reactionTarget) {
    this.hitReaction('A');
    return;
  }
  this.pulseMiss();
  this.notice = '没有抢到亮点,继续观察';
}

电脑的F、J键也分别进入A、B计分入口,heldKeyCodes避免按住一个键重复触发。该分支来自源码核对,本轮只用手机触摸操作,没有进行键盘实测。

这一区别影响产品说明:不能说“双方都必须点中亮点才能得分”。如果后续要实现双方各自点位选择,需要事件同时携带player与index,再统一验证命中。

先计分再推进轮次

hitReaction 先拒绝已经结束的比赛,然后给对应玩家加一分。到达最后一轮时直接结算,否则增加轮次并计算下一目标。

if (player === 'A') {
  this.reactionScoreA += 1;
} else {
  this.reactionScoreB += 1;
}
if (this.reactionRound >= this.reactionRoundTotal()) {
  this.finishReactionTap();
  return;
}
this.reactionRound += 1;
this.reactionTarget = this.nextReactionIndex(player === 'A' ? 2 : 5);

分数属于玩家,轮次和亮点属于整场比赛。若把轮次也拆成双方各一份,就会变成两个独立训练,而不是同一个亮点的竞争。

最后一轮先计分再结束,保证最终抢答计入成绩。提前设置finished再调用统一计分函数,可能导致末轮被入口保护拒绝。

目标切换与难度配置

难度格子数量比赛轮数
入门2×2,共4格8轮
标准3×3,共9格12轮
挑战4×4,共16格16轮

下一目标由当前索引、轮次和offset计算:

private nextReactionIndex(offset: number): number {
  return Math.abs((this.reactionTarget * 5 +
    this.reactionRound * 3 + offset) % this.reactionCellTotal());
}

这是确定性公式,不是均匀随机抽样,也没有显式排除与上一轮相同的目标。不能仅凭界面高亮位置改变过,就认为每轮一定不同。

“下一点位”工具会直接增加轮次,但不加任何一方的分数;最后一轮使用它则结束比赛。因此总分可能小于总轮数。如果需要“必须作答才能推进”,应改变这个工具的产品语义,而不是在结算时强行补分。

结束与重新开始

结算比较双方得分,相同为平局,较高者获胜。finishReactionTap标记finished,停止音乐,保存难度、比分与用时。它没有计算单次命中延迟,也没有每轮反应时间数组。

重开将轮次设为1、双方分数与用时归零,并根据时间取一个合法初始目标。初始目标始终位于当前格子数量范围内。难度变化需要检查格子数、轮数和目标范围同时一致,不能只换网格模板。

模拟器效果与改进方向

进入反应记忆分类,选择反应抢点,再切入门并重开。本次先点一个暗格,检查双方仍为0分;再点亮格,A加1分。后续交替使用双方抢答按钮完成8轮,结果为4:4平局,再来一局恢复零分。

反应抢点误点不计分,命中后推进轮次,双方抢答完成八轮平局并重开

动图把格子、比分和轮次放在同一条操作路径里。误点不能计分,命中后题面推进,结束后不能继续累计,这些比初始亮点是否好看更能说明玩法是否工作。

如果要把它升级成严格反应竞赛,建议增加准备、等待信号、允许响应和结束四个阶段;在允许响应时记录时间戳,并验证当前轮标识。倒计时期间输入应判抢跑或拒绝,双人输入必须竞争同一轮,结束后旧输入不能进入新局。这些属于下一步设计,本轮没有在应用中实现。

源码入口:pages/Index.ets 的 ReactionCell、handleReactionCell、hitReaction、nextReactionTarget 和 restartReactionTap。参考HarmonyOS官方文档。下一篇把同样的轮次和计分思想用于算术选答。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐