// File: Soma.java // Author: Alberg, Mehta, & Ward // // Last Update: 12-10-96 // // This is the basic controller object for running the Soma applet import java.awt.*; import java.applet.*; public class Soma extends Applet { Piece [] piece = new Piece[7]; private int clickX, clickY; private Cube cubeClicked = null; private static final int UP = 1; private static final int DOWN = -1; // private Canvas workArea; private Catalog catalog; //image and its graphics object in memory act as a second drawing buffer private Image surface2; private Graphics buffer; public void init() { Dimension d = size(); int cx = d.width / 3; int cy = d.height / 5; Face.SetDrawingConstants(cx, cy, getBackground()); int workWidth = 2*d.width/3; int workHeight = 9*d.height/10; catalog = new Catalog(d.width -workWidth, workHeight, cy, Color.gray); scramble(); surface2 = createImage(workWidth, workHeight); buffer = surface2.getGraphics(); buffer.setColor(Color.lightGray); buffer.setPaintMode(); buffer.fillRect(0, 0, workWidth, workHeight); setLayout(new BorderLayout()); add("East", catalog); Panel p = new Panel(); p.resize(d.width, d.height -workHeight); p.add(new Button("Rotate Puzzle")); p.add(new Button("Scramble Pieces")); Choice c = new Choice(); c.addItem("Cube"); c.addItem("Bed"); c.addItem("Canal"); c.addItem("Castle I"); c.addItem("Castle II"); c.addItem("Crystal"); c.addItem("Gateway"); c.addItem("High & Low I"); c.addItem("High & Low II"); c.addItem("Steamboat"); c.addItem("Tower"); c.addItem("Zig-Zag"); p.add(c); p.add(new Button("Show Solution")); p.add(new Button("Rotate Solution")); add("South", p); catalog.init(); } public boolean mouseDown(Event e, int x, int y) { cubeClicked = Cube.FindCube(x, y); if(cubeClicked != null) { if(e.controlDown()) // then this is a rotation { Piece selectedPiece = cubeClicked.parent; Face face = cubeClicked.whichFace(x, y); if(face instanceof Zface) selectedPiece.rotateZ(e.shiftDown(), cubeClicked, this); else if(face instanceof Xface) selectedPiece.rotateX(e.shiftDown(), cubeClicked, this); else if(face instanceof Yface) selectedPiece.rotateY(e.shiftDown(), cubeClicked, this); } else // this is a movement { clickX = x; clickY = y; // mouseDrag will handle the movement. } return true; } else return false; } public boolean mouseDrag(Event e, int x, int y) { if(cubeClicked == null) return false; if(e.controlDown()) return false; int dy = y - clickY; int dx = x - clickX; Piece selectedPiece = cubeClicked.parent; if(e.shiftDown()) // then changing z only { if(dy >= 8) // && dy <= Face.XINC) //Face.YINC-3) { selectedPiece.moveZ(DOWN, this); clickX = x; clickY = y; } else if(dy <= -8) // && dy >= -Face.XINC)// Face.YINC-3) { selectedPiece.moveZ(UP, this); clickX = x; clickY = y; } } else // either x or y changing { if(dx >= 8) // && dx <= Face.XINC) //Face.XINC-5) { if(dy >= 8) // && dy <= Face.XINC) //Face.YINC-5) { selectedPiece.moveY(UP, this); clickX = x; clickY = y; } else if(dy <= -8) // && dy >= -Face.XINC) //Face.YINC-5) { selectedPiece.moveX(DOWN, this); clickX = x; clickY = y; } } else if(dx <= -8) // && dx >= -Face.XINC)//Face.XINC-5) { if(dy >= 8) // && dy <= Face.XINC) //Face.YINC-5) { selectedPiece.moveX(UP, this); clickX = x; clickY = y; } else if(dy <= -8) // && dy >= -Face.XINC) //Face.YINC-5) { selectedPiece.moveY(DOWN, this); clickX = x; clickY = y; } } } return true; } public boolean action(Event e, Object arg) { if(e.target instanceof Button) { if("Rotate Puzzle".equals(arg)) { for(int i=0; i < 7; ++i) piece[i].removeFromGrid(buffer); for(int i=0; i < 7; ++i) piece[i].rotateTable(); display(); } else if ("Rotate Solution".equals(arg)) { catalog.RotateTable(); } else if ("Show Solution".equals(arg)) { catalog.SetSolve(); } else if ("Scramble Pieces".equals(arg)) { for(int i=0; i < 7; ++i) piece[i].removeFromGrid(buffer); scramble(); display(); } return true; } else if(e.target instanceof Choice) { catalog.ResetPuzzle((String)arg); return true; } return false; } void scramble() { int[] array = {1, 2, 3, 4, 5, 6, 7}; int i = 200; while (i-- > 0) { int what = (int)(Math.random() * 10000) % 7; int who = (int)(Math.random() * 30000) % 7; int temp = array[what]; array[what] = array[who]; array[who] = temp; } piece[0] = new Piece(10, 2, 0, array[0]); piece[1] = new Piece(6, 2, 0, array[1]); piece[2] = new Piece(10, 6, 0, array[2]); piece[3] = new Piece(2, 2, 0, array[3]); piece[4] = new Piece(2, 6, 0, array[4]); piece[5] = new Piece(6, 10, 0, array[5]); piece[6] = new Piece(2, 10, 0, array[6]); } //display is called after any kind of movement to redraw the scene void display() { //paint(super.getGraphics()); Graphics g = super.getGraphics(); Dimension d = size(); Face.DrawBackground(buffer, d); Cube.Redraw(buffer); g.drawImage(surface2, 0, 0, this); g.dispose(); } //paint shouldn't be called by any other classes directly, //since they might not have the right graphics object. //They should call display instead. public void paint(Graphics g) { display(); } //overriding update to minimize 'flicker' caused by default update public void update(Graphics g) { paint(g); } //return the back buffer for all getGraphics calls. This is only really //needed for the cube undraw method. public Graphics getGraphics() { return buffer; } }