# 围棋势力图 **Repository Path**: lp9906/go-power-map ## Basic Information - **Project Name**: 围棋势力图 - **Description**: 网页围棋 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-26 - **Last Updated**: 2026-10-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 围棋势力图 一个用 **Vite + 原生 TypeScript + Canvas 2D** 写的网页围棋:零框架、零运行时依赖。 ![围棋势力图:半透明势力遮罩把全盘地盘一眼画清楚](docs/screenshots/territory.png) 除标准玩法外,它解决新手最大的痛点——**看不懂"谁占了哪块地"**。 每颗棋子都是势力种子,把整个棋盘划分成互不相交的黑区与白区, 黑区铺半透明黑、白区铺半透明白,交界处划一条高亮"国境线"。 地盘于是变成画面上的明暗色块:不用数气、不用棋感,一眼看懂。 > 状态:M1–M8 已全部完成。构建 `npm run build`,测试 `npm run test`。 > 代码遵循 `AGENTS.md` 架构规范:类化、一个类一个文件、模块门面出口、字符串枚举。 --- ## 核心特性 ### 标准围棋 | 功能 | 说明 | | --- | --- | | 棋盘规格 | 9 / 13 / 19 路一键切换 | | 基本规则 | 落子、提子、禁着点(自杀手)、打劫、虚手、悔棋与重做 | | 终局 | 双方连续虚手后标记死子,按中国数子法或日本数目法结算 | | 棋谱 | SGF 导入 / 导出 | | 操作 | 鼠标 / 触摸落子;滚轮缩放与拖拽平移默认关闭,可在“显示”面板开启 | ### 势力图(核心特色) - **全盘势力遮罩**:每个交叉点归属到最近的一方,黑区 / 白区整片铺色,随落子实时重划。 - **势力分界线**:两区交界处绘制高亮描边,即当前局面的"国境线"。 - **争议地带**:双方距离差小于阈值的窄带用中性灰 + 斜纹标出,提示"这里还没定型"。 - **气的可视化**:仅剩 1–2 气的棋块呼吸闪烁,并虚线圈出气点。 - **形势条**:实时显示双方控制点、目数差与胜率趋势。 - **连续热力图**:平滑渐变的势力视图,适合中盘大局判断。 - **新手模式**:一键只保留遮罩与分界线,画面最干净。 --- ## 界面 实战对局(浏览器中的实际使用效果): ![实战对局](docs/screenshots/playing.jpg) | 势力遮罩(默认视图) | 新手模式(只留遮罩与分界线) | | --- | --- | | ![势力遮罩](docs/screenshots/territory.png) | ![新手模式](docs/screenshots/beginner.png) | | 暗色主题 | 连续势力热力图 | | ![暗色主题](docs/screenshots/dark.png) | ![连续势力热力图](docs/screenshots/heatmap.png) | 打开 `?demo=1` 载入内置演示局面,`?view=beginner|dark|heat` 切换视图, 例如 `index.html?demo=1&view=beginner`。截图由 `npm run shots` 自动重新生成。 --- ## 技术栈 - 构建:Vite 5;语言:TypeScript `strict`(原生,无 React / Vue) - 渲染:Canvas 2D,五层离屏画布 - 测试:Vitest - 依赖:`dependencies` 为空 --- ## 快速开始 ```bash npm install npm run dev # 开发服务器 npm run build # tsc --noEmit && vite build npm run test # 单元测试 ``` --- ## 目录结构 ``` 围棋势力图/ ├─ index.html · vite.config.ts · tsconfig.json · package.json ├─ scripts/gen-territory-preview.mjs # 算法原型出图脚本(零依赖,直接产 PNG) ├─ tests/smoke.test.ts # 规则与分析冒烟用例 └─ src/ ├─ main.ts # 装配点:引擎 / 分析 / 渲染 / 界面 ├─ core/ # 规则引擎:棋盘、棋串与气、结算、SGF ├─ analysis/ # 势力划分、区域、形势判断 ├─ render/ # 几何、调色板、分层 Canvas 绘制 ├─ ui/ # 控件面板、形势条、快捷键、指针交互 └─ styles/main.css ``` 分层原则:`core` 纯逻辑不含 DOM;`analysis` 只读棋盘;`render` 只读状态; `main` 是唯一装配点。每个模块只从自己的 `index.ts` 对外。 --- ## 玩法与交互 - **落子**:鼠标左键 / 触摸点按。**虚手**:`P`。 - **悔棋 / 重做**:`Ctrl+Z` / `Ctrl+Shift+Z`。 - **显示开关**:`M` 遮罩、`B` 分界线、`H` 热力图、`G` 坐标、`N` 手数、`L` 气提示。 - **面板**:`A` 展开 / 收起;`K` 新手模式;`R` 新局。 - **视图**:棋盘默认固定;勾选“显示”面板的“缩放拖动”后可用滚轮缩放(0.6×–2.5×)与拖拽平移,复位按钮随时可用。 - **悬停**:显示交叉点坐标,以及该点归属(黑区 / 白区 / 争议)与距离差。 - **侧栏**:棋盘规格、规则与贴目、对局操作、遮罩透明度、分界线粗细、四套配色、SGF 导入导出;始终固定在右侧,窄屏只收窄宽度不换位。 - **配色**:经典 / 木色 / 暗色 / 色盲四套主题只换棋盘底色,界面底色取同一颜色,面板与控件层次由同底色的白色叠加而来,界面与棋盘浑然一体。 - **自动存档**:整盘棋(规格、规则、贴目与全部着手)连同显示开关、配色、遮罩参数、缩放开关都存在浏览器本地,下次打开自动续上;“重置设置”只清界面设置,不动棋局。 --- ## 势力图算法 1. **多源测地距离场**:所有棋子同时作为种子做带权最短路—— 走空格代价 `1.0`,紧贴对方棋子的格子 `× wallPenalty`(默认 1.2,体现厚壁挡路), 斜向穿越两颗对方棋子不可通行。得到每个交叉点到最近黑子 / 白子的步数。 2. **归属判定**:`gap = distBlack - distWhite`;`gap < -margin` 归黑、`gap > margin` 归白、 其间为争议(`margin` 默认 0.9)。棋子自身距离为 0,必然归本方。 3. **连通域标记**:对归属结果做 8 连通标记得到区域(面积、是否贴边、稳定度), 逐区填色、逐区描边,而不是逐子画光晕。 绘制要点:区域按格合并为 `Path2D` 一次填充,遮罩层位于网格之上、棋子之下, 色块不会糊住棋子;分界线取相邻不同归属的格边并合并共线。 分析计算放在 `requestIdleCallback`,手数不变时复用缓存,落子手感不受影响。 --- ## 形势判断 建立在区域划分结果之上,逻辑透明可解释:稳定区域计入确定地, 争议地带与低稳定度区域按双方距离差加权分配为期望目数, 再按所选规则(含贴目 `komi`)换算目数差,经 sigmoid 映射为胜率趋势。 因为每个交叉点都有明确归属,**形势条与画面色块完全自洽**: 玩家看到某块地变白,形势条就同步向白方移动,不会出现"图和数不一致"。 --- ## 开发状态 - [x] M1 脚手架:Vite + TS、Canvas 自适应、DPR、网格与星位 - [x] M2 规则引擎:落子、提子、禁着点、打劫、悔棋、虚手 - [x] M3 基础交互:落子、最后一手标记、坐标与手数、缩放平移 - [x] M4 全盘划分:距离场 + 归属判定 + 连通域 - [x] M5 势力遮罩:整片填充、分界线、透明度与配色、争议斜纹 - [x] M6 形势判断:由区域面积与稳定度推导目数、形势条 - [x] M7 ~~落子建议~~:曾实现,后按要求从 UI 与分析层一并移除 - [x] M8 终局与打磨:死子标记、中日规则结算、SGF、移动端适配 ## 尚未实现 - 落子建议(恢复见 git 历史 `d94cb41`)、变化图预览、教学标注(棋块编号与假眼可视化) - Web Worker 分析引擎、WebGPU 后端、GTP 对接引擎、复盘模式、死活题库、无障碍支持 --- ## 许可 [MIT](LICENSE) © 2026 LP