import java.io.*; /** * A basic implementation of the MineSweeper game, using a TextBoard for * display purposes and a StringTokenizer to parse commands entered at the * keyboard. No support yet for anything fancy like high score tables (or * graphics :) We do, however, time how long it takes you to finish the * game. */ public class MineSweeper { // The game board private Board board; // Tokenizer for commands private StreamTokenizer tok; // Various flags used by play() and doCommand() private boolean done, quit, win; // Contents of last cell revealed private int lastCell; /** * Create and initialise a new game of the given dimensions. */ public MineSweeper(int width, int height, int mines) { // Create the game board board = new TextBoard(width, height, mines); // Set up the command tokenizer tok = new StreamTokenizer(new InputStreamReader(System.in)); done = win = quit = false; } /** * Main game loop. */ public void play() throws IOException { // Start the clock long startTime = System.currentTimeMillis(); // Loop until game over, for whatever reason while (!done) { // Redraw board board.draw(); // Get next command System.out.print("Command: "); System.out.flush(); tok.nextToken(); // Dispatch on command switch (tok.ttype) { case StreamTokenizer.TT_WORD: doCommand(); break; case StreamTokenizer.TT_EOL: continue; case StreamTokenizer.TT_EOF: done = quit = true; break; default: System.out.println("Unknown command -- try 'help'"); } // Check whether the game is up. If the number of unknown cells = the // number of mines, you must have won (by finding all the mines). If, // on the other hand, you revealed a mine, time to die :( if (board.getUnknown() == board.getMines()) { done = win = true; } else if (lastCell == Board.MINE) { done = true; } // Suck any remaining crap out of the input stream. I'm not sure that // this works properly (not on my machine, at least). System.in.skip(System.in.available()); } // Game over, one way or another. Figure out how long it took long elapsedTime = System.currentTimeMillis() - startTime; // Reveal everything, just so the stats are correct for (int i = 0; i < board.getWidth(); i++) { for (int j = 0; j < board.getHeight(); j++) { board.reveal(i, j); } } // Redraw the board and print out some messages board.draw(); if (win) { System.out.println("Congratulations -- you found all the mines!"); } else if (!quit) { System.out.println("Bad luck -- you stepped on a mine!"); } System.out.println("Total game time: "+(elapsedTime/1000)+" seconds"); } /** * Process commands. 'Help' gives a summary of the huge range of available * commands. */ private void doCommand() throws IOException { int x, y; if (tok.sval.equals("reveal")) { // Reveal a cell (and perhaps some around it) tok.nextToken(); x = (int)tok.nval; tok.nextToken(); y = (int)tok.nval; lastCell = board.reveal(x, y); if (lastCell == 0) { board.revealMore(x, y); } } else if (tok.sval.equals("mark")) { // Mark a cell tok.nextToken(); x = (int)tok.nval; tok.nextToken(); y = (int)tok.nval; board.mark(x, y); } else if (tok.sval.equals("unmark")) { // Unmark a cell tok.nextToken(); x = (int)tok.nval; tok.nextToken(); y = (int)tok.nval; board.unmark(x, y); } else if (tok.sval.equals("help")) { // Print some help System.out.println("reveal "); System.out.println("mark "); System.out.println("unmark "); System.out.println("help"); System.out.println("quit"); } else if (tok.sval.equals("quit")) { // Quit and die quit = done = true; } else { System.out.println("Unknown command -- try 'help'"); } } /** * Main program to start and run a new game. Expects three command line * parameters: width, height and mine count. */ public static void main(String[] args) throws IOException { MineSweeper game; if (args.length < 3) { System.out.println("Usage: java MineSweeper "); System.exit(0); } else { int width = Integer.parseInt(args[0]); int height = Integer.parseInt(args[1]); int mines = Integer.parseInt(args[2]); game = new MineSweeper(width, height, mines); game.play(); } } }