// Checks if the game state that is being sent back to the oppenent will cause the opponent to win. If so find another solution, // if no solution or no win send that game state. public static QuartoSearchTree.Node checkForOpponentWin(QuartoSearchTree.Node currentNode) { QuartoSearchTree.Node newWinNode = null; bool hasWon = true; string[] gameBoard; string piece; int move; for (int i = 0; hasWon && currentNode.parent.children[i] != null; i++) { gameBoard = currentNode.parent.children[i].gameBoard; piece = currentNode.parent.children[i].pieces[currentNode.parent.children[i].pieceToPlay].getPiece(); move = currentNode.parent.children[i].moveOnBoard; hasWon = isWinOnBoard(gameBoard, piece); if (!hasWon) { newWinNode = currentNode.parent.children[i]; } } if (hasWon && newWinNode == null) { newWinNode = currentNode; } return(newWinNode); }
// Checks if the game state that is being sent back to the oppenent will cause the opponent to win. If so find another solution, // if no solution or no win send that game state. public static QuartoSearchTree.Node checkForOpponentWin(QuartoSearchTree.Node currentNode, string winBlockPiece) { QuartoSearchTree.Node newWinNode = null; bool hasWon = true; string[] gameBoard; string piece; bool piecePlayable; if (winBlockPiece != null) { for (int i = 0; hasWon && i < QuartoSearchTree.MAXGAMEBOARD; i++) { gameBoard = currentNode.gameBoard; piece = currentNode.pieces[i].getPiece(); piecePlayable = currentNode.pieces[i].getPlayablePiece(); if (piecePlayable) { hasWon = isWinOnBoard(gameBoard, piece); if (!hasWon && piece != winBlockPiece) { newWinNode = currentNode; newWinNode.pieceToPlay = i; } else if (!hasWon && piece == winBlockPiece) { hasWon = true; } } } } else { for (int i = 0; hasWon && currentNode.parent.children[i] != null; i++) { gameBoard = currentNode.parent.children[i].gameBoard; piece = currentNode.parent.children[i].pieces[currentNode.parent.children[i].pieceToPlay].getPiece(); hasWon = isWinOnBoard(gameBoard, piece); if (!hasWon) { newWinNode = currentNode.parent.children[i]; } } } if (hasWon && newWinNode == null) { newWinNode = currentNode; } return(newWinNode); }
// Copies a node's piece map to a string array public static void copyPieceMap(QuartoSearchTree.Node recievingNode, QuartoSearchTree.Node nodeToCopy, int pieceToFind) { string pieceString; bool piecePlayable; for (int i = 0; i < QuartoSearchTree.MAXGAMEBOARD; i++) { pieceString = nodeToCopy.pieces[i].getPiece(); piecePlayable = nodeToCopy.pieces[i].getPlayablePiece(); recievingNode.pieces[i].setValues(pieceString, piecePlayable); } recievingNode.pieces[pieceToFind].setPlayable(false); }
// Searches tree generated for the best play. Selects the best move from the move given by the opponent. public static winningMove searchForBestPlay(QuartoSearchTree.Node currentNode, int depth, int minimax, int alpha, int beta, bool maxPlayer) { int j = 0; string pieceString; int boardPosition = 0; int minimaxCompare; winningMove winChoice = new winningMove(); winningMove winChoice2 = new winningMove(); winChoice.winningNode = new QuartoSearchTree.Node(); // If only root in tree if (currentNode.parent == null && currentNode.children[0] == null) { } // Detects for win if (currentNode.parent == null) { for (int i = 0; i < QuartoSearchTree.MAXGAMEBOARD && currentNode.children[i] != null; i++) { if (currentNode.pieceToPlay == QuartoSearchTree.NULLPIECE) { pieceString = null; } else { pieceString = currentNode.pieces[currentNode.pieceToPlay].piece; } while (currentNode.gameBoard[boardPosition] != null) { boardPosition++; } bool win = Heuristic.isWin(currentNode.gameBoard, pieceString, boardPosition); if (win) { winChoice.winningNode = currentNode.children[i]; winChoice.heuristicValue = 0; return(winChoice); } boardPosition++; } } // If it is the bottom of the tree if (currentNode.children[0] == null) { int value; for (int i = 0; i < QuartoSearchTree.MAXGAMEBOARD && currentNode.parent.children[i] != null; i++) { if (currentNode.parent.children[i].pieceToPlay == QuartoSearchTree.NULLPIECE) { pieceString = null; } else { pieceString = currentNode.parent.children[i].pieces[currentNode.parent.children[i].pieceToPlay].piece; } minimaxCompare = Heuristic.calculateHeuristic(currentNode.parent.children[i].gameBoard, pieceString); if (i == 0) { minimax = Heuristic.calculateHeuristic(currentNode.parent.children[i].gameBoard, pieceString); winChoice.winningNode = currentNode.parent.children[i]; winChoice.heuristicValue = minimax; totalSearch++; } else if ((minimaxCompare > minimax && maxPlayer == true) || (minimaxCompare < minimax && maxPlayer == false)) { minimax = minimaxCompare; winChoice.winningNode = currentNode.parent.children[i]; winChoice.heuristicValue = minimax; totalSearch++; } //prunes the rest of children if they can be pruned if (maxPlayer) { value = -INFINITY; if (winChoice.heuristicValue > value) { value = winChoice.heuristicValue; } if (value > alpha) { alpha = value; } if (alpha >= beta) { break; } } else { value = INFINITY; if (winChoice.heuristicValue < value) { value = winChoice.heuristicValue; } if (value < beta) { beta = value; } if (alpha >= beta) { break; } } j++; } } // Iterates through all children nodes else { int value; while (j < QuartoSearchTree.MAXGAMEBOARD && currentNode.children[j] != null) { if (j == 0) { winChoice = searchForBestPlay(currentNode.children[j], depth, minimax, alpha, beta, !maxPlayer); if (currentNode.parent == null || currentNode.parent.parent == null) { } // When it is evaluating the next move from the root else if (currentNode.parent.parent.parent == null) { winChoice.winningNode = currentNode; totalSearch++; } } else { winChoice2 = searchForBestPlay(currentNode.children[j], depth, minimax, alpha, beta, !maxPlayer); if ((winChoice2.heuristicValue > winChoice.heuristicValue && maxPlayer == true) || (winChoice2.heuristicValue < winChoice.heuristicValue && maxPlayer == false)) { winChoice.heuristicValue = winChoice2.heuristicValue; if (currentNode.parent == null) { winChoice.winningNode = winChoice2.winningNode; totalSearch++; } else if (currentNode.parent.parent == null) { winChoice.heuristicValue = winChoice2.heuristicValue; winChoice.winningNode = winChoice2.winningNode; totalSearch++; } // When it is evaluating the next move from the root else if (currentNode.parent.parent.parent == null) { winChoice.winningNode = currentNode; winChoice.heuristicValue = winChoice2.heuristicValue; totalSearch++; } } } //prunes the rest of children if they can be pruned if (maxPlayer) { value = -INFINITY; if (winChoice.heuristicValue > value) { value = winChoice.heuristicValue; } if (value > alpha) { alpha = value; } if (alpha >= beta) { break; } } else { value = INFINITY; if (winChoice.heuristicValue < value) { value = winChoice.heuristicValue; } if (value < beta) { beta = value; } if (alpha >= beta) { break; } } j++; } } if (currentNode.parent == null) { RandomPlay(winChoice); } return(winChoice); }