// Arup Guha
// 4/22/2010
// Solution for AP CS Program Minesweeper

import java.util.*;

public class mine {
	
	final public static int SIZE = 5;
	final public static int NUMBOMBS = 6;
	
	public static void main(String[] args) {
		
		Random ran = new Random();
		Scanner stdin = new Scanner(System.in);
		
		// Set up the grid.
		char[][] grid = new char[SIZE][SIZE];
		init(grid, ran);
		
		System.out.println("Welcome to Minesweeper!");
		
		// Loop till game is over		
		while (true) {
			
			// Get user move.
			print(grid);
			System.out.println("What square do you want, row then column?");
			int r = stdin.nextInt();
			int c = stdin.nextInt();
			
			// Invalid move.
			if (outofbounds(r,c) || taken(r,c,grid)) {
				System.out.println("Sorry, that is an invalid square.");
				continue;
			}
			
			// Hit a bomb
			if (!domove(r,c,grid)) {
				System.out.println("Sorry you hit a bomb, you lose.");
				break;
			}
			
			// Last move!
			else if (win(grid)) {
				System.out.println("Congrats, you win!");
				break;
			}
			
		}	
			
		// Show the user what the grid looks like, with the bombs.
		printend(grid);
	}
	
	// Sets up the grid, ready to play.
	public static void init(char[][] grid, Random ran) {
		
		// Defaults for each square.
		for (int i=0; i<grid.length; i++) 
			for (int j=0; j< grid[i].length; j++) 
				grid[i][j] = '_';	
			
		int n = 0;
		
		// Fill in NUMBOMBS number of bombs.
		while (n < NUMBOMBS) {
			
			int r = Math.abs(ran.nextInt()%SIZE);
			int c = Math.abs(ran.nextInt()%SIZE);
			
			// Found a new square to put a bomb in.
			if (grid[r][c] == '_') {
				grid[r][c] = '*';
				n++;
			}
		}
	}
	
	// Prints out the board for a reuglar turn.
	public static void print(char[][] grid) {
		
		System.out.println("Here is the board: ");
		
		// Print column headers.
		System.out.print("  ");
		for (int i=0; i<grid[0].length; i++)
			System.out.print(i+" ");
		System.out.println();
		
		// Go through each row.
		for (int i=0; i<grid.length; i++) {
			
			System.out.print(i+" ");
			
			// Print out what's in the square, unless it's a bomb.
			for (int j=0; j<grid[i].length; j++) {
				if (grid[i][j] != '*')
					System.out.print(grid[i][j]+" ");
				else
					System.out.print("_ ");
			}
			
			// Go to the next line.
			System.out.println();
		}
	}
	
	// Prints out the board for the end of the game.
	public static void printend(char[][] grid) {
		
		System.out.println("Here is the final board: ");
		
		// Regular print without checking for bombs.
		System.out.print("  ");
		for (int i=0; i<grid[0].length; i++)
			System.out.print(i+" ");
		System.out.println();
			
		for (int i=0; i<grid.length; i++) {
			System.out.print(i+" ");
			for (int j=0; j<grid[i].length; j++) {
			
				System.out.print(grid[i][j]+" ");
			
			}
			System.out.println();
		}
	}
	
	// Returns true iff r and c are out of bounds.
	public static boolean outofbounds(int r, int c) {
		return (r < 0 || c < 0 || r >= SIZE || c >= SIZE);
	}
	
	// Returns true iff grid[r][c] has been played already.
	public static boolean taken(int r, int c, char[][] grid) {
		return grid[r][c] >= '0' && grid[r][c] <= '9';
	}
	
	// Executes clearing the square (r,c) in the grid.
	// Returns false if the game's over because you lost, true otherwise.
	public static boolean domove(int r, int c, char[][] grid) {
		
		// You hit a bomb, you die!
		if (grid[r][c] == '*')
			return false;
			
		// Change this square.
		int ans = numBombsAdj(r,c,grid);
		grid[r][c] = (char)('0'+ans);
		
		// Recursively clear
		if (ans == 0) {
			for (int i=-1; i<=1; i++)
				for (int j=-1; j<=1; j++)
					// We only clear squares in bounds that haven't yet
					// been cleared...
					if (!outofbounds(r+i,c+j) && grid[r+i][c+j] == '_')
						domove(r+i, c+j, grid);
		}
		
		return true;
		
	}
	
	// Counts the number of bombs adjacent to grid[r][c]
	public static int numBombsAdj(int r, int c, char[][] grid) {
		
		// Loop through all adjacent squares - it's okay to count (r,c)
		// since there's no bomb there.
		int cnt = 0;
		for (int i=-1; i<=1; i++)
			for (int j=-1; j<=1; j++)
				if (!outofbounds(r+i,c+j) && grid[r+i][c+j] == '*')
					cnt++;
					
		// Return the count.
		return cnt;
	}
	
	// Returns true iff you've won.
	public static boolean win(char[][] grid) {
		for (int i=0; i<grid.length; i++)
			for (int j=0; j<grid[i].length; j++)
				if (grid[i][j] == '_')
					return false;
					
		// If there were no underscores, you've cleared everything!
		return true;
	}
}