164 lines
3.5 KiB
Java
164 lines
3.5 KiB
Java
package reversi.model;
|
|
|
|
import java.util.LinkedList;
|
|
|
|
/**
|
|
* Class for a gamenode. Is needed to build a gametree for e.g. minmax
|
|
* algorithm. A node represents a virtual move.
|
|
*
|
|
*/
|
|
public class GameNode {
|
|
|
|
/**
|
|
* Reversi-board of the node.
|
|
*/
|
|
private Reversi state;
|
|
|
|
/**
|
|
* Scoring of the node.
|
|
*/
|
|
private double score;
|
|
|
|
/**
|
|
* The Move.
|
|
*/
|
|
private Field move;
|
|
|
|
/**
|
|
* Children of the node.
|
|
*/
|
|
private LinkedList<GameNode> children;
|
|
|
|
/**
|
|
* Constructor for the root node.
|
|
*
|
|
* @param move Root move
|
|
* @param state Board of the root node
|
|
*/
|
|
GameNode(final Field move, final Reversi state) {
|
|
this.move = move;
|
|
this.state = state;
|
|
this.children = new LinkedList<GameNode>();
|
|
}
|
|
|
|
/**
|
|
* Constructor for node.
|
|
*
|
|
* @param move Move of node
|
|
* @param state Board of node
|
|
* @param parent Parent of node
|
|
*/
|
|
GameNode(final Field move, final Reversi state, final GameNode parent) {
|
|
this(move, state);
|
|
parent.children.add(this);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param score Score to set
|
|
*/
|
|
public final void setScore(final double score) {
|
|
this.score = score;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return Score
|
|
*/
|
|
public final double getScore() {
|
|
return score;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return Board
|
|
*/
|
|
public final Reversi getState() {
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return Move
|
|
*/
|
|
public final Field getMove() {
|
|
return move;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return Children
|
|
*/
|
|
public final LinkedList<GameNode> getChildren() {
|
|
return children;
|
|
}
|
|
|
|
/**
|
|
* Is needed to calculate the combined score of the parent node.
|
|
*
|
|
* @return GameNode with highest score
|
|
*/
|
|
public final GameNode getChildrensHighestScore() {
|
|
GameNode highest = children.getFirst();
|
|
|
|
for (GameNode node : children) {
|
|
if (node.getScore() > highest.getScore()) {
|
|
highest = node;
|
|
}
|
|
}
|
|
return highest;
|
|
}
|
|
|
|
/**
|
|
* Is needed to calculate the combined score of the parent node.
|
|
*
|
|
* @return GameNode with lowest score
|
|
*/
|
|
public final GameNode getChildrensLowestScore() {
|
|
GameNode lowest = children.getFirst();
|
|
|
|
for (GameNode node : children) {
|
|
if (node.getScore() < lowest.getScore()) {
|
|
lowest = node;
|
|
}
|
|
}
|
|
return lowest;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return If node has at least one child
|
|
*/
|
|
public final boolean hasChild() {
|
|
return (children.size() > 0);
|
|
}
|
|
|
|
/**
|
|
* Set children of a node.
|
|
*/
|
|
public final void fillNode() {
|
|
for (Field move : generateChildren()) {
|
|
Reversi tmpBoard = this.getState().clone();
|
|
tmpBoard.performMove(move.row(), move.col());
|
|
new GameNode(move, tmpBoard, this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return <code>Linkedlist</code> with possible moves in the
|
|
* current reversi-board.
|
|
*/
|
|
private LinkedList<Field> generateChildren() {
|
|
LinkedList<Field> movesList = new LinkedList<Field>();
|
|
|
|
for (int row = 0; row < Board.SIZE; row++) {
|
|
for (int col = 0; col < Board.SIZE; col++) {
|
|
if (getState().isValidMove(row, col)) {
|
|
movesList.add(new Field(row, col));
|
|
}
|
|
}
|
|
}
|
|
return movesList;
|
|
}
|
|
} |