Perl,933个字符
$m=<<'';$_=' ';
sub h{/^(?:...)*(\d)\1\1/|/^.?.?(\d)..\1..\1/|/(\d)...\1...\1/|/^..(\d).\1.\1/&&$1}
sub r{substr($_,$p-1,1)=pop}sub p{my$w=pop;my@b=(0,h==$w||h&&-1);if(!$b[1]&&/ /){$b[1]=-9;
while(/ /g){local($_,$p)=($_,pos);r$w;$r=-(p($w^1))[1];@b=($p,$r)if$r>$b[1]}}@b}
if(($w=h||!/ /)||!@ARGV){$w--&&print+(nobody,X,O)[$w]," wins\n";s/(...)/$1\n/g;
tr/ 23/.XO/;print}else{$w=3;$w^=1for/\d/g;($p=pop)?r($w^1)&&!h&&(($p)=p$w)&&r$w:s/ /2/;
print"\$m=<<'';\$_='$_';\n$m\n$m"}
sub h{/^(?:...)*(\d)\1\1/|/^.?.?(\d)..\1..\1/|/(\d)...\1...\1/|/^..(\d).\1.\1/&&$1}
sub r{substr($_,$p-1,1)=pop}sub p{my$w=pop;my@b=(0,h==$w||h&&-1);if(!$b[1]&&/ /){$b[1]=-9;
while(/ /g){local($_,$p)=($_,pos);r$w;$r=-(p($w^1))[1];@b=($p,$r)if$r>$b[1]}}@b}
if(($w=h||!/ /)||!@ARGV){$w--&&print+(nobody,X,O)[$w]," wins\n";s/(...)/$1\n/g;
tr/ 23/.XO/;print}else{$w=3;$w^=1for/\d/g;($p=pop)?r($w^1)&&!h&&(($p)=p$w)&&r$w:s/ /2/;
print"\$m=<<'';\$_='$_';\n$m\n$m"}
请注意,实际上需要在脚本中间插入空白行。(除了为了清晰起见,不需要在长行末尾使用换行符,并且不包括在字符计数中。)
用法:在没有参数的情况下运行该程序时,它将显示当前游戏状态。由于开始时板是空的,因此输出为:
...
...
...
运行参数在1到9之间的程序,以声明该平方作为您的移动。该程序将自行移动,然后输出具有新状态的替换脚本。因此,例如:
$ perl ./qttt 5 > ./qttt-2
$ perl ./qttt-2
O..
.X.
...
仅在第一转时,您可以移动0
来表示计算机应该先移动。请注意,第一个玩家将永远是X
。
游戏结束后,显示输出将包含有关该效果的注释:
$ perl ./qttt-4 6 > ./qttt-5
$ perl ./qttt-5
O wins
OXX
OOX
X.O
该程序通过对游戏树进行标准的minimax搜索来工作。(井字游戏足够小,每次运行都可以生成完整的游戏树。)这种情况的例外是计算机先移动时-在这种情况下,最初移动到左上角很困难-编码。
请注意,该程序以适当的形式工作-脚本在任何时候都不会访问其自己的源文件以产生其输出。