static int CalculateMoves(GameBoard board) { /* goes through all the possible moves * on a gameboard * returns number of moves */ int moves = 0; Colour player_colour = Colour.NONE; GameBoard.MinMax child_type = GameBoard.MinMax.Null; if (board.GetNodeType() == GameBoard.MinMax.Max) { player_colour = Colour.BLACK; child_type = GameBoard.MinMax.Min; }else if (board.GetNodeType() == GameBoard.MinMax.Min) { player_colour = Colour.WHITE; child_type = GameBoard.MinMax.Max; } for (int x = 0; x <= 3; x++) { for (int y = 0; y <= 3; y++) { if (board.ReturnPosition(x,y).stones > 0 && board.ReturnPosition(x,y).colour == player_colour) { //if statement to sort number of stones //1-2 stones = 1 square if (board.ReturnPosition(x, y).stones == 1 || board.ReturnPosition(x, y).stones == 2) { //north int a = x; int b = y + 1; moves = CheckAdjacentMove(board, child_type, player_colour, x, y, a, b, moves); //south a = x; b = y - 1; moves = CheckAdjacentMove(board, child_type, player_colour, x, y, a, b, moves); //east a = x - 1; b = y; moves = CheckAdjacentMove(board, child_type, player_colour, x, y, a, b, moves); //west a = x + 1; b = y; moves = CheckAdjacentMove(board, child_type, player_colour, x, y, a, b, moves); //ne a = x + 1; b = y - 1; moves = CheckAdjacentMove(board, child_type, player_colour, x, y, a, b, moves); //nw a = x - 1; b = y - 1; moves = CheckAdjacentMove(board, child_type, player_colour, x, y, a, b, moves); //se a = x + 1; b = y + 1; moves = CheckAdjacentMove(board, child_type, player_colour, x, y, a, b, moves); //sw a = x - 1; b = y + 1; moves = CheckAdjacentMove(board, child_type, player_colour, x, y, a, b, moves); } else if (board.ReturnPosition(x, y).stones == 3)//3 stones = 2 squares { //north x2 int a = x; int b = y + 1; int c = x; int d = y + 2; moves = CheckTwoSquares(board, child_type, player_colour, x, y, a, b, c, d, moves); //south x2 a = x; b = y - 1; c = x; d = y - 2; moves = CheckTwoSquares(board, child_type, player_colour, x, y, a, b, c, d, moves); //eastx2 a = x - 1; b = y; c = x - 2; d = y; moves = CheckTwoSquares(board, child_type, player_colour, x, y, a, b, c, d, moves); //westx2 a = x + 1; b = y; c = x + 2; d = y; moves = CheckTwoSquares(board, child_type, player_colour, x, y, a, b, c, d, moves); //nex2 a = x + 1; b = y - 1; c = x + 2; d = y - 2; moves = CheckTwoSquares(board, child_type, player_colour, x, y, a, b, c, d, moves); //nwx2 a = x - 1; b = y - 1; c = x - 2; d = y - 2; moves = CheckTwoSquares(board, child_type, player_colour, x, y, a, b, c, d, moves); //se x2 a = x + 1; b = y + 1; c = x + 2; d = y + 2; moves = CheckTwoSquares(board, child_type, player_colour, x, y, a, b, c, d, moves); //swx2 a = x - 1; b = y + 1; c = x - 2; d = y + 2; moves = CheckTwoSquares(board, child_type, player_colour, x, y, a, b, c, d, moves); } else // 4+ stones = 3 squares { //north x3 int a = x; int b = y + 1; int c = x; int d = y + 2; int e = x; int f = y + 3; moves = CheckThreeSquares(board, child_type, player_colour, x, y, a, b, c, d, e, f, moves); //south x3 a = x; b = y - 1; c = x; d = y - 2; e = x; f = y - 3; moves = CheckThreeSquares(board, child_type, player_colour, x, y, a, b, c, d, e, f, moves); //westx3 a = x - 1; b = y; c = x - 2; d = y; e = x - 3; f = y; moves = CheckThreeSquares(board, child_type, player_colour, x, y, a, b, c, d, e, f, moves); //eastx3 a = x + 1; b = y; c = x + 2; d = y; e = x + 3; f = y; moves = CheckThreeSquares(board, child_type, player_colour, x, y, a, b, c, d, e, f, moves); //nex3 a = x + 1; b = y + 1; c = x + 2; d = y + 2; e = x + 3; f = y + 3; moves = CheckThreeSquares(board, child_type, player_colour, x, y, a, b, c, d, e, f, moves); //nwx3 //---------???? a = x - 1; b = y + 1; c = x - 2; d = y + 2; e = x - 3; f = y + 3; moves = CheckThreeSquares(board, child_type, player_colour, x, y, a, b, c, d, e, f, moves); //se x3 a = x + 1; b = y - 1; c = x + 2; d = y - 2; e = x + 3; f = y - 3; moves = CheckThreeSquares(board, child_type, player_colour, x, y, a, b, c, d, e, f, moves); //swx3 a = x - 1; b = y - 1; c = x - 2; d = y - 2; e = x - 3; f = y - 3; moves = CheckThreeSquares(board, child_type, player_colour, x, y, a, b, c, d, e, f, moves); } } } } //store moves in parent - number of squares covereed - failed eval fxn /* int squares = 0; for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { if (board.ReturnPosition(x, y).colour == player_colour) { squares++; } } } board.SetAlphaBetaValue(squares); return squares; */ board.SetAlphaBetaValue(moves); return moves; }
static GameBoard CalculateMaxMove(GameBoard parent) { /* Alpha values are stored in the max nodes * Alpha value = max(children's Beta Values of min nodes) * Because we want to minimize opponent moves * */ if (parent.GetChildren().Count <= 0) { CalculateMoves(parent); } GameBoard best_child = null; if (parent.GetChildren().Count > 0) { best_child = parent.GetChildren().ElementAt(0); //best is first child foreach (GameBoard child in parent.GetChildren()) { if (CalculateMoves(child) >= parent.GetAlphaBetaValue()) //get max { best_child = child; //new best child parent.SetAlphaBetaValue(best_child.GetAlphaBetaValue()); } } return best_child; } return null; }
static GameBoard CalculateMinMove(GameBoard parent) { /* Beta values are stored in the min nodes * Beta value = min(alpha Values of max nodes) * Because we want to maximize our moves * */ if (parent.GetChildren().Count <= 0) { CalculateMoves(parent); } GameBoard worst_child = null; if (parent.GetChildren().Count > 0) { worst_child = parent.GetChildren().ElementAt(0); foreach (GameBoard child in parent.GetChildren()) { if (CalculateMoves(child) <= parent.GetAlphaBetaValue()) { worst_child = child; parent.SetAlphaBetaValue(worst_child.GetAlphaBetaValue()); } } return worst_child; } return null; }
static void AlphaBetaSearch() { GameBoard parent = new GameBoard(); parent.SetNodeType(GameBoard.MinMax.Min); int total_moves = 0; Console.WriteLine("Starting move:"); displayBoard(parent); CalculateMoves(parent); bool turn = false; //turn 0 = player's turn(black,min), turn 1 = our turn(white,max) GameBoard next_move = parent; while (total_moves < 5000) { if (turn == false)//their turn (BLACK) { Console.WriteLine("Their Move / Player 1"); //next_move = CalculateBeta(parent); //Random Agent :( //choose random child if (parent.GetChildren().Count <= 0) { CalculateMoves(parent); } if (parent.GetChildren().Count <= 0) { break; //win condition for player 2 } Random random_number = new Random(); int black_move = random_number.Next(parent.GetChildren().Count - 1); next_move = parent.GetChildren().ElementAt(black_move); turn = true; } else //my move (WHITE) { Console.WriteLine("My Move / Player 2"); //next_move = null; int best = 100000; if (parent.GetChildren().Count <= 0) { CalculateMoves(parent); } if (parent.GetChildren().Count <= 0) { break; //win condition for player 1 } //the parent is a max node (next_move) //the children are min nodes Collection<GameBoard> potentialMoves = new Collection<GameBoard>(); foreach (GameBoard child in parent.GetChildren()) { CalculateAlphaBeta(child, 3, -100000, best, GameBoard.MinMax.Min); if (child.GetAlphaBetaValue() < best) { best = child.GetAlphaBetaValue(); potentialMoves.Clear(); potentialMoves.Add(child); } else if (child.GetAlphaBetaValue() == best) { potentialMoves.Add(child); } } Random random_number = new Random(); int white_move = random_number.Next(potentialMoves.Count - 1); next_move = potentialMoves.ElementAt(white_move); potentialMoves.Clear(); parent.SetAlphaBetaValue(best); //System.GC.Collect(); turn = false; } //each move Console.WriteLine("Move #: " + total_moves); displayBoard(next_move); parent = next_move; total_moves++; next_move.SetParent(null); System.GC.Collect(); } //WINNER if (next_move.GetNodeType() == GameBoard.MinMax.Max) { Console.WriteLine("Player 1 wins"); } else { Console.WriteLine("Computer wins"); } }