/* Import the Java I/O package */ import java.io.*; import AppletConsoleApp; /** * Solution to the 1999 British Informatics Olympiad exam * question 2: Black Box (Atom) * * This application that can be run either from the console * as a stand-alone application or from an in-applet * console created with the AppletConsole applet. * * Solution copyright (c) 1999 The British Informatics Olympiad (BIO). * * This program may be freely copied by persons or organisations * involved in the British Informatics Olympiad or the International * Olympiad in Informatics, on condition that no changes are made and * this notice is not altered. Distribution for profit is forbidden * unless permission is first obtained in writing from the BIO. * * This program is for educational purposes only and comes with no * warranty, implied or otherwise, as to its fitness for any purpose. * * Author: Antony Rix * Internet: http://www.christs.cam.ac.uk/bio/ * E-mail: a.rix@lineone.net * S-mail: The British Informatics Olympiad * Christ's College * Cambridge CB2 3BU * United Kingdom * * @author Antony Rix * @version 0.1 * @see AppletConsoleApp * @see AppletConsole */ class BIO99R1Q2App extends AppletConsoleApp { /** * Start the application from the command line. */ public static void main(String[] args) { BIO99R1Q2App thisApp = new BIO99R1Q2App(); thisApp.redirectStreams(System.in, System.out); thisApp.run(); } /** * Key constants. */ static int Blank = 0; static int Atom = 1; static int Ray = 2; static int Hit = 3; /** * Array holding board. */ int[][] Board = new int[12][12]; /** * Result of injecting the atom */ String result = ""; /** * The implementation of this application. */ public void run() { int i, x, y; String side; init_board(); out.println( "Enter 5 co-ordinates in the form x y" ); try { /* Create a StreamTokenizer to allow us to read in the start numbers */ StreamTokenizer sin = new StreamTokenizer( in ); for( i = 1; i <= 5; i++ ) { out.print( ">" ); sin.nextToken(); x = (int)sin.nval; sin.nextToken(); y = (int)sin.nval; Board[x][y] = Atom; } show_board(); out.println(); /* Main program loop: read in a character/number pair and then perform that action */ do { out.print( ">" ); sin.nextToken(); side = sin.sval; sin.nextToken(); i = (int)sin.nval; if( (side.equalsIgnoreCase("T") || side.equalsIgnoreCase("B") || side.equalsIgnoreCase("L") || side.equalsIgnoreCase("R")) && (i > 0) && (i < 11) ) { trace_ray( side, i ); show_board(); reset_board(); out.println( result ); out.println(); } else if( !side.equalsIgnoreCase("X") ) out.println( "Invalid input '" + side + " " + i + "'" ); } while ( !side.equalsIgnoreCase("X") ); } catch (IOException e) { out.println("I/O failure"); }; out.println( "Program finished." ); } /** * */ public void init_board() { int i, j; for( i = 0; i < 12; i++ ) for( j = 0; j < 12; j++ ) Board[i][j] = Blank; } /** * */ public void reset_board() { int x, y; for( x = 0; x < 12; x++ ) for( y = 0; y < 12; y++ ) switch (Board[x][y]) { case 0: Board[x][y] = Blank; break; case 1: Board[x][y] = Atom; break; case 2: Board[x][y] = Blank; break; case 3: Board[x][y] = Atom; break; } } /** * Display the current board. */ public void show_board() { int x, y; for( y = 10; y >= 1; y-- ) { for( x = 1; x <= 10; x++ ) switch (Board[x][y]) { case 0: out.print( "." ); break; case 1: out.print( "A" ); break; case 2: out.print( "+" ); break; case 3: out.print( "*" ); break; } out.print( "\n" ); } } /** * Follow the path of the ray. */ public void trace_ray( String side, int pos ) { int direct; int x, y, nx, ny; /* Starting position and direction */ if( side.equalsIgnoreCase("B") ) { direct = 0; x = pos; y = 1; } else if( side.equalsIgnoreCase("L") ) { direct = 1; y = pos; x = 1; } else if( side.equalsIgnoreCase("T") ) { direct = 2; x = pos; y = 10; } else if( side.equalsIgnoreCase("R") ) { direct = 3; y = pos; x = 10; } else return; /* Follow ray until it runs out of the box */ while( (x > 0) && (x < 11) && (y > 0) && (y < 11) ) { Board[x][y] = Ray; /* Find new position then apply the rules */ nx = x; ny = y; switch (direct) { case 0: ny = y + 1; break; case 1: nx = x + 1; break; case 2: ny = y - 1; break; case 3: nx = x - 1; break; } /* If absorbed, show the hit and return */ if( Board[nx][ny] == Atom ) { Board[nx][ny] = Hit; result = "Absorbed"; return; } /* If reflected, simply return - the ray will retrace its path */ if( (direct == 0) || (direct == 2) ) { if( (Board[nx-1][ny] == Atom) && (Board[nx+1][ny] == Atom) ) { result = "Reflected"; return; } } else { if( (Board[nx][ny-1] == Atom) && (Board[nx][ny+1] == Atom) ) { result = "Reflected"; return; } } /* Check for a deflection. If we deflect, move back to the last position and change direction. */ if( (direct == 0) || (direct == 2) ) { if( Board[nx-1][ny] == Atom) { direct = 1; ny = y; } if( Board[nx+1][ny] == Atom) { direct = 3; ny = y; } } else { if( Board[nx][ny-1] == Atom) { direct = 0; nx = x; } if( Board[nx][ny+1] == Atom) { direct = 2; nx = x; } } /* Update position */ x = nx; y = ny; } /* Find exit point */ if( x == 0 ) result = "L " + y; if( y == 0 ) result = "B " + x; if( x == 11 ) result = "R " + y; if( y == 11 ) result = "T " + x; result = "Exits at " + result; } }