Files
NumberSwipe_New/modes/01-number-stroke/tools/ascii.ts
T
cabinw 8026e4628d 初始提交:三玩法 Web 原型与设计文档
- 玩法一 数字一笔:规则库、求解器、26 关、竖屏触摸 Web 原型、测试
- 玩法二 连连气球:连消畅玩版核心、Web 原型、Cocos 球槽组件与导出脚本
- 玩法三 六边一笔:规则库、求解器、10 关 + 转墙实验包、Web 原型、测试
- 产品文档、UI 设计规范、各玩法 GDD / HANDOFF
- 文档移除全部外部参考作引用;删除玩法二 v0 旧稿
2026-09-16 14:30:59 +08:00

45 lines
1.4 KiB
TypeScript

// 终端里把盘面画成字符图,方便设计时看形状。只给工具用。
import type { Board } from '../src/board';
import { clueLabel, hasClue } from '../src/clue';
/**
* 每个单位格 4 字符宽。1×1 显示 id(或线索),大格用同一个标记铺满,空洞是 '.'。
* 传 path 时改为显示步号。
*/
export function renderAscii(board: Board, path?: number[]): string {
const stepOf = new Map<number, number>();
path?.forEach((c, i) => stepOf.set(c, i + 1));
const lines: string[] = [];
for (let y = 0; y < board.rows; y++) {
let line = '';
for (let x = 0; x < board.cols; x++) {
const ci = board.cellAtUnit(x, y);
if (ci < 0) {
line += ' . ';
continue;
}
const c = board.cells[ci];
let label: string;
if (path) {
const s = stepOf.get(ci);
label = s === undefined ? '?' : String(s);
} else if (hasClue(c)) {
label = `[${clueLabel(c)}]`;
} else {
label = c.id;
}
const big = c.w > 1 || c.h > 1;
const [ax, ay] = board.anchorUnit(ci);
const isOrigin = x === ax && y === ay;
const text = big && !isOrigin ? (path ? '·' : '·') : label;
line += text.padStart(3, ' ') + ' ';
}
lines.push(line.replace(/\s+$/, ''));
}
return lines.join('\n');
}
export function pathToIds(board: Board, path: number[]): string {
return path.map((c) => board.cells[c].id).join(' → ');
}