Board.java :  » Game » letsgo-imerir » com » letsgo » Android Open Source

Android Open Source » Game » letsgo imerir 
letsgo imerir » com » letsgo » Board.java
package com.letsgo;

import java.util.ArrayList;

/**
 * Class used to represent the Board of a game
 */
public class Board {
  private int width ;
  private int height ;
  private BoardNode[][] grid ;
  private boolean nextPlayerWhite = true;
  
  /**
   * Board constructor which creates a grid with the given width and height
   * @param width
   * @param height
   */
  public Board(int width, int height)
  {
    this.width = width ;
    this.height = height ;
    this.grid = new BoardNode[this.width][this.height];
    for(int i=0 ; i<this.width ; i++)
    {
      for(int j=0 ; j<this.height ; j++)
      {
        this.grid[i][j] = new BoardNode(i,j);
      }
    }
  }
  
  /**
   * Basic constructor which creates a grid 9x9
   */
  public Board()
  {
    this(9,9);
  }
  
  /**
   * Return a String filled with the coordinates of each BoardNode and its type
   * ex : 3.4-BLACK
   */
  public String toString()
  {
    String s = "";
    
    if(this.grid != null)
    {
      for(int i=0 ; i<this.width ; i++)
      {
        for(int j=0 ; j<this.height ; j++)
        {
          s += " "+this.grid[i][j].getRow()+"."+this.grid[i][j].getCol()+"-"+this.grid[i][j].getType();
        }
      }
    }
    
    return s ;
  }
  
  /**
   * Fills the board from an ArrayList of BoardMovement (recalculates the game)
   * @param bms ArrayList of BoardMovement, it must start from seq 1
   * @throws BoardBadHistory if the BoardMovement's sequence number are not following each other or if the first is not 1
   */
  public void fillFromHistory(ArrayList<BoardMovement> bms) throws BoardBadHistory
  {
    if(bms == null)
      return ;
    
    if(bms.get(0).getSeq() > 1)
      throw new BoardBadHistory();
    
    int seq = 1 ;
    BNT currentType ;
    
    for(BoardMovement bm : bms)
    {
      // If the sequence number are not in order throw an error
      if(bm.getSeq() != seq)
        throw new BoardBadHistory();
      
      // Setting the current colors for the turn
      if(bm.getSeq()%2 == 0)
      {
        currentType = BNT.WHITE;
      }
      else
      {
        currentType = BNT.BLACK;
      }
      
      // If the node is already filled an error is thrown
      if(this.grid[bm.getRow()][bm.getColumn()].getType().equals(BNT.BLACK) || this.grid[bm.getRow()][bm.getColumn()].getType().equals(BNT.WHITE))
        throw new BoardBadHistory();
      else
      {
        // Setting the new color of the node
        this.grid[bm.getRow()][bm.getColumn()].setType(currentType);
      }

      // Check if some tokens are deleted due to the last movement
      checkArea(bm.getRow(), bm.getColumn());
      
      seq++ ;
      
    }
    this.nextPlayerWhite = (seq % 2 == 1);
  }
  
  /**
   * Start a check around the node given, this function should be called after each movement
   * it will check if some opponent's tokens need to be removed
   * @param row of the last movement
   * @param col of the last movement
   * @see checkFleeWay
   */
  private void checkArea(int row, int col)
  {
    if(row < 0 || col < 0 || row > width || col > height)
      return ;
    
    BNT currentType = this.grid[row][col].getType() ;
    BNT currentOpponentType ;
    
    if(currentType.equals(BNT.BLACK))
      currentOpponentType = BNT.WHITE ;
    else if(currentType.equals(BNT.WHITE))
      currentOpponentType = BNT.BLACK ;
    else
      return ;
  
    // CHECK TOP
    if(row > 0 && this.grid[row-1][col].getType().equals(currentOpponentType))
    {
      checkFleeWay(row-1, col, currentType, currentOpponentType);
    }
    
    // CHECK RIGHT
    if(col < this.width-1 && this.grid[row][col+1].getType().equals(currentOpponentType))
    {
      checkFleeWay(row, col+1, currentType, currentOpponentType);
    }
    
    // CHECK DOWN
    if(row < this.height-1 && this.grid[row+1][col].getType().equals(currentOpponentType))
    {
      checkFleeWay(row+1, col, currentType, currentOpponentType);
    }
    
    // CHECK LEFT
    if(col > 0 && this.grid[row][col-1].getType().equals(currentOpponentType))
    {
      checkFleeWay(row, col-1, currentType, currentOpponentType);
    }
  }
  
  /**
   * Checks the Area around the given node, if the node has a color it searchs if a flee way is available
   * if there is no flee way available, the funcion removes all the nodes from the chain linked to the given coordinates
   * @param row of the node to check
   * @param col of the node to check
   * @param currentType color of the last movement
   * @param currentOpponentType color of the opponent
   * @see checkArea
   */
  private void checkFleeWay(int row, int col, BNT currentType, BNT currentOpponentType)
  {    
    // This ArrayList is used to know which nodes were visited during the search
    // if the search finished without finding an empty node around the chain, 
    // all the visited nodes will be deleted
    ArrayList<BoardNode> visited = new ArrayList<BoardNode>();
    
    // This ArrayList is used to know which nodes are part of the chain, and need to be visited
    // the search finish when this list is empty
    ArrayList<BoardNode> unvisited = new ArrayList<BoardNode>() ;
    
    BoardNode current ;
    int cRow ;
    int cCol ;
    
    boolean fleeWay = false ;
    unvisited.add(this.grid[row][col]);
    while(!unvisited.isEmpty() && !fleeWay)
    {
      current = unvisited.remove(0);
      visited.add(current);
      cRow = current.getRow();
      cCol = current.getCol();
      
      if(cRow > 0) // Top
      {
        if(this.grid[cRow-1][cCol].getType().equals(BNT.EMPTY))
          fleeWay = true ; // An empty node was found
        else if(this.grid[cRow-1][cCol].getType().equals(currentOpponentType))
          unvisited.add(this.grid[cRow-1][cCol]); // An opponent token was found, so we add it to the unvisited list
      }
      
      if(cCol < this.width-1) // Right
      {
        if(this.grid[cRow][cCol+1].getType().equals(BNT.EMPTY))
          fleeWay = true ; // An empty node was found
        else if(this.grid[cRow][cCol+1].getType().equals(currentOpponentType))
          unvisited.add(this.grid[cRow][cCol+1]); // An opponent token was found, so we add it to the unvisited list
      }
      
      if(cRow < this.height-1) // Down
      {
        if(this.grid[cRow+1][cCol].getType().equals(BNT.EMPTY))
          fleeWay = true ; // An empty node was found
        else if(this.grid[cRow+1][cCol].getType().equals(currentOpponentType))
          unvisited.add(this.grid[cRow+1][cCol]); // An opponent token was found, so we add it to the unvisited list
      }
      
      if(cCol > 0) // Left
      {
        if(this.grid[cRow][cCol-1].getType().equals(BNT.EMPTY))
          fleeWay = true ; // An empty node was found
        else if(this.grid[cRow][cCol-1].getType().equals(currentOpponentType))
          unvisited.add(this.grid[cRow][cCol-1]); // An opponent token was found, so we add it to the unvisited list
      }
    }
    
    
    // If there is no fleeWay at the end of the search, all the visited nodes are deleted
    if(!fleeWay)
    {
      // Remove BoardNode from the grid
      for(BoardNode b : visited)
      {
        this.grid[b.getRow()][b.getCol()] = new BoardNode(b.getRow(), b.getCol(), this.grid[b.getRow()][b.getCol()].getValue(), BNT.EMPTY);
      }
    }
  }
  
  /**
   * Retrieve the BoardNode at the given position
   * @param x position of the node to modify
   * @param y position of the node to modify
   * @return the BoardNode at the given position
   * @throws BoardException
   */
  public BoardNode get(int x, int y) throws BoardException
  {
    if(x<0 || x>=this.width || y<0 || y>=this.height)
      throw new BoardException();
    return grid[x][y];
  }
  
  /**
   * Change the type of a BoardNode in the grid
   * @param x position of the node to modify
   * @param y position of the node to modify
   * @param type new type of the node : BNT {EMPTY, BLACK, WHITE}
   * @throws BoardException if x or y are out of bound
   */
  public void set(int x, int y, BNT type) throws BoardException
  {
    if(x<0 || x>=this.width || y<0 || y>=this.height)
      throw new BoardException();
    this.grid[x][y].setType(type) ;
  }
  
  /**
   * Plays a move
   * @param x position of the new rock
   * @param y position of the new rock
   * @throws BoardException if x or y are out of bound
   */
  public void playMove(int x, int y) throws BoardException
  {
    this.set(x, y, nextPlayerWhite ? BNT.WHITE : BNT.BLACK);
    nextPlayerWhite = !nextPlayerWhite;
  }
  
  /**
   * @return the width of the grid
   */
  public int getWidth() {
    return width;
  }

  /**
   * @param width the width of the grid to set
   */
  public void setWidth(int width) {
    this.width = width;
  }

  /**
   * @return the height of the grid
   */
  public int getHeight() {
    return height;
  }

  /**
   * @param height the height of the grid to set
   */
  public void setHeight(int height) {
    this.height = height;
  }

  /**
   * @return the grid
   */
  public BoardNode[][] getGrid() {
    return grid;
  }

  /**
   * @param grid the grid to set
   */
  public void setGrid(BoardNode[][] grid) {
    this.grid = grid;
  }

  /**
   * @return the nextPlayerWhite
   */
  public boolean isNextPlayerWhite() {
    return nextPlayerWhite;
  }
}
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.