Game.java :  » Game » ticktackdoh » ticktackdoh » app » Android Open Source

Android Open Source » Game » ticktackdoh 
ticktackdoh » ticktackdoh » app » Game.java
/*
 * TickTackDoh - a cross'n'naughts style game for Android
 * Copyright (C) 2008 Karo Launonen
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package ticktackdoh.app;

public class Game {
  public final static String GAME_TAG = "Game";
  
    public final static byte MIN_DIMENSION = 10;
    public final static byte MAX_DIMENSION = 100;

    public final static byte PLAYER_O = 1;
    public final static byte PLAYER_X = 2;

    public final static byte MOVE_ILLEGAL = 1;
    public final static byte MOVE_LEGAL = 2;
    
    public final static byte STATE_PLAYER_O_WINS = 1;
    public final static byte STATE_PLAYER_X_WINS = 2;
    public final static byte STATE_GAME_DRAW = 3;
    public final static byte STATE_GAME_ONGOING = 4;
    
    public final static byte MARKS_IN_A_ROW_TO_WIN = 5;
    
    private byte    mBoardColumns = 0;
    private byte    mBoardRows = 0;
    private byte    mBoard[];
    private int     mMovesMade = 0;
    private int    mMovesAvailable = 0;
    private byte    mWhoseMove = 0;
    private byte    mGameState = STATE_GAME_ONGOING;
    
    Game(byte boardColumns, byte boardRows, byte startingPlayer) throws Exception
    {
        if (boardColumns < MIN_DIMENSION || boardRows < MIN_DIMENSION) {
            throw new Exception("Columns and/or rows less than " + MIN_DIMENSION);
        } else if (boardColumns > MAX_DIMENSION || boardRows > MAX_DIMENSION) {
            throw new Exception("Columns and/or rows greater than " + MAX_DIMENSION);
        }
        if (startingPlayer != PLAYER_O && startingPlayer != PLAYER_X) {
            throw new Exception("Invalid starting player");
        }

        mBoardColumns = boardColumns;
        mBoardRows = boardRows;
        mMovesAvailable = boardColumns * boardRows;
        mBoard = new byte[mMovesAvailable];
        mWhoseMove = startingPlayer;
    }

    public byte getWhoseMove() {
        return mWhoseMove;
    }
    
    public void setWhoseMove(byte player) {
      mWhoseMove = player;
    }

    public int getMoves() {
        return mMovesMade;
    }

    public byte getCell(byte column, byte row) throws Exception {
        if (column < 0 || column >= mBoardColumns ||
                row < 0 || row >= mBoardRows) {
            throw new Exception("Out-of-range dimensions");
        }

        return mBoard[row * mBoardColumns + column];
    }
    
    public byte tryMove(byte column, byte row) {
      if (mGameState != STATE_GAME_ONGOING || mMovesMade == mMovesAvailable) {
        return MOVE_ILLEGAL;
      }
      
      int cell = row * mBoardColumns + column;
      if (mBoard[cell] != 0) {
        return MOVE_ILLEGAL;
      }
 
      makeMove(column, row);
      /* Turn change */
         mWhoseMove = (mWhoseMove == PLAYER_O ? PLAYER_X : PLAYER_O);
 
      return MOVE_LEGAL;
    }
    
    public byte getGameState() {
      return mGameState;
    }
    
    private void makeMove(byte column, byte row) {
      int marksInARow = 1;
      int cell = row * mBoardColumns + column;
      int x, y, checkCell, xBound, yBound;
      
      mBoard[cell] = mWhoseMove;
      mMovesMade++;
      
      /* Check the game state */
      
      /* Check horizontal, first to left and then right */
      checkCell = cell - 1;
      x = column - 1;
      xBound = column - MARKS_IN_A_ROW_TO_WIN + 1;
      if (xBound < 0) {
        xBound = 0;
      }
      
      while (x >= xBound && mBoard[checkCell] == mWhoseMove) {
        marksInARow++;
        x--;
        checkCell--;
      }

      if (marksInARow < MARKS_IN_A_ROW_TO_WIN) {
        x = column + 1;
        checkCell = cell + 1;
        xBound = column + MARKS_IN_A_ROW_TO_WIN - 1;
        if (xBound > mBoardColumns) {
          xBound = mBoardColumns;
        }
        
        /* To the right */
        while (x < xBound && mBoard[checkCell] == mWhoseMove) {
          marksInARow++;
          x++;
          checkCell++;
        }
      }
      
      if (marksInARow < MARKS_IN_A_ROW_TO_WIN) {
        /* No win, reset counter */
        marksInARow = 1;
        /* Check vertical, first up */
        y = row - 1;
        checkCell = cell - mBoardColumns;
        yBound = row - MARKS_IN_A_ROW_TO_WIN + 1;
        if (yBound < 0) {
          yBound = 0;
        }
        
        while (y >= yBound && mBoard[checkCell] == mWhoseMove) {
          marksInARow++;
          y--;
          checkCell -= mBoardColumns;
        }
      }
      
      if (marksInARow < MARKS_IN_A_ROW_TO_WIN) {
        /* No win, check down */
        y = row + 1;
        checkCell = cell + mBoardColumns;
        yBound = row + MARKS_IN_A_ROW_TO_WIN - 1;
        if (yBound > mBoardRows) {
          yBound = mBoardRows;
        }
        
        while (y < yBound && mBoard[checkCell] == mWhoseMove) {
          marksInARow++;
          y++;
          checkCell += mBoardColumns;
        }
      }
      
      /* Check diagonals, first from top-left to bottom-right */
      if (marksInARow < MARKS_IN_A_ROW_TO_WIN) {
        marksInARow = 1;
        xBound = column - MARKS_IN_A_ROW_TO_WIN + 1;
        if (xBound < 0) {
          xBound = 0;
        }
        
        yBound = row - MARKS_IN_A_ROW_TO_WIN + 1;
        if (yBound < 0) {
          yBound = 0;
        }
        
        x = column - 1;
        y = row - 1;
        checkCell = cell - mBoardColumns - 1;
        while (x >= xBound && y >= yBound && mBoard[checkCell] == mWhoseMove) {
          marksInARow++;
          x--;
          y--;
          checkCell -= (mBoardColumns + 1);
        }
      }
      
      if (marksInARow < MARKS_IN_A_ROW_TO_WIN) {
        xBound = column + MARKS_IN_A_ROW_TO_WIN - 1;
        if (xBound > mBoardColumns) {
          xBound = mBoardColumns;
        }
        
        yBound = row + MARKS_IN_A_ROW_TO_WIN - 1;
        if (yBound > mBoardRows) {
          yBound = mBoardRows;
        }
        
        x = column + 1;
        y = row + 1;
        checkCell = cell + mBoardColumns + 1;
        while(x < xBound && y < yBound && mBoard[checkCell] == mWhoseMove) {
          marksInARow++;
          x++;
          y++;
          checkCell += (mBoardColumns + 1);
        }
      }
      
      /* Check diagonal top-right to bottom-left */
      if (marksInARow < MARKS_IN_A_ROW_TO_WIN) {
        marksInARow = 1;
        
        xBound = column + MARKS_IN_A_ROW_TO_WIN - 1;
        if (xBound > mBoardColumns) {
          xBound = mBoardColumns;
        }
        
        yBound = row - MARKS_IN_A_ROW_TO_WIN + 1;
        if (yBound < 0) {
          yBound = 0;
        }
        
        x = column + 1;
        y = row - 1;
        checkCell = cell - mBoardColumns + 1;
        while (x < xBound && y >= yBound && mBoard[checkCell] == mWhoseMove) {
          marksInARow++;
          x++;
          y--;
          checkCell -= (mBoardColumns - 1);
        }
      }
      
      if (marksInARow < MARKS_IN_A_ROW_TO_WIN) {
        xBound = column - MARKS_IN_A_ROW_TO_WIN + 1;
        if (xBound < 0) {
          xBound = 0;
        }
        
        yBound = row + MARKS_IN_A_ROW_TO_WIN - 1;
        if (yBound >= mBoardRows) {
          yBound = mBoardRows;
        }
        
        x = column - 1;
        y = row + 1;
        checkCell = cell + mBoardColumns - 1;
        while (x >= xBound && y < yBound && mBoard[checkCell] == mWhoseMove) {
          marksInARow++;
          x--;
          y++;
          checkCell += (mBoardColumns - 1);
        }
      }
      
      if (marksInARow == MARKS_IN_A_ROW_TO_WIN) {
        /* Win! */
        mGameState = (mWhoseMove == PLAYER_O ? STATE_PLAYER_O_WINS : STATE_PLAYER_X_WINS);
      } else if (mMovesMade == mMovesAvailable) {
        mGameState = STATE_GAME_DRAW;
      }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.