暂时忘却神经网络和大模型,回顾一下古典的博弈搜索算法
博弈树,是指用于描述博弈过程中所有可能状态序列的树结构,其中节点代表游戏局面,边代表合法策略。
博弈树,也有人称之为搜索树,或者博弈搜索树,指的都是同一个对象。本文中统一称为“博弈树”。
以下是一棵节点有四个分枝的博弈树:
在井字棋中,博弈树要比上图大得多:
第一层(根节点)有九个分枝。
第二层的节点有八个分枝(去掉第一步选择的点)。
第三步的节点有七个分枝(去掉第一、第二点选择的点)。
以此类推。
语言的选择
在“井字棋”篇中,我们用 JavaScript(ES6) 来描述算法
“象棋”和“五子棋”的计算量大,所以采用C++编写搜索引擎,并编译成WASM供网页使用
class Modal 是井字棋搜索树的模型:
当模型实现以上的属性和方法,就可以开始最优策略搜索了。
详细代码如下:
class Modal {
constructor() {
this.path = [];
this.values = [];
this.indexs = [];
this.reset();
}
get MATE_VALUE() {
return 100;
}
get player() {
return this.path.length % 2;
}
get depth() {
return this.path.length;
}
get moves() {
var moves = [];
for (var x of this.indexs) {
if (this.values[x] == -1) {
moves.push(x);
}
}
return moves;
}
reset() {
this.path = [];
this.values = [-1,-1,-1,-1,-1,-1,-1,-1,-1];
this.indexs = [0,1,2,3,4,5,6,7,8];
for (var x=0; x<9; x++) {
var y = Math.floor(Math.random() * 9);
var temp = this.indexs[x];
this.indexs[x] = this.indexs[y];
this.indexs[y] = temp;
}
}
isfinal(move) {
const lines = [
[[1,2],[3,6],[4,8]],
[[0,2],[4,7]],
[[0,1],[4,6],[5,8]],
[[0,6],[4,5]],
[[0,8],[1,7],[2,6],[3,5]],
[[2,8],[3,4]],
[[0,3],[2,4],[7,8]],
[[6,8],[1,4]],
[[0,4],[2,5],[6,7]],
];
if (move < 0 || move >= 9) {
throw new Error('isfinal error: index out of bounds.');
}
if (this.values[move] != -1) {
throw new Error('isfinal error: data duplication.');
}
for (var x of lines[move]) {
if (this.values[x[0]] == this.values[x[1]] && this.values[x[1]] == this.player) {
return {score: this.MATE_VALUE-this.depth, points: [move, x[0], x[1]]};
}
}
return {score: 0, points: [-1, -1, -1]};
}
undomove() {
if (this.depth == 0) {
throw new Error('undomove error: empty stack.');
}
var move = this.path.pop();
this.values[move] = -1;
return 0;
}
domove(move) {
if (move < 0 || move >= 9) {
return new Error('domove error: index out of bounds.');
}
if (this.values[move] != -1) {
return new Error('domove error: data duplication.');
}
var result = this.isfinal(move);
this.values[move] = this.player;
this.path.push(move);
return result;
}
}