<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Feng.Li's Java See

    抓緊時間,大步向前。
    隨筆 - 95, 文章 - 4, 評論 - 58, 引用 - 0
    數據加載中……

    五子棋的博弈樹實現

    五子棋是一種受大眾廣泛喜愛的游戲,其規則簡單,變化多端,非常富有趣味性和消遣性。這里設計和實現了一個人機對下的五子棋程序,采用了博弈樹的方法,應用了剪枝和最大最小樹原理進行搜索發現最好的下子位置。介紹五子棋程序的數據結構、評分規則、勝負判斷方法和搜索算法過程。    
       
      一、相關的數據結構    
              關于盤面情況的表示,以鏈表形式表示當前盤面的情況,目的是可以允許用戶進行悔棋、回退等操作。    
              CList   StepList;    
              其中Step結構的表示為:    
       
              struct   Step  
      {  
            int     m;   //m,n表示兩個坐標值  
            int     n;  
            char   side;   //side表示下子方  
      };  
      以數組形式保存當前盤面的情況,  
      目的是為了在顯示當前盤面情況時使用:  
            char   FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];  
       
              其中FIVE_MAX_LINE表示盤面最大的行數。    
       
              同時由于需要在遞歸搜索的過程中考慮時間和空間有效性,只找出就當前情況來說相對比較好的幾個盤面,而不是對所有的可下子的位置都進行搜索,這里用變量CountList來表示當前搜索中可以選擇的所有新的盤面情況對象的集合:    
       
          CList   CountList;  
              其中類CBoardSituiton為:  
          class   CBoardSituation  
          {  
          CList       StepList;   //每一步的列表  
          char   FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];  
          struct   Step   machineStep;           //機器所下的那一步  
          double   value;     //該種盤面狀態所得到的分數  
      }  
       
      二、評分規則    
              對于下子的重要性評分,需要從六個位置來考慮當前棋局的情況,分別為:-,|,/,\,//,\\    
         
       
              實際上需要考慮在這六個位置上某一方所形成的子的布局的情況,對于在還沒有子的地方落子以后的當前局面的評分,主要是為了說明在這個地方下子的重要性程度,設定了一個簡單的規則來表示當前棋面對機器方的分數。    
       
              基本的規則如下:    
       
      判斷是否能成5,   如果是機器方的話給予100000分,如果是人方的話給予-100000   分;    
      判斷是否能成活4或者是雙死4或者是死4活3,如果是機器方的話給予10000分,如果是人方的話給予-10000分;    
      判斷是否已成雙活3,如果是機器方的話給予5000分,如果是人方的話給予-5000   分;    
      判斷是否成死3活3,如果是機器方的話給予1000分,如果是人方的話給予-1000   分;    
      判斷是否能成死4,如果是機器方的話給予500分,如果是人方的話給予-500分;    
      判斷是否能成單活3,如果是機器方的話給予200分,如果是人方的話給予-200分;    
      判斷是否已成雙活2,如果是機器方的話給予100分,如果是人方的話給予-100分;    
      判斷是否能成死3,如果是機器方的話給予50分,如果是人方的話給予-50分;    
      判斷是否能成雙活2,如果是機器方的話給予10分,如果是人方的話給予-10分;    
      判斷是否能成活2,如果是機器方的話給予5分,如果是人方的話給予-5分;    
      判斷是否能成死2,如果是機器方的話給予3分,如果是人方的話給予-3分。  
       
              實際上對當前的局面按照上面的規則的順序進行比較,如果滿足某一條規則的話,就給該局面打分并保存,然后退出規則的匹配。注意這里的規則是根據一般的下棋規律的一個總結,在實際運行的時候,用戶可以添加規則和對評分機制加以修正。    
       
      三、勝負判斷    
              實際上,是根據當前最后一個落子的情況來判斷勝負的。實際上需要從四個位置判斷,以該子為出發點的水平,豎直和兩條分別為   45度角和135度角的線,目的是看在這四個方向是否最后落子的一方構成連續五個的棋子,如果是的話,就表示該盤棋局已經分出勝負。具體見下面的圖示:    
         
       
      四、搜索算法實現描述    
              注意下面的核心的算法中的變量currentBoardSituation,表示當前機器最新的盤面情況,   CountList表示第一層子節點可以選擇的較好的盤面的集合。核心的算法如下:    
      void   MainDealFunction()  
      {  
            value=-MAXINT;   //對初始根節點的value賦值  
        CalSeveralGoodPlace(currentBoardSituation,CountList);  
        //該函數是根據當前的盤面情況來比較得到比較好的可以考慮的幾個盤面的情況,可以根據實際的得分情況選取分數比較高的幾個盤面,也就是說在第一層節點選擇的時候采用貪婪算法,直接找出相對分數比較高的幾個形成第一層節點,目的是為了提高搜索速度和防止堆棧溢出。  
      pos=CountList.GetHeadPosition();  
      CBoardSituation*   pBoard;  
      for(i=0;ivalue=Search(pBoard,min,value,0);  
            Value=Select(value,pBoard->value,max);      
          //取value和pBoard->value中大的賦給根節點  
      }  
      for(i=0;ivalue)      
      //找出那一個得到最高分的盤面  
          {  
                currentBoardSituation=pBoard;  
                PlayerMode=min;   //當前下子方改為人  
                Break;  
          }  
      }  
       
              其中對于Search函數的表示如下:實際上核心的算法是一個剪枝過程,其中在這個搜索過程中相關的四個參數為:(1)當前棋局情況;(2)當前的下子方,可以是機器(max)或者是人(min);(3)父節點的值oldValue;(4)當前的搜索深度depth。    
       
      double   Search(CBoardSituation&    
      board,int   mode,double   oldvalue,int   depth)  
      {  
            CList       m_DeepList;  
            if(deptholdvalue))== TRUE)  
                    {  
                          if(mode==max)  
                              value=select(value,search(successor  
                            Board,min,value,depth+1),max);  
                          else  
                              value=select(value,search(successor  
                              Board,max,value,depth+1),min);  
                    }  
                    return   value;  
            }  
            else  
            {  
        if   (   goal(board)<>0)      
      //這里goal(board)<>0表示已經可以分出勝負  
            return   goal(board);  
        else  
            return   evlation(board);  
                      }  
              }  
       
              注意這里的goal(board)函數是用來判斷當前盤面是否可以分出勝負,而evlation(board)是對當前的盤面從機器的角度進行打分。    
       
              下面是Select函數的介紹,這個函數的主要目的是根據   PlayerMode情況,即是機器還是用戶來返回節點的應有的值。    
       
      double   Select(double   a,double   b,int   mode)  
      {  
          if(a>b   &&   mode==max)||   (a<   b   &&   mode==min)  
      return   a;  
          else  
      return   b;  
      }  
       
      五、小結    
              在Windows操作系統下,用VC++實現了這個人機對戰的五子棋程序。和國內許多只是采用規則或者只是采用簡單遞歸而沒有剪枝的那些程序相比,在智力上和時間有效性上都要好于這些程序。同時所討論的方法和設計過程為用戶設計其他的游戲(如象棋和圍棋等)提供了一個參考

    posted on 2007-08-28 18:27 小鋒 閱讀(2774) 評論(2)  編輯  收藏

    評論

    # re: 五子棋的博弈樹實現  回復  更多評論   

    好像不是java 編寫 的
    我想java編寫 的
    2008-11-07 17:16 | EHOOF

    # re: 五子棋的博弈樹實現  回復  更多評論   

    拜托。。。。教我怎么在java里用結構體。。。
    2012-05-13 23:47 | dsf

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 国产色在线|亚洲| 人体大胆做受免费视频| 国产在线98福利播放视频免费| 菠萝菠萝蜜在线免费视频| 亚洲色中文字幕无码AV| 亚洲视频免费播放| 国产亚洲综合一区二区三区| 国产亚洲综合成人91精品| 91成人免费观看网站| 日韩免费在线中文字幕| 亚洲精品国产成人中文| 免费一级毛片在级播放| 日韩插啊免费视频在线观看| 亚洲色偷精品一区二区三区| 国产亚洲综合久久系列| 暖暖免费高清日本一区二区三区 | 国产精品永久免费| 亚洲精品在线不卡| 精品国产人成亚洲区| 最近免费中文字幕大全视频| 日韩a级无码免费视频| 亚洲精品9999久久久久无码| 亚洲国产精品热久久| 免费一级特黄特色大片在线| 18禁男女爽爽爽午夜网站免费| 男女猛烈xx00免费视频试看| 亚洲国产电影在线观看| 激情97综合亚洲色婷婷五| 日韩免费无砖专区2020狼| 久久精品无码专区免费东京热| 美女露100%胸无遮挡免费观看| 亚洲欧洲久久精品| 久久久久久久尹人综合网亚洲| 免费看国产曰批40分钟| 毛色毛片免费观看| 免费看又黄又无码的网站| 成在线人视频免费视频| 爱情岛论坛免费视频| 最新亚洲精品国偷自产在线| 亚洲精品视频专区| 香蕉视频在线观看亚洲|