极小极大算法和alpha-beta算法
作者:互联网
package com.jn.rz.实验三; import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * @author 江南大学1033190417 * @date 2022/5/5 10:42 */ public class Status { public char[][] status; public Status(char[][] status) { this.status = status; } //估价函数 public int f() { //计算MAX所有赢线 int M = 0; for (int i = 0; i < 3; i++) { if (status[i][0] != 'O' && status[i][1] != 'O' && status[i][2] != 'O') { ++M; } if (status[0][i] != 'O' && status[1][i] != 'O' && status[2][i] != 'O') { ++M; } } if (status[0][0] != 'O' && status[1][1] != 'O' && status[2][2] != 'O') { ++M; } if (status[0][2] != 'O' && status[1][1] != 'O' && status[2][0] != 'O') { ++M; } //计算MIN所有赢线 int O = 0; for (int i = 0; i < 3; i++) { if (status[i][0] != 'X' && status[i][1] != 'X' && status[i][2] != 'X') { ++O; } if (status[0][i] != 'X' && status[1][i] != 'X' && status[2][i] != 'X') { ++O; } } if (status[0][0] != 'X' && status[1][1] != 'X' && status[2][2] != 'X') { ++O; } if (status[0][2] != 'X' && status[1][1] != 'X' && status[2][0] != 'X') { ++O; } return M - O; } //判断胜负 public boolean isWin(char temp) { return ((status[0][0] == temp && status[0][1] == temp && status[0][2] == temp) || (status[1][0] == temp && status[1][1] == temp && status[1][2] == temp) || (status[2][0] == temp && status[2][1] == temp && status[2][2] == temp) || (status[0][0] == temp && status[1][0] == temp && status[2][0] == temp) || (status[0][1] == temp && status[1][1] == temp && status[2][1] == temp) || (status[0][2] == temp && status[1][2] == temp && status[2][2] == temp) || (status[0][0] == temp && status[1][1] == temp && status[2][2] == temp) || (status[0][2] == temp && status[1][1] == temp && status[2][0] == temp)); } //判断赢家 public int winner() { /* 当玩家先手时,max为玩家,所以返回1表示玩家赢,返回-1表示电脑赢,返回0表示平局或者还没结束; 当电脑先手时,max为电脑,所以返回1表示电脑赢,返回-1表示玩家赢,返回0表示平局或者还没结束。 */ if ((isWin('O') && first == 1) || (isWin('X') && first == -1)) { return 1; } else if ((isWin('X') && first == 1) || (isWin('O') && first == -1)) { return -1; } else { return 0; } } //判断棋牌是否下满 public boolean isFull() { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (status[i][j] == '.') return false; } } return true; } /** * 极小极大算法 * 通过递归,从叶子节点,推出父子节点(即往上推出)的值,该树的取值只有三种要么1,要么-1,要么0。 * * @param player 当前玩家 * @param nextPlayer 下一个玩家 * @return */ public int maxMinSearch(char player, char nextPlayer) { int maxVal = 2, minVal = 2; int win = winner(); if (win != 0) {//如果是叶子结点 return win; } if (isFull()) {//如果下满没有赢家是平局 return 0; } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (status[i][j] == '.') { status[i][j] = player; int val = maxMinSearch(nextPlayer, player); status[i][j] = '.'; if ((player == 'O' && first == 1) || (player == 'X' && first == -1)) { if (maxVal < val) maxVal = val; } else if ((player == 'X' && first == 1) || (player == 'O' && first == -1)) { if (minVal > val) minVal = val; } } } } int reval = 0; if ((player == 'O' && first == 1) || (player == 'X' && first == -1)) { reval = maxVal; } else if ((player == 'X' && first == 1) || (player == 'O' && first == -1)) { reval = minVal; } return reval; } /** * alpha-beta算法 * @param player * @param nextPlayer * @param alpha -2 * @param beta 2 * @return */ public int alphaBetaSearch(char player,char nextPlayer,int alpha,int beta){ int win = winner(); if (win != 0) {//如果是叶子结点 return win; } if (isFull()) {//如果下满没有赢家是平局 return 0; } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (status[i][j] == '.') { status[i][j] = player; int val = alphaBetaSearch(nextPlayer, player,alpha,beta); status[i][j] = '.'; if ((player == 'O' && first == 1) || (player == 'X' && first == -1)) { if (alpha<val) alpha=val; else return beta; } else if ((player == 'X' && first == 1) || (player == 'O' && first == -1)) { if (beta>val) beta=val; else return alpha; } } } } int reval = 0; if ((player == 'O' && first == 1) || (player == 'X' && first == -1)) { reval = alpha; } else if ((player == 'X' && first == 1) || (player == 'O' && first == -1)) { reval = beta; } return reval; } //玩家下棋 public void player() { Scanner scanner = new Scanner(System.in); while (true) { System.out.print("输入要下的位置(0-8):"); int pos = scanner.nextInt(); int x = pos / 3; int y = pos % 3; if (status[x][y] == '.') { status[x][y] = piece; break; } else { System.out.println("该位置有棋子了,请重新输入!"); } } } //电脑下棋,根据极小极大算法 public int computer() { int bestVal = 2;//用来记录先手为玩家时,电脑取min时,能取的最小值 int bestVal2 = -2;//用来记录先手为电脑时,电脑取max时,能取的最大值 List<Integer> myMoves = new ArrayList<>();//记录电脑能做的位置 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (status[i][j] == '.') { status[i][j] = comPiece; int val = maxMinSearch(piece, comPiece); status[i][j] = '.'; if (first == 1) { if (val < bestVal) { bestVal = val; myMoves = new ArrayList<>(); myMoves.add(3 * i + j); } else if (val == bestVal) { myMoves.add(3 * i + j); } } else if (first == -1) { if (val > bestVal2) { bestVal2 = val; myMoves = new ArrayList<>(); myMoves.add(3 * i + j); } else if (val == bestVal2) { myMoves.add(3 * i + j); } } } } } return myMoves.get((int) (Math.random() * (myMoves.size()) - 1)); } //电脑下棋,根据alpha-beta算法 public int computer2() { int bestVal = 2;//用来记录先手为玩家时,电脑取min时,能取的最小值 int bestVal2 = -2;//用来记录先手为电脑时,电脑取max时,能取的最大值 List<Integer> myMoves = new ArrayList<>();//记录电脑能做的位置 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (status[i][j] == '.') { status[i][j] = comPiece; int val = alphaBetaSearch(piece, comPiece,-2,2); status[i][j] = '.'; if (first == 1) { if (val < bestVal) { bestVal = val; myMoves = new ArrayList<>(); myMoves.add(3 * i + j); } else if (val == bestVal) { myMoves.add(3 * i + j); } } else if (first == -1) { if (val > bestVal2) { bestVal2 = val; myMoves = new ArrayList<>(); myMoves.add(3 * i + j); } else if (val == bestVal2) { myMoves.add(3 * i + j); } } } } } return myMoves.get((int) (Math.random() * (myMoves.size()) - 1)); } public void main(){ int nextMove = first; while (!isFull() && winner() == 0) { if (nextMove == 1 && !isFull()) {//玩家下 player(); print(status); nextMove = -1; } if (nextMove == -1 && !isFull()) {//电脑下 int computer = computer2(); status[computer / 3][computer % 3] = comPiece; System.out.println("电脑下的棋子"); print(status); nextMove = 1; } } printResult(); } //答应输赢结果 public void printResult(){ if (first==1){ if (piece=='O'){ System.out.println(new String[]{"电脑赢了", "平局", "你赢了"}[winner() + 1]); }else { System.out.println(new String[]{"你赢了", "平局", "电脑赢了"}[winner() + 1]); } }else if (first==-1){ if (piece=='X'){ System.out.println(new String[]{"电脑赢了", "平局", "你赢了"}[winner() + 1]); }else { System.out.println(new String[]{"你赢了", "平局", "电脑赢了"}[winner() + 1]); } } } //玩家优先是1 public static int first; //玩家选择的棋子 public static char piece; //电脑的棋子 public static char comPiece; public static void print(char[][] status) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { System.out.print(status[i][j] + "\t"); } System.out.println(); } } public static void main(String[] args) { char[][] begin = new char[][]{ {'.', '.', '.'}, {'.', '.', '.'}, {'.', '.', '.'}, }; Status status = new Status(begin); Scanner scanner = new Scanner(System.in); System.out.print("Human first[y/n]:"); String flag = scanner.nextLine(); first = flag.equals("y") ? 1 : -1; System.out.print("Human select X/O[X/O]:"); piece = scanner.nextLine().charAt(0); comPiece = piece == 'O' ? 'X' : 'O'; print(begin);//打印初始棋盘 status.main(); } }
标签:status,temp,int,beta,player,算法,&&,alpha,first 来源: https://www.cnblogs.com/msboke/p/16224914.html