/** * A brief description of this class... * * @author Author Name */ //package packageName import java.util.*; public class Col extends CombinatorialGame { /* constants */ //neither red nor blue public static final int UNCOLORED = 2; //red public static final int RED = CombinatorialGame.RIGHT; //blue public static final int BLUE = CombinatorialGame.LEFT; /* fields */ //the graph to play on private Graph<Integer> graph; //the coloring of each node //private HashMap<Integer, Integer> coloring; /* constructors */ /** * Creates a new instance of Col with all vertices uncolored. * @param graph The graph to build this on top of. */ public Col(Graph<Integer> graph) { Collection<Integer> legalColors = new ArrayList<Integer>(); legalColors.add(UNCOLORED); legalColors.add(RED); legalColors.add(BLUE); //check that the graph is colored legally. for (Vertex<Integer> vertex : graph.getVertices()) { if (!legalColors.contains(vertex.getValue())) { throw new IllegalArgumentException(vertex.getValue() + " is not a legal color for a Col vertex!"); } } //create the graph without connections this.graph = new Graph<Integer>(graph.getVertices()); //now add the connections. for (Vertex<Integer> vertex : graph.getVertices()) { Vertex<Integer> vertexClone = this.graph.getVertexById(vertex.getId()); for (Vertex<Integer> neighbor : vertex.getNeighbors()) { //System.out.println("vertex: " + vertex); Vertex<Integer> neighborClone = this.graph.getVertexById(neighbor.getId()); vertexClone.addEdge(neighborClone); //System.out.println("==?: " + (vertexClone == vertex)); } } this.graph = this.copyGraph(graph); } /* public methods */ /** * Returns a String version of this. * * @return A String description of this. */ public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Col:\n"); for (Vertex<Integer> vertex : this.graph.getVertices()) { builder.append(vertex.getId() + ": ["); if (vertex.getValue().equals(UNCOLORED)) { builder.append(" "); } else if (vertex.getValue().equals(BLUE)) { builder.append("BLUE"); } else { builder.append("RED "); } builder.append("], adj. to: "); for (Vertex<Integer> neighbor : vertex.getNeighbors()) { builder.append(neighbor.getId() + ", "); } builder.append("\n"); } return builder.toString(); } //@override public Collection<CombinatorialGame> getOptions(int playerId) { Collection<CombinatorialGame> options = new ArrayList<CombinatorialGame>(); // testing code //System.out.println(); //System.out.println(); //System.out.println("Options of " + this + " for player " + playerId + ":"); //end of small testing block for (Vertex<Integer> vertex: this.graph.getVertices()) { if (vertex.getValue().equals(UNCOLORED)) { boolean adjacentToSameColor = false; for (Vertex<Integer> neighbor : vertex.getNeighbors()) { if (neighbor.getValue().equals(playerId)) { adjacentToSameColor = true; break; } } if (!adjacentToSameColor) { //add the option that includes coloring vertex //make the change Graph<Integer> graphCopy = this.copyGraph(this.graph); Vertex<Integer> copyVertex = graphCopy.getVertexById(vertex.getId()); copyVertex.setValue(playerId); Col option = new Col(graphCopy); //vertex.setValue(playerId); //Col option = new Col(this.graph); //this copies the graph, so we can change it back options.add(option); //System.out.println(option); //System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); //put it back //vertex.setValue(UNCOLORED); } } } return options; } //@override public static String getName() { return "Col"; } /** * Returns the underlying graph. * @return A copy of the underlying graph of Integers. */ public Graph<Integer> getGraph() { return this.copyGraph(this.graph); } /** * Returns a copy of this. * * @return A deepish copy of this. */ public CombinatorialGame clone() { return new Col(this.getGraph()); } /** * Determines whether this is equivalent to another Object. * * @param object Another object to compare to this. * @return Whether this is equivalent to object. */ public boolean equals(Object object) { if (object == null || this.getClass() != object.getClass()) { return false; } else { return this.equals((Col) object); } } /** * Determines whether this is equivalent to another Combinatorial Game. * * @param game Another CombinatorialGame * @return Whether this is equivalent to game. */ public boolean equals(CombinatorialGame game) { if (game == null || this.getClass() != game.getClass()) { return false; } else { Col other = (Col) game; return this.graph.equals(other.graph); } } /** * Represents a factory that creates instances of Col. All instances generated are in a grid. */ public static class PositionBuilder implements PositionFactory<Col> { //fields //the minimum width of a board private int minWidth; //the maximum width of a board private int maxWidth; //the minimum height of a board private int minHeight; //the maximum height of a board private int maxHeight; //the probability that each vertex will be colored private double colorDensity; /** * Class constructor. * * @param minWidth Minimum width of the board. * @param maxWidth Maximum width of the board. * @param minHeight Minimum height of the board. * @param maxHeight Maximum height of the board. * @param colorDensity The probability a vertex will be colored. (Color chosen uniformly at random.) */ public PositionBuilder(int minWidth, int maxWidth, int minHeight, int maxHeight, double colorDensity) { this.minWidth = minWidth; this.maxWidth = maxWidth; this.minHeight = minHeight; this.maxHeight = maxHeight; this.colorDensity = colorDensity; } /** * Returns a Col position in the shape of a grid. */ public Col getPosition() { Random generator = new Random(); int width = this.minWidth + generator.nextInt(this.maxWidth - this.minWidth + 1); int height = this.minHeight + generator.nextInt(this.maxHeight - this.minHeight + 1); Collection<Vertex<Integer>> vertices = new ArrayList<Vertex<Integer>>(); //build the vertices for (int i = 0; i < width * height; i++) { int color = UNCOLORED; if (generator.nextDouble() <= colorDensity) { color = (generator.nextDouble() < .5 ? BLUE : RED); } vertices.add(new Vertex<Integer>(color , i)); } //create the graph Graph<Integer> graph = new Graph<Integer>(vertices); //add the edges for (int i = 0; i < width * height; i++) { Vertex<Integer> vertex = graph.getVertexById(i); if (i % width != 0) { vertex.addEdge(graph.getVertexById(i-1)); } if (i >= width) { vertex.addEdge(graph.getVertexById(i-width)); } } //return the position return new Col(graph); } } /* hidden methods (private/protected) (JavaDoc not necessary) */ //copies a graph of Integers private Graph<Integer> copyGraph(Graph<Integer> graph) { //first, create a list of copied vertices Collection<Vertex<Integer>> vertices = new ArrayList<Vertex<Integer>>(); for (Vertex<Integer> vertex : graph.getVertices()) { vertices.add(new Vertex<Integer>(vertex.getValue(), vertex.getId())); } //create the graph without connections Graph<Integer> copy = new Graph<Integer>(vertices); //now add the connections. for (Vertex<Integer> vertex : graph.getVertices()) { Vertex<Integer> vertexClone = copy.getVertexById(vertex.getId()); for (Vertex<Integer> neighbor : vertex.getNeighbors()) { Vertex<Integer> neighborClone = copy.getVertexById(neighbor.getId()); vertexClone.addEdge(neighborClone); } } return copy; } /* main method for testing */ /** * Unit test for Col * @param args Arguments used to test this class. */ public static void main(String[] args) { int minWidth = 1; int maxWidth = 3; int minHeight = 1; int maxHeight = 3; double colorDensity = .55; PositionFactory<Col> builder = new Col.PositionBuilder(minWidth, maxWidth, minHeight, maxHeight, colorDensity); Col position = builder.getPosition(); System.out.println(position); System.out.println("***********************************\nOptions for Blue:"); for (CombinatorialGame option : position.getOptions(CombinatorialGame.LEFT)) { System.out.println(option); System.out.println("********************************"); } } } //end of Col