/** * Returns all the children of this node found so far. You probably won't * want to call this method until you're sure you're done with getChild(). * * @return <code>Node[]</code> of all known children for this node. * @see getChild() */ public Node[] children() { Node[] temp = new Node[this.childNum + 1]; for (int i = 0; i < this.childNum + 1; i++) { temp[i] = this._children[i]; } return temp; }
/// <summary> /// /// </summary> /// <param name="n"></param> /// <param name="min"></param> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> private int minimaxAB( Node n, bool min, int a,int b) { int alpha = a; int beta = b; if (n.isLeaf()) { return n.value(this._player); } if (alpha > beta) return min ? beta : alpha; //Node child; // if (min) { foreach (var child in n.Successors(null)){ int val = minimaxAB(child, false, alpha, beta); if (val < beta) { beta = val; } } return beta; } else { foreach (var child in n.Successors(null)){ int val = minimaxAB(child, true, alpha, beta); if (val > alpha) { alpha = val; } } return alpha; } }
// Implementation of mimimax with alpha-beta pruning. private int minimaxAB( Node n, bool min, int a, int b) { int alpha = a; int beta = b; if (n.isLeaf()) { return n.value(this._player); } Node child; if (min) { while (((child = n.getChild()) != null) && !(alpha > beta)) { int val = minimaxAB(child, false, alpha, beta); if (val < beta) { beta = val; } } return beta; } else { while (((child = n.getChild()) != null) && !(alpha > beta)) { int val = minimaxAB(child, true, alpha, beta); if (val > alpha) { alpha = val; } } return alpha; } }
/** * Gets the next move of this player. * * @param board * <code>Board</code> representation of the current game state. * @param prev * <code>Move</code> representing the previous move in the the * game. * @param color * <code>int</code> representing the pieces this * <code>Player</code> is playing with. One of * <code>TicTacToe.NOUGHTS</code> or * <code>TicTacToe.CROSSES</code> * @return <code>Move</code> Next move of this player. */ public Move getMove( int[,] board, Move prev, int color) { this._player = color; Node root = new Node(board, prev); int max = int.MinValue; Node child; Node bestNode = null; while ((child = root.getChild()) != null) { int val = minimaxAB(child, true, int.MinValue, int.MaxValue); if (val >= max) { max = val; bestNode = child; } } return bestNode.move(); }
/// <summary> /// Gets random successor /// </summary> /// <param name="heuristic"></param> /// <returns></returns> public IEnumerable<Node> Successors(Func<bool, int, int> heuristic) { Move[] moves = Board.GetEmptyPositions(_board, player()); moves = moves.Randomize(); int length = moves.Length; for (int i = 0; i < length; i++) { int[,] newPos = Board.copy(_board); Move move = moves[i]; Board.placePiece(newPos, move); Node successor = new Node(newPos, move); yield return successor; } }
/** * Gets the "next" child for this node, or <code>null</code> if all * children of this node have already been found. * * @return <code>Node</code> Representation of child (one move on) in the * game tree. */ public Node getChild() { bool firstColumn = true; for (int x = this._x; x < 3; x++) { int starter = 0; if (firstColumn) { starter = this._y; } for (int y = starter; y < 3; y++) { Move m = new Move(x, y, this.player()); if (Board.isEmpty(this._board, m)) { int[,] newPos = Board.copy(this._board); Board.placePiece(newPos, m); Node child = new Node(newPos, m); this._children[this.childNum++] = child; if (y >= (3 - 1)) { this._x = (int) (x + 1); this._y = 0; } else { this._x = x; this._y = (int) (y + 1); } this._leaf = false; this._leafdef = true; return child; } } firstColumn = false; } this._leaf = true; this._leafdef = true; return null; }