package cs.min2phase;
import cs.min2phase.Tools;
import cs.min2phase.Search;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.Color;
import java.awt.event.*;
import java.io.*;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//A simple GUI example to demonstrate how to use the package org.kociemba.twophase
/**
* This code was edited or generated using CloudGarden's Jigloo SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation, company or business for any purpose whatever) then
* you should purchase a license for each developer using Jigloo. Please visit www.cloudgarden.com for details. Use of
* Jigloo implies acceptance of these licensing terms. A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR THIS MACHINE, SO
* JIGLOO OR THIS CODE CANNOT BE USED LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
public class MainProgram extends javax.swing.JFrame {
// +++++++++++++These variables used only in the GUI-interface+++++++++++++++++++++++++++++++++++++++++++++++++++++++
private static final long serialVersionUID = 1L;
private JButton[][] facelet = new JButton[6][9];
private final JButton[] colorSel = new JButton[6];
private final int FSIZE = 45;
private final int[] XOFF = { 3, 6, 3, 3, 0, 9 };// Offsets for facelet display
private final int[] YOFF = { 0, 3, 3, 6, 3, 3 };
private final Color[] COLORS = { Color.white, Color.red, Color.green, Color.yellow, Color.orange, Color.blue };
private JCheckBox checkBoxShowStr;
private JButton buttonRandom;
private JCheckBox checkBoxUseSep;
private JCheckBox checkBoxInv;
private JCheckBox checkBoxShowLen;
private JButton Solve;
private JLabel jLabel2;
private JLabel jLabel1;
private JSpinner spinnerMaxMoves;
private JSpinner spinnerTimeout;
private Color curCol = COLORS[0];
private int maxDepth = 21, maxTime = 5;
boolean useSeparator = true;
boolean showString = false;
boolean inverse = true;
boolean showLength = true;
Search search = new Search();
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainProgram inst = new MainProgram();
inst.setLocationRelativeTo(null);
inst.setVisible(true);
}
});
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public MainProgram() {
super();
initGUI();
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
private void initGUI() {
getContentPane().setLayout(null);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
this.setTitle("Two-Phase Package GUI-Example");
// ++++++++++++++++++++++++++++++++++ Set up Solve Cube Button ++++++++++++++++++++++++++++++++++++++++++++++++++++
Solve = new JButton("Solve Cube");
getContentPane().add(Solve);
Solve.setBounds(422, 64, 114, 48);
Solve.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
solveCube(evt);
}
});
// ++++++++++++++++++++++++++++++++++ Set up Move Limit Spinner +++++++++++++++++++++++++++++++++++++++++++++++++++
{
jLabel1 = new JLabel();
getContentPane().add(jLabel1);
jLabel1.setText("Move Limit");
jLabel1.setBounds(282, 65, 72, 16);
}
{
SpinnerModel model = new SpinnerNumberModel(21, 1, 24, 1);
spinnerMaxMoves = new JSpinner(model);
getContentPane().add(spinnerMaxMoves);
spinnerMaxMoves.setBounds(354, 62, 56, 21);
spinnerMaxMoves.getEditor().setPreferredSize(new java.awt.Dimension(37, 19));
spinnerMaxMoves.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent evt) {
maxDepth = ((Integer) spinnerMaxMoves.getValue()).intValue();
}
});
}
// ++++++++++++++++++++++++++++++++++ Set up Time Limit Spinner +++++++++++++++++++++++++++++++++++++++++++++++++++
{
jLabel2 = new JLabel();
getContentPane().add(jLabel2);
jLabel2.setText("Time Limit");
jLabel2.setBounds(282, 93, 72, 16);
}
{
SpinnerModel model = new SpinnerNumberModel(5, 1, 3600, 1);
spinnerTimeout = new JSpinner(model);
getContentPane().add(spinnerTimeout);
spinnerTimeout.setModel(model);
spinnerTimeout.setBounds(354, 90, 56, 21);
spinnerTimeout.getEditor().setPreferredSize(new java.awt.Dimension(36, 17));
spinnerTimeout.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent evt) {
maxTime = ((Integer) spinnerTimeout.getValue()).intValue();
}
});
}
// ++++++++++++++++++++++++++++++++++ Set up Use Separator CheckBox +++++++++++++++++++++++++++++++++++++++++++++++
{
checkBoxInv = new JCheckBox("Inverse", true);
getContentPane().add(checkBoxInv);
checkBoxInv.setBounds(12, 297, 121, 20);
checkBoxInv.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
inverse = checkBoxInv.isSelected();
}
});
checkBoxUseSep = new JCheckBox("Use Separator", true);
getContentPane().add(checkBoxUseSep);
checkBoxUseSep.setBounds(12, 320, 121, 20);
checkBoxUseSep.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
useSeparator = checkBoxUseSep.isSelected();
}
});
}
{
checkBoxShowStr = new JCheckBox("Show String", false);
getContentPane().add(checkBoxShowStr);
checkBoxShowStr.setBounds(12, 343, 121, 20);
checkBoxShowStr.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
showString = checkBoxShowStr.isSelected();
}
});
checkBoxShowLen = new JCheckBox("Show Length", true);
getContentPane().add(checkBoxShowLen);
checkBoxShowLen.setBounds(12, 366, 121, 20);
checkBoxShowLen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
showLength = checkBoxShowLen.isSelected();
}
});
}
// ++++++++++++++++++++++++++++++++++ Set up Random Button ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
buttonRandom = new JButton("Random Cube");
getContentPane().add(buttonRandom);
buttonRandom.setBounds(422, 17, 114, 22);
buttonRandom.setText("Scramble");
buttonRandom.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// +++++++++++++++++++++++++++++ Call Random function from package org.kociemba.twophase ++++++++++++++++++++
String r = Tools.randomCube();
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
for (int i = 0; i < 6; i++)
for (int j = 0; j < 9; j++) {
switch (r.charAt(9 * i + j)) {
case 'U':
facelet[i][j].setBackground(COLORS[0]);
break;
case 'R':
facelet[i][j].setBackground(COLORS[1]);
break;
case 'F':
facelet[i][j].setBackground(COLORS[2]);
break;
case 'D':
facelet[i][j].setBackground(COLORS[3]);
break;
case 'L':
facelet[i][j].setBackground(COLORS[4]);
break;
case 'B':
facelet[i][j].setBackground(COLORS[5]);
break;
}
}
}
});
}
// ++++++++++++++++++++++++++++++++++ Set up editable facelets ++++++++++++++++++++++++++++++++++++++++++++++++++++
for (int i = 0; i < 6; i++)
for (int j = 0; j < 9; j++) {
facelet[i][j] = new JButton();
getContentPane().add(facelet[i][j]);
facelet[i][j].setBackground(Color.gray);
facelet[i][j].setRolloverEnabled(false);
facelet[i][j].setOpaque(true);
facelet[i][j].setBounds(FSIZE * XOFF[i] + FSIZE * (j % 3), FSIZE * YOFF[i] + FSIZE * (j / 3), FSIZE, FSIZE);
facelet[i][j].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
((JButton) evt.getSource()).setBackground(curCol);
}
});
}
String[] txt = { "U", "R", "F", "D", "L", "B" };
for (int i = 0; i < 6; i++)
facelet[i][4].setText(txt[i]);
for (int i = 0; i < 6; i++) {
colorSel[i] = new JButton();
getContentPane().add(colorSel[i]);
colorSel[i].setBackground(COLORS[i]);
colorSel[i].setOpaque(true);
colorSel[i].setBounds(FSIZE * (XOFF[1] + 1) + FSIZE / 4 * 3 * i, FSIZE * (YOFF[3] + 1), FSIZE / 4 * 3,
FSIZE / 4 * 3);
colorSel[i].setName("" + i);
colorSel[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
curCol = COLORS[Integer.parseInt(((JButton) evt.getSource()).getName())];
}
});
}
pack();
this.setSize(556, 441);
}
// ++++++++++++++++++++++++++++++++++++ End initGUI +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++ Generate cube from GUI-Input and solve it ++++++++++++++++++++++++++++++++++++++++
private void solveCube(ActionEvent evt) {
StringBuffer s = new StringBuffer(54);
for (int i = 0; i < 54; i++)
s.insert(i, 'B');// default initialization
for (int i = 0; i < 6; i++)
// read the 54 facelets
for (int j = 0; j < 9; j++) {
if (facelet[i][j].getBackground() == facelet[0][4].getBackground())
s.setCharAt(9 * i + j, 'U');
if (facelet[i][j].getBackground() == facelet[1][4].getBackground())
s.setCharAt(9 * i + j, 'R');
if (facelet[i][j].getBackground() == facelet[2][4].getBackground())
s.setCharAt(9 * i + j, 'F');
if (facelet[i][j].getBackground() == facelet[3][4].getBackground())
s.setCharAt(9 * i + j, 'D');
if (facelet[i][j].getBackground() == facelet[4][4].getBackground())
s.setCharAt(9 * i + j, 'L');
if (facelet[i][j].getBackground() == facelet[5][4].getBackground())
s.setCharAt(9 * i + j, 'B');
}
String cubeString = s.toString();
if (showString) {
JOptionPane.showMessageDialog(null, "Cube Definiton String: " + cubeString);
}
int mask = 0;
mask |= useSeparator ? Search.USE_SEPARATOR : 0;
mask |= inverse ? Search.INVERSE_SOLUTION : 0;
mask |= showLength ? Search.APPEND_LENGTH : 0;
long t = System.nanoTime();
// ++++++++++++++++++++++++ Call Search.solution method from package org.kociemba.twophase ++++++++++++++++++++++++
String result = search.solution(cubeString, maxDepth, maxTime << 10, 0, mask);
t = System.nanoTime() - t;
// +++++++++++++++++++ Replace the error messages with more meaningful ones in your language ++++++++++++++++++++++
if (result.contains("Error"))
switch (result.charAt(result.length() - 1)) {
case '1':
result = "There are not exactly nine facelets of each color!";
break;
case '2':
result = "Not all 12 edges exist exactly once!";
break;
case '3':
result = "Flip error: One edge has to be flipped!";
break;
case '4':
result = "Not all 8 corners exist exactly once!";
break;
case '5':
result = "Twist error: One corner has to be twisted!";
break;
case '6':
result = "Parity error: Two corners or two edges have to be exchanged!";
break;
case '7':
result = "No solution exists for the given maximum move number!";
break;
case '8':
result = "Timeout, no solution found within given maximum time!";
break;
}
JOptionPane.showMessageDialog(null, result, Double.toString((t/1000)/1000.0) + "ms", JOptionPane.INFORMATION_MESSAGE);
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
}
}