/*
 * Board.java
 *
 * Nadeem Abdul Hamid - Fall 2004 - CSC120A
 *
 * Class representing the board of a TicTacToe game
 * Marks are represented by single characters 'X' and 'O' and
 * positions on the board are designated by integers in the range
 * 0 to 8.
 *
 *  0  |1   |2
 *     |    |
 *     |    |
 *  ------------
 *  3  |4   |5
 *     |    |
 *     |    |
 *  ------------
 *  6  |7   |8
 *     |    |
 *     |    |
 *
 */

public class Board {
    
    /* fields of the Board class */
    private String sqrs;       // stores 9 characters representing the
                                // marks on the board
        
    /* methods of the Board class */
    
    /* Constructor: initializes the board to have no marks,
       ie., a string of 9 spaces
    */
    public Board() {
        sqrs = "         ";
    }
    
    /* Returns the mark at a given position */
    public char getMark(int pos) {
        return sqrs.charAt(pos);
    }
    
    /* Sets the mark at a given position, as long as the mark is a valid
       one and if there is not already a mark at that position. This
       method returns true if it successfully sets a mark at the given
      position and false otherwise */
    public boolean setMark(int pos, char ch) {
        if (ch=='X' || ch=='O') {
            if (sqrs.charAt(pos) == ' ') {
                sqrs = sqrs.substring(0,pos)
                        + ch + sqrs.substring(pos+1, sqrs.length());
            } else {
                return false;
            }
        } else {
            return false;
        }
        
        return true;
    }
    
    /* Erases the mark at a given position in the board */
    public void clearMark(int pos) {
        sqrs = sqrs.substring(0,pos) + " " + sqrs.substring(pos+1, sqrs.length());
    }
    
    /* Tests if there are no marks on the board yet */
    public boolean isEmpty() {
	int i = 0;
	while (i < 9) {
            if (getMark(i) != ' ') return false;
	    i++;
	}
        return true;
    }
    
    /* Tests if the game is over, due to a tie or win for one of the
       players */
    public boolean gameOver() {
        return isTie() || isWin('X') || isWin('O');
    }
    
    /* Tests if the game is a tie */
    public boolean isTie() {
        if (!isWin('X') && !isWin('O') && sqrs.indexOf(" ")<0)
            return true;
        return false;
    }
    
    /* Tests if the game is a win ... checks if there are three in a 
       row of the specified mark (ch) */
    public boolean isWin(char ch) {
        // check rows
        int row = 0;
        while (row < 3) {
            if (getMark(3*row) == ch &&
                getMark(3*row+1) == ch &&
                getMark(3*row+2) == ch) return true;
            row++;
        }
        
        // check columns
        int col = 0;
        while (col<3) {
            if (getMark(col) == ch &&
                getMark(3+col) == ch &&
                getMark(6+col) == ch) return true;
            col++;
        }
        
        // check diagonals
        if (getMark(0) == ch &&
            getMark(4) == ch &&
            getMark(8) == ch) return true;
        
        if (getMark(2) == ch &&
            getMark(4) == ch &&
            getMark(6) == ch) return true;
        
        return false;
    }
    
    /* Converts the internal representation of marks on the board
       to a string which can be printed out */
    public String toString() {
        String str = "";
        str += ("0  |1  |2  \n");
        str += (" " + getMark(0) + " | " + getMark(1) + " | " + getMark(2) + " \n");
        str += ("   |   |   \n");
        str += ("-----------\n");
        str += ("3  |4  |5  \n");
        str += (" " + getMark(3) + " | " + getMark(4) + " | " + getMark(5) + " \n");
        str += ("   |   |   \n");
        str += ("-----------\n");
        str += ("6  |7  |8  \n");
        str += (" " + getMark(6) + " | " + getMark(7) + " | " + getMark(8) + " \n");
        str += ("   |   |   ");
        
        return str;        
    }
    
    
    /* A test method to test the functionality of the methods 
       in this class */
    public static void main(String[] args) {
        Board b = new Board();
        System.out.println(b);
        
        b.setMark(2, 'O');
        b.setMark(3, 'P'); // error
        b.setMark(0, 'O');
        b.setMark(1, 'X');
        b.setMark(4, 'X');
        b.setMark(8, 'X');
        b.setMark(2, 'X'); // error
        b.setMark(6, 'X');
        b.setMark(3, 'O');
        b.setMark(5, 'X');
        b.setMark(7, 'O');
        
        System.out.println(b);
        System.out.println(b.isWin('X'));
        System.out.println(b.isWin('O'));
        System.out.println(b.isTie());
    }
    
}