⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 怎样编制黑白棋(3).txt

📁 c语言的常用函数以及一些小游戏代码,如文曲星小游戏、五子棋游戏等
💻 TXT
字号:
怎样编制黑白棋(3)估值函数
 这是一个程序中最重要的部分,如果这个模块太弱,则就算算法再好也没有用。这里将要叙述三种不同的估值函数范例。大多数的黑白棋程序都可以归结于此。  
棋格表 
    这种算法的意思是,不同的棋格有不同的值,角的值大而角旁边的格子值要小。忽视对称的话,棋盘上有10个不同的位置,每个格子根据三种可能性赋值:黑棋、白棋和空。更有经验的逼近是在游戏的不同阶段对格子赋予不同的值。例如,角在开局阶段和中局开始阶段比终局阶段更重要。 

    一般认为,采用这种算法的程序总是很弱,但另一方面,它很容易实现,于是许多程序开始采用这种逼近。并且,对于许多程序设计者来说,它有能力使程序强到击败它的创造者... 
 
基于行动力的估值 
    这种更久远的接近有很强的全局观,而不像棋格表那样局部化。观察表明,许多人类玩者努力获得最大的行动力(可下棋的数目)和潜在行动力(临近对手棋子的空格,见技巧篇)。如果代码有效率的话,可以很快发现,它们提高棋力很多。和另一种人类的策略一样,许多基于行动力估值的程序同时还有一些边角配置的知识,试图在中盘早期使棋子最少。
 
基于模版的估值 
    正如上面提及的,许多中等力量的程序经常合并一些边角判断的知识,最大行动力和潜在行动力是全局特性,但是他们可以被切割成局部配置,再加在一起。棋子最少化也是如此。 这导致了以下的概括:在估值函数中仅用局部配置(模版),通常单独计算每一行、一列、斜边和角落的模板,再线性叠加在一起来实现。并且,配置情况的值非常依赖于游戏的不同阶段。比如,一条边有3321种配置情况((3^8-3^4)/2+3^4),每种情况的分值好坏在游戏的不同阶段都不相同。分值基于强力玩者和程序的游戏结果统计,他们存于数据库中,游戏启动时自动调入。 

常见的有这样一些模板: 名称 类似区域 配置数 去掉对称后的配置数 
corner5x2 a1:e2 3^10=59049 (3^10-3^5)/2+3^5 = 29646 
diag5 a5:e1 3^5 =243 (3^5 -3^3)/2+3^3 = 135 
diag6 a6:f1 3^6 =729 (3^6 -3^3)/2+3^3 = 378 
diag7 a7:g1 3^7 =2187 (3^7 -3^4)/2+3^4 = 1134 
diag8 a8:h1 3^8 =6561 (3^8 -3^4)/2+3^4 = 3321 
edge2x a1:h1 + b2 + g2 3^10=59049 (3^10-3^5)/2+3^5 = 29646 
hor2 a2:h2 3^8 =6561 (3^8 -3^4)/2+3^4 = 3321 
hor3 a3:h3 3^8 =6561 (3^8 -3^4)/2+3^4 = 3321 
hor4 a4:h4 3^8 =6561 (3^8 -3^4)/2+3^4 = 3321 
triangle a1:a4:d1 3^10=59049 (3^10-3^5)/2+3^5 = 29646 

 
估值合并 
    一般程序的估值基于许多的参数,如行动力、潜在行动力、余裕手、边角判断、稳定子(见技巧篇)。但是怎么样将他们合并起来得到一个估值呢?为了提高速度,一般的程序采用线性合并。设a1,a2,a3,a4为参数,则估值s:=n1*a1+n2*a2+n3*a3+n4*a4。其中n1,n2,n3,n4为常数,术语叫“权重”(weight),它决定了参数的重要性,来自于统计值。
 
一个基于棋格表和行动力估值的例子 
function Evalution: Double;
var
  i, j: Integer;
  oppMobility, compMobility: Integer;          //双方行动力
  oppValue, compValue: Integer;                //双方棋格表值
  temp: Double;
  Final: Boolean;
begin
  oppValue := 0;
  compValue := 0;
  if Final then                                //如果是终局搜索
  begin
    for i := 1 to 8 do
      for j := 1 to 8 do
      begin
        if Board[i, j] = compColor then
          Inc(compValue);                      //电脑的棋子数
        if Board[i, j] = oppColor then
          Inc(oppValue);                       //对手的棋子数
      end;
    Result := compValue - oppValue;
    Exit;
  end;
  oppMobility := 0;
  compMobility := 0;
  changeCost;                                  //动态修正棋格表的值
  for i := 1 to 8 do
    for j := 1 to 8 do
    begin
      if (Board[i, j] = compcolor) then
        compValue := compValue + cost[i, j];   //电脑的棋格表值
      if (Board[i, j] = oppColor) then
        oppValue := oppValue + cost[i, j];     //对手的棋格表值
    end;
  for i := 1 to 8 do
    for j := 1 to 8 do
    begin
      if chessable(i, j, compColor) then       //电脑在位置[i,j]可以下棋
        inc(compMobility);                     //增加电脑的行动力
      if chessable(i, j, oppColor) then        //对手在位置[i,j]可以下棋
        inc(oppMobility);                      //增加对手的行动力
    end;
  temp := sqrt(compMobility * 100) - sqrt(oppMobility * 100);
  if compValue - oppValue >= 0 then            //估值合并,不过这里用的并不是线性合并法
    Result := round((sqrt(compValue - oppValue) * 2 + temp) * 100) / 100
  else
    Result := -round((sqrt(oppValue - compValue) * 2 - temp) * 100) / 100;
end;
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -