diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..15a15b218a29e09c9190992732698d646e4d659a
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/sg_dist.iml b/sg_dist.iml
index 26db12c9c2267aa8a29c059b94b6848a81860c0f..bfc53fbcabf9c8dd51b8816710d62a7cc9f6227e 100644
--- a/sg_dist.iml
+++ b/sg_dist.iml
@@ -1,7 +1,6 @@
-
-
+
diff --git a/src/edu/bu/ec504/spr19/sameGame/sg.java b/src/edu/bu/ec504/spr19/sameGame/sg.java
index ee42b852b32d36b02bfee51295f0fae3feccac18..bb9ecfb3257e47f17dc07dada211ff2794b61427 100644
--- a/src/edu/bu/ec504/spr19/sameGame/sg.java
+++ b/src/edu/bu/ec504/spr19/sameGame/sg.java
@@ -1,17 +1,16 @@
package edu.bu.ec504.spr19.sameGame;
-/*
- An implementation of the "samegnome" game, possibly with a computer-aided solver.
- Written by Prof. Ari Trachtenberg, January 20, 2019.
-*/
-
-
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
-import java.awt.event.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
import javax.swing.ButtonGroup;
+import javax.swing.JApplet;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
@@ -30,123 +29,126 @@ import edu.bu.ec504.spr19.Brain.Brain;
import edu.bu.ec504.spr19.Brain.lazyBrain;
import edu.bu.ec504.spr19.Brain.simpleBrain;
+// Ari's implementation of the "samegnome" game, possibly with a computer-aided solver.
+
class sg extends GUI implements ActionListener,ItemListener {
- // constants
- private static final int DEFAULT_WIDTH =15;
- private static final int DEFAULT_HEIGHT =10; // sizes in terms of numbers of circles
- private static final int DEFAULT_WINDOW_WIDTH =500;
- private static final int DEFAULT_WINDOW_HEIGHT =300; // default window size, if run as a standalone application
- private static final int NUM_COLORS = 3; // the number of colors available for circles
- private static final int DISPLAY_TIME = 1000; // number of milliseconds to display (highlight) a move before actually making it
- static private final int SINGLE_CIRCLE_PENALTY = -10; // the penalty for clicking on a single circle
- private static final String HIGH_SCORE_FILE =".highscores.db"; // where high scores are kept
- private static final long serialVersionUID = 1L; // required for serializability
-
- // fields
- final JLabel regionPoints = new JLabel("0"); // keeps track of the number of selected points
- final JLabel totalPoints = new JLabel("0"); // keeps track of the total number of points so far
- private int width = DEFAULT_WIDTH, height= DEFAULT_HEIGHT; // initial width and height of the array of circles
- private SelfAwareCircle circles[][];
- private String highScoreName = null; // the name to use for the high score
-
- // ... GUI elements
- private JPanel circlePanel; // the panel containing the circles
- private JPanel textPanel; // the panel containing scoring information
- // ... ... menu items
- private JMenuItem changeBoard;
- private JMenuItem quitGame;
- private JRadioButtonMenuItem noPlayerMenuItem,simplePlayerMenuItem, lazyPlayerMenuItem, // various automatic player options
- smarterPlayerMenuItem;
-
- // ... Brain elements
- private Brain theBrain; // the Brain (automated player) for the game
- private Thread brainThread; // the thread that will run the Brain
-
- // Public access methods
-
- /*
- * Default no-args constructor
- */
- private sg() {
- super("Ari's sameGame");
- try {
- SwingUtilities.invokeAndWait(
- this::setupGUI
- );
- }
- catch (Exception e) { System.out.println("Saw exception "+e); }
- }
-
- /*
- * Returns the color of the circle at location [xx][yy], or NONE if the circle has been cleared
- * @param xx must be between 0 and width
- * @param yy must be between 0 and height
- */
- public CircleColor colorAt(int xx, int yy) {
- if (circles[xx][yy].isCleared())
- return CircleColor.NONE;
- else
- return circles[xx][yy].clr;
- }
-
- /*
- * Returns the width of the current board
- */
- public int boardWidth() {
- return width;
- }
-
- /*
- * Returns the height of the current board
- */
- public int boardHeight() {
- return height;
- }
-
- /*
- * Returns true iff the game is over
- * (i.e. every circle is surrounded by cleared circles or circles of a different color)
- */
- public boolean gameOverQ() {
- for (int xx=0; xxlevel
- */
- final public int score(int level, CircleColor theColor) {
- int tmp;
+ // constants
+ static public final int defaultWidth=15, defaultHeight=10; // sizes in terms of numbers of circles
+ static public final int defaultWindowWidth=500, defaultWindowHeight=300; // default window size, if run as a standalone application
+ static public final int numColors = 3; // the number of colors available for circles
+ static public final int displayTime = 1000; // number of milliseconds to display (highlight) a move before actually making it
+ static public final String highScoreFile=".highscores.db"; // where high scores are kept
+ private static final long serialVersionUID = 1L; // required for serializability
+
+ // fields (all static - only one instance of the game should be running at a time)
+ final JLabel regionPoints = new JLabel("0"); // keeps track of the number of selected points
+ final JLabel totalPoints = new JLabel("0"); // keeps track of the total number of points so far
+ private int width = defaultWidth, height=defaultHeight; // initial width and height of the array of circles
+ private SelfAwareCircle circles[][];
+ private String highScoreName = null; // the name to use for the high score
+
+ // ... GUI elements
+ private JPanel circlePanel; // the panel containing the circles
+ private JPanel textPanel; // the panel containing scoring information
+ // ... ... menu items
+ private JMenuItem changeBoard;
+ private JMenuItem quitGame;
+ private JRadioButtonMenuItem noPlayerMenuItem,simplePlayerMenuItem, lazyPlayerMenuItem, // various automatic player options
+ smarterPlayerMenuItem;
+
+ // ... Brain elements
+ Brain theBrain; // the Brain (automated player) for the game
+ Thread brainThread; // the thread that will run the Brain
+
+ // Public access methods
+
+ /*
+ * Default no-args constructor
+ */
+ public sg() {
+ super("Ari's samegame");
+ try {
+ SwingUtilities.invokeAndWait(
+ new Runnable() {
+ public void run() {
+ setupGUI();
+ }
+ }
+ );
+ }
+ catch (Exception e) { System.out.println("Saw exception "+e); }
+ }
+
+ /*
+ * Returns the color of the circle at location [xx][yy], or NONE if the circle has been cleared
+ * @param xx must be between 0 and width
+ * @param yy must be between 0 and height
+ */
+ public CircleColor colorAt(int xx, int yy) {
+ if (circles[xx][yy].isCleared())
+ return CircleColor.NONE;
+ else
+ return circles[xx][yy].clr;
+ }
+
+ /*
+ * Returns the width of the current board
+ */
+ public int boardWidth() {
+ return width;
+ }
+
+ /*
+ * Returns the height of the current board
+ */
+ public int boardHeight() {
+ return height;
+ }
+
+ /*
+ * Returns true iff the game is over
+ * (i.e. every circle is surrounded by cleared circles or circles of a different color)
+ */
+ public boolean gameOverQ() {
+ for (int xx=0; xxlevel
+ */
+ final public int score(int level, CircleColor theColor) {
+ int tmp;
if (level==1)
- return -SINGLE_CIRCLE_PENALTY;
+ return -10;
else
tmp = (int) (level * Math.log(level));
switch (theColor) {
@@ -157,355 +159,362 @@ class sg extends GUI implements ActionListener,ItemListener {
default:
return 0;
}
- }
-
-
- /*
- * setupGUI helper
- * - adds to circle[ii][jj] a SelfAwareListener of circle[xx][yy] as 0<=xx=width || yy>=height || circles[xx][yy].isCleared())
- return false;
- else
- return circles[xx][yy].getColor().equals(theColor);
- }
-
- /*
- * Moves circle c1 into location c2, leaving c1 as a clear circle that
- * does not receive mouse events
- */
- private void moveCircle(SelfAwareCircle orig, SelfAwareCircle dest) {
- // copy the immutable, position independent values
- orig.copy(dest);
-
- // clear the top item
- orig.setClear();
- }
-
- /*
- * Called to request a reshifting of the board (as necessary).
- * This should happen if some circles are rendered "clear"ed
- * @return true if game continues; false otherwise
- */
-
- final boolean shiftCircles() {
- /* start at the bottom and move up ... all cleared circles are
- * removed, with upper circles falling into their positions;
- * if a column is totally empty, then its rightmost columns
- * shift into it
- */
-
- // 1. SHIFT VERTICALLY
- for (int xx=0; xx firstClr)
- firstFull = firstClr; // only move items "down" the column
-
- // find the lowest non-cleared entry in the column (if it exists)
- try {
- while (circles[xx][firstFull].isCleared())
- firstFull--;
- } catch (ArrayIndexOutOfBoundsException e) {
- moveOn = true;
- continue; // i.e. the whole column is clear --- for now, go to the next column
- }
-
- moveCircle(circles[xx][firstFull],circles[xx][firstClr]);
-
- firstFull--; firstClr--; // iterate
- }
- }
-
- // 2. SHIFT HORIZONTALLY
- // Check to see if any column is now empty
- // ... this could have been done within the loop above, but it would detract from readability of the code
- boolean emptySoFar=true; // remains true if all columns seen so far have only cleared circles
- for (int xx=width-1; xx>=0; xx--) {
- boolean allCleared=true; // remains true if all circles in column xx have been cleared
- for (int yy=0; yy=width || yy>=height || circles[xx][yy].isCleared())
+ return false;
+ else
+ return circles[xx][yy].getColor().equals(theColor);
+ }
+
+ /*
+ * Moves circle c1 into location c2, leaving c1 as a clear circle that
+ * does not receive mouse events
+ */
+ private void moveCircle(SelfAwareCircle orig, SelfAwareCircle dest) {
+ // copy the immutable, position independent values
+ orig.copy(dest);
+
+ // clear the top item
+ orig.setClear();
+ }
+
+ /*
+ * Called to request a reshifting of the board (as necessary).
+ * This should happen if some circles are rendered "clear"ed
+ * @return true if game continues; false otherwise
+ */
+
+ final boolean shiftCircles() {
+ /* start at the bottom and move up ... all cleared circles are
+ * removed, with upper circles falling into their positions;
+ * if a column is totally empty, then its rightmost columns
+ * shift into it
+ */
+
+ // 1. SHIFT VERTICALLY
+ for (int xx=0; xx firstClr)
+ firstFull = firstClr; // only move items "down" the column
+
+ // find the lowest non-cleared entry in the column (if it exists)
+ try {
+ while (circles[xx][firstFull].isCleared())
+ firstFull--;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ moveOn = true;
+ continue; // i.e. the whole column is clear --- for now, go to the next column
+ }
+
+ moveCircle(circles[xx][firstFull],circles[xx][firstClr]);
+
+ firstFull--; firstClr--; // iterate
+ }
+ }
+
+ // 2. SHIFT HORIZONTALLY
+ // Check to see if any column is now empty
+ // ... this could have been done within the loop above, but it would detract from readability of the code
+ boolean emptySoFar=true; // remains true if all columns seen so far have only cleared circles
+ for (int xx=width-1; xx>=0; xx--) {
+ boolean allCleared=true; // remains true if all circles in column xx have been cleared
+ for (int yy=0; yy