练练手,近期实现的一个基于alpha-beta剪枝技术的机器人“追逐”程序

所谓的机器人“追逐”,就是在一个二维网格中,有两个机器人,位于网格中的两个相异的位置。一个“追捕”,一个“逃跑”。每回合机器人必须走出一步,且只能上下左右移动,不可斜向移动。当两个机器人位于同一位置时,追捕方获胜。

通俗的说,“追捕”希望离“逃跑”的距离越近越好,“逃跑”则希望和“追捕”保持足够的距离。每一方在决策此回合怎么走时,需要依据当前敌我双方在网格中的位置,并且预测对方可能的决策来做出最优的选择。例如,“追捕”在选择下一步的位置时,有四个选择,每一个选择都有一个评价值标明该选择的好坏。“追捕”需要在四个位置中选取评价分值最高的。当然,“逃跑”在其决策过程中也会采取其最优的选择,因此,“追捕”在决策时不但要考虑本回合我怎么走,还要考虑下回合对方怎么走,以及下下回合我该怎么应对。这就好比一个不断揣测对方心里的过程。

上述的决策过程在程序内部被表示成为在博弈树中计算倒退值的过程。由于每个节点都有n种决策,即n个子节点,k层的博弈树就有 n的k次方-1 个节点。决策中,完全遍历这些子节点在时空上都是不允许的。因此,需要引进裁剪技术。alpha-beta剪枝就是这样一种裁剪技术,其好处在于在遍历的同时,实时地删去一些无用节点。具体的做法就不再赘述了,只要记住永远是“与节点”的下界alpha值>大于“或节点”的上界beta值即可。

我的这个示例程序,设定了一个15*15的网格,红方为“追捕”机器人,由程序控制;绿方为用户控制的“逃跑”机器人。“逃跑”先行。很简陋。。。。

image

通过对话框设定双方初始位置

image

image

经过n步。。。被捕了。。。

image

附上alpha-beta剪枝的核心代码。

第一个是机器人做决策的线程函数,机器人通过博弈树搜索得到了下一步将要走到的位置,一个递归搜索的过程。

   1:  UINT RobotMakeChoice(LPVOID pParam)
   2:  {
   3:      CRobotChaseDlg *pRobotDlg = (CRobotChaseDlg *)(AfxGetApp()->m_pMainWnd);
   4:      if (IsRobotCatchHuman())//Judge whether the game is over
   5:      {
   6:          AfxMessageBox("Successfully Catch!");
   7:          gl_isGameStart = false;
   8:          gl_isRobotExist = false;
   9:          gl_isHumanExist = false;
  10:          gl_isCanHumanMove = false;
  11:          (CButton *)(pRobotDlg->GetDlgItem(IDC_BTN_SETPOS))->EnableWindow(true);
  12:          (CButton *)(pRobotDlg->GetDlgItem(IDC_BTN_START))->EnableWindow(false);
  13:          return 0;
  14:      }
  15:      int i = 0, iReturn;
  16:      int iMaxScore = INT_MIN;
  17:      Position posRobotNext;
  18:      Position posRobotNext_Best;
  19:      while (i < DIRECTION_NUM)
  20:      {
  21:          posRobotNext = gl_RobotPos;
  22:          if (i == 0)//left
  23:          {
  24:              --posRobotNext.X;
  25:          }
  26:          else if (i == 1)//right
  27:          {
  28:              ++posRobotNext.X;
  29:          }
  30:          else if (i == 2)//up
  31:          {
  32:              --posRobotNext.Y;
  33:          }
  34:          else//i == 3 down
  35:          {
  36:              ++posRobotNext.Y;
  37:          }
  38:          if (IsMoveLegal(posRobotNext))
  39:          {
  40:              iReturn = BetaPruning(1, iMaxScore, posRobotNext, gl_HumanPos);
  41:              if (iReturn > iMaxScore)
  42:              {
  43:                  iMaxScore = iReturn;
  44:                  posRobotNext_Best = posRobotNext;
  45:              }
  46:          }
  47:          i++;
  48:      }
  49:   
  50:      CDC *pDC = pRobotDlg->m_GameGrid.GetDC();
  51:      pRobotDlg->m_GameGrid.EraseRobot(pDC);
  52:      gl_RobotPos = posRobotNext_Best; // the robot move!!!
  53:      pRobotDlg->m_GameGrid.DrawRobot(pDC);
  54:      pRobotDlg->ReleaseDC(pDC);
  55:   
  56:      if (IsRobotCatchHuman())//Judge whether the game is over after the robot move
  57:      {
  58:          AfxMessageBox("Successfully Catch!");
  59:          gl_isGameStart = false;
  60:          gl_isRobotExist = false;
  61:          gl_isHumanExist = false;
  62:          gl_isCanHumanMove = false;
  63:          (CButton *)(pRobotDlg->GetDlgItem(IDC_BTN_SETPOS))->EnableWindow(true);
  64:          (CButton *)(pRobotDlg->GetDlgItem(IDC_BTN_START))->EnableWindow(false);
  65:      }
  66:      else
  67:      {
  68:          gl_isCanHumanMove = true;
  69:      }
  70:      return 0;
  71:  }

然后是节点处理函数,在处理节点的时候应用剪枝规则。(注意我的函数名起的不好,AlphaPruning实际上是在或节点中应用beta剪枝,BetaPruning是在与节点中应用alpha剪枝)

   1:  //alpha_pruning
   2:  int AlphaPruning(int iDepth, int iParentBeta, Position posRobot, Position posHuman)
   3:  {
   4:      if (iDepth == SEARCH_DEPTH)
   5:      {
   6:          return -(abs((posRobot.X-posHuman.X)*(posRobot.X-gl_HumanPos.X)) +
   7:                   abs((posRobot.Y-posHuman.Y)*(posRobot.Y-posHuman.Y)));
   8:      }
   9:      else
  10:      {
  11:          int i = 0, iReturn;
  12:          int iNowAlpha = INT_MIN;
  13:          Position posRobotNext;
  14:          while (i < DIRECTION_NUM)
  15:          {
  16:              posRobotNext = posRobot;
  17:              if (iNowAlpha > iParentBeta)
  18:              {
  19:                  //AfxMessageBox("beta!");//debug output
  20:                  break;
  21:              }
  22:              if (i == 0)//left
  23:              {
  24:                  --posRobotNext.X;
  25:              }
  26:              else if (i == 1)//right
  27:              {
  28:                  ++posRobotNext.X;
  29:              }
  30:              else if (i == 2)//up
  31:              {
  32:                  --posRobotNext.Y;
  33:              }
  34:              else//i == 3 down
  35:              {
  36:                  ++posRobotNext.Y;
  37:              }
  38:              if (IsMoveLegal(posRobotNext))
  39:              {
  40:                  iReturn = BetaPruning(iDepth+1, iNowAlpha, posRobotNext, posHuman);
  41:                  if (iReturn > iNowAlpha)
  42:                  {
  43:                      iNowAlpha = iReturn;
  44:                  }
  45:              }
  46:              i++;
  47:          }
  48:          return iNowAlpha;
  49:      }
  50:  }
  51:   
  52:  int BetaPruning(int iDepth, int iParentAlpha, Position posRobot, Position posHuman)
  53:  {
  54:      if (iDepth == SEARCH_DEPTH)
  55:      {
  56:          return -(abs((posRobot.X-posHuman.X)*(posRobot.X-gl_HumanPos.X)) +
  57:              abs((posRobot.Y-posHuman.Y)*(posRobot.Y-posHuman.Y)));
  58:      }
  59:      else
  60:      {
  61:          int i = 0, iReturn;
  62:          int iNowBeta = INT_MAX;
  63:          Position posHumanNext;
  64:          while (i < DIRECTION_NUM)
  65:          {
  66:              posHumanNext = posHuman;
  67:              if (iNowBeta < iParentAlpha)
  68:              {
  69:                  //AfxMessageBox("alpha!");//debug output
  70:                  break;
  71:              }
  72:              if (i == 0)//left
  73:              {
  74:                  --posHumanNext.X;
  75:              }
  76:              else if (i == 1)//right
  77:              {
  78:                  ++posHumanNext.X;
  79:              }
  80:              else if (i == 2)//up
  81:              {
  82:                  --posHumanNext.Y;
  83:              }
  84:              else//i == 3 down
  85:              {
  86:                  ++posHumanNext.Y;
  87:              }
  88:              if (IsMoveLegal(posHumanNext))
  89:              {
  90:                  iReturn = AlphaPruning(iDepth+1, iNowBeta, posRobot, posHumanNext);
  91:                  if (iReturn < iNowBeta)
  92:                  {
  93:                      iNowBeta = iReturn;
  94:                  }
  95:              }
  96:              i++;
  97:          }
  98:          return iNowBeta;
  99:      }
 100:  }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值