//-------------------------- // triangle.java // // by Lei Yu // May 6, 1996 //-------------------------- import java.applet.*; import java.awt.*; import java.awt.image.*; import java.lang.Math; import java.net.*; import java.util.*; public class triangle extends Applet { Trianglewindow Twin; Frame f; // from peg number to peg position (x,y) public final int loc[] = { 100, 30, 85, 60, 115, 60, 70, 90, 100, 90, 130, 90, 55, 120, 85, 120, 115, 120, 145, 120, 40, 150, 70, 150, 100, 150, 130, 150, 160, 150}; public final int radius = 10; public final int num = 15; public final int count = 39; //***************************************************************** // The triangle is SYMMETRIC, so there are only 4 possible // solutions to solve the puzzle depending on the different // starting position //***************************************************************** //-----------------The solution is same for 1,2,6,9,11,13-------------------------// //solution for starting position at 1 public final int solve1[] = { 6, 3, 1, 5, 4, 3, 0, 2, 5, 1, 3, 6, 11, 7, 4, 10, 6, 3, 9, 5, 2, 3, 4, 5, 2, 5, 9, 14, 9, 5, 13, 12, 11, 5, 8, 12, 11, 12, 13}; //solution for starting position at 2 public final int solve2[] = { 9, 5, 2, 3, 4, 5, 0, 1, 3, 2, 5, 9, 13, 8, 4, 14, 9, 5, 6, 3, 1, 5, 4, 3, 1, 3, 6, 10, 6, 3, 11, 12, 13, 3, 7, 12, 13, 12, 11}; //solution for starting position at 6 public final int solve6[] = { 1, 3, 6, 12, 7, 3, 10, 11, 12, 6, 3, 1, 2, 4, 7, 0, 1, 3, 13, 12, 11, 3, 7, 12, 11, 12, 13, 14, 13, 12, 9, 5, 2, 12, 8, 5, 2, 5, 9}; //solution for starting position at 9 public final int solve9[] = { 2, 5, 9, 12, 8, 5, 14, 13, 12, 9, 5, 2, 1, 4, 8, 0, 2, 5, 11, 12, 13, 5, 8, 12, 13, 12, 11, 10, 11, 12, 6, 3, 1, 12, 7, 3, 1, 3, 6}; //solution for starting position at 11 public final int solve11[] = { 13, 12, 11, 3, 7, 12, 10, 6, 3, 11, 12, 13, 9, 8, 7, 14, 13, 12, 1, 3, 6, 12, 7, 3, 6, 3, 1, 0, 1, 3, 2, 5, 9, 3, 4, 5, 9, 5, 2}; //solution for starting position at 13 public final int solve13[] = { 11, 12, 13, 5, 8, 12, 14, 9, 5, 13, 12, 11, 6, 7, 8, 10, 11, 12, 2, 5, 9, 12, 8, 5, 9, 5, 2, 0, 2, 5, 1, 3, 6, 5, 4, 3, 6, 3, 1}; //------------------The solution is same for 0,10,14-------------------------// //solution for starting position at 0 public final int solve0[] = { 3, 1, 0, 12, 7, 3, 10, 11, 12, 6, 3, 1, 0, 1, 3, 2, 4, 7, 13, 12, 11, 3, 7, 12, 11, 12, 13, 14, 13, 12, 9, 5, 2, 12, 8, 5, 5, 2, 0}; //solution for starting position at 10 public final int solve10[] = { 12, 13, 10, 5, 8, 12, 14, 9, 5, 11, 12, 13, 10, 13, 12, 6, 7, 8, 2, 5, 9, 12, 8, 5, 9, 5, 2, 0, 2, 5, 1, 3, 6, 5, 4, 3, 3, 6, 10}; //solution for starting position at 14 public final int solve14[] = { 5, 9, 14, 3, 4, 5, 0, 1, 3, 2, 5, 9, 14, 9, 5, 13, 8, 4, 6, 3, 1, 5, 4, 3, 1, 3, 6, 10, 6, 3, 11, 12, 13, 3, 7, 12, 12, 13, 14}; //------------------The solution is same for 3,5,12-------------------------// //solution for starting position at 3 public final int solve3[] = { 5, 4, 3, 0, 2, 5, 13, 8, 4, 6, 7, 8, 1, 3, 6, 10, 6, 3, 11, 12, 13, 9, 5, 2, 3, 4, 5, 2, 5, 9, 14, 9, 5, 5, 8, 12, 12, 13, 14}; //solution for starting position at 5 public final int solve5[] = { 3, 4, 5, 0, 1, 3, 11, 7, 4, 9, 8, 7, 2, 5, 9, 14, 9, 5, 13, 12, 11, 6, 3, 1, 5, 4, 3, 1, 3, 6, 10, 6, 3, 3, 7, 12, 12, 11, 10}; //solution for starting position at 12 public final int solve12[] = { 5, 8, 12, 14, 9, 5, 1, 4, 8, 11, 7, 4, 13, 12, 11, 10, 11, 12, 6, 3, 1, 2, 5, 9, 12, 8, 5, 9, 5, 2, 0, 2, 5, 5, 4, 3, 3, 1, 0}; //------------------The solution is same for 4, 7, 8-------------------------// //------------------Don't know yet------------------------------------------// Circle peg[]; int oldPos, newPos, interPos; int left; int initial = 0; //initial hole position int step; boolean drag; public void init() { resize(230, 230); // generate pegs peg = new Circle[num]; for (int i = 0; i < num; i++) peg[i] = new Circle(loc[2*i], loc[2*i+1], radius); initPegs(); } public void initPegs() { int open; // set all holes to have pegs for (int i = 0; i < num; i++) peg[i].occupied = true; // generate the empty hole open = initial; peg[open].occupied = false; // how many pegs left left = num - 1; step = 0; } public void paint(Graphics g) { // reset parameters drag = false; oldPos = newPos = interPos = 0; // draw the board g.setColor(Color.black); g.fillRect(0, 0, 230, 230); g.setColor(Color.white); g.fillRect(2, 2, 228, 228); g.setColor(Color.lightGray); g.drawLine(105, 35, 45, 155); g.drawLine(105, 35, 165, 155); g.drawLine(45, 155, 165, 155); g.drawLine(90, 65, 135, 155); g.drawLine(120, 65, 75, 155); g.drawLine(90, 65, 120, 65); g.drawLine(75, 95, 135, 95 ); g.drawLine(75, 95, 105, 155 ); g.drawLine(60, 125, 150, 125); g.drawLine(60, 125, 75, 155); g.drawLine(135, 95, 105, 155); g.drawLine(150, 125, 135, 155); // Show what's peg and what's hole g.setColor(Color.black); g.drawString("Peg = ", 10, 40); g.setColor(Color.blue); g.fillOval(50, 30, radius, radius); g.setColor(Color.black); g.drawString("Hole = ", 5, 70); g.setColor(Color.black); g.fillOval(50, 60, radius, radius); // paint pegs for (int i = 0; i < num; i++) peg[i].paint(g); // number of pegs left g.setColor(Color.red); g.drawString("Pegs left = "+Integer.toString(left), 65, 20); // Initial hole position g.setColor(Color.magenta); g.drawString("Set 1st hole at "+Integer.toString(initial), 55, 178); // + button g.setColor(Color.lightGray); g.fill3DRect(87, 185, 20, 15, true); g.setColor(Color.black); g.drawLine(92, 192, 102, 192); g.drawLine(97, 187, 97, 197); // - button g.setColor(Color.lightGray); g.fill3DRect(107, 185, 20, 15, true); g.setColor(Color.black); g.drawLine(112, 192, 122, 192); // window button g.setColor(Color.lightGray); g.fill3DRect(15, 205, 55, 20, true); g.setColor(Color.black); g.drawString("Window", 18, 220); // restart button g.setColor(Color.lightGray); g.fill3DRect(80, 205, 55, 20, true); g.setColor(Color.black); g.drawString("Restart", 85, 220); // solve button g.setColor(Color.lightGray); g.fill3DRect(145, 205, 55, 20, true); g.setColor(Color.black); g.drawString("Solve", 155, 220); } // determine where peg is clicked public int where(int x, int y) { for (int i = 0; i < num; i++) if (peg[i].inside(x, y)) return i; // no peg is clicked return -1; } void pause(int time){ try { Thread.sleep(time);} catch (InterruptedException e) {} } // move to solve puzzle public void move(int from, int inter, int to ) { peg[from].occupied = false; peg[inter].occupied = false; peg[to].occupied = true; left--; repaint(); pause(1000); } // in mouseDown, mouseUp, mouseDrag: // return false - event will get processed // return true - event will be ignored public boolean mouseDown(Event evt, int x, int y) { // is it request for window if ((x > 15) && (x < 70) && (y > 205) && (y < 225)) { f = new Frame("Triangle Puzzle Message Window"); f.resize(0,0); f.show(); Twin = new Trianglewindow (f, "Triangle Puzzle Message Window", "starting Triangle Puzzle"); Twin.resize(230, 460); //Twin.show(); Twin.write_msg("starting Triangle Puzzle"); } // is it request for restart if ((x > 80) && (x < 135) && (y > 205) && (y < 225)) { initPegs(); repaint(); return false; } // is it request for solve //starting position at 0 if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 0)) { move(solve0[step], solve0[step+1], solve0[step+2]); step = step + 3; } //starting position at 1 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 1)) { move(solve1[step], solve1[step+1], solve1[step+2]); step = step + 3; } //starting position at 2 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 2)) { move(solve2[step], solve2[step+1], solve2[step+2]); step = step + 3; } //starting position at 3 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 3)) { move(solve3[step], solve3[step+1], solve3[step+2]); step = step + 3; } //starting position at 5 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 5)) { move(solve5[step], solve5[step+1], solve5[step+2]); step = step + 3; } //starting position at 6 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 6)) { move(solve6[step], solve6[step+1], solve6[step+2]); step = step + 3; } //starting position at 9 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 9)) { move(solve9[step], solve9[step+1], solve9[step+2]); step = step + 3; } //starting position at 10 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 10)) { move(solve10[step], solve10[step+1], solve10[step+2]); step = step + 3; } //starting position at 11 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 11)) { move(solve11[step], solve11[step+1], solve11[step+2]); step = step + 3; } //starting position at 12 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 12)) { move(solve12[step], solve12[step+1], solve12[step+2]); step = step + 3; } //starting position at 13 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 13)) { move(solve13[step], solve13[step+1], solve13[step+2]); step = step + 3; } //starting position at 14 else if ((x > 145) && (x < 200) && (y > 205) && (y < 225) && (initial == 14)) { move(solve14[step], solve14[step+1], solve14[step+2]); step = step + 3; } // is it + request for resetting initial hole if ((x > 87) && (x < 107) && (y > 185) && (y < 200)) { if (initial < 14){ initial ++; repaint(); } else repaint(); return false; } // is it - request for resetting initial hole if ((x > 107) && (x < 127) && (y > 185) && (y < 200)) { if (initial > 0){ initial --; repaint(); } else repaint(); return false; } if ((oldPos = where(x, y)) < 0) return true; // does the move-from hole have a peg if (peg[oldPos].occupied) return false; else return true; } public boolean mouseDrag(Event evt, int x, int y) { drag = true; return false; } public boolean mouseUp(Event evt, int x, int y) { int a, b; if (drag) { drag = false; if ((newPos = where(x, y)) < 0) return true; // does the move-to have have a peg if (peg[newPos].occupied) return true; else { // determine the intermediate hole a = (peg[oldPos].X + peg[newPos].X) / 2; b = (peg[oldPos].Y + peg[newPos].Y) / 2; // is it a valid jump if (((interPos = where(a, b)) < 0) || (interPos == oldPos) || (interPos == newPos) || (!peg[interPos].occupied)) return true; else { // valid jump peg[oldPos].occupied = false; peg[newPos].occupied = true; peg[interPos].occupied = false; left--; repaint(); return true; } } } else return true; } } class Circle { public int X, Y, R; public boolean occupied; Circle(int x, int y, int r) { X = x; Y = y; R = r; } public boolean inside(int x, int y) { // use sqrt(x^2 + y^2) to determine the distance // between mouse click and circle center double dis = Math.sqrt(Math.pow((double)(X-x), 2) + Math.pow((double)(Y-y), 2)); if (dis <= R) return true; else return false; } public void paint(Graphics g) { if (occupied) g.setColor(Color.blue); else g.setColor(Color.black); g.fillOval(X, Y, R, R); } } class Trianglewindow extends Dialog { protected Button button; protected TextField inputfield; protected TextArea outputarea; public Trianglewindow (Frame parent, String title, String message) { // Create a dialog with the specified title super(parent, title, false); this.resize(230, 300); // Create and use a BorderLayout manager with margins this.setLayout(new BorderLayout(15, 15)); // Create input and output fields inputfield = new TextField(15); outputarea = new TextArea(); outputarea.setEditable(false); this.add("Center", outputarea); // Create QUIT button in panel; add Panel to window // Use a FlowLayout to center the button button = new Button("QUIT"); Panel p = new Panel(); p.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 15)); p.add(button); this.add("South", p); // Resize the window to preferred size of components this.pack(); } public boolean action(Event e, Object what) { if (e.target instanceof Button) { String label = (String)what; if (label.equals ("QUIT")) { if (this.isShowing()) { this.hide(); this.dispose(); } } return true; } return false; } // When the window gets keyboard focus, give it to button. // This allows keyboard shortcuts to pop down the dialog. public boolean gotFocus (Event e, Object arg) { button.requestFocus(); return true; } public void write_msg(String message) { outputarea.setText(message); this.show(); } public void kill() { this.hide(); this.dispose(); } }