用dot语言画围棋棋谱

突发奇想要用dot语言来画围棋棋谱。

代码实现

测试了一下,交叉点用 point,棋子用 circle并fillcolor,可以完成棋谱的绘制。然而一个个点的画当然不现实,首先想到的就是将sgf棋谱转换为dot语言。用shell脚本实现,首先设置所有的点为point,然后重定义有棋子的点为circle。

#!/bin/bash

[ $# -lt 1 ] && echo "args error" && exit 1

sgf=$1
echo >$sgf.gv
cat >$sgf.gv << EOF
graph go {
size=15;
bgcolor="lightgoldenrod3";
node [shape="point", fontsize=27, fontname="SimHei"];
EOF

play=`grep ";B\ [" $sgf |tr -d ' \n)' |tr -s ';' ' '`   #\ [直接本没有空格,跟latex插件冲突。。臃肿难用,想放弃WordPress了。。

function sgf() {
	i=1
	for id in $play; do
		color=`echo $id | awk -F "[" '{print $1}'`
		point=`echo $id |awk -F "[" '{print $2}' |tr -d ']'`
		[ $i -lt 10 ] && num="  $i"
		[ $i -lt 100 ] && num=" $i"
		[ $i -gt 99 ] && num=$i
		
		if [ $color == B ]; then
			echo "$point [label=\"$num\", width=\"0.9\", fontcolor=\"cornsilk\", shape=\"circle\", style=\"filled\", fillcolor=\"black\"];" >>$sgf.gv
		elif [ $color == W ]; then
			echo "$point [label=\"$num\", width=\"0.9\", shape=\"circle\", style=\"filled\", fillcolor=\"cornsilk\"];" >>$sgf.gv
		fi
		let i+=1
		
	done
}

sgf

功能是实现了,然而速度非常慢。

棋子画好了,接下来是连线。连线比较固定,可以生成一次以后直接用。

arr=(a b c d e f g h i j k l m n o p q r s)

function a2d() {
	offset=96
	hex=`printf "%s" "'$1"`  #注意:$1前有个单引号
	ret=`echo "$hex $offset" | awk '{print $1-$2}'`
	return $ret
}

function d2a {
	echo "${arr[$1]}${arr[$2]}"
}

function draw() {
	for x in {0..18}; do
		for  y in {0..18}; do
			point=`d2a $x $y`
			l=`echo $x |awk '{print $1-1}'`
			r=`echo $x |awk '{print $1+1}'`
			u=`echo $y |awk '{print $1-1}'`
			d=`echo $y |awk '{print $1+1}'`
			
			left=`d2a $l $y`
			right=`d2a $r $y`
			up=`d2a $x $u`
			down=`d2a $x $d`
			if [ $r -lt 19 ]; then
				echo "$point -- $right;" >> $sgf.gv
			fi
			if [ $d -lt 19 ]; then
				echo "$point -- $down;" >> $sgf.gv
			fi
		done
	done
	echo "}" >>$sgf.gv
}

这里涉及到数字和字母的对照,a2d是字母转数字,这个比较通用,然而在这里并没有什么卵用,用数字计算点的边比较方便,所以需要数字转字母。找不到现成的通用函数,只好自己写了个d2a函数,只能处理特定字母和数字。

接下来,sgf函数生成棋子,然后将draw函数生成的文本追加到dot源码中,最后的dot源码片段示例:

graph go {
size=15;
bgcolor="lightgoldenrod3";
node [shape="point", fontsize=27, fontname="SimHei"];
pd [label=" 1", width="0.9", fontcolor="cornsilk", shape="circle", style="filled", fillcolor="black"];
dp [label=" 2", width="0.9", shape="circle", style="filled", fillcolor="cornsilk"];
pq [label=" 3", width="0.9", fontcolor="cornsilk", shape="circle", style="filled", fillcolor="black"];
...
aa -- ba;
ab -- ac;
ac -- bc;
...
}

GraphViz各种引擎生成的棋谱

neato引擎,就这个最靠谱

neato生成的棋谱
neato生成的棋谱

dot

dot画棋谱
dot画棋谱

twopi,放射状

twopi画棋谱
twopi画棋谱

fdp,变形的棋盘

fdp画棋谱
fdp画棋谱

参考资料

[1]. http://www.graphviz.org/content/attrs
[2]. http://www.graphviz.org/content/node-shapes
[3]. http://www.graphviz.org/content/color-names

One thought on “用dot语言画围棋棋谱

  1. Pingback: Discuz插件处理大型dot源码 | 知行近思

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注