C++五子棋(四)——走棋原理及权值计算

原理

计算

  • 计算每个落子点的**“权值”**,找到权值最大的落子点
  • 对于每个空白点,分别计算周围的八个方向
  • 不妨以该空白点作为参照原点,以水平向右作为X轴正方向,以竖直向下Y轴正方向建立平面直角坐标系
  • 因为在计算某个方向时,正向和反向需同时考虑,实际上只需要四个方向,即向量(1,0)的方向向量(1,1)方向向量(0,1)方向向量(-1,1)方向,图示如下(灵魂画图,请勿吐槽 滑稽)
灵魂画图

走棋原理

连2 活3 死3 活4 死4 连5

产生效果

  • 黑棋走这个点
产生效果评分
连210
死330
活340
死460
活4200
连520000

  • 如果白棋(AI)走这个点
产生效果评分
连15
连210
死325
活350
死455
活4300
连530000

权值计算

  • chessData.h
void calcScore(ChessData* data);
  • chessData.cpp
#include <string>
void calcScore(ChessData* data){
  if(!data) return;
  
  //统计玩家或AI连子
  int personNum = 0;	//玩家
  int botNum = 0;	//AI
  int emptyNum = 0;	//各方向空白位数
  
  
  //清空评分数组
  memset(data->scoreMap, 0, sizeof(data->scoreMap));
  for (int row = 0; row < BOARD_GRAD_SIZE; row++){
    for(int col = 0; col < BOARD_GRAD_SIZE; col++){
      //空白点计算
      if(row >= 0 && col >= 0 && data->chessMap[row][col] == 0){
        //遍历四个方向,然后分别计算正反四个方向
        int directs[4][2] = {{1,0}, {1,1}, {0,1}, {-1,1}};
        
        for(int k = 0; k < 4; k++){
          int x = directs[k][0];
          int y = directs[k][1];
          
          //重置
          personNum = 0;
          botNum = 0;
          emptyNum = 0;
          
          //对黑棋评分(正向)
          for(int i = 1; i <= 4; i++){
            if(row + i * y >= 0 && row + i * y < BOARD_GRAD_SIZE && 
             col + i * x >= 0 && col + i * x < BOARD_GRAD_SIZE && 
              data->chessMap[row + i * y][col + i * x] == 1){
              //玩家的子
              personNum++;
              
            }else if(row + i * y >= 0 && row + i * y < BOARD_GRAD_SIZE &&
                    col + i * x >= 0 && col + i * x < BOARD_GRAD_SIZE && data->chessMap[row + i * y][col + i * x] == 0){
              //空白位
              emptyNum++;
              break;	//遇到空白位置停止该方向搜索
              
            }else{
              break;	//出边界或遇到白棋停止搜索
            }
            
            
          }
          
          //对黑棋评分(反向)
          for(int i = 1; i<= 4; i++){
            if(row - i * y >= 0 && row - i * y < BOARD_GRAD_SIZE && 
              col - i * x >= 0 && col - i * x <BOARD_GRAD_SIZE && 
              data->chessMap[row - i * y][col - i * x] == 1){
              personNum++;
            }else if(row - i * y >= 0 && row - i * y <BOARD_GRAD_SIZE && 
                    col - i * x >= 0 && col - i * x < BOARD_GRAD_SIZE &&
                     data->chessMap[row -i * y][col - i * x] == 0){
              emptyNum++;
              break;
            }else{
              break;
            }
          }
          
          if(personNum == 1){
            data->scoreMap[row][col] += 10;
          }else if(personNum == 2){
            if(emptyNum == 1){
              //死3
              data->scoreMap[row][col] += 30;
            }else if(emptyNum == 2){
              //活3
              data->scoreMap[row][col] += 40;
            }
          }else if(personNum == 3){
            if(empty == 1){
              //死4
              data->scoreMap[row][col] += 60;
            }else if (emptyNum == 2){
              //活4
              data->scoreMap[row][col] += 200;
            }
          }else if(personNum == 4){
            data->scoreMap[row][col] += 20000;
          }
          emptyNum = 0;	//清空
          
          //对白棋评分(正向)
          for(int i = 1; i <= 4; i++){
            if(row + i * y > 0 && row + i * y < BOARD_GRAD_SIZE && 
              col + i * x > 0 && col + i * x < BOARD_GARD_SIZE &&
              data->chessMap[row + i * y][col + i * x == -1]){
              botNum++;
            }else if(row + i * y >0 && row + i * y < BOARD_GRAD_SIZE && 
                    col + i * x > 0 && col + i * x < BOARD_GRAD_SIZE && 
                    data->chessMap[row + i * y][col + i *x] == 0){
              emptyNum++;
              break;
            }else{
              break;
            }
          }
          //白棋评分(反向)
          for(int i = 1; i <= 4; i++){
            if(row - i * y > 0 && row - i * y <BOARD_GRAD_SIZE && 
              col - i * x > 0 && col - i * x < BOARD_GRAD_SIZE && 
              data->chessMap[row - i * y][col -i * x] == -1){
              botNum++;
            }else if (row - i * y >0 && row - i * y < BOARD_GRAD_SIZE &&
                     col - i * x > 0 && col - i * x < BOARD_GRAD_SIZE &&
                     data->chessMap[row - i * y][col - i * x] == 0){
              emptyNum++;
              break;
            }else{
              break;	//出边界
            }
          }
          
          if(botNum == 0){
            //连1
            data->scoreMap[row][col] += 5;
          }else if(botNum == 1){
            //活2
            data->scoreMap[row][col] += 10;
          }else if(botNum == 2){
            if(emptyNum == 1){
              //死3
              data->scoreMap[row][col] += 25;
            }else if(emptyNum == 2){
              //活3
              data->scoreMap[row][col] += 50;
            }
          }else if(botNum == 3){
            if(emptyNum == 1){
              //死4
              data->scoreMap[row][col] += 55;
            }else if(botNum == 2){
              //活4
              data->scoreMap[row][col] += 300;
            }
          }else if(botNum >= 4){
            //活5
            data->scoreMap[row][col] += 30000;
          }
          
        }
        
      }
    }
  }
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值