npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@go-board/tool

v0.4.0

Published

Go Board 工具库

Downloads

429

Readme

@go-board/tool

围棋棋局状态管理、不可变棋盘规则、坐标转换、布局创建与校验工具。

安装

# pnpm
pnpm add @go-board/tool

# npm
npm install @go-board/tool

# yarn
yarn add @go-board/tool

基础使用

import { GoGameData } from '@go-board/tool';

const game = new GoGameData({ size: 9 });

if (game.play('D4')) {
  game.rotate();
}

console.log(game.layout);
console.log(game.getSign('D4')); // 1

棋子标记:1 表示黑子,-1 表示白子,0 表示空位。文本坐标字母不使用 I,例如 A1、D4;顶点坐标使用 [x, y],左上角为 [0, 0]。

导出常量

| 名称 | 类型 | 说明 | | --- | --- | --- | | DEFAULT_SIZE | number | 默认棋盘边长,值为 19。 | | MIN_SIZE | number | 棋盘边长最小值,值为 1。 | | MAX_SIZE | number | 棋盘边长最大值,值为 25。 |

GoBoardData

GoBoardData 基于二维布局实现落子、提子、棋块、气、提子计数和简单劫规则。构造函数会复制传入布局和劫点;layout、ko、makeMove() 与 clone() 也不会向外暴露内部数组引用。传入行长度不一致的二维数组时,构造函数会抛出 layout is not well-formed 异常。

import { GoBoardData } from '@go-board/tool';

const board = new GoBoardData([
  [0, 1, 0],
  [0, -1, 0],
  [0, 0, 0],
], {
  sign: 1,
  vertex: [2, 1],
});

| 属性 | 类型 | 说明 | | --- | --- | --- | | height | number | 棋盘行数。 | | width | number | 棋盘列数。 | | widLen | [number, number] | 按 [width, height] 返回棋盘尺寸。 | | layout | GoLayout | 当前布局的深拷贝。 | | ko | KoInfo | 当前劫子信息的深拷贝。 |

| 方法 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | get | vertex: GoVertex | GoSign \| null | 获取顶点棋子,越界时返回 null。 | | has | vertex: GoVertex | boolean | 判断顶点是否位于棋盘内。 | | makeMove | sign: GoSignvertex: GoVertexoptions?: { preventOverwrite?: boolean; preventSuicide?: boolean; preventKo?: boolean } | GoBoardData | 返回落子后的新实例;可阻止覆盖、自杀和立即回提。棋子标记为 0 或顶点越界时返回当前状态的副本。 | | analyzeMove | sign: GoSignvertex: GoVertex | { pass: boolean; overwrite: boolean; capturing: boolean; suicide: boolean; ko: boolean } | 在不修改当前实例的前提下分析停着、覆盖、提子、自杀和劫。 | | getCaptures | sign: GoSign | number \| null | 返回黑方或白方的累计提子数,传入 0 时返回 null。 | | isValid | 无 | boolean | 校验棋子标记是否合法,并确认每个现有棋块至少有一口气。 | | getNeighbors | vertex: GoVertex | GoVertex[] | 返回顶点上下左右的有效相邻点。 | | getConnectedComponent | vertex: GoVertexpredicate: (vertex) => booleanresult?: GoVertex[] | GoVertex[] | 按条件查找连通顶点集合。 | | getChain | vertex: GoVertex | GoVertex[] | 返回与指定棋子同色且相连的完整棋块。 | | getLiberties | vertex: GoVertex | GoVertex[] | 返回指定棋块所有不重复的气。 | | hasLiberties | vertex: GoVertex | boolean | 判断指定棋块是否至少有一口气。 | | clone | 无 | GoBoardData | 复制布局、劫点和提子计数并返回新实例。 |

makeMove() 选项中的 preventOverwrite、preventSuicide 和 preventKo 默认均未启用;启用后发生对应冲突会分别抛出 Overwrite prevented、Suicide prevented 或 Ko prevented 异常。GoGameData 调用规则实例落子时会同时启用这三项限制,并将规则异常转换为 false。

GoGameData

构造参数 GoGameOptions

interface GoGameOptions {
  size?: number | string;
  layout?: GoLayout;
  player?: PlayerSign;
  ko?: KoInfo;
  latestVertex?: GoVertex;
}

| 参数 | 类型 | 说明 | 默认值 | | --- | --- | --- | --- | | size | number \| string | 棋盘边长,最终会被截断并限制在 1~25。 | 19 | | layout | GoLayout | 初始棋盘布局,必须是 size × size 的二维数组,且现有棋块必须至少有一口气。 | 空棋盘 | | player | PlayerSign | 当前执棋方:1 黑方,-1 白方。 | 1 | | ko | KoInfo | 初始劫子信息,包含受限方和劫点;不传时表示无劫。 | undefined | | latestVertex | GoVertex | 最新一手棋子的棋盘坐标;坐标无棋子或越界时自动置空。 | undefined |

构造配置无效时会回退到对应尺寸的空棋盘和黑方执棋。

属性

| 属性 | 类型 | 说明 | | --- | --- | --- | | board | GoBoardData | 当前规则实例的副本。 | | size | number | 当前棋盘边长。 | | player | PlayerSign | 当前执棋方。 | | ko | KoInfo \| undefined | 当前劫子信息的副本;无劫时返回 undefined。 | | cached | GoGameSnapshot | 最近一次通过 reset() 成功缓存的完整对局快照。 | | layout | GoLayout | 当前棋盘布局的副本。修改返回值不会影响棋局。 | | snapshot | GoGameSnapshot | 当前棋盘边长、布局、执棋方、劫子信息和最新落点的完整副本。 |

方法

| 方法 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | update | options: GoGameOptions | boolean | 按配置更新当前棋局但不更新 reset() 使用的缓存;布局或规则校验失败时返回 false 并保留原状态;无效 latestVertex 会被置空。 | | reset | options?: GoGameOptions | boolean | 按配置重置棋局并更新缓存。布局或规则校验失败时返回 false 并保留原状态;无效 latestVertex 会被置空;不传参数时恢复最近一次有效配置。 | | clear | size?: number \| stringnext?: PlayerSign | void | 清空棋盘,并设置棋盘边长和执棋方;不会更新 reset() 使用的最近有效配置。 | | play | position: GoGamePositionplayer?: PlayerSign | boolean | 尝试落子并执行占位、提子、自杀手和立即回提校验。成功后更新 latestVertex,但不会自动切换执棋方;可选 player 会在合法性预检通过后写入当前执棋方。 | | rotate | 无 | void | 在黑方和白方之间切换执棋方。 | | getSign | position: GoGamePosition | GoSign \| undefined | 获取指定位置的棋子标记;位置无效或越界时返回 undefined。 | | isLegal | position: GoGamePosition | boolean | 判断指定位置对当前执棋方是否为合法落点。 | | hasStone | position: GoGamePosition | boolean | 判断指定位置在当前棋盘中是否存在棋子。 |

player 参数不是临时覆盖:合法性预检使用调用前的当前执棋方,预检通过后才写入指定执棋方,并且不会自动恢复;如果随后规则实例抛出异常,方法返回 false,但已写入的执棋方仍会保留。

示例:初始化棋局

import { GoGameData } from '@go-board/tool';

const game = new GoGameData({
  size: 5,
  player: -1,
  layout: [
    [0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0],
    [0, -1, 0, 0, 0],
    [0, 0, 0, 0, 0],
  ],
});

示例:判断并落子

if (game.isLegal('C3') && game.play('C3')) {
  game.rotate();
}

GoHistoryData

GoHistoryData 按顺序保存 GoGameOptions 快照,并维护当前浏览位置。构造时默认定位到最后一条快照;历史为空时当前位置为 -1。历史容器会复制传入数组,但快照对象本身不会深拷贝。

import { GoHistoryData } from '@go-board/tool';

const history = new GoHistoryData([
  { size: 9, player: 1 },
  { size: 9, player: -1 },
]);

history.backward();
const current = history.snapshot;
history.forward();
history.jump(0);
history.insert({ size: 9, player: 1 });

| 属性 | 类型 | 说明 | | --- | --- | --- | | length | number | 历史快照数量。 | | current | number | 当前历史位置;空历史为 -1。 | | snapshot | GoGameOptions \| undefined | 当前历史位置对应的快照。 | | snapshots | GoGameOptions[] | 全部历史快照;返回内部数组,快照对象不复制。 |

| 方法 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | clear | 无 | void | 清空全部历史并将当前位置设为 -1。 | | backward | step?: number | GoGameOptions \| undefined | 向前移动指定步数,默认 1 步;步数必须为正整数。 | | forward | step?: number | GoGameOptions \| undefined | 向后移动指定步数,默认 1 步;步数必须为正整数。 | | jump | position: number | GoGameOptions \| undefined | 跳转到指定历史位置;越界或非整数时保持当前位置不变。 | | insert | snapshot: GoGameOptionsposition?: number | boolean | 在指定位置插入快照,并丢弃该位置之后的全部历史;默认插入当前位置之后。 |

形势布局

getInfluenceLayout() 仅使用 @sabaki/deadstones 的 getProbabilityMap() 计算形势布局。每个位置的概率绝对值大于 0.15 时才有效,正值归为黑方势力,负值归为白方势力,否则归为中立。无论该位置是否已有棋子,均以概率计算结果为准。函数不会修改传入布局。

import { getInfluenceLayout } from '@go-board/tool';

const influence = await getInfluenceLayout(layout, {
  iterations: 300,
});

| 函数 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | getInfluenceLayout | layout: GoLayoutoptions?: GoInfluenceOptions | Promise<GoLayout> | 使用概率图直接计算黑白双方势力归属。 |

创建函数

| 函数 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | cloneLayout | layout: GoLayout | GoLayout | 深拷贝棋盘布局,避免直接修改原二维数组。 | | cloneVertex | vertex?: GoVertex | GoVertex \| undefined | 复制顶点坐标,避免共享可变数组引用。 | | createLayout | size: number | GoLayout | 创建指定边长的空棋盘布局。 |

import { cloneLayout, cloneVertex, createLayout } from '@go-board/tool';

const layout = createLayout(9);
const copiedLayout = cloneLayout(layout);
const copiedVertex = cloneVertex([1, 2]);

归一化函数

| 函数 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | normalizePlayer | value?: number | PlayerSign | 只有 -1 会保留为白方,其他值按黑方 1 处理。 | | normalizeSize | value?: number \| string | number | 将棋盘边长截断为整数并限制在 1~25;无效值使用 19。 | | normalizePosition | position: GoGamePositionlen: number | string \| null | 将文本或 GoVertex 坐标统一转换为大写文本坐标;拒绝字母 I、缺少行号或小于 1 的行号。 | | normalizeVertex | position: GoGamePositionlen: number | GoVertex \| null | 将文本坐标转换为左上角原点的顶点坐标;传入顶点时原样返回,不校验棋盘边界。 |

import { normalizePlayer, normalizePosition, normalizeSize, normalizeVertex } from '@go-board/tool';

normalizePlayer(undefined); // 1
normalizeSize('9.8'); // 9
normalizePosition(' d4 ', 9); // 'D4'
normalizePosition([1, 2], 3); // 'B1'
normalizePosition('I4', 9); // null
normalizeVertex('A3', 3); // [0, 0]

校验函数

| 函数 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | isValidLayout | layout: GoLayout \| undefinedsize: number | boolean | 校验布局是否为 size × size 的二维数组,且每个棋子标记只能是 -1、0 或 1。 | | vertexEquals | first: GoVertexsecond: GoVertex | boolean | 判断两个顶点的横纵坐标是否相等。 |

import { isValidLayout, vertexEquals } from '@go-board/tool';

const layout = [
  [0, 1],
  [-1, 0],
];

isValidLayout(layout, 2); // true
vertexEquals([0, 1], [0, 1]); // true

类型导出

| 类型 | 说明 | | --- | --- | | GoSign | 棋子标记:-1 \| 0 \| 1。 | | GoLayout | 棋盘二维布局数据,类型为 GoSign[][]。 | | GoVertex | 棋盘顶点坐标,类型为 [number, number]。 | | GoGamePosition | 落子位置:文本坐标或 GoVertex。 | | PlayerSign | 执棋方:-1 \| 1。 | | KoInfo | 劫子信息,包含 sign 和 vertex。 | | GoGameOptions | GoGameData 的初始化和重置配置。 | | GoGameSnapshot | 必填棋局字段与可为空的 latestVertex 组成的完整对局快照。 |

License

MIT License