Created
July 9, 2013 01:13
-
-
Save JenniferShola/5953863 to your computer and use it in GitHub Desktop.
This is an assignment I did for CS 108 at Stanford. The instructors provided the bare, very bare, backbone for the assignment (MyDB.java, the default Sudoku grids and stringToGrid/parsing functions in Sudoku.java). This program is a Sudoku solver interface that prints out the puzzle, the solution, the number of available solutions and the time e…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package assign3; | |
import java.awt.*; | |
import java.awt.event.ActionEvent; | |
import java.awt.event.ActionListener; | |
import javax.swing.*; | |
@SuppressWarnings("serial") | |
public class DatabaseViewer extends JFrame implements ActionListener { | |
private static JTable table; | |
private MetropolisModel model; | |
private static JTextField metroText; | |
private static JTextField continentText; | |
private static JTextField populationText; | |
private static JButton add; | |
private static JButton search; | |
private static JComboBox options; | |
private static JComboBox exactness; | |
static String[] optionsText = { "Population Greater Than", "Population Smaller Than" }; | |
static String[] exactnessText = { "Exact Match", "Partial Match" }; | |
public DatabaseViewer() { | |
JPanel top = new JPanel(); | |
top.setLayout(new FlowLayout()); | |
metroText = new JTextField(15); | |
continentText = new JTextField(15); | |
populationText = new JTextField(15); | |
top.add(new JLabel("Metropolis: ")); | |
top.add(metroText); | |
top.add(new JLabel("Continent: ")); | |
top.add(continentText); | |
top.add(new JLabel("Population: ")); | |
top.add(populationText); | |
add(top, BorderLayout.PAGE_START); | |
JPanel side = new JPanel(); | |
side.setLayout(new BoxLayout(side, BoxLayout.PAGE_AXIS)); | |
add = new JButton("Add"); | |
search = new JButton("Search"); | |
options = new JComboBox(optionsText); | |
exactness = new JComboBox(exactnessText); | |
side.add(add); | |
side.add(search); | |
side.add(new JLabel("Search Options")); | |
side.add(options); | |
side.add(exactness); | |
add(side, BorderLayout.LINE_END); | |
add.addActionListener(this); | |
search.addActionListener(this); | |
metroText.addActionListener(this); | |
continentText.addActionListener(this); | |
populationText.addActionListener(this); | |
model = new MetropolisModel(); | |
table = new JTable(model); | |
JScrollPane scrollpane = new JScrollPane(table); | |
add(scrollpane, BorderLayout.CENTER); | |
setVisible(true); | |
} | |
public static void main(String[] args) { | |
JFrame frame = new DatabaseViewer(); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.pack(); | |
frame.setVisible(true); | |
} | |
public void actionPerformed(ActionEvent e) { | |
if(e.getSource() == add){ | |
model.add(metroText.getText(), continentText.getText(), populationText.getText()); | |
model.fireTableDataChanged(); | |
metroText.setText(""); | |
continentText.setText(""); | |
populationText.setText(""); | |
}else if(e.getSource() == search){ | |
boolean opt, ext; | |
if(options.getSelectedItem() == "Population Greater Than") opt = true; | |
else opt = false; | |
if(exactness.getSelectedItem() == "Exact Match") ext = true; | |
else ext = false; | |
model.search(metroText.getText(), continentText.getText(), populationText.getText(), opt, ext); | |
model.fireTableDataChanged(); | |
metroText.setText(""); | |
continentText.setText(""); | |
populationText.setText(""); | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package assign3; | |
import java.sql.Connection; | |
import java.sql.ResultSet; | |
import java.sql.ResultSetMetaData; | |
import java.sql.SQLException; | |
import java.sql.Statement; | |
import javax.swing.table.AbstractTableModel; | |
/* | |
* CS108 Student: This file will be used to help the staff grade your assignment. | |
* You can modify this file as much as you like, provided three restrictions: | |
* 1) Do not change the class/file name | |
* - The class/file name should be MetropolisModel | |
* 2) Do not modify the MetropolisControl interface | |
* 3) MetropolisModel must implement the MetropolisControl interface | |
* - You can modify MetropolisModel to inherit/implement any additional class/interface | |
*/ | |
@SuppressWarnings("serial") | |
public class MetropolisModel extends AbstractTableModel implements MetropolisControl { | |
private static Connection con; | |
private static ResultSet set; | |
private static ResultSetMetaData rsData; | |
private static final String MYSQL_DATABASE_NAME = "c_cs108_soyedele"; | |
private static final String tableName = "metropolises"; | |
/** | |
* Represents an implementation of the AbstractTableModel | |
* This class implements Metropolis Control. | |
* The model writes and displays data from a MySQL database. | |
*/ | |
public MetropolisModel (){ | |
con = MyDB.getConnection(); | |
set = null; | |
try { | |
Statement st = con.createStatement(), use = con.createStatement(); | |
use.executeQuery("USE "+MYSQL_DATABASE_NAME+";"); | |
set = st.executeQuery("SELECT * FROM "+tableName+" WHERE metropolis = \"START_FIELD_OFF_EMPTY\";"); | |
rsData = set.getMetaData(); | |
} catch (SQLException e) { | |
System.out.print("Error in the MetropolisModel constructor."); | |
e.printStackTrace(); | |
} | |
} | |
public ResultSet search(String metropolis, String continent, String population, boolean populationLargerThan, boolean exactMatch) { | |
try { | |
Statement st = con.createStatement(); | |
set = st.executeQuery(getQuery(metropolis, continent, population, populationLargerThan, exactMatch)); | |
} catch (SQLException e) { | |
e.printStackTrace(); | |
} | |
return set; | |
} | |
public void add(String metropolis, String continent, String population) { | |
try { | |
Statement st = con.createStatement(), st2 = con.createStatement(); | |
st.executeUpdate("INSERT INTO "+tableName+" VALUES(\""+metropolis+"\",\""+continent+"\",\""+population+"\");"); | |
set = st2.executeQuery("SELECT * FROM "+ tableName +" WHERE metropolis =\"" | |
+ metropolis +"\" AND continent = \""+continent+"\" AND population = "+population+";"); | |
//update model - fireTableStructureChanged | |
} catch (SQLException e) { | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* Constructs the correct MYSQL query string based on their values | |
* Returns a search query string based on valid parameters | |
* | |
* @param metropolis value of the metropolis field | |
* @param continent value of the continent field | |
* @param population value of the population field | |
* @param populationLargerThan True if "Population Larger Than" has been selected | |
* @param exactMatch True if "Exact Match" has been selected | |
* | |
* @return String Resulting string query | |
*/ | |
private String getQuery(String metropolis, String continent, String population, boolean populationLargerThan, boolean exactMatch){ | |
String query = "SELECT * FROM "+tableName; | |
int count = 0; | |
if(!metropolis.isEmpty()) count += 100; | |
if(!continent.isEmpty()) count += 10; | |
if(!population.isEmpty()) count += 1; | |
switch(count){ | |
case 0: | |
query += ";"; | |
break; | |
case 100: //Metropolis Only | |
query += " WHERE metropolis "; | |
if(exactMatch){ | |
query += "= \""; | |
query += metropolis; | |
query +="\";"; | |
}else{ | |
query += "LIKE \""; | |
query += metropolis; | |
query +="%\";"; | |
} | |
break; | |
case 10: //Continent Only | |
query += " WHERE continent "; | |
if(exactMatch){ | |
query += "= \""; | |
query += continent; | |
query +="\";"; | |
}else{ | |
query += "LIKE \""; | |
query += continent; | |
query +="%\";"; | |
} | |
break; | |
case 1: //Population Only | |
query += " WHERE population "; | |
if(populationLargerThan) query += "> "; | |
else query += "< "; | |
query += population; | |
query +=";"; | |
break; | |
case 11: //Continent and Population Only | |
query += " WHERE continent "; | |
if(exactMatch){ | |
query += "= \""; | |
query += continent; | |
query +="\" AND "; | |
}else{ | |
query += "LIKE \""; | |
query += continent; | |
query +="%\" AND "; | |
} | |
query += "population "; | |
if(populationLargerThan) query += "> "; | |
else query += "< "; | |
query += population; | |
query +=";"; | |
break; | |
case 110: //Metropolis and Continent Only | |
query += " WHERE metropolis "; | |
if(exactMatch){ | |
query += "= \""; | |
query += metropolis; | |
query +="\" AND continent = \""; | |
query += continent; | |
query +="\";"; | |
}else{ | |
query += "LIKE \""; | |
query += metropolis; | |
query +="%\" AND continent LIKE \""; | |
query += continent; | |
query +="%\";"; | |
} | |
break; | |
case 101: //Metropolis and Population Only | |
query += " WHERE metropolis "; | |
if(exactMatch){ | |
query += "= \""; | |
query += metropolis; | |
query +="\" AND "; | |
}else{ | |
query += "LIKE \""; | |
query += metropolis; | |
query +="%\" AND "; | |
} | |
query += "population "; | |
if(populationLargerThan) query += "> "; | |
else query += "< "; | |
query += population; | |
query +=";"; | |
break; | |
case 111: //Metropolis, Continent and Population Only | |
query += " WHERE metropolis "; | |
if(exactMatch){ | |
query += "= \""; | |
query += metropolis; | |
query +="\" AND continent = \""; | |
query += continent; | |
query +="\""; | |
}else{ | |
query += "LIKE \""; | |
query += metropolis; | |
query +="%\" AND continent LIKE \""; | |
query += continent; | |
query +="%\""; | |
} | |
query += " AND population "; | |
if(populationLargerThan) query += "> "; | |
else query += "< "; | |
query += population; | |
query +=";"; | |
break; | |
} | |
return query; | |
} | |
/** | |
* Returns the number of columns in the database | |
* | |
* @return Math.int Number of columns in the database | |
*/ | |
@Override | |
public int getColumnCount() { | |
try { | |
int cols = rsData.getColumnCount(); | |
return cols; | |
} catch (SQLException e) { | |
System.out.print("Metropolis Model getColumnCount() error!"); | |
e.printStackTrace(); | |
} | |
return 0; | |
} | |
/** | |
* Returns the number of rows in the database | |
* | |
* @return Math.int Number of rows in the database | |
*/ | |
@Override | |
public int getRowCount() { | |
try { | |
set.first(); | |
int numRows = -1; | |
while(numRows < set.getRow()){ | |
if(numRows < set.getRow()) numRows = set.getRow(); | |
set.next(); | |
} | |
return numRows; | |
} catch (SQLException e) { | |
System.out.print("Metropolis Model getRowCount() error!"); | |
e.printStackTrace(); | |
} | |
return 0; | |
} | |
/** | |
* Searches the Metropolis data-set for the value | |
* Returns the string found at the parameters provided | |
* | |
* @param arg0 row index | |
* @param arg1 column index | |
* | |
* @return Object Results the string at the appropriate parameters | |
*/ | |
@Override | |
public Object getValueAt(int arg0, int arg1) { | |
try { | |
set.first(); | |
for(int i = 0; i < arg0; i++) | |
set.next(); | |
return set.getObject(arg1+1); | |
} catch (SQLException e) { | |
System.out.print("Metropolis Model getValueAt() error!"); | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
/** | |
* Returns the column label associated with the given column index | |
* | |
* @param col column index | |
* | |
* @return String Column label associated with the @param col | |
*/ | |
@Override | |
public String getColumnName(int col){ | |
try { | |
return rsData.getColumnLabel(col+1); | |
} catch (SQLException e) { | |
e.printStackTrace(); | |
} | |
return "Column Not Found!"; | |
} | |
} | |
interface MetropolisControl { | |
/** | |
* Searches the Metropolis data-set for the provided search parameters. | |
* Returns the query results as a java.sql.ResultSet | |
* | |
* @param metropolis value of the metropolis field | |
* @param continent value of the continent field | |
* @param population value of the population field | |
* @param populationLargerThan True if "Population Larger Than" has been selected | |
* @param exactMatch True if "Exact Match" has been selected | |
* | |
* @return resultSet Results for the given query | |
*/ | |
public ResultSet search(String metropolis, String continent, String population, boolean populationLargerThan, boolean exactMatch); | |
/** | |
* Adds the entry to the Metropolis data-set. | |
* | |
* @param metropolis value of the metropolis field | |
* @param continent value of the continent field | |
* @param population value of the population field | |
*/ | |
public void add(String metropolis, String continent, String population); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package assign3; | |
import java.sql.Connection; | |
import java.sql.DriverManager; | |
import java.sql.SQLException; | |
/* | |
* CS108 Student: This file will be replaced when we test your code. So, do not add any of your | |
* assignment code to this file. Also, do not modify the public interface of this file. | |
* Only change the private MySQL constants so that it works with the database login credentials | |
* that we emailed to you. | |
* | |
* Usage: | |
* Connection con = MyDB.getConnection(); | |
* | |
* Optional, but recommended: Call the close function when you no longer need to work with the database | |
* MyDB.close() | |
*/ | |
public class MyDB { | |
private static final String MYSQL_USERNAME = "ccs108soyedele"; | |
private static final String MYSQL_PASSWORD = "iaghowuk"; | |
private static final String MYSQL_DATABASE_SERVER = "mysql-user.stanford.edu"; | |
private static final String MYSQL_DATABASE_NAME = "c_cs108_soyedele"; | |
private static Connection con; | |
static { | |
try { | |
Class.forName("com.mysql.jdbc.Driver"); | |
String url = "jdbc:mysql://" + MYSQL_DATABASE_SERVER + "/" + MYSQL_DATABASE_NAME; | |
con = DriverManager.getConnection(url, MYSQL_USERNAME, MYSQL_PASSWORD); | |
} catch (SQLException e) { | |
e.printStackTrace(); | |
System.err.println("CS108 student: Update the MySQL constants to correct values!"); | |
} catch (ClassNotFoundException e) { | |
e.printStackTrace(); | |
System.err.println("CS108 student: Add the MySQL jar file to your build path!"); | |
} | |
} | |
public static Connection getConnection() { | |
return con; | |
} | |
public static void close() { | |
try { | |
con.close(); | |
} catch (SQLException e) { | |
e.printStackTrace(); | |
} | |
} | |
/* | |
* CS108 student: Do not add/remove any methods to this file since this file will be replaced | |
* when we test your code! | |
*/ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package assign3; | |
import java.util.*; | |
/* | |
* Encapsulates a Sudoku grid to be solved. | |
* CS108 Stanford. | |
*/ | |
public class Sudoku { | |
// Provided grid data for main/testing | |
// The instance variable strategy is up to you. | |
// Provided easy 1 6 grid | |
// (can paste this text into the GUI too) | |
public static final int[][] easyGrid = Sudoku.stringsToGrid( | |
"1 6 4 0 0 0 0 0 2", | |
"2 0 0 4 0 3 9 1 0", | |
"0 0 5 0 8 0 4 0 7", | |
"0 9 0 0 0 6 5 0 0", | |
"5 0 0 1 0 2 0 0 8", | |
"0 0 8 9 0 0 0 3 0", | |
"8 0 9 0 4 0 2 0 0", | |
"0 7 3 5 0 9 0 0 1", | |
"4 0 0 0 0 0 6 7 9"); | |
// Provided medium 5 3 grid | |
public static final int[][] mediumGrid = Sudoku.stringsToGrid( | |
"530070000", | |
"600195000", | |
"098000060", | |
"800060003", | |
"400803001", | |
"700020006", | |
"060000280", | |
"000419005", | |
"000080079"); | |
// Provided hard 3 7 grid | |
// 1 solution this way, 6 solutions if the 7 is changed to 0 | |
public static final int[][] hardGrid = Sudoku.stringsToGrid( | |
"3 7 0 0 0 0 0 8 0", | |
"0 0 1 0 9 3 0 0 0", | |
"0 4 0 7 8 0 0 0 3", | |
"0 9 3 8 0 0 0 1 2", | |
"0 0 0 0 4 0 0 0 0", | |
"5 2 0 0 0 6 7 9 0", | |
"6 0 0 0 2 1 0 4 0", | |
"0 0 0 5 3 0 9 0 0", | |
"0 3 0 0 0 0 0 5 1"); | |
public static final int SIZE = 9; // size of the whole 9x9 puzzle | |
public static final int PART = 3; // size of each 3x3 part | |
public static final int MAX_SOLUTIONS = 100; | |
private static final String tab = "\t"; | |
private final static String newline = "\n"; | |
private final static String quotes = "\""; | |
private final static String quotesComma = "\","; | |
private final static String charEnding = "\");"; | |
private static int[][] solution; | |
private static int[][] grid; | |
private static long time; | |
private static int numSolutions; | |
ArrayList<Spot> unassigned; | |
// Provided various static utility methods to | |
// convert data formats to int[][] grid. | |
/** | |
* Returns a 2-d grid parsed from strings, one string per row. | |
* The "..." is a Java 5 feature that essentially | |
* makes "rows" a String[] array. | |
* (provided utility) | |
* @param rows array of row strings | |
* @return grid | |
*/ | |
public static int[][] stringsToGrid(String... rows) { | |
int[][] result = new int[rows.length][]; | |
for (int row = 0; row<rows.length; row++) { | |
result[row] = stringToInts(rows[row]); | |
} | |
return result; | |
} | |
/** | |
* Given a single string containing 81 numbers, returns a 9x9 grid. | |
* Skips all the non-numbers in the text. | |
* (provided utility) | |
* @param text string of 81 numbers | |
* @return grid | |
*/ | |
public static int[][] textToGrid(String text) { | |
int[] nums = stringToInts(text); | |
if (nums.length != SIZE*SIZE) { | |
throw new RuntimeException("Needed 81 numbers, but got:" + nums.length); | |
} | |
int[][] result = new int[SIZE][SIZE]; | |
int count = 0; | |
for (int row = 0; row<SIZE; row++) { | |
for (int col=0; col<SIZE; col++) { | |
result[row][col] = nums[count]; | |
count++; | |
} | |
} | |
return result; | |
} | |
/** | |
* Given a string containing digits, like "1 23 4", | |
* returns an int[] of those digits {1 2 3 4}. | |
* (provided utility) | |
* @param string string containing ints | |
* @return array of ints | |
*/ | |
public static int[] stringToInts(String string) { | |
int[] a = new int[string.length()]; | |
int found = 0; | |
for (int i=0; i<string.length(); i++) { | |
if (Character.isDigit(string.charAt(i))) { | |
a[found] = Integer.parseInt(string.substring(i, i+1)); | |
found++; | |
} | |
} | |
int[] result = new int[found]; | |
System.arraycopy(a, 0, result, 0, found); | |
return result; | |
} | |
// Provided -- the deliverable main(). | |
// You can edit to do easier cases, but turn in | |
// solving hardGrid. | |
public static void main(String[] args) { | |
Sudoku sudoku = new Sudoku(hardGrid); | |
System.out.println(sudoku); | |
int count = sudoku.solve(); | |
System.out.println("solutions:" + count); | |
System.out.println("elapsed: " + sudoku.getElapsed() + "ms"); | |
System.out.println(sudoku.getSolutionText()); | |
} | |
/** | |
* Sets up based on the given ints. | |
*/ | |
public Sudoku(int[][] ints) { | |
unassigned = getSpots(ints); | |
numSolutions = 0; | |
grid = ints; | |
time = 0; | |
} | |
/** | |
* Solves the puzzle, invoking the underlying recursive search. | |
*/ | |
public int solve() { | |
numSolutions = 0; | |
long startTime = System.currentTimeMillis(); | |
solveHelper(0); | |
long endTime = System.currentTimeMillis(); | |
time = endTime - startTime; | |
return numSolutions; | |
} | |
private void solveHelper(int index){ | |
if(index >= unassigned.size()){ | |
numSolutions++; | |
if(numSolutions == 1){ | |
solution = new int[SIZE][SIZE]; | |
for(int i = 0; i < SIZE; i++) | |
for(int j = 0; j < SIZE; j++) | |
solution[i][j] = grid[i][j]; | |
} | |
}else if(numSolutions != MAX_SOLUTIONS){ | |
Spot spot = unassigned.get(index); | |
Set<Integer> set = spot.getPossibleValues(); | |
for(Integer val : set) { | |
index++; | |
spot.set(val); | |
solveHelper(index); | |
spot.set(0); | |
index--; | |
} | |
} | |
} | |
private ArrayList<Spot> getSpots(int[][] grid){ | |
unassigned = new ArrayList<Spot>(); | |
Spot spot; | |
for(int i = 0; i < SIZE; i++) | |
for(int j = 0; j < SIZE; j++) | |
if(grid[i][j] == 0){ | |
spot = new Spot(i, j); | |
unassigned.add(spot); | |
} | |
return unassigned; | |
} | |
@Override | |
public String toString(){ | |
String text = ""; | |
for(int i = 0; i < SIZE; i++){ | |
text += tab; | |
text+= quotes; | |
for(int j = 0; j < SIZE; j++){ | |
text += Integer.toString(grid[i][j]); | |
text += " "; | |
} | |
if(i != SIZE-1) text += quotesComma; | |
else text += charEnding; | |
text += newline; | |
} | |
return text; | |
} | |
public String getSolutionText() { | |
if(solution == null) return "No Solution Found! \n"; | |
String text = ""; | |
for(int i = 0; i < SIZE; i++){ | |
for(int j = 0; j < SIZE; j++){ | |
text += Integer.toString(solution[i][j]); | |
text += " "; | |
} | |
text += newline; | |
} | |
return text; | |
} | |
public long getElapsed() { | |
if(solution == null) return 0; //For use when there is no valid solution | |
return time; | |
} | |
public int getNumSolutions(){ | |
return numSolutions; | |
} | |
public static class Spot { | |
private int spotX; | |
private int spotY; | |
Spot(int x, int y){ | |
spotX = x; | |
spotY = y; | |
} | |
private void set(int value){ | |
grid[spotX][spotY] = value; | |
} | |
private Set<Integer> getPossibleValues(){ | |
Set<Integer> set = new HashSet<Integer>(); | |
for(int i = 1; i <= SIZE; i++) | |
if(checkRow(i) && checkColumn(i) && checkSquare(i)) | |
set.add(i); | |
return set; | |
} | |
private boolean checkRow(int value){ | |
for(int i = 0; i < SIZE; i++) | |
if(grid[i][spotY] == value) return false; | |
return true; | |
} | |
private boolean checkColumn(int value){ | |
for(int i = 0; i < SIZE; i++) | |
if(grid[spotX][i] == value) return false; | |
return true; | |
} | |
private boolean checkSquare(int value){ | |
int indexX = spotX/PART, indexY = spotY/PART; | |
for(int row = indexX*PART; row < indexX*PART + PART; row++) | |
for(int col = indexY*PART; col < indexY*PART + PART; col++) | |
if(grid[row][col] == value) return false; | |
return true; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package assign3; | |
import javax.swing.*; | |
import javax.swing.border.TitledBorder; | |
import javax.swing.event.*; | |
import java.awt.*; | |
import java.awt.event.*; | |
@SuppressWarnings("serial") | |
public class SudokuFrame extends JFrame implements ActionListener, DocumentListener { | |
private static JButton check; | |
private static JCheckBox auto; | |
private static JTextArea original; | |
private static JTextArea results; | |
private static Sudoku sudoku; | |
private static String newline = "\n"; | |
public SudokuFrame() { | |
super("Sudoku Solver"); | |
JFrame frame = new JFrame(); | |
frame.setLayout(new BorderLayout(4,4)); | |
check = new JButton("Check"); | |
auto = new JCheckBox("Auto Check"); | |
auto.setSelected(false); | |
original = new JTextArea(15, 20); | |
results = new JTextArea(15, 20); | |
original.setBorder(new TitledBorder("Puzzle")); | |
results.setBorder(new TitledBorder("Solution")); | |
JPanel pane = new JPanel(); | |
pane.setLayout(new FlowLayout()); | |
pane.add(original); | |
pane.add(results); | |
JPanel bottomPane = new JPanel(); | |
bottomPane.setLayout(new FlowLayout()); | |
bottomPane.add(check); | |
bottomPane.add(auto); | |
add(pane, BorderLayout.PAGE_START); | |
add(bottomPane, BorderLayout.LINE_START); | |
check.addActionListener(this); | |
auto.addActionListener(this); | |
original.getDocument().addDocumentListener(this); | |
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
pack(); | |
setVisible(true); | |
} | |
public static void main(String[] args) { | |
// GUI Look And Feel | |
// Do this incantation at the start of main() to tell Swing | |
// to use the GUI LookAndFeel of the native platform. It's ok | |
// to ignore the exception. | |
try { | |
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | |
} catch (Exception ignored) { } | |
new SudokuFrame(); | |
sudoku = new Sudoku(Sudoku.hardGrid); | |
original.setText(sudoku.toString()); | |
} | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
int count = sudoku.solve(); | |
if(e.getSource() == check){ | |
String newText = sudoku.getSolutionText() + newline | |
+ "solutions: " + count + newline + "elapsed: " + sudoku.getElapsed() + "ms" + newline; | |
results.setText(newText + newline); | |
} | |
} | |
@Override | |
public void changedUpdate(DocumentEvent e) { | |
// DO NOTHING | |
} | |
@Override | |
public void insertUpdate(DocumentEvent arg0) { | |
if(auto.isSelected()){ | |
String grid = original.getText(); | |
if(!malformed(grid)){ | |
sudoku = new Sudoku(Sudoku.textToGrid(grid)); | |
}else{ | |
sudoku = null; | |
results.setText("Parsing Problem"); | |
} | |
if(sudoku != null){ | |
int count = sudoku.solve(); | |
String newText = sudoku.getSolutionText() + newline | |
+ "solutions: " + count + newline + "elapsed: " + sudoku.getElapsed() + "ms" + newline; | |
results.setText(newText + newline); | |
} | |
} | |
} | |
@Override | |
public void removeUpdate(DocumentEvent arg0) { | |
if(auto.isSelected()){ | |
String grid = original.getText(); | |
if(!malformed(grid)){ | |
sudoku = new Sudoku(Sudoku.textToGrid(grid)); | |
}else{ | |
sudoku = null; | |
results.setText("Parsing Problem"); | |
} | |
if(sudoku != null){ | |
int count = sudoku.solve(); | |
String newText = sudoku.getSolutionText() + newline | |
+ "solutions: " + count + newline + "elapsed: " + sudoku.getElapsed() + "ms" + newline; | |
results.setText(newText + newline); | |
} | |
} | |
} | |
private boolean malformed(String text){ | |
int count = 0; | |
for (int i=0; i<text.length(); i++) { | |
if (Character.isDigit(text.charAt(i))) count++; | |
if (count > 81) return true; | |
} | |
if (count < 81) return true; | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment