五子棋智能算法-博弈树算法思想详解(一)

学习这个算法之前必会链表 关于链表看这两篇博文

https://blog.csdn.net/viafcccy/article/details/84502334

https://blog.csdn.net/viafcccy/article/details/85041942

 

在五子棋下棋中 我们最容易想到的算法就是对于棋局的推演 从而找到一种最佳的情况去使棋局向这个方向发展

为了简单思考我们首先想一个五子棋的开局

 

这种情况下黑棋有两种选择就是下方这两种棋型由于考虑到建模的复杂程度 和 计算机下棋的考虑时间 我们只考虑所有的直线型的棋型 将所有的直线型棋局穷举出来是可能的(我这里相当于将直线作为下棋的单位 所有的推演都是去寻找直线的棋局)

这里我列举出来

/***************一子/二子******************/
x0
0                  
00
0_0 
0_ _0
0_ _ _0
x00
x0_0
x0_ _0    
x0_ _ _0

/*****************三子**********************/ 
000 
0_00                            
00_ _0   
0_0_0
x000 
x0_00
x00_0
X0_ _00
X0_0_0
X00_ _0

/*****************四子**********************/
0000
0_000
00_00
x0000
x000_0
x0_000
x00_00

/*****************五子**********************/
00000

于是 此时 我们需要的是电脑去搜索所有的棋型 并把所有的情况列举出来构成一棵树 去推演最后选择最有利的一种棋型

下面我们需要的是为各个棋型打出分值 显然 例如 连成五子的棋型 对于我方来说是正无穷分 但是如果对方构成就需要打分负无穷分... 但是剩下的棋型打分需要自己去权衡和思考 可以是从你下棋的角度 认为某种棋型有利就是高分(对方就是相反数 会更小)

现在我要记住这棵树是从电脑出发去思考(所有的打分都是根据电脑去打分) 也就是 在电脑下棋的时候选择分数最高的一种局势 在对手下棋的时候肯定是去思考对对手最有利的情况(也就是分数最小的情况) 【这里为啥是最小很好想 对手四个连成一排 势必要去先处理这个位置的四个棋子 事情肯定是最紧急的优先去处理】 于是构成了下面的这棵博弈树

构建好这样一棵博弈树之后  就要去从最底层去逐层选择最小值和最大值去逐层推演 直到选择一种最佳的棋型 其实在编程时 我们要

1.搜索下一步所有的棋型

2.为每一种棋型建立一颗博弈树 最后选出分数最高的下一步

alpha-beta剪枝搜索 

 但是这里存在一个问题随着树的深度、广度的不断扩张 运算的数量是成指数级上涨的 也就是说电脑的运算次数有限 也就是整棵树的深度、广度是有限的 我们想要去在一定的时间里推演出更多的步骤 就需要去剔除一些显然不可能向上传递的分支 这里这个过程就叫做alpha-beta剪枝搜索 

重新回到开始的模型

也就是说不需要遍历完每一个节点 在遍历中遇到不可能的值时就直接剔除(图树的遍历是有深度和广度遍历的不要忘记) 

同理在上一层是选择最小值的时候 也是同一个道理

最后总结一下最基本的博弈树 和 alpha-beta剪枝算法步骤

1.搜索周边所有的棋型

2.选择每一种可能的走法 不断的搜索棋型 建立一棵博弈树 遍历 剪枝 推导出初始节点分值

3.最终选择一棵分值最高的博弈树的初始节点 按照这种棋型

4.等待人落子

5.重复1

  • 28
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
博弈树搜索算法是一种用于解决博弈问题的算法,其中五子棋是一个常见的应用场景。下面是一个基于博弈树搜索算法五子棋代码示例: ```cpp #include <iostream> #include <vector> const int BOARD_SIZE = 15; const int WIN_COUNT = 5; enum class Player { NONE, BLACK, WHITE }; struct Move { int row; int col; }; class Game { public: Game() : currentPlayer(Player::BLACK) { board.resize(BOARD_SIZE, std::vector<Player>(BOARD_SIZE, Player::NONE)); } void makeMove(const Move& move) { board[move.row][move.col] = currentPlayer; currentPlayer = (currentPlayer == Player::BLACK) ? Player::WHITE : Player::BLACK; } bool isGameOver() const { return checkWin() || isBoardFull(); } Player getWinner() const { return winner; } private: std::vector<std::vector<Player>> board; Player currentPlayer; Player winner; bool checkWin() { // 检查行 for (int row = 0; row < BOARD_SIZE; row++) { for (int col = 0; col <= BOARD_SIZE - WIN_COUNT; col++) { if (board[row][col] != Player::NONE) { bool win = true; for (int i = 1; i < WIN_COUNT; i++) { if (board[row][col + i] != board[row][col]) { win = false; break; } } if (win) { winner = board[row][col]; return true; } } } } // 检查列 for (int col = 0; col < BOARD_SIZE; col++) { for (int row = 0; row <= BOARD_SIZE - WIN_COUNT; row++) { if (board[row][col] != Player::NONE) { bool win = true; for (int i = 1; i < WIN_COUNT; i++) { if (board[row + i][col] != board[row][col]) { win = false; break; } } if (win) { winner = board[row][col]; return true; } } } } // 检查对角线 for (int row = 0; row <= BOARD_SIZE - WIN_COUNT; row++) { for (int col = 0; col <= BOARD_SIZE - WIN_COUNT; col++) { if (board[row][col] != Player::NONE) { bool win = true; for (int i = 1; i < WIN_COUNT; i++) { if (board[row + i][col + i] != board[row][col]) { win = false; break; } } if (win) { winner = board[row][col]; return true; } } } } // 检查反对角线 for (int row = WIN_COUNT - 1; row < BOARD_SIZE; row++) { for (int col = 0; col <= BOARD_SIZE - WIN_COUNT; col++) { if (board[row][col] != Player::NONE) { bool win = true; for (int i = 1; i < WIN_COUNT; i++) { if (board[row - i][col + i] != board[row][col]) { win = false; break; } } if (win) { winner = board[row][col]; return true; } } } } return false; } bool isBoardFull() const { for (int row = 0; row < BOARD_SIZE; row++) { for (int col = 0; col < BOARD_SIZE; col++) { if (board[row][col] == Player::NONE) { return false; } } } return true; } }; int main() { Game game; // 玩家输入示例 while (!game.isGameOver()) { int row, col; std::cout << "请输入下棋位置的行和列(以空格分隔):"; std::cin >> row >> col; Move move{row, col}; game.makeMove(move); } // 游戏结束后输出结果 Player winner = game.getWinner(); if (winner == Player::BLACK) { std::cout << "黑方获胜!" << std::endl; } else if (winner == Player::WHITE) { std::cout << "白方获胜!" << std::endl; } else { std::cout << "平局!" << std::endl; } return 0; } ``` 这段代码实现了一个简单的五子棋游戏,使用了博弈树搜索算法来判断胜负。玩家通过输入行和列来下棋,游戏会判断是否有一方获胜或者平局,并输出结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值