import java.io.*; /** * Traffic Jam Application. * Traffic Jam is a simple brain teaser style puzzle game. *
* Software Architecure: Sequential *
* Design Overview:
* This version uses a classic functional decomposition.
* The main module controls the overall game logic. It is * essentially a loop which repeats taking turns until the player * wins the game. * *
  while puzzle not solved
 *                        make a move
 *                        display updated board
 *         end while
 *  
*
* Design Issues:
* The choice of an array for the data structure was obvious, since we * needed a linear structure which allowed access to any element. * The only tradeoff we made was whether or not to keep track of the spot * on the board that is empty.
* Cons: Requires a "state" variable to record the empty position.
* Pros: Avoids having to search the array each time to find where * the current empty spot is.
* We decided that keeping an extra "state" variable was worth the * reduction in algorithm complexity we would gain by not having to * search the array at each move. *
* Tools: JDK 1.4 *
* Libraries: none *
* External References: http://www.csc.calpoly.edu/~jdalbey/205/TrafficJam/ * * @author John Dalbey * @version 4.0 Java 11/2003 */ public class TrafficJam_SD { /** * * Traffic Jam Puzzle Board *
* Description: * A traffic puzzle board is an abstraction of the playing board in the * traffic jam game. It is a linear arrangement of 11 "stones" on which two * groups of five people are trying to pass each other. *
* Structure: * The board has a linear structure. *
* Elements: * There are 11 elements (stones) on the board, numbered 1 - 11, that can be * either occupied or empty. If occupied, the rock contains a person facing * either left or right. *
* Implementation: * An array of 11 spots. * Note: Java requires arrays be zero-based so we declare an array one larger * than needed and we never use the zeroth spot. * */ private final int kBoardSize = 11; private int[] Puzzle = new int[kBoardSize+1]; // Values that can be assigned to a spot on the board. /** A person facing to the Left */ public final static int L = 1; /** A person facing Right */ public final static int R = 3; /** An Empty spot on the board */ public final static int E = 2; /** the starting board configuration */ private int[] startPuzzle = {0,R,R,R,R,R,E,L,L,L,L,L}; /** the winning board configuration */ private int[] Solution = {0,L,L,L,L,L,E,R,R,R,R,R}; /** almost solved configuration, to be used for testing */ private int[] Almost = {0,L,L,L,L,L,R,E,R,R,R,R}; /** the location of the empty spot on the board */ private int emptyPosition; /** Entry point for this application */ public static void main(String[] args) { TrafficJam_SD myApp = new TrafficJam_SD(); myApp.runGame(); } /** * Creates the initial board position. */ public void resetBoard() { System.arraycopy(startPuzzle,0,Puzzle,0,startPuzzle.length); emptyPosition = 6; // Initially the empty spot is in the middle // optional statements for testing end of game //System.arraycopy(Almost,0,Puzzle,0,Almost.length); //emptyPosition = 7; // use 7 for testing, use 6 for real game } /** Run the game by controlling the high level game logic. */ public void runGame() { showHelp(); resetBoard(); displayBoard(); // while puzzle not solved while (! isSolved() ) { makeMove(); displayBoard(); } System.out.println(); System.out.println(" *** Hurray, you won! ***"); } /** Allow the player to make a move in the game. */ public void makeMove() { BufferedReader consoleIn = new BufferedReader(new InputStreamReader(System.in)); int userMove = 99; // initialize usermove to an illegal value // repeat until legal move do { // Prompt for move System.out.println("Your move? "); try { userMove = getMove(consoleIn); } // Handle I/O errors catch (IOException ex) { ex.printStackTrace(); } // IF nonumeric character entered THEN catch (NumberFormatException ex) { // Quit the game System.out.println("Game terminated."); System.exit(0); } // IF user wants to reset the board (userMove = 0) THEN if ( userMove == 0 ) { resetBoard(); displayBoard(); } } while (! isLegal (userMove) ); //System.out.println("Echo: " + userMove); // Apply the move to the board (call updateBoard with userMove) updateBoard (userMove); } /** * Get the user's move from the console. * @param consoleIn an open BufferedReader to read from. * @return int an integer representing which stone is occupied by * the person to be moved. */ public int getMove(BufferedReader consoleIn) throws IOException, NumberFormatException { // Read a line from the console String inputLine = consoleIn.readLine(); // Convert user input to an integer return Integer.parseInt(inputLine); } /** * Update the board by moving a person to the empty spot. * @param position integer indicating the position on the board from which a person * is to be moved. *
Pre: 1 <= Position <= 11 */ public void updateBoard(int position) { // Swap the person with the empty spot Puzzle[emptyPosition] = Puzzle[position]; Puzzle[position] = E; // Indicate where the new empty spot is. emptyPosition = position; } /** * Check if the move follows the rules of the game. * @param theMove integer indicating the position on the board to be checked. * @return true if the move is legal, false otherwise. */ public boolean isLegal(int theMove) { // IF theMove is not negative THEN if (theMove > 0) { try { // Evaluate each direction the piece is facing switch (Puzzle[theMove]) { case E: return false; // can't move from empty spot case R: // facing right can move if return (Puzzle[theMove+1] == E) // adjacent to empty || // or else (Puzzle[theMove+1]==L && // could leapfrog Puzzle[theMove+2]==E); case L: // facing right can move if return (Puzzle[theMove-1] == E) // adjacent to empty || // or else (Puzzle[theMove-1]==R && // could leapfrog Puzzle[theMove-2]==E); }// end switch return true; // dummy return - compiler insists on it } // IF index out of bounds THEN catch (ArrayIndexOutOfBoundsException exception) { // the move is illegal return false; } } return false; } // END isLegal /** * See if the board is in the winning configuration. * @return true if the board is in the winning configuration, false otherwise. */ public boolean isSolved() { // FOR each position on the board for (int i=1; i<=kBoardSize; i++) { // IF the current board doesn't match solution THEN if (Puzzle[i] != Solution[i]) { return false; } } // END FOR return true; } /** * Display the current board configuration. */ public void displayBoard() { // FOR each position on the board for (int i=1; i<=kBoardSize; i++) { // Determine the printable symbol for the position switch (Puzzle[i]) { case E: System.out.print(" . "); break; case R: System.out.print(" > "); break; case L: System.out.print(" < "); break; }// END CASE } // END FOR System.out.println(); System.out.println("--- --- --- --- --- --- --- --- --- --- ---"); System.out.println(" 1 2 3 4 5 6 7 8 9 10 11"); } /** Display directions for how to play the game. */ public void showHelp() { System.out.println (" TRAFFIC JAM"); System.out.println ("Two groups of 5 people (shown as arrows) are crossing a river in opposite "); System.out.println ("directions by hopping on rocks. There are eleven rocks and in the starting "); System.out.println ("configuration, the empty rock (.) is in between the two groups."); System.out.println ("> > > > > . < < < < < "); System.out.println ("GOAL: The objective is for the two groups to exchange sides, that is,"); System.out.println ("to pass each other. Thus, the winning configuration is:"); System.out.println ("< < < < < . > > > > > "); System.out.println ("RULES: 1. People can only move forward in the direction they are facing. "); System.out.println ("No backstepping or turning around. 2. Only one person may move at a time."); System.out.println ("3. There are two kinds of legal moves:"); System.out.println (" A) A person may move into an adjacent empty space immediately"); System.out.println (" in front of them. "); System.out.println (" B) A person may move around someone (or leapfrog over them)"); System.out.println (" into an empty space behind them, if they are adjacent"); System.out.println (" and FACING each other."); System.out.println ("MOVING: Enter the number of the person you desire to move. Enter 0 to "); System.out.println ("start over, any alphabetic key to quit."); System.out.println (); } } // end class