找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2835|回复: 0
打印 上一主题 下一主题
收起左侧

象棋的一个弱智级的AI程序

[复制链接]
跳转到指定楼层
楼主
ID:72008 发表于 2015-1-11 20:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

  1. 这个就是AI的主要部分,实现原理是枚举当前棋盘状况下的所有可走棋步然后随机输出一个棋步,
  2. 因为没有任何其他的判断所以是很原始的AI,象棋NB的童鞋可在此基础上加上更多的判断技巧使
  3. 它显的更智能。
  4. package xq;
  5. import java.util.ArrayList;//引入相关包
  6. import java.util.List;
  7. /**
  8. *
  9. * 该类是象棋的规则类,其他类通过调用canMove方法给出起始位置与结束位置
  10. * 其他类通过调用searchAGoodMove方法得到最当然棋局最好的走法
  11. * 而其中的allPossibleMoves方法得到的是当前棋局的所有的走法
  12. *
  13. */
  14. public class GuiZe {
  15. boolean isRedGo = false;//是不是红方走棋
  16. public boolean canMove(int[][] qizi, int fromX ,int fromY, int toX, int toY ){
  17.   int i = 0;
  18.   int j = 0;
  19.   int moveChessID;//起始位置是什么棋子
  20.   int targetID;//目的地是什么棋子或空地
  21.   if(toX<0){//当左边出界时
  22.    return false;
  23.   }
  24.   if(toX>8){//当右边出界时
  25.    return false;
  26.   }
  27.   if(toY<0){//当上边出界时
  28.    return false;
  29.   }
  30.   if(toY>9){//当下边出界时
  31.    return false;
  32.   }
  33.   if(fromX==toX && fromY==toY){//目的地与出发点相同,
  34.    return false;
  35.   }
  36.   moveChessID = qizi[fromY][fromX];//得到起始棋子
  37.   targetID = qizi[toY][toX];//得带终点棋子
  38.   if(isSameSide(moveChessID,targetID)){//如果是同一阵营的
  39.    return false;
  40.   }
  41.   switch(moveChessID){
  42.    case 1://黑帅
  43.     if(toY>2||toX<3||toX>5){//出了九宫格
  44.      return false;
  45.     }
  46.     if((Math.abs(fromY-toY)+Math.abs(toX-fromX))>1){//只能走一步
  47.      return false;
  48.     }
  49.     break;
  50.    case 5://黑士
  51.     if(toY>2||toX<3||toX>5){//出了九宫格
  52.      return false;
  53.     }
  54.     if(Math.abs(fromY-toY) != 1 || Math.abs(toX-fromX) != 1){//走斜线
  55.      return false;
  56.     }
  57.     break;
  58.    case 6://黑象
  59.     if(toY>4){//不能过河
  60.      return false;
  61.     }
  62.     if(Math.abs(fromX-toX) != 2 || Math.abs(fromY-toY) != 2){//相走“田”字
  63.      return false;
  64.     }
  65.     if(qizi[(fromY+toY)/2][(fromX+toX)/2] != 0){
  66.      return false;//相眼处有棋子
  67.     }
  68.     break;
  69.    case 7://黑兵
  70.     if(toY < fromY){//不能回头
  71.      return false;
  72.     }
  73.     if(fromY<5 && fromY == toY){//过河前只能直走
  74.      return false;
  75.     }
  76.     if(toY - fromY + Math.abs(toX-fromX) > 1){//只能走一步,并且是直线
  77.      return false;
  78.     }
  79.     break;
  80.    case 8://红将
  81.     if(toY<7||toX>5||toX<3){//出了九宫格
  82.      return false;
  83.     }
  84.     if((Math.abs(fromY-toY)+Math.abs(toX-fromX))>1){//只能走一步
  85.      return false;
  86.     }
  87.     break;
  88.    case 2://黑车
  89.    case 9://红车
  90.     if(fromY != toY && fromX != toX){//只能走直线
  91.      return false;
  92.     }
  93.     if(fromY == toY){//走横线
  94.      if(fromX < toX){//向右走
  95.       for(i = fromX + 1; i < toX; i++){//循环
  96.        if(qizi[fromY][i] != 0){
  97.         return false;//返回false
  98.        }
  99.       }
  100.      }
  101.      else{//向左走
  102.       for(i = toX + 1; i < fromX; i++){//循环
  103.        if(qizi[fromY][i] != 0){
  104.         return false;//返回false
  105.        }
  106.       }
  107.      }
  108.     }
  109.     else{//走的是竖线
  110.      if(fromY < toY){//向右走
  111.       for(j = fromY + 1; j < toY; j++){
  112.        if(qizi[j][fromX] != 0)
  113.        return false;//返回false      
  114.       }
  115.      }
  116.      else{//想左走
  117.       for(j= toY + 1; j < fromY; j++){
  118.        if(qizi[j][fromX] != 0)
  119.        return false;//返回false      
  120.       }
  121.      }
  122.     }
  123.     break;
  124.    case 10://红马
  125.    case 3://黑马
  126.     if(!((Math.abs(toX-fromX)==1 && Math.abs(toY-fromY)==2)
  127.       || (Math.abs(toX-fromX)==2 && Math.abs(toY-fromY)==1))){
  128.      return false;//马走的不是日字时
  129.     }
  130.     if(toX-fromX==2){//向右走
  131.      i=fromX+1;//移动
  132.      j=fromY;
  133.     }
  134.     else if(fromX-toX==2){//向左走
  135.      i=fromX-1;//移动
  136.      j=fromY;
  137.     }
  138.     else if(toY-fromY==2){//向下走
  139.      i=fromX;//移动
  140.      j=fromY+1;
  141.     }
  142.     else if(fromY-toY==2){//向上走
  143.      i=fromX;//移动
  144.      j=fromY-1;
  145.     }
  146.     if(qizi[j][i] != 0)
  147.      return false;//绊马腿
  148.     break;
  149.    case 11://红砲
  150.    case 4://黑炮
  151.     if(fromY!=toY && fromX!=toX){//炮走直线
  152.      return false;//返回false
  153.     }
  154.     if(qizi[toY][toX] == 0){//不吃子时
  155.      if(fromY == toY){//横线
  156.       if(fromX < toX){//想右走
  157.        for(i = fromX + 1; i < toX; i++){
  158.         if(qizi[fromY][i] != 0){
  159.          return false;//返回false
  160.         }
  161.        }
  162.       }
  163.       else{//向走走
  164.        for(i = toX + 1; i < fromX; i++){
  165.         if(qizi[fromY][i]!=0){
  166.          return false;//返回false
  167.         }
  168.        }
  169.       }
  170.      }
  171.      else{//竖线
  172.       if(fromY < toY){//向下走
  173.        for(j = fromY + 1; j < toY; j++){
  174.         if(qizi[j][fromX] != 0){
  175.          return false;//返回false
  176.         }
  177.        }
  178.       }
  179.       else{//向上走
  180.        for(j = toY + 1; j < fromY; j++){
  181.         if(qizi[j][fromX] != 0){
  182.          return false;//返回false
  183.         }
  184.        }
  185.       }
  186.      }
  187.     }
  188.     else{//吃子时
  189.      int count=0;
  190.      if(fromY == toY){//走的是横线
  191.       if(fromX < toX){//向右走
  192.        for(i=fromX+1;i<toX;i++){
  193.         if(qizi[fromY][i]!=0){
  194.          count++;
  195.         }
  196.        }
  197.        if(count != 1){
  198.         return false;//返回false
  199.        }
  200.       }
  201.       else{//向左走
  202.        for(i=toX+1;i<fromX;i++){
  203.         if(qizi[fromY][i] != 0){
  204.          count++;
  205.         }
  206.        }
  207.        if(count!=1){
  208.         return false;//返回false
  209.        }
  210.       }
  211.      }
  212.      else{//走的是竖线
  213.       if(fromY<toY){//向下走
  214.        for(j=fromY+1;j<toY;j++){
  215.         if(qizi[j][fromX]!=0){
  216.          count++;//返回false
  217.         }
  218.        }
  219.        if(count!=1){
  220.         return false;//返回false
  221.        }
  222.       }
  223.       else{//向上走
  224.        for(j=toY+1;j<fromY;j++){
  225.         if(qizi[j][fromX] != 0){
  226.          count++;//返回false
  227.         }
  228.        }
  229.        if(count!=1){
  230.         return false;//返回false
  231.        }
  232.       }
  233.      }
  234.     }
  235.     break;
  236.    case 12://红仕
  237.     if(toY<7||toX>5||toX<3){//出了九宫格
  238.      return false;
  239.     }
  240.     if(Math.abs(fromY-toY) != 1 || Math.abs(toX-fromX) != 1){//走斜线
  241.      return false;
  242.     }
  243.     break;
  244.    case 13://红相
  245.     if(toY<5){//不能过河
  246.      return false;//返回false
  247.     }
  248.     if(Math.abs(fromX-toX) != 2 || Math.abs(fromY-toY) != 2){//相走“田”字
  249.      return false;//返回false
  250.     }
  251.     if(qizi[(fromY+toY)/2][(fromX+toX)/2] != 0){
  252.      return false;//相眼处有棋子
  253.     }
  254.     break;
  255.    case 14://红卒
  256.     if(toY > fromY){//不能回头
  257.      return false;
  258.     }
  259.     if(fromY > 4 && fromY == toY){
  260.      return false;//不让走
  261.     }
  262.     if(fromY - toY + Math.abs(toX - fromX) > 1){//只能走一步,并且是直线
  263.      return false;//返回false不让走
  264.     }
  265.     break;
  266.    default:
  267.     return false;
  268.   }
  269.   return true;
  270. }
  271. /**
  272.   *
  273.   * 电脑是通过该方法得到当前棋局最好的走法
  274.   */
  275. public ChessMove searchAGoodMove(int[][] qizi){//查询一个好的走法
  276.   List<ChessMove> ret = allPossibleMoves(qizi);//产生所有走法
  277.   try {
  278.    Thread.sleep(2000);//睡眠四秒钟,以便调试
  279.   } catch (InterruptedException e) {//捕获异常
  280.    e.printStackTrace();//打印堆栈信息
  281.   }
  282.   return ret.get((int)(Math.random()*ret.size()));
  283. }
  284. public List<ChessMove> allPossibleMoves(int qizi[][]){//产生所有可能的走法
  285.    List<ChessMove> ret = new ArrayList<ChessMove>();//用来装所有可能的走法
  286.    for (int y = 0; y < 10; y++){
  287.     for (int x = 0; x < 9; x++){//循环所有的棋牌位置
  288.      int chessman = qizi[y][x];
  289.      if (chessman != 0){//当次位置不为空时,即有棋子时
  290.       if(chessman > 7){//是红方,即是玩家棋子时跳过
  291.        continue;
  292.       }
  293.       switch (chessman){
  294.        case 1://黑帅
  295.         if(canMove(qizi, x, y, x, y+1)){//向下走一格
  296.                        ret.add(new ChessMove(chessman, x, y, x, y+1, 0));
  297.                       }
  298.                       if(canMove(qizi, x, y, x, y-1)){//向上走一格
  299.                        ret.add(new ChessMove(chessman, x, y, x, y-1, 0));
  300.                       }
  301.                       if(canMove(qizi, x, y, x+1, y)){//向左走一格
  302.                        ret.add(new ChessMove(chessman, x, y, x+1, y, 0));
  303.                       }
  304.                       if(canMove(qizi, x, y, x-1, y)){//向右走一格
  305.                        ret.add(new ChessMove(chessman, x, y, x-1, y, 0));
  306.                       }
  307.                       break;
  308.       case 5://黑士
  309.       case 12://红仕
  310.        if(canMove(qizi, x, y, x-1, y+1)){//左下走
  311.         ret.add(new ChessMove(chessman, x, y, x-1, y+1, 1));
  312.        }
  313.        if(canMove(qizi, x, y, x-1, y-1)){//左上走
  314.         ret.add(new ChessMove(chessman, x, y, x-1, y-1, 1));
  315.        }
  316.        if(canMove(qizi, x, y, x+1, y+1)){//右下走
  317.         ret.add(new ChessMove(chessman, x, y, x+1, y+1, 1));
  318.        }
  319.        if(canMove(qizi, x, y, x+1, y-1)){//右上走
  320.         ret.add(new ChessMove(chessman, x, y, x+1, y-1, 1));
  321.        }
  322.        break;
  323.              case 6://黑象
  324.              case 13://红相
  325.        if(canMove(qizi, x, y, x-2, y+2)){//左上走
  326.         ret.add(new ChessMove(chessman, x, y, x-2, y+2, 1));
  327.        }
  328.        if(canMove(qizi, x, y, x-2, y-2)){//左下走
  329.         ret.add(new ChessMove(chessman, x, y, x-2, y-2, 1));
  330.        }
  331.        if(canMove(qizi, x, y, x+2, y+2)){//右下走
  332.         ret.add(new ChessMove(chessman, x, y, x+2, y+2, 1));
  333.        }
  334.        if(canMove(qizi, x, y, x+2, y-2)){//右上走
  335.         ret.add(new ChessMove(chessman, x, y, x+2, y-2, 1));
  336.        }
  337.               break;
  338.              case 7://黑兵
  339.               if(canMove(qizi, x, y, x, y+1)){//直走
  340.                ret.add(new ChessMove(chessman, x, y, x, y+1, 2));
  341.               }
  342.               if(y >= 5){//过河了
  343.                                 if (canMove(qizi, x, y, x - 1, y)) {//过河后向左走
  344.                                     ret.add(new ChessMove(chessman, x, y, x - 1, y, 2));
  345.                                 }
  346.                                 if (canMove(qizi, x, y, x + 1, y)) {//过河走向右走
  347.                                     ret.add(new ChessMove(chessman, x, y, x + 1, y, 2));
  348.                                 }
  349.               }
  350.               break;
  351.              case 14://红兵
  352.               if(canMove(qizi, x, y, x, y-1)){//向前走
  353.                ret.add(new ChessMove(chessman, x, y, x, y-1, 2));
  354.               }
  355.               if(y <=4 ){//过河了
  356.                                 if (canMove(qizi, x, y, x - 1, y)) {//过河后向左走
  357.                                     ret.add(new ChessMove(chessman, x, y, x - 1, y, 2));
  358.                                 }
  359.                                 if (canMove(qizi, x, y, x + 1, y)) {//过河走向右走
  360.                                     ret.add(new ChessMove(chessman, x, y, x + 1, y, 2));
  361.                                 }
  362.               }
  363.               break;
  364.              case 8://红将
  365.                       if(canMove(qizi, x, y, x, y+1)){//向下走一格
  366.                        ret.add(new ChessMove(chessman, x, y, x, y+1, 0));
  367.                       }
  368.                       if(canMove(qizi, x, y, x, y-1)){//向上走一格
  369.                        ret.add(new ChessMove(chessman, x, y, x, y-1, 0));
  370.                       }
  371.                       if(canMove(qizi, x, y, x+1, y)){//向右走一格
  372.                        ret.add(new ChessMove(chessman, x, y, x+1, y, 0));
  373.                       }
  374.                       if(canMove(qizi, x, y, x-1, y)){//向左走一格
  375.                        ret.add(new ChessMove(chessman, x, y, x-1, y, 0));
  376.                       }
  377.                       break;
  378.              case 2://黑车
  379.              case 9://红车
  380.               for(int i=y+1; i<10; i++){//向下走
  381.                if(canMove(qizi, x, y, x, i)){ //可以走时
  382.                 ret.add(new ChessMove(chessman, x, y, x, i, 0));
  383.                }else{//不可以走时直接 break
  384.                 break;
  385.                }
  386.               }
  387.               for(int i=y-1; i>-1; i++){//向上走
  388.                if(canMove(qizi, x, y, x, i)){//可以走时
  389.                 ret.add(new ChessMove(chessman, x, y, x, i, 0));
  390.                }else{//不可以走时
  391.                 break;
  392.                }
  393.               }
  394.               for(int j=x-1; j>-1; j++){//向走走
  395.                if(canMove(qizi, x, y, j, y)){//可以走时
  396.                 ret.add(new ChessMove(chessman, x, y, j, y, 0));
  397.                }else{//不可以走时
  398.                 break;
  399.                }
  400.               }
  401.               for(int j=x+1; j<9; j++){//向右走
  402.                if(canMove(qizi, x, y, j, y)){//可以走时
  403.                 ret.add(new ChessMove(chessman, x, y, j, y, 0));
  404.                }else{//不可以走时
  405.                 break;
  406.                }
  407.               }
  408.               break;
  409.              case 10://红马
  410.              case 3://黑马
  411.                       if(canMove(qizi, x, y, x-1, y-2)){//向上左走“日”字
  412.                        ret.add(new ChessMove(chessman, x, y, x-1, y-2, 0));
  413.                       }
  414.                       if(canMove(qizi, x, y, x-1, y+2)){//向下走“日”字
  415.                        ret.add(new ChessMove(chessman, x, y, x-1, y+2, 0));
  416.                       }
  417.                       if(canMove(qizi, x, y, x+1, y-2)){//向上右走“日”字
  418.                        ret.add(new ChessMove(chessman, x, y, x+1, y-2, 0));
  419.                       }
  420.                       if(canMove(qizi, x, y, x+1, y+2)){//向下右走“日”字
  421.                        ret.add(new ChessMove(chessman, x, y, x+1, y+2, 0));
  422.                       }
  423.                       if(canMove(qizi, x, y, x-2, y-1)){//向上右走“日”字
  424.                        ret.add(new ChessMove(chessman, x, y, x-2, y-1, 0));
  425.                       }
  426.                       if(canMove(qizi, x, y, x-2, y+1)){//向下右走“日”字
  427.                        ret.add(new ChessMove(chessman, x, y, x-2, y+1, 0));
  428.                       }
  429.                       if(canMove(qizi, x, y, x+2, y-1)){//向上右走“日”字
  430.                        ret.add(new ChessMove(chessman, x, y, x+2, y-1, 0));
  431.                       }
  432.                       if(canMove(qizi, x, y, x+2, y+1)){//向下右走“日”字
  433.                        ret.add(new ChessMove(chessman, x, y, x+2, y+1, 0));
  434.                       }
  435.               break;
  436.              case 11://红砲
  437.              case 4://黑炮
  438.               for(int i=y+1; i<10; i++){//向下走时
  439.                if(canMove(qizi, x, y, x, i)){//当可以走时
  440.                 ret.add(new ChessMove(chessman, x, y, x, i, 0));
  441.                }
  442.               }
  443.               for(int i=y-1; i>-1; i--){//向上走时
  444.                if(canMove(qizi, x, y, x, i)){//当可以走时
  445.                 ret.add(new ChessMove(chessman, x, y, x, i, 0));
  446.                }
  447.               }
  448.               for(int j=x-1; j>-1; j--){//向左走时
  449.                if(canMove(qizi, x, y, j, y)){//当可以走时
  450.                 ret.add(new ChessMove(chessman, x, y, j, y, 0));
  451.                }
  452.               }
  453.               for(int j=x+1; j<9; j++){//向右走时
  454.                if(canMove(qizi, x, y, j, y)){//当可以走时
  455.                 ret.add(new ChessMove(chessman, x, y, j, y, 0));
  456.                }
  457.               }
  458.               break;
  459.      }
  460.      }
  461.     }
  462.    }
  463.    return ret.isEmpty() ? null : ret;//当ret中没有走法时,返回空,有时返回ret
  464. }
  465. public boolean isSameSide(int moveChessID, int targetID){//判断两个子是否为同一阵营
  466.   if(targetID == 0){// 当目标地位空地时
  467.    return false;
  468.   }
  469.   if(moveChessID>7&&targetID>7){//当都为红色棋子时
  470.    return true;
  471.   }
  472.   else if(moveChessID<=7&&targetID<=7){//都为黑色棋子时
  473.    return true;
  474.   }
  475.   else{//其他情况
  476.    return false;
  477.   }
  478. }
  479. }
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表