181 lines
5.6 KiB
TypeScript
181 lines
5.6 KiB
TypeScript
import DotConnectDraw from '../shared/service/dotConnectDraw';
|
|
import { createFocusPage } from '../shared/common/focusPageMixin';
|
|
import { DotConnectData } from '../shared/service/dotConnectDraw';
|
|
import { getRandomUniqueNumberColors } from '../../constants/colors';
|
|
|
|
createFocusPage({
|
|
canvas: null as Canvas | null,
|
|
ctx: null as RenderingContext | null,
|
|
boxHeight: 0,
|
|
boxWidth: 0,
|
|
drawService: null as DotConnectDraw | null,
|
|
dotConnectData: null as DotConnectData | null,
|
|
|
|
data: {
|
|
pageTitle: '数字点连线',
|
|
functionId: '',
|
|
hasContent: false,
|
|
showShareDialog: false,
|
|
},
|
|
|
|
onLoad(options: { id?: string }) {
|
|
const functionId = options.id || 'dot-connect';
|
|
this.setData({
|
|
functionId,
|
|
});
|
|
this.initPageInfo(functionId, '数字点连线');
|
|
},
|
|
|
|
onReady() {
|
|
this.initCanvas({
|
|
createDrawService: (
|
|
canvas: Canvas,
|
|
ctx: RenderingContext,
|
|
options?: Record<string, any>,
|
|
) => {
|
|
return new DotConnectDraw(canvas, ctx, options);
|
|
},
|
|
drawServiceOptions: {
|
|
title: this.data.pageTitle,
|
|
functionId: this.data.functionId,
|
|
},
|
|
onCanvasReady: () => {
|
|
// 初始随机生成
|
|
this.onRandom();
|
|
},
|
|
});
|
|
},
|
|
|
|
/**
|
|
* 绘制Canvas内容
|
|
*/
|
|
async drawCanvas() {
|
|
if (!this.ctx || !this.drawService || !this.dotConnectData) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await this.drawService.draw(this.dotConnectData);
|
|
this.setData({ hasContent: true });
|
|
} catch (error) {
|
|
console.error('绘制失败:', error);
|
|
this.setData({ hasContent: false });
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 生成不走回头路的数字序列
|
|
* @param length 序列长度
|
|
* @returns 数字序列数组
|
|
*/
|
|
generateNonBacktrackingSequence(length: number): number[] {
|
|
// 3x3 网格中数字的位置映射
|
|
// 1: (0,0), 2: (1,0), 3: (2,0)
|
|
// 4: (0,1), 5: (1,1), 6: (2,1)
|
|
// 7: (0,2), 8: (1,2), 9: (2,2)
|
|
const getPosition = (num: number): [number, number] => {
|
|
const row = Math.floor((num - 1) / 3);
|
|
const col = (num - 1) % 3;
|
|
return [row, col];
|
|
};
|
|
|
|
// 检查从位置A到位置B再到位置C是否走回头路
|
|
const isBacktrack = (
|
|
posA: [number, number],
|
|
posB: [number, number],
|
|
posC: [number, number],
|
|
): boolean => {
|
|
// 如果C等于A,说明走回头路了
|
|
return posC[0] === posA[0] && posC[1] === posA[1];
|
|
};
|
|
|
|
const sequence: number[] = [];
|
|
const used = new Set<number>();
|
|
|
|
// 随机选择起始数字
|
|
const startNum = Math.floor(Math.random() * 9) + 1;
|
|
sequence.push(startNum);
|
|
used.add(startNum);
|
|
|
|
let prevPos = getPosition(startNum);
|
|
let prevPrevPos: [number, number] | null = null;
|
|
|
|
// 生成剩余的数字
|
|
while (sequence.length < length) {
|
|
const candidates: number[] = [];
|
|
for (let num = 1; num <= 9; num++) {
|
|
if (used.has(num)) continue;
|
|
|
|
const currentPos = getPosition(num);
|
|
// 如果有前前一个位置,检查是否走回头路
|
|
if (prevPrevPos) {
|
|
if (isBacktrack(prevPrevPos, prevPos, currentPos)) {
|
|
continue;
|
|
}
|
|
}
|
|
candidates.push(num);
|
|
}
|
|
|
|
if (candidates.length === 0) {
|
|
// 如果没有候选数字,随机选择一个未使用的数字
|
|
const remaining = Array.from(
|
|
{ length: 9 },
|
|
(_, i) => i + 1,
|
|
).filter((n) => !used.has(n));
|
|
if (remaining.length === 0) break;
|
|
const nextNum =
|
|
remaining[Math.floor(Math.random() * remaining.length)];
|
|
sequence.push(nextNum);
|
|
used.add(nextNum);
|
|
prevPrevPos = prevPos;
|
|
prevPos = getPosition(nextNum);
|
|
} else {
|
|
// 随机选择一个候选数字
|
|
const nextNum =
|
|
candidates[Math.floor(Math.random() * candidates.length)];
|
|
sequence.push(nextNum);
|
|
used.add(nextNum);
|
|
prevPrevPos = prevPos;
|
|
prevPos = getPosition(nextNum);
|
|
}
|
|
}
|
|
|
|
return sequence;
|
|
},
|
|
|
|
/**
|
|
* 随机生成
|
|
*/
|
|
onRandom() {
|
|
// 生成1-9的数字颜色映射(每个数字使用随机颜色)
|
|
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
const colors = getRandomUniqueNumberColors(9);
|
|
const colorMap = numbers.map((number, index) => ({
|
|
number,
|
|
color: colors[index],
|
|
}));
|
|
|
|
// 生成9个组的题目
|
|
const groups: Array<{
|
|
sequence: number[];
|
|
}> = [];
|
|
|
|
for (let i = 0; i < 9; i++) {
|
|
// 生成不走回头路的数字序列,长度在4-6之间
|
|
const sequenceLength = Math.floor(Math.random() * 3) + 4; // 4, 5, 或 6
|
|
const sequence =
|
|
this.generateNonBacktrackingSequence(sequenceLength);
|
|
groups.push({
|
|
sequence,
|
|
});
|
|
}
|
|
|
|
this.dotConnectData = {
|
|
colorMap,
|
|
groups,
|
|
};
|
|
|
|
this.drawCanvas();
|
|
},
|
|
});
|