簡介
極大極小博弈樹(Minimax Game Tree)用於編寫電腦之間的遊戲程式,這類程式由兩個遊戲者輪流,每次執行一個步驟。當然,所有可能的步驟構成了一個樹的結構。例如下面的圖就是一個MGT,它表示了Tic-Tac-Toe遊戲的前兩步所有可能的步驟。
在每一層中的節點通常代表不同遊戲者的選擇,這兩個遊戲者通常被稱作馬克思(MAX)和米恩(Min)。
例如如果第二層是Max turn,則第三層就是Min turn,第二層的每個節點就是Max的choice,它們之間是或的關係,第三層的每個節點就是Min的choice,它們之間是與的關係。根據這個樹,Max要做出的選擇就讓下次Min做出的任意選擇都最小,即Minimax這個詞的含義,極小化對手的最大收益。所以它不同於Maximin最大化自己的收益。
因為往往一局要下到最後才能分出勝負,而Game Tree上nodes的增長是以指數方式的,比如深藍(Deep Blue)可以搜尋12步,假設各方每步都有10種選擇,那麼一次的搜尋量也有1萬億次,所以對於普通的電腦能夠搜尋到4步也有1萬次了,所以就需要一個評分系統,對局面進行打分,考慮到是雙人對戰,則評分從負無窮到正無窮。所以馬克思就是要找到一個最大的分數,而米恩就是要找到一個最小的分數。
例子
下面用一個例子來說明,Tic-Tac-Toe遊戲。
其中‘o’代表PC,‘x’代表玩家。
其中有三個主要的函數:
int minSearch( char _board[9] )
int maxSearch( char _board[9] )
int gameState(char _board[9])
分別扮演max和min的角色,尋找最大和最小值,以及一個評分函數。
下面重點說說這個遊戲的核心部分,gameState評分函數:
連三 100分
雙連二 50分
平局 0分
不分勝負 1
其中如果評分時不分勝負則還會繼續搜尋,直到找到其他三種狀態。
implementation
1: int gameState(char _board[9])
2: {
3: int state;
4: static int table[][3] =
5: {
6: {0, 1, 2},
7: {3, 4, 5},
8: {6, 7, 8},
9: {0, 3, 6},
10: {1, 4, 7},
11: {2, 5, 8},
12: {0, 4, 8},
13: {2, 4, 6},
14: };
15: char chess = _board[0];
16: for (char i = 1; i < 9; ++i)
17: {
18: chess &= _board[i];
19: }
20: bool isFull = 0 != chess;
21: bool isFind = false;
22: for (int i = 0; i < sizeof(table) / sizeof(int[3]); ++i)
23: {
24: chess = _board[table[i][0]];
25: int j;
26: for (j = 1; j < 3; ++j)
27: if (_board[table[i][j]] != chess)
28: break;
29: if (chess != empty && j == 3)
30: {
31: isFind = true;
32: break;
33: }
34: }
35: if (isFind)
36: //got win or lose
37: state = chess == o ? WIN : LOSE;
38: else
39: {
40: if (isFull)
41: //all position has been set without win or lose
42: return DRAW;
43: else
44: {
45: //finds[0] -> 'o', finds[1] -> 'x'
46: int finds[2] = {0, };
47: for (int i = 0; i < sizeof(table) / sizeof(int[3]); ++i)
48: {
49: bool findEmpty = false;
50: chess = 0xff;
51: int j;
52: for (j = 0; j < 3; ++j)
53: if (_board[table[i][j]] == empty && !findEmpty)
54: findEmpty = true;
55: else
56: chess &= _board[table[i][j]];
57: if ((chess == o || chess == x) && findEmpty)
58: {
59: isFind = true;
60: if (o == chess)
61: ++finds[0];
62: else
63: ++finds[1];
64: }
65: }
66: if (finds[0] > 1 && finds[1] < 1)
67: //2 'o' has been founded twice in row, column or diagonal direction
68: state = -(INFINITY / 2) * finds[0];
69: else if (finds[1] > 1 && finds[0] < 1)
70: //2 'x' has been founded twice in row, column or diagonal direction
71: state = INFINITY / 2 * finds[1];
72: else
73: //need to search more.
74: state = INPROGRESS;
75: }
76: }
77: return state;
78: }
最後附上源碼:http://files.cnblogs.com/chinese-zmm/Tic-Tac-Toe.7z
Reference
http://en.wikipedia.org/wiki/Minimax
http://www.cnblogs.com/goodness/archive/2010/05/27/1745756.html