像我看到的许多其他人一样,我对游戏Connect4的Minmax算法的实现有问题。在下面的示例中,算法不会尝试阻止播放器两个,我不明白为什么。我的评估函数非常基本:二元函数。也许这是因为深度,但我不这么认为。
代码:
public class Moteur {
public static void addPawn(int[][] game, int column, int player) {
int i = 0;
while (i < 6 && game[i][column] == 0) {
i++;
}
game[(i==6)?5:i-1][column] = player;
}
public static void kickPawn(int[][] game, int column) {
int i = 0;
while (i < 6 && game[i][column] == 0) {
i++;
}
game[i][column] = 0;
}
public static void AI_play(int[][] game, int depth) {
int max = -10000;
int tmp = 0;
int maxj = -5;
int j;
for (j = 0; j < 7; j++) {
if(game[0][j] == 0) {
addPawn(game, j, 1);
tmp = Min(game, depth - 1);
if (tmp > max) {
max = tmp;
maxj = j;
}
kickPawn(game, j);
}
}
addPawn(game, maxj, 1);
}
public static int Max(int[][] game, int depth) {
if(depth == 0 || winner(game) != 0) {
return eval(game);
}
int max = -10000;
int j, tmp;
for(j = 0; j < 7; j++) {
if(game[0][j] == 0) {
addPawn(game, j, 2);
tmp = Min(game, depth - 1);
if(tmp > max) {
max = tmp;
}
kickPawn(game, j);
}
}
return max;
}
public static int Min(int[][] game, int depth) {
if(depth == 0 || winner(game) != 0) {
return eval(game);
}
int min = 10000;
int j, tmp;
for(j = 0; j < 7; j++) {
if(game[0][j] == 0) {
addPawn(game, j, 1);
tmp = Max(game, depth - 1);
if(tmp < min) {
min = tmp;
}
kickPawn(game, j);
}
}
return min;
}
public static int eval(int[][] game) {
int gameWinner, nb_pawns = 0;
for (int i = 0; i < game.length; i++) {
for (int j = 0; j < game[0].length; j++) {
if(game[i][j] != 0) {
nb_pawns++;
}
}
}
gameWinner = winner(game);
if(gameWinner == 1) {
return 1000 - nb_pawns;
} else if (gameWinner == 2) {
return -1000 + nb_pawns;
} else {
return 0;
}
}
public static int winner(int[][] game) {
Integ e = new Integ();
for (int j = 0; j < game[0].length; j++) {
if(game[5][j]!= 0 && testWinner(game, j, e)) {
return e.getI();
}
}
return 0;
}
public static boolean testWinner(int[][] game, int lastColumn, Integ e) {
int lastRow = 0;
while (lastRow < 6 && game[lastRow][lastColumn] == 0) {
lastRow++;
}
lastRow = lastRow;
int i = 0;
int j = 0;
int currentPlayer = game[lastRow][lastColumn];
e.setI(currentPlayer);
int sequence = 0;
i = lastRow;
boolean b = i < 3
&& game[i][lastColumn] == currentPlayer
&& game[i+1][lastColumn] == currentPlayer
&& game[i+2][lastColumn] == currentPlayer
&& game[i+3][lastColumn] == currentPlayer;
if(b) {
return true;
}
sequence = 0;
j = lastColumn;
do {
j--;
} while(0 < j && game[lastRow][j] == currentPlayer);
if(j < 0 || game[lastRow][j] != currentPlayer) {
j++;
}
while(j <= 6 && game[lastRow][j] == currentPlayer) {
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
sequence = 0;
i = lastRow;
j = lastColumn;
do {
i--;
j--;
} while(0 < i && 0 < j && game[i][j] == currentPlayer);
if(i < 0 || j < 0 || game[i][j] != currentPlayer) {
i++;
j++;
}
while(i <= 5 && j <= 6 && game[i][j] == currentPlayer) {
i++;
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
sequence = 0;
i = lastRow;
j = lastColumn;
do {
i++;
j--;
} while(i < 5 && 0 < j && game[i][j] == currentPlayer);
if (5 < i || j < 0 || game[i][j] != currentPlayer) {
i--;
j++;
}
while(0 <= i && j <= 6 && game[i][j] == currentPlayer) {
i--;
j++;
sequence++;
}
if (sequence >= 4) {
return true;
}
return false;
}
public static void main(String[] args) {
int[][] game = new int[6][7];
int depth = 5;
game[5][3] = 2;
game[4][3] = 2;
game[3][3] = 2;
AI_play(game, depth);
//game[4][0] = 2;
//AI_play(game, depth);
//game[5][2] = 2;
//AI_play(game, depth);
//game[5][3] = 2;
//AI_play(game, depth);
//game[1][0] = 2;
//AI_play(game, depth);
//game[5][4] = 2;
//AI_play(game, depth);
for (int i = 0; i < game.length; i++) {
for (int j = 0; j < game[0].length; j++) {
System.out.print(game[i][j]);
}
System.out.println("");
}
}
private static class Integ {
private int i;
public Integ() {
this.i = 0;
}
public void increment() {
this.i = this.i + 1;
}
public int getI() {
return this.i;
}
public void setI(int i) {
this.i = i;
}
}
}