Tic-Tac-Toe加强版
上一版的Tic-Tac-Toe智商肯定无法令人满意,既然有了MiniMax算法,为什么不动手实现一下呢?
在Eclipse中打开上回建立的项目。首先在TicTacToe类中加入估计函数evalauate()。这个估计函数与上文介绍的估计函数略有不同,这里通过线性函数考虑了更多的因素,强调了三连通棋局的重要性,以及提高了两连通棋局的地位。通过这个估计函数,读者朋友应该能够体会到砍树也是很有艺术性的,对于复杂的棋类,估计函数几乎决定了程序棋力的高下。源代码如下:
/** * 估计函数。 * @param board 要被估计的棋盘 * @return 估计值 */ private int evalauate(int[] board) { int x2 = 0, o2 = 0, x1 = 0, o1 = 0;
for (int i = 0; i < lines.length; i++) { int[] line = lines[i]; int sum = 0; for (int j = 0; j < line.length; j++) { sum += board[line[j]]; } switch (sum) { case 3: // 圆圈联通 return -100; case 12: // 大叉联通 return 100; case 8: x2++; break; case 4: x1++; break; case 2: o2++; break; case 1: o1++; break; } } return 3 * (x2 - o2) + x1 - o1; } 下面列出了应用MiniMax算法的模仿专业棋力的professional()函数,请各位朋友参考注释阅读:
/** * 拥有职业选手棋力的机器人下一步棋。 */ public void professional() { ArrayList blanks = new ArrayList(); // 获取当前棋局所有可以下的位置 for (int i = 0; i < 9; i++) { if (board[i] == 0) { blanks.add(new Integer(i)); } } // 若已经没有空格可以下了便和局 if (blanks.size() == 0) { message = "平局"; gameover = true; return; } // 利用MiniMax算法找出计算机最可能赢的一步棋 // 枚举Min的每一种可能下法 int minBoards[][] = new int[blanks.size()][9]; int max = -100, best = 0; for (int i = 0; i < minBoards.length; i++) { // 复制当前棋局 int[] minBoard = (int[]) board.clone(); // 测试下第一步棋 minBoard[((Integer) (blanks.get(i))).intValue()] = CROSS; minBoards[i] = minBoard; // 剩下的空格就是Max的落子范围 ArrayList maxBlanks = (ArrayList) blanks.clone(); maxBlanks.remove(i); // 根据当前的测试棋局枚举Max的每一种可能下法 int min = 100; for (int j = 0; j < maxBlanks.size(); j++) { // 复制当前棋局 int[] maxBoard = (int[]) minBoard.clone(); // 测试下第一步棋 maxBoard[((Integer) (maxBlanks.get(j))).intValue()] = NOUGHT; // Min将取这些Max的取值中最小者 int value = evalauate(maxBoard); if (value < min) { min = value; } } if (min > max) { max = min; best = i; } } board = minBoards[best]; } 最后记得把mouseReleased()中的amateur();代码改成professional(),这样加强版的游戏就算完成了。运行一下,计算机是不是已经威风八面了?
|