Loading .idea/workspace.xml +46 −16 Original line number Diff line number Diff line Loading @@ -10,20 +10,14 @@ </component> <component name="ChangeListManager"> <list default="true" id="78671b20-6a1e-42c8-be28-50b7f38fa7ff" name="Default Changelist" comment=""> <change beforePath="$PROJECT_DIR$/.highscores.db" beforeDir="false" afterPath="$PROJECT_DIR$/.highscores.db" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" /> <change afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/Board.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/Brain/Brain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/Brain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/Brain/lazyBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/LazyBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/Brain/simpleBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SimpleBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/Brain/smarterBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SmarterBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/highScores/highScore.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/highScores/highScore.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/CircleColor.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/CircleColor.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/CircleRolloverEvent.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/CircleRolloverEvent.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/GUI.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/GUI.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/SelfAwareCircle.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/SelfAwareCircle.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/SelfAwareListener.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/SelfAwareListener.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/sge.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/Brain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/Brain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/LazyBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/LazyBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SimpleBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SimpleBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SmarterBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SmarterBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/SelfAwareCircle.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/SelfAwareCircle.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java" afterDir="false" /> </list> <option name="SHOW_DIALOG" value="false" /> <option name="HIGHLIGHT_CONFLICTS" value="true" /> Loading Loading @@ -73,6 +67,9 @@ <recent name="edu.bu.ec504.spr19" /> <recent name="edu.bu.ec504.spr19.sameGameTris" /> </key> <key name="MoveInnerDialog.RECENTS_KEY"> <recent name="edu.bu.ec504.spr24.Brain" /> </key> </component> <component name="RunManager"> <configuration name="EC504 SameGameTris" type="Application" factoryName="Application"> Loading @@ -97,7 +94,7 @@ <workItem from="1548370619328" duration="375000" /> <workItem from="1580056843261" duration="23542000" /> <workItem from="1706041955741" duration="38000" /> <workItem from="1706042051986" duration="3619000" /> <workItem from="1706042051986" duration="5200000" /> </task> <task id="LOCAL-00001" summary="Apparently working version."> <created>1580084914114</created> Loading @@ -120,7 +117,23 @@ <option name="project" value="LOCAL" /> <updated>1580097683638</updated> </task> <option name="localTasksCounter" value="4" /> <task id="LOCAL-00004" summary="Cleaning up."> <option name="closed" value="true" /> <created>1706048258917</created> <option name="number" value="00004" /> <option name="presentableId" value="LOCAL-00004" /> <option name="project" value="LOCAL" /> <updated>1706048258917</updated> </task> <task id="LOCAL-00005" summary="Cleaning up."> <option name="closed" value="true" /> <created>1706048316975</created> <option name="number" value="00005" /> <option name="presentableId" value="LOCAL-00005" /> <option name="project" value="LOCAL" /> <updated>1706048316975</updated> </task> <option name="localTasksCounter" value="6" /> <servers /> </component> <component name="TypeScriptGeneratedFilesManager"> Loading @@ -130,6 +143,23 @@ <MESSAGE value="Apparently working version." /> <MESSAGE value="Final version." /> <MESSAGE value="Minor tweaks" /> <option name="LAST_COMMIT_MESSAGE" value="Minor tweaks" /> <MESSAGE value="Cleaning up." /> <option name="LAST_COMMIT_MESSAGE" value="Cleaning up." /> </component> <component name="XDebuggerManager"> <breakpoint-manager> <breakpoints> <line-breakpoint enabled="true" type="java-line"> <url>file://$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java</url> <line>643</line> <option name="timeStamp" value="1" /> </line-breakpoint> <line-breakpoint enabled="true" type="java-line"> <url>file://$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java</url> <line>167</line> <option name="timeStamp" value="3" /> </line-breakpoint> </breakpoints> </breakpoint-manager> </component> </project> No newline at end of file src/edu/bu/ec504/spr24/Brain/Board.java 0 → 100644 +198 −0 Original line number Diff line number Diff line package edu.bu.ec504.spr24.Brain; import edu.bu.ec504.spr24.sameGameTris.CircleColor; import edu.bu.ec504.spr24.sameGameTris.sge; import java.util.LinkedList; import java.util.Objects; /** * An internal recording of a board set up. */ class Board { /** * A 2-d Linked list of colors on the board. */ final LinkedList<LinkedList<CircleColor>> data; /** * The width and height of the board. */ final private int width, height; // constructs a board of specified width and height Board(int width, int height) { this.width = width; this.height = height; // allocate the data structure for storing board contents data = new LinkedList<>(); // set up the data structure for (int ii = 0; ii < width; ii++) { LinkedList<CircleColor> temp = new LinkedList<>(); for (int jj = 0; jj < height; jj++) {temp.add(CircleColor.NONE);} data.add(temp); } } /** * default constructor */ Board() { this(sge.getInstance().boardWidth(), sge.getInstance().boardHeight()); } /** * copy constructor * * @param baseBoard the board to copy */ Board(Board baseBoard) { // allocate memory for the new board this(baseBoard.width, baseBoard.height); // copy over all the specific items for (int xx = 0; xx < columns(); xx++) { for (int yy = 0; yy < rows(xx); yy++) {modify(xx, yy, baseBoard.getAt(xx, yy));} } } /** * @return the color of the yy'th item in the xx'th column, or CircleColor.NONE * if the cell is not in the <b>data</b> container */ CircleColor getAt(int xx, int yy) { try { return data.get(xx).get(yy); } catch (IndexOutOfBoundsException e) { return CircleColor.NONE; } } /** * @return the xx'th column, or null if the xx'th column does not exist in the <b>data</b> container */ private LinkedList<CircleColor> getAt(int xx) { try { return data.get(xx); } catch (IndexOutOfBoundsException e) { return null; } } /** * Changes yy'th item in xx'th column * %R: The circle at this location must still be in the <b>data</b> field */ void modify(int xx, int yy, CircleColor col) { data.get(xx).set(yy, col); } /** * Deletes yy'th item in xx'th column * %R: The circle at this location must still be in the <b>data</b> field */ private void delete(int xx, int yy) { data.get(xx).remove(yy); } /** * Deletes the column at (horizontal) board location xx * * %R: The column at this location must still be in the <b>data</b> field */ private void delete(int xx) { data.remove(xx); } // public accessors /** * Simulates a click on the yy'th cell of the xx'th column * * @return the number of cells deleted * @modifies Deletes cells in the same region as cell (xx,yy) * @expects The clicked cell is assumed not to be empty */ int clickNode(int xx, int yy) { CircleColor myColor = getAt(xx, yy); // the color to match // mark the region int count = clickNodeHelper(xx, yy, myColor); // clean up // ... delete all cells with no color // ... delete from the end to the front so that there are no problems with re-indexing for (int ii = data.size() - 1; ii >= 0; ii--) { for (int jj = Objects.requireNonNull(getAt(ii)).size() - 1; jj >= 0; jj--) { if (getAt(ii, jj) == CircleColor.NONE) {delete(ii, jj);} } // ... delete the column if it is empty if (Objects.requireNonNull(getAt(ii)).size() == 0) {delete(ii);} } return count; } /** * Recursive procedure for propagating a click at a location with color "col". * All items in the same region as the clicked cell are made to have CircleColor.NONE * * @return the number of cells changed to CircleColor.NONE in this call (and its recursive subcalls) * @modifies the color of some cells, but no cells are actually deleted */ int clickNodeHelper(int xx, int yy, CircleColor col) { if (getAt(xx, yy) == CircleColor.NONE || // we've either already seen this, or we've hit an empty space getAt(xx, yy) != col) // this is not the color we want {return 0;} // modify the current cell modify(xx, yy, CircleColor.NONE); return 1 + // 1 is for the current cell clickNodeHelper(xx - 1, yy, col) + // cell to the left clickNodeHelper(xx + 1, yy, col) + // cell to the right clickNodeHelper(xx, yy - 1, col) + // cell below clickNodeHelper(xx, yy + 1, col) // cell above ; } /** * @return the number of columns in the current state */ int columns() { return data.size(); } /** * @param xx the column being considered (assumed to exist) * @return the number of rows in column <b>xx</b> */ int rows(int xx) { return data.get(xx).size(); } /** * @return a "pretty-printed" version of the data structure */ public String display() { String temp = data.toString(); return temp.replace("], [", "]\n["); } /** * Stores an (xx,yy) position on the board. */ static class Pos { final int xx; final int yy; Pos(int xx, int yy) { this.xx = xx; this.yy = yy; } } } src/edu/bu/ec504/spr24/Brain/Brain.java +30 −14 Original line number Diff line number Diff line package edu.bu.ec504.spr24.Brain; import edu.bu.ec504.spr24.sameGameTris.GUI; import edu.bu.ec504.spr24.sameGameTris.sge; /** * The Brain is the artificial intelligence that tries to come up with the Loading @@ -10,32 +11,47 @@ import edu.bu.ec504.spr24.sameGameTris.GUI; */ public abstract class Brain implements Runnable { // FIELDS protected final GUI myGUI; // the GUI class attached to this Brain protected final GUI myGUI; // stores the GUI class attached to this Brain /** * When set to true, the Brain should stop what it's doing and exit as soon as is appropriate. */ private volatile boolean allDone = false; // METHODS /** * Constructs the brain * @param myGUI A reference to the Graphical User Interface on which the game is being played. */ Brain(GUI myGUI) { this.myGUI = myGUI; } /** * Each Brain should have a name, which is provided by this method. * @return the name of the brain */ public abstract String myName(); Brain() { this.myGUI = sge.getInstance(); } /** * This is called when the Brain is being asked to close down (i.e., the game is over). * It should clean up any data structures and/or signal threads to close, etc. */ public abstract void allDone(); final public void allDone() { allDone=true; }; /** * Starts the Brain a'thinking. * This is the code for making decisions about which circles you Brain selects. * This is the code for requests decisions about which circles you Brain selects. * @see java.lang.Runnable#run() */ public abstract void run(); final public void run() { while (!allDone && !myGUI.gameOverQ()) { Board.Pos theNextMove = nextMove(); myGUI.makeMove(theNextMove.xx, theNextMove.yy); // i.e. click on the lower left corner } } // ... METHODS FOR SUBCLASSES TO DEFINE /** * Each Brain should have a name, which is provided by this method. * @return the name of the brain */ public abstract String myName(); /** * Returns the next move of the Brain. */ public abstract Board.Pos nextMove(); } src/edu/bu/ec504/spr24/Brain/LazyBrain.java +10 −211 Original line number Diff line number Diff line package edu.bu.ec504.spr24.Brain; import java.util.LinkedList; import java.util.Objects; import edu.bu.ec504.spr24.sameGameTris.GUI; import edu.bu.ec504.spr24.Brain.Board.Pos; import edu.bu.ec504.spr24.sameGameTris.CircleColor; /** Loading @@ -13,11 +10,6 @@ public class LazyBrain extends Brain { // FIELDS /** * When set to true, the Brain should stop what it's doing and exit as soon as is appropriate. */ private volatile boolean allDone = false; /** * The Brain's recording of the current state of the board. */ Loading @@ -25,18 +17,11 @@ public class LazyBrain extends Brain { // METHODS /** Constructs a Brain linked to a specified myGUI * @param myGUI The GUI that will be instantiating the Brain */ public LazyBrain(GUI myGUI) { super(myGUI); } /** * {@inheritDoc} * Constructs a Brain linked to a specified myGUI */ public void allDone() { allDone = true; public LazyBrain() { super(); } /** Loading @@ -46,23 +31,18 @@ public class LazyBrain extends Brain { return "Lazy Brain"; } /** * {@inheritDoc} */ public void run() { @Override public Pos nextMove() { // Initialize and set up the internal board state with the current position currBoard = new Board(); for (int xx=0; xx<myGUI.boardWidth(); xx++) for (int yy=0; yy<myGUI.boardHeight(); yy++) currBoard.modify(xx, yy, myGUI.colorAt(xx, myGUI.boardHeight()-yy-1)); // Keep making moves until the game is over while (!allDone && !myGUI.gameOverQ()) { Board.Pos nextMove = chooseMove(); myGUI.makeMove(nextMove.xx, nextMove.yy); // i.e. click on the lower left corner } return chooseMove(); } // PRIVATE METHODS /** * Chooses the next move to make. Loading @@ -76,9 +56,9 @@ public class LazyBrain extends Brain { for (int xx=0; xx< currBoard.columns(); xx++) for (int yy=0; yy< currBoard.rows(xx); yy++) { if (currStateCopy.get(xx,yy)!= CircleColor.NONE) { if (currStateCopy.getAt(xx,yy)!= CircleColor.NONE) { Board test = new Board(currStateCopy); currStateCopy.clickNodeHelper(xx, yy, test.get(xx,yy)); // mark all other nodes in the region as "clear" (but does not delete anything) currStateCopy.clickNodeHelper(xx, yy, test.getAt(xx,yy)); // mark all other nodes in the region as "clear" (but does not delete anything) int count = test.clickNode(xx, yy); // try removing the region to see what is left over if (count > max) { // record a new best move Loading @@ -101,186 +81,5 @@ public class LazyBrain extends Brain { // INTERNAL CLASSES /** * Stores a board set up */ private class Board { /** * A 2-d Linked list of colors on the board. */ final LinkedList< LinkedList <CircleColor>> data; /** * The width and height of the board. */ final private int width, height; // constructs a board of specified width and height Board(int width, int height) { this.width = width; this.height = height; // allocate the data structure for storing board contents data = new LinkedList<>(); // set up the data structure for (int ii=0; ii<width; ii++) { LinkedList<CircleColor> temp = new LinkedList<>(); for (int jj=0; jj<height; jj++) temp.add(CircleColor.NONE); data.add(temp); } } /** * default constructor */ Board() { this(myGUI.boardWidth(),myGUI.boardHeight()); } /** * copy constructor * @param baseBoard the board to copy */ Board(Board baseBoard) { // allocate memory for the new board this(baseBoard.width, baseBoard.height); // copy over all the specific items for (int xx=0; xx<columns(); xx++) for (int yy=0; yy<rows(xx); yy++) modify(xx,yy,baseBoard.get(xx, yy)); } /** * @return the color of the yy'th item in the xx'th column, or CircleColor.NONE * if the cell is not in the <b>data</b> container */ private CircleColor get(int xx, int yy) { try { return data.get(xx).get(yy); } catch (IndexOutOfBoundsException e) { return CircleColor.NONE; } } /** * @return the xx'th column, or null if the xx'th column does not exist in the <b>data</b> container */ private LinkedList<CircleColor> get(int xx) { try { return data.get(xx); } catch (IndexOutOfBoundsException e) { return null; } } /** * Changes yy'th item in xx'th column * %R: The circle at this location must still be in the <b>data</b> field */ private void modify(int xx, int yy, CircleColor col) { data.get(xx).set(yy, col); } /** * Deletes yy'th item in xx'th column * %R: The circle at this location must still be in the <b>data</b> field */ private void delete(int xx, int yy) { data.get(xx).remove(yy); } /** * Deletes the column at (horizontal) board location xx * * %R: The column at this location must still be in the <b>data</b> field */ private void delete(int xx) { data.remove(xx); } // public accessors /** * Simulates a click on the yy'th cell of the xx'th column * @return the number of cells deleted * @modifies Deletes cells in the same region as cell (xx,yy) * @expects The clicked cell is assumed not to be empty */ int clickNode(int xx, int yy) { CircleColor myColor = get(xx,yy); // the color to match // mark the region int count = clickNodeHelper(xx, yy, myColor); // clean up // ... delete all cells with no color // ... delete from the end to the front so that there are no problems with re-indexing for (int ii=data.size()-1; ii>=0; ii--) { for (int jj = Objects.requireNonNull(get(ii)).size()-1; jj>=0; jj--) if (get(ii,jj)==CircleColor.NONE) delete(ii, jj); // ... delete the column if it is empty if (Objects.requireNonNull(get(ii)).size()==0) delete(ii); } return count; } /** * Recursive procedure for propagating a click at a location with color "col". * All items in the same region as the clicked cell are made to have CircleColor.NONE * @modifies the color of some cells, but no cells are actually deleted * @return the number of cells changed to CircleColor.NONE in this call (and its recursive subcalls) */ private int clickNodeHelper(int xx, int yy, CircleColor col) { if (get(xx,yy) == CircleColor.NONE || // we've either already seen this, or we've hit an empty space get(xx,yy) != col) // this is not the color we want return 0; // modify the current cell modify(xx,yy,CircleColor.NONE); return 1 + // 1 is for the current cell clickNodeHelper(xx-1, yy, col) + // cell to the left clickNodeHelper(xx+1, yy, col) + // cell to the right clickNodeHelper(xx, yy-1, col) + // cell below clickNodeHelper(xx, yy+1, col) // cell above ; } /** * @return the number of columns in the current state */ int columns() { return data.size(); } /** * * @param xx the column being considered (assumed to exist) * @return the number of rows in column <b>xx</b> */ int rows(int xx) { return data.get(xx).size(); } /** * @return a "pretty-printed" version of the data structure */ public String display() { String temp = data.toString(); return temp.replace("], [", "]\n["); } /** * Stores an (xx,yy) position on the board. */ static class Pos { final int xx; final int yy; Pos(int xx, int yy) {this.xx=xx; this.yy=yy;} } } } src/edu/bu/ec504/spr24/Brain/SimpleBrain.java +6 −15 Original line number Diff line number Diff line package edu.bu.ec504.spr24.Brain; import edu.bu.ec504.spr24.sameGameTris.GUI; import edu.bu.ec504.spr24.Brain.Board.Pos; /** * A very simple Brain for the game. Loading @@ -10,16 +10,10 @@ public class SimpleBrain extends Brain { // fields private volatile boolean allDone = false; // when set to true, the Brain should stop what it's doing and exit (at an appropriate time) public SimpleBrain(GUI myGUI) { super(myGUI); public SimpleBrain() { super(); } /** * {@inheritDoc} */ public void allDone() { allDone = true; } /** * {@inheritDoc} Loading @@ -28,11 +22,8 @@ private volatile boolean allDone = false; // when set to true, the Brain should return "Simple Brain"; } /** * {@inheritDoc} */ public void run() { while (!allDone && !myGUI.gameOverQ()) myGUI.makeMove(0, myGUI.boardHeight()-1); // i.e. click on the lower left corner @Override public Pos nextMove() { return new Pos(0, myGUI.boardHeight()-1); } } Loading
.idea/workspace.xml +46 −16 Original line number Diff line number Diff line Loading @@ -10,20 +10,14 @@ </component> <component name="ChangeListManager"> <list default="true" id="78671b20-6a1e-42c8-be28-50b7f38fa7ff" name="Default Changelist" comment=""> <change beforePath="$PROJECT_DIR$/.highscores.db" beforeDir="false" afterPath="$PROJECT_DIR$/.highscores.db" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" /> <change afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/Board.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/Brain/Brain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/Brain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/Brain/lazyBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/LazyBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/Brain/simpleBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SimpleBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/Brain/smarterBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SmarterBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/highScores/highScore.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/highScores/highScore.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/CircleColor.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/CircleColor.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/CircleRolloverEvent.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/CircleRolloverEvent.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/GUI.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/GUI.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/SelfAwareCircle.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/SelfAwareCircle.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/SelfAwareListener.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/SelfAwareListener.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr19/sameGameTris/sge.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/Brain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/Brain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/LazyBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/LazyBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SimpleBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SimpleBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SmarterBrain.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/Brain/SmarterBrain.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/SelfAwareCircle.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/SelfAwareCircle.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java" afterDir="false" /> </list> <option name="SHOW_DIALOG" value="false" /> <option name="HIGHLIGHT_CONFLICTS" value="true" /> Loading Loading @@ -73,6 +67,9 @@ <recent name="edu.bu.ec504.spr19" /> <recent name="edu.bu.ec504.spr19.sameGameTris" /> </key> <key name="MoveInnerDialog.RECENTS_KEY"> <recent name="edu.bu.ec504.spr24.Brain" /> </key> </component> <component name="RunManager"> <configuration name="EC504 SameGameTris" type="Application" factoryName="Application"> Loading @@ -97,7 +94,7 @@ <workItem from="1548370619328" duration="375000" /> <workItem from="1580056843261" duration="23542000" /> <workItem from="1706041955741" duration="38000" /> <workItem from="1706042051986" duration="3619000" /> <workItem from="1706042051986" duration="5200000" /> </task> <task id="LOCAL-00001" summary="Apparently working version."> <created>1580084914114</created> Loading @@ -120,7 +117,23 @@ <option name="project" value="LOCAL" /> <updated>1580097683638</updated> </task> <option name="localTasksCounter" value="4" /> <task id="LOCAL-00004" summary="Cleaning up."> <option name="closed" value="true" /> <created>1706048258917</created> <option name="number" value="00004" /> <option name="presentableId" value="LOCAL-00004" /> <option name="project" value="LOCAL" /> <updated>1706048258917</updated> </task> <task id="LOCAL-00005" summary="Cleaning up."> <option name="closed" value="true" /> <created>1706048316975</created> <option name="number" value="00005" /> <option name="presentableId" value="LOCAL-00005" /> <option name="project" value="LOCAL" /> <updated>1706048316975</updated> </task> <option name="localTasksCounter" value="6" /> <servers /> </component> <component name="TypeScriptGeneratedFilesManager"> Loading @@ -130,6 +143,23 @@ <MESSAGE value="Apparently working version." /> <MESSAGE value="Final version." /> <MESSAGE value="Minor tweaks" /> <option name="LAST_COMMIT_MESSAGE" value="Minor tweaks" /> <MESSAGE value="Cleaning up." /> <option name="LAST_COMMIT_MESSAGE" value="Cleaning up." /> </component> <component name="XDebuggerManager"> <breakpoint-manager> <breakpoints> <line-breakpoint enabled="true" type="java-line"> <url>file://$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java</url> <line>643</line> <option name="timeStamp" value="1" /> </line-breakpoint> <line-breakpoint enabled="true" type="java-line"> <url>file://$PROJECT_DIR$/src/edu/bu/ec504/spr24/sameGameTris/sge.java</url> <line>167</line> <option name="timeStamp" value="3" /> </line-breakpoint> </breakpoints> </breakpoint-manager> </component> </project> No newline at end of file
src/edu/bu/ec504/spr24/Brain/Board.java 0 → 100644 +198 −0 Original line number Diff line number Diff line package edu.bu.ec504.spr24.Brain; import edu.bu.ec504.spr24.sameGameTris.CircleColor; import edu.bu.ec504.spr24.sameGameTris.sge; import java.util.LinkedList; import java.util.Objects; /** * An internal recording of a board set up. */ class Board { /** * A 2-d Linked list of colors on the board. */ final LinkedList<LinkedList<CircleColor>> data; /** * The width and height of the board. */ final private int width, height; // constructs a board of specified width and height Board(int width, int height) { this.width = width; this.height = height; // allocate the data structure for storing board contents data = new LinkedList<>(); // set up the data structure for (int ii = 0; ii < width; ii++) { LinkedList<CircleColor> temp = new LinkedList<>(); for (int jj = 0; jj < height; jj++) {temp.add(CircleColor.NONE);} data.add(temp); } } /** * default constructor */ Board() { this(sge.getInstance().boardWidth(), sge.getInstance().boardHeight()); } /** * copy constructor * * @param baseBoard the board to copy */ Board(Board baseBoard) { // allocate memory for the new board this(baseBoard.width, baseBoard.height); // copy over all the specific items for (int xx = 0; xx < columns(); xx++) { for (int yy = 0; yy < rows(xx); yy++) {modify(xx, yy, baseBoard.getAt(xx, yy));} } } /** * @return the color of the yy'th item in the xx'th column, or CircleColor.NONE * if the cell is not in the <b>data</b> container */ CircleColor getAt(int xx, int yy) { try { return data.get(xx).get(yy); } catch (IndexOutOfBoundsException e) { return CircleColor.NONE; } } /** * @return the xx'th column, or null if the xx'th column does not exist in the <b>data</b> container */ private LinkedList<CircleColor> getAt(int xx) { try { return data.get(xx); } catch (IndexOutOfBoundsException e) { return null; } } /** * Changes yy'th item in xx'th column * %R: The circle at this location must still be in the <b>data</b> field */ void modify(int xx, int yy, CircleColor col) { data.get(xx).set(yy, col); } /** * Deletes yy'th item in xx'th column * %R: The circle at this location must still be in the <b>data</b> field */ private void delete(int xx, int yy) { data.get(xx).remove(yy); } /** * Deletes the column at (horizontal) board location xx * * %R: The column at this location must still be in the <b>data</b> field */ private void delete(int xx) { data.remove(xx); } // public accessors /** * Simulates a click on the yy'th cell of the xx'th column * * @return the number of cells deleted * @modifies Deletes cells in the same region as cell (xx,yy) * @expects The clicked cell is assumed not to be empty */ int clickNode(int xx, int yy) { CircleColor myColor = getAt(xx, yy); // the color to match // mark the region int count = clickNodeHelper(xx, yy, myColor); // clean up // ... delete all cells with no color // ... delete from the end to the front so that there are no problems with re-indexing for (int ii = data.size() - 1; ii >= 0; ii--) { for (int jj = Objects.requireNonNull(getAt(ii)).size() - 1; jj >= 0; jj--) { if (getAt(ii, jj) == CircleColor.NONE) {delete(ii, jj);} } // ... delete the column if it is empty if (Objects.requireNonNull(getAt(ii)).size() == 0) {delete(ii);} } return count; } /** * Recursive procedure for propagating a click at a location with color "col". * All items in the same region as the clicked cell are made to have CircleColor.NONE * * @return the number of cells changed to CircleColor.NONE in this call (and its recursive subcalls) * @modifies the color of some cells, but no cells are actually deleted */ int clickNodeHelper(int xx, int yy, CircleColor col) { if (getAt(xx, yy) == CircleColor.NONE || // we've either already seen this, or we've hit an empty space getAt(xx, yy) != col) // this is not the color we want {return 0;} // modify the current cell modify(xx, yy, CircleColor.NONE); return 1 + // 1 is for the current cell clickNodeHelper(xx - 1, yy, col) + // cell to the left clickNodeHelper(xx + 1, yy, col) + // cell to the right clickNodeHelper(xx, yy - 1, col) + // cell below clickNodeHelper(xx, yy + 1, col) // cell above ; } /** * @return the number of columns in the current state */ int columns() { return data.size(); } /** * @param xx the column being considered (assumed to exist) * @return the number of rows in column <b>xx</b> */ int rows(int xx) { return data.get(xx).size(); } /** * @return a "pretty-printed" version of the data structure */ public String display() { String temp = data.toString(); return temp.replace("], [", "]\n["); } /** * Stores an (xx,yy) position on the board. */ static class Pos { final int xx; final int yy; Pos(int xx, int yy) { this.xx = xx; this.yy = yy; } } }
src/edu/bu/ec504/spr24/Brain/Brain.java +30 −14 Original line number Diff line number Diff line package edu.bu.ec504.spr24.Brain; import edu.bu.ec504.spr24.sameGameTris.GUI; import edu.bu.ec504.spr24.sameGameTris.sge; /** * The Brain is the artificial intelligence that tries to come up with the Loading @@ -10,32 +11,47 @@ import edu.bu.ec504.spr24.sameGameTris.GUI; */ public abstract class Brain implements Runnable { // FIELDS protected final GUI myGUI; // the GUI class attached to this Brain protected final GUI myGUI; // stores the GUI class attached to this Brain /** * When set to true, the Brain should stop what it's doing and exit as soon as is appropriate. */ private volatile boolean allDone = false; // METHODS /** * Constructs the brain * @param myGUI A reference to the Graphical User Interface on which the game is being played. */ Brain(GUI myGUI) { this.myGUI = myGUI; } /** * Each Brain should have a name, which is provided by this method. * @return the name of the brain */ public abstract String myName(); Brain() { this.myGUI = sge.getInstance(); } /** * This is called when the Brain is being asked to close down (i.e., the game is over). * It should clean up any data structures and/or signal threads to close, etc. */ public abstract void allDone(); final public void allDone() { allDone=true; }; /** * Starts the Brain a'thinking. * This is the code for making decisions about which circles you Brain selects. * This is the code for requests decisions about which circles you Brain selects. * @see java.lang.Runnable#run() */ public abstract void run(); final public void run() { while (!allDone && !myGUI.gameOverQ()) { Board.Pos theNextMove = nextMove(); myGUI.makeMove(theNextMove.xx, theNextMove.yy); // i.e. click on the lower left corner } } // ... METHODS FOR SUBCLASSES TO DEFINE /** * Each Brain should have a name, which is provided by this method. * @return the name of the brain */ public abstract String myName(); /** * Returns the next move of the Brain. */ public abstract Board.Pos nextMove(); }
src/edu/bu/ec504/spr24/Brain/LazyBrain.java +10 −211 Original line number Diff line number Diff line package edu.bu.ec504.spr24.Brain; import java.util.LinkedList; import java.util.Objects; import edu.bu.ec504.spr24.sameGameTris.GUI; import edu.bu.ec504.spr24.Brain.Board.Pos; import edu.bu.ec504.spr24.sameGameTris.CircleColor; /** Loading @@ -13,11 +10,6 @@ public class LazyBrain extends Brain { // FIELDS /** * When set to true, the Brain should stop what it's doing and exit as soon as is appropriate. */ private volatile boolean allDone = false; /** * The Brain's recording of the current state of the board. */ Loading @@ -25,18 +17,11 @@ public class LazyBrain extends Brain { // METHODS /** Constructs a Brain linked to a specified myGUI * @param myGUI The GUI that will be instantiating the Brain */ public LazyBrain(GUI myGUI) { super(myGUI); } /** * {@inheritDoc} * Constructs a Brain linked to a specified myGUI */ public void allDone() { allDone = true; public LazyBrain() { super(); } /** Loading @@ -46,23 +31,18 @@ public class LazyBrain extends Brain { return "Lazy Brain"; } /** * {@inheritDoc} */ public void run() { @Override public Pos nextMove() { // Initialize and set up the internal board state with the current position currBoard = new Board(); for (int xx=0; xx<myGUI.boardWidth(); xx++) for (int yy=0; yy<myGUI.boardHeight(); yy++) currBoard.modify(xx, yy, myGUI.colorAt(xx, myGUI.boardHeight()-yy-1)); // Keep making moves until the game is over while (!allDone && !myGUI.gameOverQ()) { Board.Pos nextMove = chooseMove(); myGUI.makeMove(nextMove.xx, nextMove.yy); // i.e. click on the lower left corner } return chooseMove(); } // PRIVATE METHODS /** * Chooses the next move to make. Loading @@ -76,9 +56,9 @@ public class LazyBrain extends Brain { for (int xx=0; xx< currBoard.columns(); xx++) for (int yy=0; yy< currBoard.rows(xx); yy++) { if (currStateCopy.get(xx,yy)!= CircleColor.NONE) { if (currStateCopy.getAt(xx,yy)!= CircleColor.NONE) { Board test = new Board(currStateCopy); currStateCopy.clickNodeHelper(xx, yy, test.get(xx,yy)); // mark all other nodes in the region as "clear" (but does not delete anything) currStateCopy.clickNodeHelper(xx, yy, test.getAt(xx,yy)); // mark all other nodes in the region as "clear" (but does not delete anything) int count = test.clickNode(xx, yy); // try removing the region to see what is left over if (count > max) { // record a new best move Loading @@ -101,186 +81,5 @@ public class LazyBrain extends Brain { // INTERNAL CLASSES /** * Stores a board set up */ private class Board { /** * A 2-d Linked list of colors on the board. */ final LinkedList< LinkedList <CircleColor>> data; /** * The width and height of the board. */ final private int width, height; // constructs a board of specified width and height Board(int width, int height) { this.width = width; this.height = height; // allocate the data structure for storing board contents data = new LinkedList<>(); // set up the data structure for (int ii=0; ii<width; ii++) { LinkedList<CircleColor> temp = new LinkedList<>(); for (int jj=0; jj<height; jj++) temp.add(CircleColor.NONE); data.add(temp); } } /** * default constructor */ Board() { this(myGUI.boardWidth(),myGUI.boardHeight()); } /** * copy constructor * @param baseBoard the board to copy */ Board(Board baseBoard) { // allocate memory for the new board this(baseBoard.width, baseBoard.height); // copy over all the specific items for (int xx=0; xx<columns(); xx++) for (int yy=0; yy<rows(xx); yy++) modify(xx,yy,baseBoard.get(xx, yy)); } /** * @return the color of the yy'th item in the xx'th column, or CircleColor.NONE * if the cell is not in the <b>data</b> container */ private CircleColor get(int xx, int yy) { try { return data.get(xx).get(yy); } catch (IndexOutOfBoundsException e) { return CircleColor.NONE; } } /** * @return the xx'th column, or null if the xx'th column does not exist in the <b>data</b> container */ private LinkedList<CircleColor> get(int xx) { try { return data.get(xx); } catch (IndexOutOfBoundsException e) { return null; } } /** * Changes yy'th item in xx'th column * %R: The circle at this location must still be in the <b>data</b> field */ private void modify(int xx, int yy, CircleColor col) { data.get(xx).set(yy, col); } /** * Deletes yy'th item in xx'th column * %R: The circle at this location must still be in the <b>data</b> field */ private void delete(int xx, int yy) { data.get(xx).remove(yy); } /** * Deletes the column at (horizontal) board location xx * * %R: The column at this location must still be in the <b>data</b> field */ private void delete(int xx) { data.remove(xx); } // public accessors /** * Simulates a click on the yy'th cell of the xx'th column * @return the number of cells deleted * @modifies Deletes cells in the same region as cell (xx,yy) * @expects The clicked cell is assumed not to be empty */ int clickNode(int xx, int yy) { CircleColor myColor = get(xx,yy); // the color to match // mark the region int count = clickNodeHelper(xx, yy, myColor); // clean up // ... delete all cells with no color // ... delete from the end to the front so that there are no problems with re-indexing for (int ii=data.size()-1; ii>=0; ii--) { for (int jj = Objects.requireNonNull(get(ii)).size()-1; jj>=0; jj--) if (get(ii,jj)==CircleColor.NONE) delete(ii, jj); // ... delete the column if it is empty if (Objects.requireNonNull(get(ii)).size()==0) delete(ii); } return count; } /** * Recursive procedure for propagating a click at a location with color "col". * All items in the same region as the clicked cell are made to have CircleColor.NONE * @modifies the color of some cells, but no cells are actually deleted * @return the number of cells changed to CircleColor.NONE in this call (and its recursive subcalls) */ private int clickNodeHelper(int xx, int yy, CircleColor col) { if (get(xx,yy) == CircleColor.NONE || // we've either already seen this, or we've hit an empty space get(xx,yy) != col) // this is not the color we want return 0; // modify the current cell modify(xx,yy,CircleColor.NONE); return 1 + // 1 is for the current cell clickNodeHelper(xx-1, yy, col) + // cell to the left clickNodeHelper(xx+1, yy, col) + // cell to the right clickNodeHelper(xx, yy-1, col) + // cell below clickNodeHelper(xx, yy+1, col) // cell above ; } /** * @return the number of columns in the current state */ int columns() { return data.size(); } /** * * @param xx the column being considered (assumed to exist) * @return the number of rows in column <b>xx</b> */ int rows(int xx) { return data.get(xx).size(); } /** * @return a "pretty-printed" version of the data structure */ public String display() { String temp = data.toString(); return temp.replace("], [", "]\n["); } /** * Stores an (xx,yy) position on the board. */ static class Pos { final int xx; final int yy; Pos(int xx, int yy) {this.xx=xx; this.yy=yy;} } } }
src/edu/bu/ec504/spr24/Brain/SimpleBrain.java +6 −15 Original line number Diff line number Diff line package edu.bu.ec504.spr24.Brain; import edu.bu.ec504.spr24.sameGameTris.GUI; import edu.bu.ec504.spr24.Brain.Board.Pos; /** * A very simple Brain for the game. Loading @@ -10,16 +10,10 @@ public class SimpleBrain extends Brain { // fields private volatile boolean allDone = false; // when set to true, the Brain should stop what it's doing and exit (at an appropriate time) public SimpleBrain(GUI myGUI) { super(myGUI); public SimpleBrain() { super(); } /** * {@inheritDoc} */ public void allDone() { allDone = true; } /** * {@inheritDoc} Loading @@ -28,11 +22,8 @@ private volatile boolean allDone = false; // when set to true, the Brain should return "Simple Brain"; } /** * {@inheritDoc} */ public void run() { while (!allDone && !myGUI.gameOverQ()) myGUI.makeMove(0, myGUI.boardHeight()-1); // i.e. click on the lower left corner @Override public Pos nextMove() { return new Pos(0, myGUI.boardHeight()-1); } }