diff --git a/.gitignore b/.gitignore
index 0be1402..987e05b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,11 @@
*.class
+.DS_Store
+.idea/
+.metadata/
+cs56-games-flood-it.iml
+out/
+
# Package Files #
*.war
*.ear
diff --git a/build.xml b/build.xml
index ba63387..493ad64 100644
--- a/build.xml
+++ b/build.xml
@@ -8,7 +8,7 @@ updated by: Chris Luo & Kevin Briggs
-->
-
+
diff --git a/src/edu/ucsb/cs56/projects/games/flood_it/view/FloodItController.java b/src/edu/ucsb/cs56/projects/games/flood_it/view/FloodItController.java
new file mode 100644
index 0000000..a7ef06a
--- /dev/null
+++ b/src/edu/ucsb/cs56/projects/games/flood_it/view/FloodItController.java
@@ -0,0 +1,265 @@
+package edu.ucsb.cs56.projects.games.flood_it.view;
+
+import java.util.Collections;
+import java.util.Arrays;
+
+/**
+ * Class for Flood it game Controller
+ *
+ * @author Gustav Schoelin
+ * @author Karl Wang
+ */
+
+public class FloodItController {
+
+ private int numColors;
+ private int dimension;
+ private int difficultyLevel;
+ private int movesLeft;
+ private int[][] grid;
+
+ /**
+ * FloodItController constructor creates an instance of the game
+ *
+ * @param dimension the grid will be dimension x dimension
+ * @param numColors the number of colors available
+ * @param difficultyLevel how difficult the game is
+ */
+ public FloodItController(int dimension, int numColors, int difficultyLevel) {
+ this.dimension = dimension;
+ this.numColors = numColors;
+ this.difficultyLevel = difficultyLevel;
+ populateGrid(dimension, numColors, difficultyLevel);
+
+ if (difficultyLevel == 1)
+ this.movesLeft = (int) (calculateBaselineMovesLeft(dimension * dimension, dimension));
+ if (difficultyLevel == 2)
+ this.movesLeft = (int) (calculateBaselineMovesLeft(dimension * dimension, dimension / 2));
+ if (difficultyLevel == 3)
+ this.movesLeft = (int) (calculateBaselineMovesLeft(dimension * dimension, 1));
+ }
+
+ /**
+ * populateGrid populates the grid of a given size and difficulty level
+ *
+ * @param dimension the grid will be dimension x dimension
+ * @param numColors the number of colors in the grid
+ * @param difficultyLevel a number 1,2,3 representing easy medium or hard
+ * @return dimensionxdimension matrix of ints represnting the game board
+ */
+ public void populateGrid(int dimension, int numColors, int difficultyLevel) {
+ if (difficultyLevel == 1)
+ grid = populateGridEasy(dimension, numColors);
+ if (difficultyLevel == 2)
+ grid = populateGridMedium(dimension, numColors);
+ if (difficultyLevel == 3)
+ grid = populateGridHard(dimension, numColors);
+ }
+
+ /**
+ * populateGridEasy populates an easy grid of a given size
+ *
+ * @param dimension the grid will be dimension x dimension
+ * @param numColors the number of colors in the grid
+ * @return dimensionxdimension matrix of ints represnting the game board
+ */
+ public int[][] populateGridEasy(int dimension, int numColors) {
+ int previousColor = (int) (Math.random() * numColors);
+ int[][] result = new int[dimension][dimension];
+ for (int i = 0; i < dimension; i++) {
+ for (int j = 0; j < dimension; j++) {
+ if (Math.random() < .5) {
+ previousColor = (int) (Math.random() * numColors);
+ } else if (Math.random() < .5) {
+ if (i > 1)
+ previousColor = result[i - 1][j];
+ }
+ result[i][j] = previousColor;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * populateGridMedium populates a medium grid of a given size
+ *
+ * @param dimension the grid will be dimension x dimension
+ * @param numColors the number of colors in the grid
+ * @return dimensionxdimension matrix of ints represnting the game board
+ */
+ public int[][] populateGridMedium(int dimension, int numColors) {
+ int[][] result = new int[dimension][dimension];
+ for (int i = 0; i < dimension; i++) {
+ for (int j = 0; j < dimension; j++) {
+ result[i][j] = (int) (Math.random() * numColors);
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * populateGridHard populates a hard grid of a given size
+ *
+ * @param dimension the grid will be dimension x dimension
+ * @param numColors the number of colors in the grid
+ * @return dimensionxdimension matrix of ints represnting the game board
+ */
+ public int[][] populateGridHard(int dimension, int numColors) {
+ int currentColor = (int) (Math.random() * numColors);
+ int[][] result = new int[dimension][dimension];
+ for (int i = 0; i < dimension; i++) {
+ for (int j = 0; j < dimension; j++) {
+ if (i == 0 && j == 0) result[i][j] = (int) (Math.random() * numColors);
+ if (i != 0 && j != 0) {
+ while (currentColor == result[i - 1][j] || currentColor == result[i][j - 1])
+ currentColor = (int) (Math.random() * numColors);
+ result[i][j] = currentColor;
+ } else if (i != 0) {
+ while (currentColor == result[i - 1][j])
+ currentColor = (int) (Math.random() * numColors);
+ result[i][j] = currentColor;
+ } else if (j != 0) {
+ while (currentColor == result[i][j - 1])
+ currentColor = (int) (Math.random() * numColors);
+ result[i][j] = currentColor;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * calculates the number of moves given to the player
+ * by running random simulations on the grid
+ * the average of the top results is provided as the recommended number of moves
+ *
+ * @return recommended number of moves, not adjusted for difficulty
+ */
+ private double calculateBaselineMovesLeft(int iterations, int tops){
+ if(tops > iterations){
+ throw new IllegalArgumentException("requesting the average of more result than that is generated");
+ }
+ int[] testResults = new int[iterations]; //the choice of 30 iterations is completely arbitrary. Feel free to change it.
+
+ for(int i = 0; i < testResults.length; i++){
+ int[][] testGrid = gridCopy(this.grid);
+ int movesUsed = 0;
+ while(!checkWin(testGrid)){
+ int newColor;
+ do{
+ newColor = (int) (Math.random() * numColors);
+ }while(newColor == testGrid[0][0]);
+ floodIt(0, 0, newColor, testGrid[0][0], testGrid);
+ movesUsed++;
+ }
+ testResults[i] = movesUsed;
+ }
+
+ Arrays.sort(testResults);
+
+ int sum = 0;
+ for (int i = 0; i < tops; i++) {
+ sum += testResults[i];
+ }
+ return (double)sum / tops;
+ }
+
+ /**
+ * floodIt redraws the matrix after the player makes a move
+ * it is adapted from Wikipedia's algorithm: en.wikipedia.org/wiki/Flood_fill
+ *
+ * @param x the x location in the matrix
+ * @param y the y location in the matrix
+ * @param newColor the new color being painted
+ * @param oldColor the color to be repainted
+ */
+ public void floodIt(int x, int y, int newColor, int oldColor) {
+ floodIt(x, y, newColor, oldColor, this.grid);
+ }
+
+ /**
+ * floodIt redraws the matrix after the player makes a move
+ * it is adapted from Wikipedia's algorithm: en.wikipedia.org/wiki/Flood_fill
+ *
+ * @param x the x location in the matrix
+ * @param y the y location in the matrix
+ * @param newColor the new color being painted
+ * @param oldColor the color to be repainted
+ * @param grid the grid to be worked on
+ */
+ private void floodIt(int x, int y, int newColor, int oldColor, int[][] grid) {
+ if(newColor == oldColor){
+ throw new IllegalArgumentException("newColor and oldColor should not be the same!");
+ }
+ if (x < 0 || y < 0 || x >= grid.length || y >= grid.length) return;
+ if (grid[x][y] != oldColor) return;
+ grid[x][y] = newColor;
+ floodIt(x, y + 1, newColor, oldColor, grid);
+ floodIt(x, y - 1, newColor, oldColor, grid);
+ floodIt(x + 1, y, newColor, oldColor, grid);
+ floodIt(x - 1, y, newColor, oldColor, grid);
+ return;
+ }
+
+ /**
+ * checkWin checks if the player has won the game
+ *
+ * @return true if win, false if not.
+ */
+ public boolean checkWin() {
+ return checkWin(this.grid);
+ }
+
+ /**
+ * checkWin checks if the player has won the game
+ *
+ * @return true if win, false if not.
+ * @param grid the grid to be worked on
+ */
+ private boolean checkWin(int[][] grid) {
+ for (int i = 0; i < grid.length; i++)
+ for (int j = 0; j < grid.length; j++)
+ if (grid[i][j] != grid[0][0]) return false;
+ return true;
+ }
+
+ public int getDifficultyLevel() {
+ return difficultyLevel;
+ }
+
+ public int getDimension() {
+ return dimension;
+ }
+
+ public int getNumColors() {
+ return numColors;
+ }
+
+ public int[][] getGrid() {
+ return grid;
+ }
+
+ public Integer getMovesLeft() {
+ return movesLeft;
+ }
+
+ public void setMovesLeft(int movesLeft) {
+ this.movesLeft = movesLeft;
+ }
+
+ /**
+ * utility method for copying a grid
+ * to be used in calculateMovesLeft()
+ *
+ * @return a copy of the provided grid
+ * @param grid the grid to be worked on
+ */
+ private int[][] gridCopy(int[][] grid){
+ int [][] newGrid = new int[grid.length][];
+ for(int i = 0; i < grid.length; i++){
+ newGrid[i] = grid[i].clone();
+ }
+ return newGrid;
+ }
+}
diff --git a/src/edu/ucsb/cs56/projects/games/flood_it/view/FloodItGUI.java b/src/edu/ucsb/cs56/projects/games/flood_it/view/FloodItGUI.java
index 0641de8..50949d7 100644
--- a/src/edu/ucsb/cs56/projects/games/flood_it/view/FloodItGUI.java
+++ b/src/edu/ucsb/cs56/projects/games/flood_it/view/FloodItGUI.java
@@ -4,314 +4,130 @@
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
-import java.util.Scanner;
/**
* Class for the Flood it game JFrame
- * includes the main method
+ *
* @author Daniel Ben-Naim
* @author Dylan Hanson
* @author Sophia Mao
* @author Kai Jann
* @author Chris Luo
* @author Kevin Briggs
+ * @author Gustav Schoelin
+ * @author Karl Wang
*/
-public class FloodItGUI extends JFrame{
-
+public class FloodItGUI extends JFrame {
+
//private variables for all the GUI components
-
+
+ private FloodItController controller;
private JFrame frame;
private Container textContainer;
private FloodItGrid gridBoard;
- private FloodItInstructGui instructions;
+ private FloodItInstructGUI instructions;
private JTextArea messageArea;
private JButton buttonInstruction;
private JPanel buttonPanel;
private JTextField countdown;
private JLabel movesLeft;
- private int [][] grid;
- private final Color[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW,
- Color.MAGENTA, Color.CYAN,Color.ORANGE,Color.BLACK};
- private String[] colorNames = {"Red","Blue","Green","Yellow","Magenta","Cyan","Orange","Black"};
- private int numColors;
- private int dimension;
- private int difficultyLevel;
- private Integer MOVES_LEFT;
-
- /**
- * FloodItGUI constructor creates an instance of the game
- *
- * @param dimension the grid will be dimension x dimension
- * @param numColors the number of colors available
- * @param difficultyLevel how difficult the game is
- */
- public FloodItGUI(int dimension, int numColors, int difficultyLevel){
- this.dimension = dimension;
- this.numColors = numColors;
- this.difficultyLevel = difficultyLevel;
- }
+ private final Color[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW,
+ Color.MAGENTA, Color.CYAN, Color.ORANGE, Color.BLACK};
+ private String[] colorNames = {"Red", "Blue", "Green", "Yellow", "Magenta", "Cyan", "Orange", "Black"};
/**
- * init initializes the game and draws the board.
- *
- */
- public void init(){
- //set MovesLeft (scales number of moves based on number of colors and dimension
- //selected using 25 moves for a 6 color, 14x14 grid as a baseline.
- MOVES_LEFT = (int)Math.floor(dimension*numColors*25/84);//Thanks, autoboxing!
- if(difficultyLevel == 1) MOVES_LEFT = (int)Math.floor(MOVES_LEFT*.8);
- if(difficultyLevel == 3) MOVES_LEFT = (int)Math.floor(MOVES_LEFT * 2.33);
- //set JFrame properties
- frame = new JFrame("Flood It! by SM and KJ and KB and CL and DH and DBN");
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setSize(1000,800);
- grid = PopulateGrid(dimension, numColors, difficultyLevel);
- gridBoard = new FloodItGrid(grid, colors);
- buttonInstruction = new JButton("Instructions");
- //set JTextArea properties for the big message returning box
- messageArea = new JTextArea(40,20);
- messageArea.setEditable(false);
- JScrollPane messageScroller = new JScrollPane(messageArea);
- messageScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
- //set JTextField properties for countdown box
- countdown = new JTextField(MOVES_LEFT.toString(),2);
- countdown.setEditable(false);
- //JLabel for the countdown JTextArea
- movesLeft = new JLabel("moves left:");
- //Panel that holds the color buttons and countdown
- buttonPanel = new JPanel();
- //add Countdown components to buttonPanel
- buttonPanel.add(movesLeft);
- buttonPanel.add(countdown);
- //ALL button properties
- for(int i=0; i1)
- previousColor = result[i-1][j];
- }
- result[i][j] = previousColor;
- }
- }
- return result;
- }
-
- /**
- * PopulateGridEasy populates a medium grid of a given size
- *
- * @param dimension the grid will be dimension x dimension
- * @param numColors the number of colors in the grid
- * @return dimensionxdimension matrix of ints represnting the game board
- */
- public int[][] PopulateGridMedium(int dimension, int numColors){
- int[][] result = new int[dimension][dimension];
- for(int i=0; i16)
- {
- System.out.println("Invalid input");
- dimension = S.nextInt();
- }
- System.out.println("Enter the number of colors you want: (between 3 and 8)");
- numColors = S.nextInt();
- while(numColors<3||numColors>8)
- {
- numColors = S.nextInt();
- System.out.println("Invalid input");
- }
- System.out.println("Enter 1 for easy, 2 for medium, 3 for hard.");
- difficultyLevel = S.nextInt();
- while(difficultyLevel<1||difficultyLevel>3)
- {
- difficultyLevel = S.nextInt();
- System.out.println("Invalid input");
- }
- FloodItGUI game = new FloodItGUI(dimension, numColors, difficultyLevel);
- game.init();
- }
-
- /**
- * floodIt redraws the matrix after the player makes a move
- * it is adapted from Wikipedia's algorithm: en.wikipedia.org/wiki/Flood_fill
- *
- * @param x the x location in the matrix
- * @param y the y location in the matrix
- * @param newColor the new color being painted
- * @param oldColor the color to be repainted
- */
- public void floodIt(int x, int y, int newColor, int oldColor){
- if(x<0 || y<0 || x>=grid.length || y>= grid.length) return;
- if(grid[x][y] != oldColor) return;
- grid[x][y] = newColor;
- floodIt(x, y+1, newColor, oldColor);
- floodIt(x, y-1, newColor, oldColor);
- floodIt(x+1, y, newColor, oldColor);
- floodIt(x-1, y, newColor, oldColor);
- return;
- }
-
- /**
- * checkWin checks if the player has won the game
- *
- * @return true if win, false if not.
- */
- public boolean checkWin(){
- for(int i=0; i
+ * This is the utility function of the class for redrawing the
* grid when the user makes a move.
- * @param grid A NxN Matrix of integers representing colors in an array
+ *
+ * @param grid A NxN Matrix of integers representing colors in an array
* @param colors an array of Colors
*/
- public void redrawLabel(int [][] grid, Color[] colors){
- removeAll();
-
- setLayout(new GridLayout(grid.length, grid.length));
- for(int j=0; j dimensionsChooser;
+ private JComboBox numColorsChooser;
+ private JComboBox difficultyChooser;
+ private boolean gameStarted = false;
+ private int dimensions;
+ private int numColors;
+ private int difficulty;
+
+ public FloodItStartMenuGUI() {
+ frame = new JFrame("Welcome to FloodIt!");
+ frame.setSize(600, 200);
+ Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+ frame.setLocation(dim.width/2-frame.getSize().width/2, dim.height/3-frame.getSize().height/2);
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+ JPanel textPanel = new JPanel();
+ textPanel.add(new JLabel("
Welcome to FloodIt!
Choose size, number of colors and difficulty
"));
+ frame.getContentPane().add(BorderLayout.NORTH, textPanel);
+
+ dimensionsChooser = new JComboBox();
+ for (int i = 4; i <= 16; i++) {
+ dimensionsChooser.addItem(i + "x" + i);
+ }
+
+ numColorsChooser = new JComboBox();
+ for (int i = 3; i <= 8; i++) {
+ numColorsChooser.addItem(i);
+ }
+
+ String[] difficulties = {"Easy", "Medium", "Hard"};
+ difficultyChooser = new JComboBox(difficulties);
+
+ JPanel chooserPanel = new JPanel();
+ chooserPanel.add(new JLabel("Size:"));
+ chooserPanel.add(dimensionsChooser);
+ chooserPanel.add(new JLabel("Number of colors:"));
+ chooserPanel.add(numColorsChooser);
+ chooserPanel.add(new JLabel("Difficulty:"));
+ chooserPanel.add(difficultyChooser);
+ frame.getContentPane().add(BorderLayout.CENTER, chooserPanel);
+
+ JPanel buttonPanel = new JPanel();
+ JButton startButton = new JButton("Start Game");
+ startButton.addActionListener(new startButtonListener());
+ JButton exitButton = new JButton(("Exit"));
+ exitButton.addActionListener(new exitButtonListener());
+
+ buttonPanel.add(startButton);
+ buttonPanel.add(exitButton);
+
+ frame.getContentPane().add(BorderLayout.SOUTH, buttonPanel);
+
+ frame.setVisible(true);
+ }
+
+ public boolean isGameStarted() {
+ return gameStarted;
+ }
+
+ public int getDimensions() {
+ return dimensions;
+ }
+
+ public int getNumColors() {
+ return numColors;
+ }
+
+ public int getDifficulty() {
+ return difficulty;
+ }
+
+ class startButtonListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ dimensions = dimensionsChooser.getSelectedIndex() + 4;
+ numColors = numColorsChooser.getSelectedIndex() + 3;
+ difficulty = difficultyChooser.getSelectedIndex() + 1;
+
+ gameStarted = true;
+ frame.setVisible(false);
+ frame.dispose();
+ }
+ }
+
+ class exitButtonListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ System.exit(0);
+ }
+ }
+}