吴昊品游戏核心算法 Round 5 —— 五子棋(无禁手)后台的判胜负AI(bfs+queue容器)(HDOJ 2699)

五子棋的历史

 

 

连子棋类游戏起源很早,在四千年前的两河文明就有古西亚连棋。

五子棋则咸信是流传于古中国的传统棋种之一,至今仍在民间广泛流传,规则相当简单。或许因没有形成一套独立完整的棋种理论及文化内涵,更无制定公平完善的规则来解决黑白平衡问题,一直没有得到发展,所以没有像围棋象棋等传统棋类流传广泛,导致缺少可考古的棋具,也没像直棋方棋等乡土棋类记载在地方县志、古人笔记等文献。

五子棋在传入日本后,被日本人发扬光大,自1899年日本棋士黒岩涙香证明了原始规则的五子棋先下必胜后,五子棋迈入一条不断改良的道路,经过数十年的修改、验证、再修改,最终发展出加入禁手的五子棋,并经过公开征名,称为连珠(RENJU),因此规则在日本成型,又称为日式规则或连珠规则。原始规则在中国依然有人在玩,也被称为无禁规则、自由规则,有软件可验证黑手必胜(这个稍后再证明)。

连珠规则禁止先下的黑棋下出双活三、双四、长连(超过五子以上的连线)下出则判败,此举限制黑棋的取胜方式,白棋则增加逼迫黑子下出禁手来取胜的手 段,使黑棋的优势稍稍减少。不过禁手也许对初学者来说是一种障碍,但下久后会发现,禁手使得双方棋手必需更加精准的掌握棋子的落点,增加了连珠的技术性、 复杂性及趣味性。

又过了几十年,人们发现单单加入禁手,尚无法完全平衡黑棋一子之先的优势,因此在国际比赛使用的“RIF规则”,在连珠规则的基础上,又加入了三手交换及五手两打,算第一个可以真正合乎公平竞技的职业规则。

  Problem——该问题,是用一串二维数组装载的字符串,用.表示空,用W表示白棋,用B表示黑棋,来判断目前的局面中的当前走棋的一方是否赢了整盘棋。

  Solve:

 /*
   该程序可以判定当前的一方是否获胜,如果暂时没有获胜或者已经告负,本
   程序会有相应的输出。
   AI的策略基本上和连连看的相似,也用的是queue容器+BFS
   (1)判断当前局势,利用目前棋盘上黑子和白子的数量进行比较
   (2)五子连环必须是恰好有五个子,也就是说,沿端点方向上的点应该是空格的
   (3)表面上是八个方向,实际上考虑到对称性,四个方向即可
   (4)在for循环的条件判断上加上flag,找到一例,即可退出循环
 */
 

  1 #include<iostream>
  2  #include<queue>//STL里面的queue容器
  3  using namespace std;
  4  
  5  struct Node //每个点有一个坐标,最大连通数以及方向
  6  {
  7    char x,y,time,dirc;
  8    bool no_stone;       
  9  };
 10  
 11  char map[15][15],c;//定义一个二维数组,表示棋盘,c表示现在轮到谁
 12  
 13  int dir[4][2]={{0,1},{1,0},{1,-1},{1,1}};//四个方向
 14  
 15  //BFS搜索,和之前的连连看类似
 16  bool bfs(int x,int y)
 17  {
 18    queue<Node> Q;
 19    Node first,next;
 20    int i;   
 21    first.x=x;
 22    first.y=y;
 23    first.no_stone=false;
 24    first.time=1;
 25    first.dirc=-1;
 26    Q.push(first);
 27    
 28    while(!Q.empty())
 29    {
 30      first=Q.front();
 31      Q.pop();
 32      //从第一个点开始,保证有且仅有五个是连在一起的,用no_stone标识没有多连
 33      if(first.time==5&&first.no_stone)
 34      {
 35        return true;                                 
 36      }             
 37      for(i=0;i<4;i++)
 38      {
 39        //初始方向不确定
 40        if(first.dirc==-1||first.dirc==i)
 41        {
 42          next.x=first.x+dir[i][0];
 43          next.y=first.y+dir[i][1];
 44          if(next.x>=0&&next.x<15&&next.y>=0&&next.y<15)
 45          {
 46            next.dirc=i;
 47            next.time=first.time+1;
 48            //唯独不标识对手的棋子,自己的棋子和空棋子用no_stone区分
 49            if(map[next.x][next.y]==c)                              
 50            {
 51              next.no_stone=first.no_stone;
 52              Q.push(next);                                                        
 53            }              
 54            else if(map[next.x][next.y]=='.'&&!first.no_stone)
 55            {
 56              next.no_stone=true;
 57              Q.push(next);     
 58            }  
 59          }                                 
 60        }                
 61      }     
 62    }  
 63    return false;
 64  }
 65  
 66  int main()
 67  {
 68    int T;
 69    scanf("%d",&T);
 70    while(T--)
 71    {
 72      int i,j;
 73      int white_num=0,black_num=0;
 74      getchar(); //读入一个回车键
 75      for(i=0;i<15;i++)
 76      {
 77        gets(map[i]);                 
 78      }          
 79      for(i=0;i<15;i++)
 80      {
 81        for(j=0;j<15;j++)
 82        {
 83          if(map[i][j]=='W')
 84          {
 85            white_num++;                  
 86          }             
 87          else if(map[i][j]=='B')
 88          {
 89            black_num++;     
 90          }     
 91        }                
 92      }
 93      //记录黑白棋子的数量,主要是判断当前下棋方是黑还是白
 94      if(black_num>white_num)
 95      {
 96        c='W';                       
 97      }
 98      else
 99      {
100        c='B';    
101      }
102      bool flag=true;
103      //只要找到一个“五子连”就可以了
104      for(i=0;i<15&&flag;i++)
105      {
106        for(j=0;j<15&&flag;j++)
107        {
108          if(map[i][j]==c)
109          {
110            flag=!bfs(i,j);                
111          }                       
112        }                       
113      }
114      if(flag) printf("NO\n");
115      else printf("YES\n");
116    }
117    return 0;    
118  }

 

 

posted on 2013-02-27 20:55  吴昊系列  阅读(489)  评论(0编辑  收藏  举报

导航