import java.util.Random; import java.awt.Color; import javax.swing.JFrame; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.Vector; public class StackedObject extends MobileSimObject { // OVERVIEW: A StackedObject is a simulator object that moves in a constant // downward direction in addition to moving left and right. private boolean inTurn; private boolean isFalling; private boolean isStacked; private boolean isSquare; private FallingObject block1, block2, block3; public StackedObject (FallingObject block1, FallingObject block2, FallingObject block3) //@ensures !isInitialized; { // will create attached objects here isFalling=true; inTurn=true; isStacked = false; isSquare = false; this.block1 = block1; this.block2 = block2; this.block3 = block3; } public Color getColor() { if (isFalling) { return Color.cyan; } else { return Color.blue; } } //@nowarn NonNullResult // ESC/Java doesn't know Color constants are not null public boolean canExecuteTurn(Direction direct) throws RuntimeException // Note: requires isInitialized is inherited from SimObject // Modifies: this // EFFECTS: Moves south. // If the move is successful, return true. If the move fails // because the spot being attempted to move into is already // occupied then return false. { if (isStacked) { return true; } Grid thisgrid = getGrid (); inTurn = true; int newrow = getRow () + direct.northerlyDirection (); int newcol = getColumn () + direct.easterlyDirection (); if (getGrid ().validLocation (newrow, newcol) ) { synchronized (getGrid ()) { if (getGrid().isSquareEmpty (newrow, newcol)) { return true; } return false; } } return false; } public void executeTurn() throws RuntimeException // Note: requires isInitialized is inherited from SimObject // Modifies: this // EFFECTS: Moves south. // If the move is successful, return true. If the move fails // because the spot being attempted to move into is already // occupied then return false. { if (isSquare) { squareExecuteTurn(); } else { Grid thisgrid = getGrid (); inTurn = true; Direction dir = thisgrid.UserDirection(); int newrow = getRow () + dir.northerlyDirection (); int newcol = getColumn () + dir.easterlyDirection (); if (canExecuteTurn(dir) && block1.canExecuteTurn(dir) && block2.canExecuteTurn(dir) && block3.canExecuteTurn(dir)) { block1.executeTurn(); block2.executeTurn(); block3.executeTurn(); setLocation (newrow, newcol); } else if (canExecuteTurn(new Direction(newrow,getColumn())) && block1.canExecuteTurn(new Direction(newrow,getColumn())) && block2.canExecuteTurn(new Direction(newrow,getColumn())) && block3.canExecuteTurn(new Direction(newrow,getColumn()))) { thisgrid.setUserDirection(new Direction(dir.northerlyDirection(), 0)); block1.executeTurn(); block2.executeTurn(); block3.executeTurn(); setLocation (newrow, 0); } else { isFalling = false; block1.isFalling = false; block2.isFalling = false; block3.isFalling = false; } if (!isFalling) { getGrid().pauseObjects(); if (getGrid().isSquareEmpty(0,getGrid().numColumns()/2)) { getGrid().setObjectAt(0,getGrid().numColumns()/2, new StackedObject(new FallingObject(), new FallingObject(),new FallingObject())); getGrid().startObjects(); } else {System.err.println("gameOVER");} } getGrid().setUserDirection(new Direction(1,0) ); inTurn = false; } } public boolean isFalling () { return isFalling; } public void run () // REQUIRES: this has been initialized // We use also_requires instead of requires, because we are adding a precondition // to an inherited method. This violates the substitution principle --- subtypes // should make preconditions weaker, not stronger. // EFFECTS: The object thread. If the object is not paused, executes one turn by calling // the executeTurn method, and sleeps for a time and repeats. If the object is paused, // does nothing (until the object is unpaused). { //isPaused ()= false; setRandomObjects (); while (isFalling) { if (!isPaused()) { executeTurn (); delay (100); } } } public void setRandomObjects (){ Random random = new Random (); int a=0,b=0,c=0,d=0,e=0,f = 0; int dir = random.nextInt (2); switch (dir) { //case 0: {a = 0; b = -1; c = 1; d = 0; e = 1; f = 1; isStacked = true; break;} // case 1: {a = 1; b = -1; c = 1; d = 0; e = 0; f = 1; isStacked = true; break;} case 0: {a = 0; b = -1; c = 0; d = 1; e = 0; f = 2; isStacked = true;break;} case 1: {a = 1; b = 0; c = 0; d = 1; e = 1; f = 1; isStacked = true;isSquare = true;break;} } getGrid().setObjectAt(getRow()+a, getColumn()+b , block1); getGrid().setObjectAt(getRow()+c, getColumn()+d , block2); getGrid().setObjectAt(getRow()+e, getColumn() +f , block3); } private void squareExecuteTurn(){ Grid thisgrid = getGrid (); inTurn = true; Direction dir = thisgrid.UserDirection (); int newrow = getRow () + dir.northerlyDirection (); int newcol = getColumn () + dir.easterlyDirection (); if ( block1.canExecuteTurn(dir)&& block3.canExecuteTurn(dir)) { block1.executeTurn(); block3.executeTurn(); block2.executeTurn(); setLocation (newrow, newcol); } else if (block1.canExecuteTurn(new Direction(newrow,getColumn())) && block3.canExecuteTurn(new Direction(newrow,getColumn()))) { thisgrid.setUserDirection(new Direction(dir.northerlyDirection(), 0)); block1.executeTurn(); block3.executeTurn(); block2.executeTurn(); setLocation (newrow, 0); } else { isFalling = false; block1.isFalling = false; block2.isFalling = false; block3.isFalling = false; } if (!isFalling) { getGrid().pauseObjects(); if (getGrid().isSquareEmpty(0,getGrid().numColumns()/2)) { getGrid().setObjectAt(0,getGrid().numColumns()/2, new StackedObject(new FallingObject(), new FallingObject(),new FallingObject())); getGrid().startObjects(); } else {System.err.println("gameOVER");} } getGrid().setUserDirection(new Direction(1,0) ); inTurn = false; } }