package test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; public class ConnectFour { private class Move { final int row, col, score; Move(int row, int col, int score) { this.row = row; this.col = col; this.score = score; } Move(int score) { this(-1, -1, score); } @Override public String toString() { return String.format("%d %d %d", row, col, score); } } private static final char HUMAN = 'X'; private static final char COMPUTER = 'O'; private static final char EMPTY = '.'; private static final char CONTINUE = '+'; private static final char DRAW = '-'; private static final int MAX_DEPTH = 9; private static final int ROWS = 6; private static final int COLS = 7; private final char[][] board = new char[ROWS][COLS]; public ConnectFour() { for (int i = 0; i < board.length; i++) { Arrays.fill(board[i], EMPTY); } } public int humanMove(final int col) { for (int row = ROWS - 1; row >= 0; row--) { if (board[row][col] == EMPTY) { board[row][col] = HUMAN; return eval(HUMAN); } } throw new IllegalArgumentException("column full: " + col); } public int computerMove() { int depth = 0; for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { if (board[row][col] == EMPTY) { depth++; } } } Move move = maximum(Math.min(MAX_DEPTH, depth)); board[move.row][move.col] = COMPUTER; return eval(COMPUTER); } private Move maximum(int depth) { if (depth == 0) { return new Move(0); } Move best = new Move(Integer.MIN_VALUE); for (Move move : getMoves()) { board[move.row][move.col] = COMPUTER; char result = eval(COMPUTER); int value = result == COMPUTER ? depth : minimum(depth-1).score; if (value > best.score) { best = new Move(move.row, move.col, value); } board[move.row][move.col] = EMPTY; } return best; } private Move minimum(int depth) { if (depth == 0) { return new Move(0); } Move worst = new Move(Integer.MAX_VALUE); for (Move move : getMoves()) { board[move.row][move.col] = HUMAN; char result = eval(HUMAN); int value = result == HUMAN ? -depth : maximum(depth-1).score; if (value < worst.score) { worst = new Move(move.row, move.col, value); } board[move.row][move.col] = EMPTY; } return worst; } private List getMoves() { List moves = new ArrayList<>(); for (int col = 0; col < COLS; col++) { for (int row = ROWS - 1; row >= 0; row--) { if (board[row][col] == EMPTY) { moves.add(new Move(row, col, 0)); break; } } } return moves; } private char eval(char player) { // Rows for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS - 3; col++) { if (board[row][col+0] == player && board[row][col+1] == player && board[row][col+2] == player && board[row][col+3] == player) { return player; } } } // Columns for (int col = 0; col < COLS; col++) { for (int row = 0; row < ROWS - 3; row++) { if (board[row+0][col] == player && board[row+1][col] == player && board[row+2][col] == player && board[row+3][col] == player) { return player; } } } // Diagonals for (int row = 0; row < ROWS - 3; row++) { for (int col = 0; col < COLS - 3; col++) { if (board[row+0][col+0] == player && board[row+1][col+1] == player && board[row+2][col+2] == player && board[row+3][col+3] == player) { return player; } } } for (int row = 0; row < ROWS - 3; row++) { for (int col = 3; col < COLS; col++) { if (board[row+0][col-0] == player && board[row+1][col-1] == player && board[row+2][col-2] == player && board[row+3][col-3] == player) { return player; } } } for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { if (board[row][col] == EMPTY) return CONTINUE; } } return DRAW; } @Override public String toString() { String s = ""; for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { s += board[row][col]; } s += "\n"; } return s; } public static void main(String[] args) { Scanner s = new Scanner(System.in); ConnectFour game = new ConnectFour(); int result = CONTINUE; while (result == CONTINUE) { // result = game.computerMove(); System.out.println(game); if (result != CONTINUE) break; System.out.print("Human move: "); String input = s.nextLine(); if (input.equals("q")) System.exit(1); int x = Integer.parseInt(input); result = game.humanMove(x-1); if (result != CONTINUE) break; result = game.computerMove(); System.out.println(game); } System.out.println(game); if (result == HUMAN) System.out.println("human won"); if (result == COMPUTER) System.out.println("computer won"); if (result == DRAW) System.out.println("draw"); s.close(); } }