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, ) => { 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(); // 生成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(); }, });