HarmonyOS7应用《拼棋派对》实战:算术对战的出题、选答与计分
两个人轮流看一道算术题,从四个数字里选择答案,十题后比较分数。这是《拼棋派对》当前的算术对战。它不需要输入法,手机上点选即可完成一轮,适合用来讲清题目生成、干扰项、行动方和结算之间的关系。
本文对应主应用1.0.19,在HarmonyOS7 API26手机模拟器上走完十题。当前是轮流选择答案,双方不是同时抢答;选错也会进入下一题。阅读时先建立这些规则,再分析状态如何推进。
本文目录
一道题需要哪些状态
页面使用mathLeft、mathRight、mathOp描述题目,mathAnswer保存正确答案,mathChoices保存四个选项。mathRound、mathCurrentPlayer和双方分数描述比赛。题面状态与累计状态分开,生成新题不应把比分清空。
| 状态 | 更新时机 |
|---|---|
| 左右数字、运算符、答案、选项 | 新题生成时 |
| 当前玩家 | 一次答题结束后切换 |
| 题号 | 有效作答后增加 |
| A/B得分 | 当前玩家答对时增加 |
| finished | 第十题处理完成时 |
| 用时 | 活跃比赛中的计时回调 |
mathScore是累计答对数,A、B分数才用于双人胜负。仅显示总分不能回答哪位玩家获胜。页面状态条要把当前行动方与题号一并显示,减少两人对轮次归属的误解。
生成加减乘题目
prepareMathQuestion 用当前时间片段加round生成seed,再通过seed%3选择加法、减法或乘法。当前没有除法题,所以不会出现小数输入或整除判断。
下面摘录乘法分支:
this.mathOp = '×';
this.mathLeft = seed % 8 + 3;
this.mathRight = seed % 7 + 2;
this.mathAnswer = this.mathLeft * this.mathRight;
this.mathChoices = this.createMathChoices(this.mathAnswer, seed);
乘法左值为3—10,右值为2—8。加法使用另外的取模范围;减法把左值设在较大区间,当前生成的差为正数。把数值范围写在出题函数中,可以直接看出玩法面向的运算难度。
这种生成方式轻量,但不是严格随机题库,也不保证一局没有重复题。若需要分龄或难度分级,应把运算类型、数字范围和重复规则组织为配置,而不是在页面多个分支中散落常量。
答案与干扰项一起排列
createMathChoices 先把正确答案放进数组,再根据三个偏移生成干扰项。若某个选项等于答案或小于0,就改为另一正向偏移,最后交换排列。
const choices: number[] = [answer];
const offsets: number[] = [seed % 5 + 1, seed % 7 + 3, seed % 9 + 5];
for (let index = 0; index < offsets.length; index++) {
let option = answer +
(index % 2 === 0 ? offsets[index] : -offsets[index]);
if (option === answer || option < 0) {
option = answer + offsets[index] + index + 2;
}
choices.push(option);
}
这里排除了干扰项等于正确答案,但没有检查干扰项之间是否重复。比如seed=9时,第一和第三个偏移都为5,两个错误选项可能相同。页面仍可答题,不过四选项未必代表四个不同数字。
如果要完善这一点,可以把“是否已在choices中”加入生成条件,重复就重新取偏移,直到得到足够数量。也应设置有限尝试次数或可用偏移池,避免循环无法终止。这个改进尚未接入当前应用。
答题后计分并换人
点击选项后,handleMathChoice 先拒绝finished状态,比较choice与mathAnswer。答对时给当前玩家加1分,答错只提示正确答案;无论对错都调用nextMathQuestion(true)。
if (choice === this.mathAnswer) {
this.mathScore += 1;
if (this.mathCurrentPlayer === 'A') {
this.mathScoreA += 1;
} else {
this.mathScoreB += 1;
}
}
this.nextMathQuestion(true);
正常推进时,题号加一、行动方切换,最后生成新题。A从第1题开始,因此十题轮流作答时双方各有五次机会。答错不让本人重试,保持了固定次数的比赛节奏。
同一选项按钮的列表键包含choice与mathRound,让新题的显示身份随轮次更新。外层页面还包含题号与双方分数的id,用于明确刷新。讲解时不能只检查题面更换,也要检查当前玩家和统计数字同步改变。
第十题结算与重开
第十题处理后,nextMathQuestion先判断round是否达到10。它结束比赛并返回,不再增加成第11题,也不再切换玩家。
if (countRound && this.mathRound >= 10) {
this.finishMathDuel();
return;
}
if (countRound) {
this.mathRound += 1;
this.mathCurrentPlayer = this.mathCurrentPlayer === 'A' ? 'B' : 'A';
}
this.prepareMathQuestion(this.mathRound);
finishMathDuel比较双方成绩,相同为平局,否则高分获胜,并写入十题战绩。重开统一把题号、分数、用时和finished恢复,重新让A作答,再准备第1题。
新题生成与整局重开应分别处理。若在prepareMathQuestion中清零得分,每次换题都会丢失成绩;若重开只改题号,又可能保留上一局finished导致无法点击。
十题实操与边界检查
从数字分类进入算术对战并重开。本次第1题刻意选择错误选项,检查A不加分但轮到B;后续九题依据当前可见题面计算并选择正确答案,走到第10题结算,再点击再来一局。
按这一操作,A答对4次、B答对5次,最终B以5:4获胜。重开回到A作答、第1/10题、双方0分。演示重点是错误也推进、比分正确归属,以及最后一题计分后再结算。
本次没有修改出题算法,也没有宣称干扰项已去重。后续值得补充的用例包括重复选项、快速连续点选、新题与旧点击事件交叉,以及应用切页后的状态恢复。若加入自由输入,还要另外处理空输入、负号和提交按钮,不能把选答逻辑直接称为输入校验。
源码入口:pages/Index.ets 的 prepareMathQuestion、createMathChoices、handleMathChoice、nextMathQuestion 与 finishMathDuel。参考HarmonyOS官方文档。下一篇转向看图找茬的显示尺寸和点击坐标映射。
更多推荐

所有评论(0)