如果你的做法是不工作,你可以嘗試模仿上wiki或僞代碼的基本結構here。在Java中,我有:
/**
* initialize MiniMax(0, player1) where player1 is computer
* @param deg depth
* @param player either MAX or MIN
* @return int {score,column}
*/
int[] MiniMax(int deg, char player) {
// list of possible columns to place a checker
List<int[]> moves = nextMoves();
int v;
char prev;
if (player==player1) prev = player2;
else prev = player1;
// IF depth = 0 OR there is a connect 4 OR the board is full (draw) THEN
// return your static evaluation (heuristic)
// if the current position has a connect 4, return -inf or inf
// depending on if player is MIN or MAX respectively
if (checkPos(prev) || (deg == this.deg) || moves.isEmpty())
return new int[] {eval(),bestMove};
//MAX
else if (player==player1) {
v = -inf;
for (int[] move : moves) { // move = {row,column}
board[move[0]][move[1]] = player1; // make move
int score = MiniMax(deg+1,player2)[0];
board[move[0]][move[1]] = ' '; // undo move
if (score>v) {
v = score;
bestMove = move[1];
}
}
return new int[] {v,bestMove};
}
//MIN
else {
v = inf;
for (int[] move : moves) { // move = {row,column}
board[move[0]][move[1]] = player2; // make move
int score = MiniMax(deg+1,player1)[0];
board[move[0]][move[1]] = ' '; // undo move
if (v>score) {
v = score;
bestMove = move[1];
}
}
return new int[] {v,bestMove};
}
}
這可能是使用字符數組或東西,而不是class
,代表執委會有用。儘管最有效的方法是將電路板表示爲long
,因爲您可以使用4位移位來檢查是否存在連接四。這裏有一些馬虎java顯示上述的東西工作:
import java.util.ArrayList;
import java.util.List;
public class Connect4 {
static final int WIDTH = 7;
static final int HEIGHT = 6;
private static final int inf = 9999999;
private static final char player1 = 'X';
private static final char player2 = 'O';
char[][] board = new char[WIDTH][HEIGHT];
private int deg;
int bestMove;
static char[][] copy(char[][] aArray) {
char[][] copy = new char[aArray.length][aArray[0].length];
for (int idy = 0; idy < aArray.length; ++idy) {
for (int idx = 0; idx < aArray[0].length; ++idx) {
copy[idy][idx] = aArray[idy][idx];
}
}
return copy;
}
void prints() {
System.out.println();
for (int i = 0; i < 6; i++) {
System.out.println("=============================");
for (int j = 0; j < 7; j++) {
if (j == (WIDTH - 1)) {
if (board[i][j]==' ') {
System.out.println("| |");
}
else {
if(board[i][j]==player1) System.out.println("| " +"\u001B[32m"+board[i][j]+"\u001B[0m" + " |");
else System.out.println("| " +"\u001B[34m"+board[i][j]+"\u001B[0m" + " |");
}
}
else {
if (board[i][j]==' ') {
System.out.print("| ");
}
else {
if(board[i][j]==player1) System.out.print("| " +"\u001B[32m"+board[i][j]+"\u001B[0m" + " ");
else System.out.print("| " +"\u001B[34m"+board[i][j]+"\u001B[0m" + " ");
}
}
}
}
System.out.println("=============================");
}
//STATIC EVALUATION
int eval3(char player) {
if (checkPos(player)) {
return inf;
}
int count;
int open;
int evaluation = 0;
//evaluation = number of open 3 in rows
//go through all possible 4in rows and check
//horz
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < 4; j++) {
count = 0;
open = 0;
if (board[i][j]==player) count++;
else if(board[i][j]==' ') open++;
if (board[i][j + 1]==player) count++;
else if(board[i][j + 1]==' ') open++;
if (board[i][j + 2]==player) count++;
else if(board[i][j + 2]==' ') open++;
if (board[i][j + 3]==player) count++;
else if(board[i][j + 3]==' ') open++;
if ((count == 3) && (open == 1)) evaluation++;
}
}
//vert
for (int j = 0; j < WIDTH; j++) {
for (int i = 0; i < 3; i++) {
count = 0;
open = 0;
if (board[i][j]==player) count++;
else if (board[i][j]==' ') open++;
if (board[i + 1][j]==player) count++;
else if (board[i+1][j]==' ') open++;
if (board[i + 2][j]==player) count++;
else if (board[i + 2][j]==' ') open++;
if (board[i + 3][j]==player) count++;
else if (board[i + 3][j]==' ') open++;
if ((count == 3) && (open == 1)) evaluation++;
}
}
// pos slope diag
for (int j = 0; j < 4; j++) {
for (int i = 3; i < HEIGHT; i++) {
count = 0;
open = 0;
if (board[i][j]==player) count++;
else if (board[i][j]==' ') open++;
if (board[i - 1][j + 1]==player) count++;
else if (board[i - 1][j + 1]==' ') open++;
if (board[i - 2][j + 2]==player) count++;
else if (board[i - 2][j + 2]==' ') open++;
if (board[i - 3][j + 3]==player) count++;
else if (board[i - 3][j + 3]==' ') open++;
if ((count == 3) && (open == 1)) evaluation++;
}
}
// neg slope diag
for (int j = 0; j < 4; j++) {
for (int i = 0; i < (3); i++) {
count = 0;
open = 0;
if (board[i][j]==player) count++;
else if (board[i][j]==' ') open++;
if (board[i + 1][j + 1]==player) count++;
else if (board[i + 1][j + 1]==' ') open++;
if (board[i + 2][j + 2]==player) count++;
else if (board[i + 2][j + 2]==' ') open++;
if (board[i + 3][j + 3]==player) count++;
else if (board[i + 3][j + 3]==' ') open++;
if ((count == 3) && (open == 1)) evaluation++;
}
}
return evaluation;
}
int eval() {return eval3(player1) - eval3(player2);}
boolean checkPos(char cur) {
//horz
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < 4; j++) {
if ( board[i][j]==cur &&
board[i][j + 1]==cur &&
board[i][j + 2]==cur &&
board[i][j + 3]==cur) {
return true;
}
}
}
//vert
for (int j = 0; j < WIDTH; j++) {
for (int i = 0; i < 3; i++) {
if ( board[i][j]==cur &&
board[i + 1][j]==cur &&
board[i + 2][j]==cur &&
board[i + 3][j]==cur) {
return true;
}
}
}
// pos slope diag
for (int j = 0; j < 4; j++) {
for (int i = 3; i < HEIGHT; i++) {
if ( board[i][j]==cur &&
board[i - 1][j + 1]==cur &&
board[i - 2][j + 2]==cur &&
board[i - 3][j + 3]==cur) {
return true;
}
}
}
// neg slope diag
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 3; i++) {
if ( board[i][j]==cur &&
board[i + 1][j + 1]==cur &&
board[i + 2][j + 2]==cur &&
board[i + 3][j + 3]==cur) {
return true;
}
}
}
return false;
}
List<int[]> nextMoves() {
List<int[]> result = new ArrayList<>();
for (int j = 0; j < WIDTH; j++) {
//if column j isnt full then add
if (board[0][j]==' ') result.add(new int[] {findY(j),j});
}
return result;
}
int findY(int col) {
int i = board.length - 1;
while (i > -1) {
if (board[i][col]==' ') break;
i--;
}
return i;
}
/**
* @param deg depth
* @param player either MAX or MIN
* @return int {score,column}
*/
int[] MiniMax(int deg, char player) {
// list of possible columns to place a checker
List<int[]> moves = nextMoves();
int v;
char prev;
if (player==player1) prev = player2;
else prev = player1;
// IF depth = 0 OR there is a connect 4 OR the board is full (draw) THEN
// return your static evaluation (heuristic)
// if the current position has a connect 4, return -inf or inf
// depending on if player is MIN or MAX respectively
if (checkPos(prev) || (deg == this.deg) || moves.isEmpty())
return new int[] {eval(),bestMove};
//MAX
else if (player==player1) {
v = -inf;
for (int[] move : moves) { // move = {row,column}
board[move[0]][move[1]] = player1; // make move
int score = MiniMax(deg+1,player2)[0];
board[move[0]][move[1]] = ' '; // undo move
if (score>v) {
v = score;
bestMove = move[1];
}
}
return new int[] {v,bestMove};
}
//MIN
else {
v = inf;
for (int[] move : moves) { // move = {row,column}
board[move[0]][move[1]] = player2; // make move
int score = MiniMax(deg+1,player1)[0];
board[move[0]][move[1]] = ' '; // undo move
if (v>score) {
v = score;
bestMove = move[1];
}
}
return new int[] {v,bestMove};
}
}
public static void main(String[] args) {
Connect4 c = new Connect4();
c.deg = 5;
char[][] b = {
{' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' '},
{' ',' ',' ',' ',' ',' ',' '},
{' ','X','X','X',' ',' ',' '},
{' ','O','X','X','X',' ',' '}
};
c.board = copy(b);
c.prints();
System.out.println("best value = " + c.MiniMax(0, player1)[1]);
}
}
它看起來像你試圖實施一些阿爾法修剪?嘗試首先實施原始極大極小。另外,你是否介意發佈GameBoard類和威脅級別函數,以便我可以擺弄這個? – Cruncher
你不應該檢查minimax裏面的「computerColor」。 Minimax不應該在意。從最低要求角度來看,它始終是球員。它不應該返回一個負面/正面的價值,如果它被稱爲對手或你自己。因爲它的目標是告訴你如果你做出這個動作,你的對手可以做出的最好的舉動(這就是爲什麼它被稱爲極小極限,其目標是儘可能地讓他們的最佳動作獲得最大的勝利機會),而最大的負面價值實際上是一個更小的數量和更糟糕的舉動。 – Cruncher
哦,我剛剛提交了一個答案。不過,我會看看。同時嘗試我的版本,看看它是否有效。 – Cruncher