/// <summary> /// Returns the best move score /// </summary> /// <param name="col_to_move_in">The best move index for this level of move</param> /// <param name="remaining_depth"></param> /// <param name="white_min"></param> /// <param name="black_max"></param> /// <param name="board"></param> /// <returns></returns> int findBestBlackMove(AbstractBoard.CommonMove col_to_move_in, int remaining_depth, int white_min, int black_max, C4Board board) { int best_score = BIG_SCORE; var best_move = new AbstractBoard.CommonMove(); var move_status = new AbstractBoard.MoveResult(); List <AbstractBoard.CommonMove> valid_moves = board.validMoves(); for (int black_move_idx = 0; black_move_idx < valid_moves.Count; ++black_move_idx) { // Make each move in turn and see if it would be a winning move var curr_move = valid_moves[black_move_idx]; var new_board = new C4Board(board); move_status = new_board.makeMove(curr_move); if (move_status.was_winning_move) { col_to_move_in.move_idx = curr_move.move_idx; return(BLACK_WIN); } int score = 0; if (remaining_depth == 0) { score = new_board.rateBoard(); } else { score = findBestWhiteMove(col_to_move_in: curr_move, remaining_depth: remaining_depth - 1, white_min: white_min, black_max: black_max, board: new_board); } if (score < best_score) { // Best move yet best_score = score; best_move.move_idx = curr_move.move_idx; if (black_max > best_score) { black_max = best_score; } } if (black_max <= white_min) { // Pruning - short-circuit rest of processing col_to_move_in.move_idx = best_move.move_idx; return(best_score); } } col_to_move_in.move_idx = best_move.move_idx; return(best_score); }
public C4Board(AbstractBoard board) { if (board is C4Board) { C4Board c4_board = board as C4Board; // Call C4Board ctor setupBoard(c4_board); } }
private void setupBoard(C4Board board) { // Copy squares for (int row_idx = 0; row_idx < NUM_ROWS; ++row_idx) { for (int col_idx = 0; col_idx < NUM_COLS; ++col_idx) { squares[row_idx, col_idx] = board.squares[row_idx, col_idx]; } } blackToMove = board.blackToMove; // Copy numPieceInCol for (int col_idx = 0; col_idx < NUM_COLS; ++col_idx) { numPiecesInCol[col_idx] = board.numPiecesInCol[col_idx]; } }
/* * Work out how much credit to give the given colour in the * current position */ public int rateBoard(PieceType colour) { const int THREE_IN_LINE_WITH_GAP_SCORE = 100; int result = 0; // Try moving in each of the empty squares and see if this // gives a win: // TO DO: Look for a move that gives us 3+ a gap in a block of 4. // Copy squares for (int row_idx = 0; row_idx < NUM_ROWS; ++row_idx) { for (int col_idx = 0; col_idx < NUM_COLS; ++col_idx) { if (squares[row_idx, col_idx] == PieceType.EMPTY) { //System.Console.WriteLine($"Considering row {row_idx} col {col_idx}"); var new_board = new C4Board(this); if (colour == PieceType.WHITE) { new_board.blackToMove = true; } else { new_board.blackToMove = false; } MoveResult res = new_board.placePiece(row_idx, col_idx); if (res.was_winning_move) { // Give more credit to a lower winning move than a higher up one result += THREE_IN_LINE_WITH_GAP_SCORE; result += NUM_COLS - col_idx; //System.Console.WriteLine("3 in line with gap found"); } } } // end for col } // end for row return(result); }
// TO DO: Use abstract board throughout public BestMoveFinder(C4Board board) { this.board = board; }
public C4Board(C4Board board) { setupBoard(board); }