2014.07.08 20:53

简介:

  Minimax策略描述的是二人在轮流操作的博弈中,尽力使自己的利益最大化(Max),使对手利益最小化(Min)的一种策略。

  这样的游戏有很多种,其中最典型的就是双人棋牌类游戏:中国象棋、五子棋、扑克牌等等。

  这样的游戏的特点是:

    1. 两人交替操作,一方先开始

    2. 两人的操作互相独立,没有协作

  游戏的种类实在太多,生活中处处是游戏。

  “游戏”和“博弈”的英语释义都是“game”,所以我们其实可以认为理论上它们是一回事,只不过一个通俗,一个深奥。

图示:

  本次我们使用书上给出的一个非常简单的棋牌游戏“三连棋”作为例子,来解释Minimax策略。

  如图:

  

  给定一个3X3的棋盘,两人轮流在上面画“O”和“X”,谁能先将三个相同符号连成一条线(横竖斜皆可),就算赢。

  本次的代码会实现这个游戏的AI,允许你和程序来玩这个游戏。运行程序后,你会发现不论你怎么下棋,你都赢不了的。

  因为这个游戏是公平的,没有必胜策略,因此电脑程序总能和你打成平局。

  如果你不好好下棋,当然也会输掉。

  

  下面我们开始讨论Minimax策略的理论部分。

  下面是一棵树(分叉数量我们不关心):

  

  上面这棵树叫“博弈树”,英文是game tree。其中Max层和Min层交替出现。关于这棵树有四点需要解释:

    1. Max层表示轮到我操作,期望我的利益最大化,所以标记为Max层

    2. Min层表示轮到对手操作,期望我的利益最小化,所以标记为Min层

    3. 节点中有一个数值,这个莫名其妙的数值是本章最难理解的东西——利益

    4. 树的底层总是叶子节点,此处每个叶子节点都表示游戏的一种结局,因为游戏结束了,树才不会继续延伸下去

  利益是什么?金钱,高考分数,身高体重,房子面积。总之说多了都是泪。

  游戏中的“利益”不能用一个“赢”字来概括,否则你无法着手去分析赢的办法。

  此处的利益,应该是具有多个参数的一个函数F(...),函数值越大,你离“赢”就越近。

  

  比如下象棋,“赢”的定义是吃掉对手的“将”或者“帅”。所以你不能将“对手的将是否存在”作为利益的判断条件。

  如果你手上现在有7个棋子,而对手只剩2个,那么很有可能你会赢,因此将双方棋子的数量差作为“利益”的标准,可能会更好。

  同样是象棋棋子,“车”的攻击力巨大,“马”的行动灵活,“士”的防御至关重要,因此不同的棋子为你带来的潜在利益各不相同。

  正是由于实际的游戏如此复杂,想用一个包含了很多参数的函数F(...)来表达利益才显得非常困难。

  对于中国象棋之类的游戏,这个估值函数可以复杂到让人吐血,也可以很简单。至于用户能看到的区别,就是“电脑厉害死了”和“电脑弱爆了”。

  

  至此,你要随时记住一个游戏中的两个条件:

    1. 赢的标准是什么(走象棋,吃掉对方的将帅)

    2. 为了达到“赢”,我应该朝什么方向努力(走象棋,努力吃掉对方的棋子)

  

  那么三连棋呢:

    1. 赢的标准,三个棋子连成一条线

    2. 为了达到“赢”,你应该尽力把自己的棋子连在一起

  

  至此我已经不知道该怎么继续讲了,因为我思考到这儿之后就直接开始编写代码了。

  现在你可以运行下面的代码,试试和电脑下棋,并单步调试观察运行过程。

  如果你要自己编码实现这个程序,请记住一条原则:你如果赢了电脑,那程序就是错的。

  在阅读代码的过程中,请尝试理解这个程序中是如何定义“利益”的。

实现:

感谢 @无聊的豆子君 指出代码中的错误。

  1 // Optimization for Minimax game strategy, using Alpha-Beta Pruning.
  2 // You can watch over the 'function_call_count' variable.
  3 #include <iostream>
  4 #include <vector>
  5 using namespace std;
  6
  7 int function_call_count;
  8
  9 bool computerWin(const vector<int> &board)
 10 {
 11     int i, j;
 12
 13     for (i = 0; i < 3; ++i) {
 14         for (j = 0; j < 3; ++j) {
 15             if (board[i * 3 + j] != -1) {
 16                 break;
 17             }
 18         }
 19         if (j == 3) {
 20             return true;
 21         }
 22     }
 23
 24     for (i = 0; i < 3; ++i) {
 25         for (j = 0; j < 3; ++j) {
 26             if (board[j * 3 + i] != -1) {
 27                 break;
 28             }
 29         }
 30         if (j == 3) {
 31             return true;
 32         }
 33     }
 34
 35     if (board[0] == board[4] && board[4] == board[8] && board[8] == -1) {
 36         return true;
 37     }
 38
 39     if (board[2] == board[4] && board[4] == board[6] && board[6] == -1) {
 40         return true;
 41     }
 42
 43     return false;
 44 }
 45
 46 bool humanWin(const vector<int> &board)
 47 {
 48     int i, j;
 49
 50     for (i = 0; i < 3; ++i) {
 51         for (j = 0; j < 3; ++j) {
 52             if (board[i * 3 + j] != 1) {
 53                 break;
 54             }
 55         }
 56         if (j == 3) {
 57             return true;
 58         }
 59     }
 60
 61     for (i = 0; i < 3; ++i) {
 62         for (j = 0; j < 3; ++j) {
 63             if (board[j * 3 + i] != 1) {
 64                 break;
 65             }
 66         }
 67         if (j == 3) {
 68             return true;
 69         }
 70     }
 71
 72     if (board[0] == board[4] && board[4] == board[8] && board[8] == 1) {
 73         return true;
 74     }
 75
 76     if (board[2] == board[4] && board[4] == board[6] && board[6] == 1) {
 77         return true;
 78     }
 79
 80     return false;
 81 }
 82
 83 bool fullBoard(const vector<int> &board)
 84 {
 85     for (int i = 0; i < 9; ++i) {
 86         if (board[i] == 0) {
 87             return false;
 88         }
 89     }
 90
 91     return true;
 92 }
 93
 94 void findComputerMove(vector<int> &board, int &best_move, int &result,
 95     int alpha, int beta)
 96 {
 97     void findHumanMove(vector<int> &, int &, int &, int, int);
 98     int dc, i, response;
 99
100     ++function_call_count;
101     best_move = -1;
102
103     if (fullBoard(board)) {
104         result = 0;
105         return;
106     }
107
108     if (humanWin(board)) {
109         result = 1;
110         return;
111     }
112
113     if (computerWin(board)) {
114         result = -1;
115         return;
116     }
117
118     result = alpha;
119     for (i = 0; i < 9 && result > beta; ++i) {
120         if (board[i] != 0) {
121             continue;
122         }
123         board[i] = -1;
124         findHumanMove(board, dc, response, result, beta);
125         board[i] = 0;
126
127         if (best_move == -1 || response < result) {
128             result = response;
129             best_move = i;
130         }
131     }
132 }
133
134 void findHumanMove(vector<int> &board, int &best_move, int &result, int alpha,
135     int beta)
136 {
137     void findComputerMove(vector<int> &, int &, int &, int, int);
138     int dc, i, response;
139
140     ++function_call_count;
141     best_move = -1;
142
143     if (fullBoard(board)) {
144         result = 0;
145         return;
146     }
147
148     if (computerWin(board)) {
149         result = -1;
150         return;
151     }
152
153     if (humanWin(board)) {
154         result = 1;
155         return;
156     }
157
158     result = beta;
159     for (i = 0; i < 9 && result < alpha; ++i) {
160         if (board[i] != 0) {
161             continue;
162         }
163         board[i] = 1;
164         findComputerMove(board, dc, response, alpha, result);
165         board[i] = 0;
166
167         if (best_move == -1 || response > result) {
168             result = response;
169             best_move = i;
170         }
171     }
172 }
173
174 void printBoard(const vector<int> &board)
175 {
176     cout << "  1 2 3" << endl;
177     int i, j;
178
179     for (i = 0; i < 3; ++i) {
180         cout << i + 1;
181         for (j = 0; j < 3; ++j) {
182             cout << ' ';
183             switch(board[i * 3 + j]) {
184             case -1:
185                 cout << 'X';
186                 break;
187             case 0:
188                 cout << '.';
189                 break;
190             case 1:
191                 cout << 'O';
192                 break;
193             }
194         }
195         cout << endl;
196     }
197 }
198
199 int main()
200 {
201     vector<int> board;
202     int n;
203     int result;
204
205     board.resize(9, 0);
206     while (cin >> n) {
207         if (n < 0 || n >= 9 || board[n]) {
208             cout << "Invalid move" << endl;
209             continue;
210         }
211
212         board[n] = 1;
213         printBoard(board);
214         if (humanWin(board)) {
215             cout << "You win." << endl;
216             break;
217         }
218
219         if (fullBoard(board)) {
220             cout << "Draw." << endl;
221             break;
222         }
223
224         result = 1;
225         function_call_count = 0;
226         findComputerMove(board, n, result, 1, -1);
227         cout << "Number of function calls: " << function_call_count << endl;
228         board[n] = -1;
229         printBoard(board);
230         if (computerWin(board)) {
231             cout << "Computer win." << endl;
232             break;
233         }
234
235         if (fullBoard(board)) {
236             cout << "Draw." << endl;
237             break;
238         }
239     }
240
241     return 0;
242 }

转载于:https://www.cnblogs.com/zhuli19901106/p/3832592.html

《数据结构与算法分析:C语言描述》复习——第十章“算法设计技巧”——Minimax策略...相关推荐

  1. s数据结构替换子表java版_数据结构与算法分析Java语言描述(第3版) PDF和源码免费 下载...

    <数据结构与算法分析Java语言描述(第3版)>PDF和源码免费 下载 免积分下载 用户下载说明: 图书简介: 数据结构:Java语言描述(原书第3版)是国外数据结构与算法分析方面的经典教 ...

  2. 数据结构与算法分析 C++语言描述第四版.Mark Allen Weiss

    数据结构与算法分析 C++语言描述第四版.Mark Allen Weiss 可用于自学数据结构与算法,数据结构与算法分析对于C++的学习至关重要,应该努力掌握好! 百度网盘: 链接:https://p ...

  3. 《数据结构与算法分析-C语言描述》习题2.6

    <数据结构与算法分析-C语言描述>([url=http://users.cis.fiu.edu/~weiss/#dsaac2e]Data Structures and Algorithm ...

  4. 算法 c语言实现 英文版 pdf,数据结构与算法分析++C语言描述++英文版++..pdf-得力文库...

    数据结构与算法分析++C语言描述++英文版++....pdf General Ination 书名数据结构与算法分析 C语言描述 英文版 第2版 作者(美)韦斯著 页数512 出版社机械工业出版社 出 ...

  5. 数据结构(c语言版) 计算机科学丛书,数据结构与算法分析--C语言描述(原书第2版)(计算机科学丛书)...

    摘要: 本书讨论数据结构和算法分析.数据结构主要研究组织大量数据的方法,而算法分析则是对算法运行时间的评估.随着计算机的速度越来越快,对于能够处理大量输入数据的程序的需求变得日益急切.可是,由于在输入 ...

  6. 《数据结构与算法分析—Java语言描述》pdf

    下载地址:网盘下载 内容简介 编辑 "数据结构"是计算机专业的基础与核心课程之一,Java是现今一种热门的语言.本书在编写过程中特别考虑到了面向对象程序设计(OOP)的思想与Jav ...

  7. 数据结构与算法分析C++语言描述(第四版)图论学习记录

    我对 9.3.1节中无权最短路径算法,进行了一点修改,对书中例子也进行了测试,发现居然也适用于有权最短路径求解. 对 赋权图最短路径求解,我仍然使用和 9.3.1节中求解无权图最短路径同样的方式,参见 ...

  8. c语言将数组的列项向左移动,【数据结构与算法分析——C语言描述】第六章:优先队列(堆)...

    第六章:优先队列(堆) [TOC] 思考如下场景,老师布置了很多作业,现在你需要将作业打印出来,你将作业文件依照队列的形式放入待打印列表中,但此时,你希望最重要(或者是马上就要上交)的作业优先打印出来 ...

  9. 数据结构与算法分析——C语言描述

    P1.1 选择问题,选择出第K大的数,并画出N为不同值的运行时间,K=N/2 毕业两年半,重写排序,感觉良好.代码使用冒泡排序,库函数clock计算大致运行时间. 1 // P1_1.cpp : De ...

最新文章

  1. Focal Loss升级:让Focal Loss动态化,类别极端不平衡也可以轻松解决
  2. python代码写好了怎么运行视频-Python的初学者你现在可以自己“看”到代码的运行了!...
  3. 完全掌握JavaMail
  4. 【星球知识卡片】人脸属性编辑都有哪些核心知识点,如何长期进行学习
  5. 数学无用论??我们欠孩子真正的数学阅读
  6. ArcGIS AO开发高亮显示某些要素
  7. mgg mysql_mgg文件怎么转换mp3格式?
  8. 信用卡还款直减500
  9. c语言存储学生信息并显示,C语言实现学生信息管理程序
  10. 平安dms开发java_Spring DMS模板同步接收非持久用户消息丢失
  11. 正则表达式学习笔记006--转义符的认识与应用
  12. 通过代理截取并修改非对称密钥加密信息
  13. 第十届中国开源黑客松等你来
  14. 如何发布ArcGIS Server离线地图(google 瓦片)
  15. 计算机硬件单片机,计算机硬件单片机总结报告
  16. Redhat8 配置使用阿里源(关闭官方订阅)
  17. AndroidTV开发-实现APP开机自启动
  18. 上海宝付发布新骗局预警:培训贷为大学生求职者而来
  19. google手机等相关产品{时间不同步}最简解决方法
  20. 替换加密(恺撒加密法)

热门文章

  1. 2017-9-11-颜色空间
  2. docker简易实践
  3. Ubuntu 修改mysql的存储目录
  4. AdventureWorksBI.msi 和 AdventureWorksDB.msi 的官方下载地址及安装方法
  5. 求解射线交点的完整代码
  6. 人生必做清单-----持续更新
  7. 安测云验证有CTA问题
  8. 如何让Android对话框全屏 Dialog 全屏
  9. activity堆栈式管理
  10. 【剑指offer-Java版】07用两个栈实现队列