169 lines
5.8 KiB
TypeScript
169 lines
5.8 KiB
TypeScript
import MakeTenDraw from '../shared/service/makeTenDraw';
|
||
import {
|
||
createMathPage,
|
||
CanvasDataState,
|
||
} from '../shared/common/mathPageMixin';
|
||
|
||
createMathPage({
|
||
canvas: null as Canvas | null,
|
||
ctx: null as RenderingContext | null,
|
||
boxHeight: 0,
|
||
boxWidth: 0,
|
||
drawService: null as MakeTenDraw | null,
|
||
makeTenData: null as {
|
||
problems: Array<{
|
||
left: number;
|
||
right: number;
|
||
result: number;
|
||
}>;
|
||
} | null,
|
||
|
||
data: {
|
||
pageTitle: '凑十法练习',
|
||
subTitle: '通过凑十法学习20以内进位加法',
|
||
functionId: '',
|
||
hasContent: false,
|
||
showShareDialog: false,
|
||
} as CanvasDataState,
|
||
|
||
onLoad(options: { id?: string }) {
|
||
const functionId = options.id || 'make-ten';
|
||
this.initPageInfo(functionId, '凑十法练习');
|
||
},
|
||
|
||
onReady() {
|
||
this.initCanvas({
|
||
createDrawService: (
|
||
canvas: Canvas,
|
||
ctx: RenderingContext,
|
||
options?: Record<string, any>,
|
||
) => {
|
||
return new MakeTenDraw(canvas, ctx, options);
|
||
},
|
||
drawServiceOptions: {
|
||
subTitle: this.data.subTitle,
|
||
},
|
||
onCanvasReady: () => {
|
||
// 初始随机生成
|
||
this.onRandom();
|
||
},
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 绘制Canvas内容
|
||
*/
|
||
async drawCanvas() {
|
||
if (!this.ctx || !this.drawService || !this.makeTenData) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await this.drawService.draw(this.makeTenData);
|
||
this.setData({ hasContent: true });
|
||
} catch (error) {
|
||
console.error('绘制失败:', error);
|
||
this.setData({ hasContent: false });
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 随机生成
|
||
*/
|
||
onRandom() {
|
||
const problems: Array<{
|
||
left: number;
|
||
right: number;
|
||
result: number;
|
||
}> = [];
|
||
// 用于记录已生成的题目,避免重复(9+2 和 2+9 视为不同)
|
||
const usedProblems = new Set<string>();
|
||
|
||
// 生成9道题目(3行3列)
|
||
let attempts = 0;
|
||
const maxAttempts = 1000; // 最大尝试次数,避免无限循环
|
||
|
||
while (problems.length < 9 && attempts < maxAttempts) {
|
||
attempts++;
|
||
// 生成两个数,确保:
|
||
// 1. 两个加数都在1-9之间(不能是10)
|
||
// 2. 和大于10且小于等于20(需要凑十法)
|
||
// 3. 大数至少是6(因为5无法满足条件:5 + 最大小数4 = 9 < 11)
|
||
let left: number;
|
||
let right: number;
|
||
|
||
// 随机决定大数在前还是在后
|
||
const bigFirst = Math.random() < 0.5;
|
||
|
||
if (bigFirst) {
|
||
// 大数在前:left 在 6-9 之间,right 在 1-9 之间
|
||
// 确保 left + right >= 11 且 left + right <= 20
|
||
left = Math.floor(Math.random() * 4) + 6; // 6-9
|
||
// right 的最小值:确保 left + right >= 11,即 right >= 11 - left
|
||
const minRight = Math.max(1, 11 - left);
|
||
// right 的最大值:确保 left + right <= 20,即 right <= 20 - left,且 right <= 9
|
||
const maxRight = Math.min(9, 20 - left);
|
||
// 确保 right < left(因为 left 是大数)
|
||
const actualMaxRight = Math.min(maxRight, left - 1);
|
||
// 检查是否有有效的 right 值
|
||
if (actualMaxRight >= minRight) {
|
||
right =
|
||
Math.floor(
|
||
Math.random() * (actualMaxRight - minRight + 1),
|
||
) + minRight;
|
||
} else {
|
||
// 如果无法生成有效值,跳过本次循环
|
||
continue;
|
||
}
|
||
} else {
|
||
// 大数在后:left 在 1-9 之间,right 在 6-9 之间
|
||
// 确保 left + right >= 11 且 left + right <= 20
|
||
right = Math.floor(Math.random() * 4) + 6; // 6-9
|
||
// left 的最小值:确保 left + right >= 11,即 left >= 11 - right
|
||
const minLeft = Math.max(1, 11 - right);
|
||
// left 的最大值:确保 left + right <= 20,即 left <= 20 - right,且 left <= 9
|
||
const maxLeft = Math.min(9, 20 - right);
|
||
// 确保 left < right(因为 right 是大数)
|
||
const actualMaxLeft = Math.min(maxLeft, right - 1);
|
||
// 检查是否有有效的 left 值
|
||
if (actualMaxLeft >= minLeft) {
|
||
left =
|
||
Math.floor(
|
||
Math.random() * (actualMaxLeft - minLeft + 1),
|
||
) + minLeft;
|
||
} else {
|
||
// 如果无法生成有效值,跳过本次循环
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// 检查是否重复(9+2 和 2+9 视为不同)
|
||
const problemKey = `${left},${right}`;
|
||
if (usedProblems.has(problemKey)) {
|
||
// 如果已存在,跳过本次循环,重新生成
|
||
continue;
|
||
}
|
||
|
||
// 添加到已使用集合
|
||
usedProblems.add(problemKey);
|
||
|
||
const result = left + right;
|
||
problems.push({
|
||
left,
|
||
right,
|
||
result,
|
||
});
|
||
}
|
||
|
||
// 如果尝试次数过多仍未生成足够的题目,输出警告
|
||
if (problems.length < 9) {
|
||
console.warn(
|
||
`只生成了 ${problems.length} 道题目,可能符合条件的题目组合不足`,
|
||
);
|
||
}
|
||
|
||
this.makeTenData = { problems };
|
||
this.drawCanvas();
|
||
},
|
||
});
|