Package pdp.scrabble.game.impl

Source Code of pdp.scrabble.game.impl.BoardImpl

package pdp.scrabble.game.impl;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import org.jdom.Element;

import pdp.scrabble.Factory;
import pdp.scrabble.Main_old;
import pdp.scrabble.game.Bag;
import pdp.scrabble.game.Board;
import pdp.scrabble.game.BoardCase;
import pdp.scrabble.game.BoardCaseState;
import pdp.scrabble.game.Dictionary;
import pdp.scrabble.game.GameEnvironment;
import pdp.scrabble.game.Letter;
import pdp.scrabble.game.Player;
import pdp.scrabble.game.Rack;
import pdp.scrabble.game.exception.BoardWrongWordPlace;
import pdp.scrabble.utility.Debug;
import pdp.scrabble.utility.Display;
import static pdp.scrabble.game.BoardCaseState.FREE;
import static pdp.scrabble.game.BoardCaseState.NEW;
import static pdp.scrabble.game.BoardCaseState.OLD;
import static pdp.scrabble.game.BoardCaseIndex.FIRST;
import static pdp.scrabble.game.BoardCaseIndex.LAST;
import static pdp.scrabble.game.BoardCaseIndex.NONE;
import static pdp.scrabble.Game.SCRABBLE_PTS;
import static pdp.scrabble.Factory.FACTORY;

public class BoardImpl extends Observable implements Board {

    /** Memory representation of the board. */
    private BoardCase[][] map = null;

    /** Dictionary reference. */
    private Dictionary dictionary = null;

    /** Center used state. */
    private boolean centerUsed = false;

    /** Last total points from formed words. */
    private int points = 0;

    /** Last length from a word. */
    private int length = 0;

    /** AutoSave flag. */
    private boolean isAutoSave = false;

    /** Last list of formed words. */
    private List<String> words = null;

    /** List of checked cases. */
    private List<BoardCase> checkedCases = null;

    /** List of new cases, addeed by the player recently. */
    private List<BoardCase> newCases = null;

    /** Valide state, use for AI board check (faster than throw exception). */
    private boolean valide = false;

    /** AI flag, to know if board called by an ai. */
    private boolean isAI = false;

    /** Number of dropped letters. */
    private int droppedLetters = 0;

    /** List of board observer*/
    private ArrayList<Observer> listObs = new ArrayList<Observer>(1);

    public BoardImpl() {
  // This offset (3) is used to avoid board border error
  // when checking letters (in order to skip critical test)
  this.map = new BoardCase[VERT_DIM + 3][HORI_DIM + 3];
  this.centerUsed = false;
  this.points = 0;
  this.length = 0;
  this.words = new ArrayList<String>(1);
  this.checkedCases = new ArrayList<BoardCase>(4);
  this.newCases = new ArrayList<BoardCase>(7);
  this.droppedLetters = 0;

  this.loadConfigBoard(Main_old.RESSOURCES_PATH + "board.txt");

  // Allocate secure cases (to avoid critical test,
  // in order to check placement as fast as possible)
  for (int v = 0; v < VERT_DIM + 3; v++) {
      for (int h = 0; h < HORI_DIM + 3; h++) {
    if (this.map[v][h] == null) {
        this.map[v][h] = FACTORY.createBoardCase(0, 0, v, h);
    }
      }
  }
    }

    private void loadConfigBoard(String cfgBoard) {
  int letterMult = 1, wordMult = 1;
  int mult, h = 0, v = 0;

  try {
      BufferedReader file = new BufferedReader(new FileReader(cfgBoard));
      String line = file.readLine();

      // Read data lines
      while (line != null) {
    for (h = 0; h < HORI_DIM; h++) {
        mult = Integer.parseInt(String.valueOf(line.charAt(h + 1)));

        // Normal case
        if (mult == 0) {
      letterMult = 1;
      wordMult = 1;
        } // Double letter case
        else if (mult == 1) {
      letterMult = 2;
      wordMult = 1;
        } // Triple letter case
        else if (mult == 2) {
      letterMult = 3;
      wordMult = 1;
        } // Double word case
        else if (mult == 3) {
      letterMult = 1;
      wordMult = 2;
        } // Triple word case
        else if (mult == 4) {
      letterMult = 1;
      wordMult = 3;
        }

        // Assign case
        this.setCase(v, h, FACTORY.createBoardCase(
          letterMult, wordMult, v, h));
    }

    // Next line until last column
    if (v < VERT_DIM - 1) {
        line = file.readLine();
        v++;
    }
    else {
        break;
    }
      }
      file.close();
  }
  catch (FileNotFoundException e) {
      Display.error("Load board configuration", "File not found:",
        " " + cfgBoard);
  }
  catch (IOException e) {
      Display.error("Load board configuration", "Can't read datas:",
        " " + cfgBoard);
  }
    }

    public void setCase(int vertIndex, int horiIndex, BoardCase boardCase) {
  this.map[vertIndex + 1][horiIndex + 1] = boardCase;
    }

    public BoardCase getCase(int vertIndex, int horiIndex) {
  return this.map[vertIndex + 1][horiIndex + 1];
    }

    public void setCaseLetter(
      int vertIndex, int horiIndex, Letter letter, boolean add) {

  BoardCase boardCase = this.getCase(vertIndex, horiIndex);
  boardCase.setLetter(letter);
  boardCase.setState(NEW);
  if (add) {
      this.newCases.add(boardCase);
  }
    }

    private void setCaseState(int vertIndex, int horiIndex, BoardCaseState bcs) {
  this.getCase(vertIndex, horiIndex).setState(bcs);
    }

    public void resetCase(int vertIndex, int horiIndex) {
  BoardCase boardCase = this.getCase(vertIndex, horiIndex);
  boardCase.setLetter(null);
  boardCase.setState(FREE);
  boardCase.setAdjacentIgnorence(false);
  boardCase.setChecked(false);
  boardCase.setMultUsed(false);
  boardCase.setIndex(NONE);
    }

    public void removeCaseNew(BoardCase newCase) {
  int len = this.newCases.size();
  for (int i = 0; i < len; i++) {
      if (this.newCases.get(i) == newCase) {
    this.newCases.remove(i);
    break;
      }
  }
    }

    public int numberOfNewCases() {
  return this.newCases.size();
    }

    public void validate(boolean confirm) throws BoardWrongWordPlace {
  this.isAI = false;
  try {
      this.checkBoardRules();
      this.resetCheckedStates();
  }
  catch (BoardWrongWordPlace bwwp) {
      this.resetCheckedStates();
      throw new BoardWrongWordPlace(bwwp.getError(), bwwp.getInfo());
  }

  // Validate all new case and set their flag to old
  if (confirm) {
      for (int v = 0; v < VERT_DIM; v++) {
    for (int h = 0; h < HORI_DIM; h++) {
        if (this.getCase(v, h).getState() == NEW) {
      this.setCaseState(v, h, OLD);
      this.droppedLetters++;

      if (!this.listObs.isEmpty()) {
          this.notifyObservers(this.getCase(v, h));
      }
        }
    }
      }
      if (!this.isAutoSave()) {
    this.newCases.clear();
      }
  }
    }

    public boolean validateAI() {
  boolean state = false;
  try {
      this.isAI = true;
      state = this.checkBoardRules();
  }
  catch (BoardWrongWordPlace ex) {
  }
  this.resetCheckedStates();
  return state;
    }

    public void prepareTurn() {
  this.words.clear();
  this.setWordPoints(0);
    }

    /** Check if word is well placed before validate.
     * @throws BoardWrongWordPlace exception thrown if word is on a wrong place.
     */
    private boolean checkBoardRules() throws BoardWrongWordPlace {

  // Number of new elements
  this.valide = true;
  int casesNum = this.newCases.size();

  this.setWordLength(casesNum);
  this.prepareTurn();

  // Has new letter ?
  if (casesNum > 0) {

      // Ensure center case is used
      this.checkCenterRules();

      // Letters must be aligned (return alignement)
      boolean isVert = this.checkAlignementRules(this.newCases, casesNum);

      // Assign indexs
      // (determin if letter is FIRST, MIDDLE, or LAST in the word)
      this.assignIndex(this.newCases, casesNum, isVert);

      // Check if word has unified letters, without blank space
      // (check from first to last index)
      this.checkWordUnifiedRules(this.newCases, casesNum, isVert);

      // Word must hit another old one
      this.checkWordHitRules(this.newCases, casesNum);

      // Apply scrabble bonus
      if (casesNum == Rack.MAX_RACK_LETTERS) {
    this.points += SCRABBLE_PTS;
      }

      // AI ignore thrown exception, using boolean will be faster
      if (this.isAI) {
    if (!this.valide) {
        return false;
    }
      }
  }

  this.resetCheckedStates();
  return true;
    }

    /** Determin letters index (is it FIRST, MIDDLE, or LAST).
     * @param newCases list of new cases.
     * @param numberOfNewCases number of new cases.
     * @param isVertical true if vertical, false else.
     */
    private void assignIndex(
      List<BoardCase> newCases, int newCasesNum, boolean isVertical) {

  int min = newCases.get(0).getH(), minID = 0;
  int max = min, maxID = 0;

  if (isVertical) {
      min = newCases.get(0).getV();
      max = min;
  }

  // Check all new letters (get min and max index)
  for (int i = 1; i < newCasesNum; i++) {
      int result = newCases.get(i).getH();

      if (isVertical) {
    result = newCases.get(i).getV();
      }
      if (min > result) {
    min = result;
    minID = i;
      }
      if (max < result) {
    max = result;
    maxID = i;
      }
  }

  // Update index
  newCases.get(minID).setIndex(FIRST);
  newCases.get(maxID).setIndex(LAST);
    }

    /** Check if the center case is used.
     * @throws BoardWrongWordPlace center uses rules violation.
     */
    private void checkCenterRules() throws BoardWrongWordPlace {
  if (!this.centerUsed) {
      if (this.getCase(VERT_DIM / 2, HORI_DIM / 2).getState() == FREE) {
    this.centerUsed = false;
    if (this.isAI) {
        this.valide = false;
        return;
    }
    else {
        throw new BoardWrongWordPlace("Word must use center case !");
    }
      }
      else {
    this.centerUsed = true;
      }
  }
    }

    /** Check if all new cases are aligned on the same axis.
     * @param newCases list of new cases.
     * @param newCasesNum number of new cases on board.
     * @return false if alignement is vertical, true if it is horizontal.
     * @throws BoardWrongWordPlace alignement rules violation.
     */
    private boolean checkAlignementRules(
      List<BoardCase> newCases, int newCasesNum)
    throws BoardWrongWordPlace {

  int vertTest = newCases.get(0).getV();
  int horiTest = newCases.get(0).getH();
  int vertCount = 1, horiCount = 1;

  // Check all cases
  for (int i = 1; i < newCasesNum; i++) {
      BoardCase boardCase = newCases.get(i);
      if (boardCase.getV() == vertTest) {
    vertCount++;
      }
      if (boardCase.getH() == horiTest) {
    horiCount++;
      }
  }

  // One or more are not aligned on the same axis
  if (vertCount != newCasesNum && horiCount != newCasesNum) {
      if (this.isAI) {
    this.valide = false;
    return false;
      }
      else {
    throw new BoardWrongWordPlace("Letters must be aligned !");
      }
  }

  // Test for just one letter
  if (newCasesNum == 1) {
      if (this.getCase(vertTest + 1, horiTest).getState() == OLD
        || this.getCase(vertTest - 1, horiTest).getState() == OLD) {

    return true;
      }
      else {
    return false;
      }
  }

  // Get axis result (will be used on future check)
  if (vertCount == newCasesNum) {
      // All letters are vertically aligned,
      // so the word is on the horizontal axis
      return false;
  }
  else {
      // All letters are horizontaly aligned,
      // so the word is on the vertical axis
      return true;
  }
    }

    /** Check if the formed word has unified letters, without blank spaces.
     * @param newCases list of new cases.
     * @param numberOfNewCases number of new cases on board.
     * @param isVert true if its for vertical axis check, false for horizontal.
     * @throws BoardWrongWordPlace ununified letters rules violation.
     */
    private void checkWordUnifiedRules(
      List<BoardCase> newCases, int numberOfNewCases, boolean isVert)
    throws BoardWrongWordPlace {

  BoardCase boardCase = null;
  int first = 0, last = 0;
  int firstP = 0, lastP = 0;
  int axis = 0;

  // Get extremity index
  for (int i = 0; i < numberOfNewCases; i++) {
      boardCase = newCases.get(i);
      if (boardCase.getIndex() == FIRST) {
    first = i;
      }
      if (boardCase.getIndex() == LAST) {
    last = i;
      }
  }

  // Check unification
  if (isVert) {
      axis = newCases.get(first).getH();
      firstP = newCases.get(first).getV();
      lastP = newCases.get(last).getV();

      for (int v = firstP; v <= lastP; v++) {
    if (this.getCase(v, axis).getState() == FREE) {
        if (this.isAI) {
      this.valide = false;
      return;
        }
        else {
      throw new BoardWrongWordPlace(
      "Word letters must be verticaly unified !");
        }
    }
      }
  }
  else {
      axis = newCases.get(first).getV();
      firstP = newCases.get(first).getH();
      lastP = newCases.get(last).getH();

      for (int h = firstP; h <= lastP; h++) {
    if (this.getCase(axis, h).getState() == FREE) {
        if (this.isAI) {
      this.valide = false;
      return;
        }
        else {
      throw new BoardWrongWordPlace(
      "Word letters must be horizontaly unified !");
        }
    }
      }
  }

  this.checkWordExistence(isVert, axis, firstP, lastP);
    }

    /** Check if new word hit an old one.
     * @param newCases list of new cases.
     * @param numberOfNewCases number of new cases on board.
     * @throws BoardWrongWordPlace word hit rules violation.
     */
    private void checkWordHitRules(List<BoardCase> newCases, int newCasesNum)
    throws BoardWrongWordPlace {

  BoardCase bCase = null;
  int numberOfHit = 0;

  // Check all cases
  for (int i = 0; i < newCasesNum; i++) {
      bCase = newCases.get(i);

      if (this.caseJoinedTo(bCase.getV(), bCase.getH(), true, OLD)
        || this.caseJoinedTo(bCase.getV(), bCase.getH(), false, OLD)) {

    numberOfHit++;
      }
  }

  // No hit (only if it is not the first word placed)
  if (numberOfHit == 0) {
      if (this.getCase(VERT_DIM / 2, HORI_DIM / 2).getState() == OLD) {
    if (this.isAI) {
        this.valide = false;
        return;
    }
    else {
        throw new BoardWrongWordPlace(
        "New word must be joined to an other one !");
    }
      }
  }
    }

    /** Check word existence.
     * @throws BoardWrongWordPlace word existence rules exception.
     */
    private void checkWordExistence(
      boolean isVertical, int axis, int first, int last)
    throws BoardWrongWordPlace {

  StringBuilder word = new StringBuilder("");
  BoardCase boardCase = null;
  List<Letter> jokers = new ArrayList<Letter>(1);
  int firstP = first, lastP = last;

  // Get complete word
  if (isVertical) {
      while (this.getCase(firstP - 1, axis).getState() != FREE) {
    firstP--; // Top index
      }
      while (this.getCase(lastP + 1, axis).getState() != FREE) {
    lastP++; // Down index
      }

      // Current word letter
      for (int v = firstP; v <= lastP; v++) {
    Letter letter = this.getCase(v, axis).getLetter();
    word = word.append(letter.getName());
    if (letter.getName() == Bag.JOKER) {
        jokers.add(letter);
    }
      }
  }
  else {
      while (this.getCase(axis, firstP - 1).getState() != FREE) {
    firstP--; // Left index
      }
      while (this.getCase(axis, lastP + 1).getState() != FREE) {
    lastP++; // Right index
      }

      // Current word letter
      for (int h = firstP; h <= lastP; h++) {
    Letter letter = this.getCase(axis, h).getLetter();
    word = word.append(letter.getName());
    if (letter.getName() == Bag.JOKER) {
        jokers.add(letter);
    }
      }
  }

  // Apply joker char to use (if has and found)
  int numOfJoker = jokers.size();
  if (numOfJoker > 0) {
      Character[] joker = this.tryJokers(word);
      jokers.get(0).setJokerChar(joker[0]);
      if (numOfJoker == 2) {
    jokers.get(1).setJokerChar(joker[1]);
      }
      jokers.clear();
      jokers = null;
      joker = null;
  }

  // Check existence
  if (!this.dictionary.contains(word)) {
      if (this.isAI) {
    this.valide = false;
    return;
      }
      else {
    throw new BoardWrongWordPlace(
      "This word doesn't exist:", " " + word);
      }
  }

  // If word exists, calculate points
  int score = this.calculateWordPoints(isVertical, axis, firstP, lastP);
  Debug.console(
    "checkWordExistence", "word = ", word + " | score = " + score);

  this.words.add(word.toString());
  this.points += score;

  // Check now adjacents words (for each word letters)
  if (isVertical) {
      for (int v = firstP; v <= lastP; v++) {
    boardCase = this.getCase(v, axis);

    // Letter has adjacent letters (right or left)
    if (!boardCase.getAdjacentIgnorence() && !boardCase.isChecked()
      && boardCase.getState() == NEW) {

        if (this.getCase(v, axis - 1).getState() == OLD
          || this.getCase(v, axis + 1).getState() == OLD) {

      boardCase.setChecked(true);
      this.checkedCases.add(boardCase);
      this.checkWordExistence(!isVertical, v, axis, axis);
        }
    }
      }
  }
  else {
      for (int h = firstP; h <= lastP; h++) {
    boardCase = this.getCase(axis, h);

    // Letter has adjacent letters (up or down)
    if (!boardCase.getAdjacentIgnorence() && !boardCase.isChecked()
      && boardCase.getState() == NEW) {

        if (this.getCase(axis - 1, h).getState() == OLD
          || this.getCase(axis + 1, h).getState() == OLD) {

      boardCase.setChecked(true);
      this.checkedCases.add(boardCase);
      this.checkWordExistence(!isVertical, h, axis, axis);
        }
    }
      }
  }
    }

    /** Try joker, returning characters used for the joker.
     * @param word input word
     * @return joker chars to use.
     */
    private Character[] tryJokers(StringBuilder word) {
  int len = word.length();
  int j1 = -1, j2 = -1;
  Character[] jokerChar = new Character[2];
  jokerChar[0] = Bag.JOKER;
  jokerChar[1] = Bag.JOKER;

  // Search jokers indexs
  for (int i = 0; i < len; i++) {
      if (word.charAt(i) == Bag.JOKER) {
    if (j1 == -1) {
        j1 = i;
    }
    else if (j2 == -1) {
        j2 = i;
    }
      }
  }

  // Replace joker using all possibilities
  int chars = Bag.AVAILABLE_LETTERS.length;
  for (int c1 = 0; c1 < chars; c1++) {
      word.setCharAt(j1, Bag.AVAILABLE_LETTERS[c1]);

      // Has 2 joker ?
      if (j2 > -1) {
    for (int c2 = 0; c2 < chars; c2++) {
        word.setCharAt(j2, Bag.AVAILABLE_LETTERS[c2]);

        if (this.dictionary.contains(word)) {
      jokerChar[0] = Bag.AVAILABLE_LETTERS[c1];
      jokerChar[1] = Bag.AVAILABLE_LETTERS[c2];
      return jokerChar;
        }
    }
      } // Has 1 joker ?
      else {
    if (this.dictionary.contains(word)) {
        jokerChar[0] = Bag.AVAILABLE_LETTERS[c1];
        return jokerChar;
    }
      }
  }

  // Nothing worked, reset joker(s)
  if (j1 > -1) {
      word.setCharAt(j1, Bag.JOKER);
  }
  if (j2 > -1) {
      word.setCharAt(j2, Bag.JOKER);
  }
  return jokerChar;
    }

    /** Check if the new case is joined to another case.
     * @param v vertical position.
     * @param h horizontal position.
     * @param isVertical false for vertical check, true for horizontal check.
     * @param state letter state.
     * @return true if case is joined, false else.
     */
    private boolean caseJoinedTo(
      int v, int h, boolean isVertical, BoardCaseState state) {

  // Check only one axis
  int addV = 0, addH = 0;
  if (isVertical) {
      addV = 1;
  }
  else {
      addH = 1;
  }

  // Check hit
  if (this.getCase(v - addV, h - addH).getState() == state
    || this.getCase(v + addV, h + addH).getState() == state) {

      return true;
  }
  return false;
    }

    /** Reset checked state after board validation. */
    private void resetCheckedStates() {
  Iterator<BoardCase> itr = this.checkedCases.iterator();
  while (itr.hasNext()) {
      itr.next().setChecked(false);
  }
  this.checkedCases.clear();
    }

    public void resetCheckMultiplicator() {
  for (int v = 0; v < VERT_DIM; v++) {
      for (int h = 0; h < HORI_DIM; h++) {
    this.getCase(v, h).setMultUsed(false);
      }
  }
    }

    /** Calculate points of a word.
     * @param isVert false for vertical check, true for horizontal check.
     * @param axis
     * @param first
     * @param last
     */
    private int calculateWordPoints(
      boolean isVert, int axis, int first, int last) {

  BoardCase boardCase = null;
  Letter letter = null;
  int wordMult = 1, score = 0, letterValue = 0;

  // Check from first letter to last
  for (int index = first; index <= last; index++) {
      if (isVert) {
    boardCase = this.getCase(index, axis);
      }
      else {
    boardCase = this.getCase(axis, index);
      }

      letter = boardCase.getLetter();
      letterValue = letter.getValue();

      // Apply bonus if not already used
      if (!boardCase.getMultUsed()) {
    letterValue *= boardCase.getLetterMult();
    wordMult *= boardCase.getWordMult();
    boardCase.setMultUsed(true);
      }

      score += letterValue;
  }

  // Apply word multiplicator found
  score *= wordMult;

  return score;
    }

    public void clear() {
  for (int v = 0; v < VERT_DIM; v++) {
      for (int h = 0; h < HORI_DIM; h++) {
    this.resetCase(v, h);
      }
  }
  this.checkedCases.clear();
  this.newCases.clear();
  this.droppedLetters = 0;
    }


    public void cancel(Player player) {
  BoardCase boardCase = null;
  int len = this.newCases.size();
  for (int i = 0; i < len; i++) {
      boardCase = this.newCases.get(i);

      // Give letter back to the player
      boardCase.getLetter().setJokerChar(Bag.NON_JOKER);
      if (player != null) {
    player.getRack().addLetter(boardCase.getLetter());
      }

      // Remove the letter from the board
      this.resetCase(boardCase.getV(), boardCase.getH());
  }

  this.newCases.clear();
    }


    public void switchCasesLetter(int v1, int h1, int v2, int h2) {
  BoardCase case1 = this.getCase(v1, h1);
  BoardCase case2 = this.getCase(v2, h2);

  Letter letter1 = case1.getLetter();
  Letter letter2 = case2.getLetter();

  BoardCaseState state1 = case1.getState();
  BoardCaseState state2 = case2.getState();

  if (state1 == FREE) {
      int len = this.newCases.size();
      for (int i = 0; i < len; i++) {
    BoardCase boardCase = this.newCases.get(i);
    if (boardCase == case2) {
        this.newCases.set(i, case1);
        break;
    }
      }
  }

  this.setCaseLetter(v1, h1, letter2, false);
  this.setCaseState(v1, h1, state2);

  this.setCaseLetter(v2, h2, letter1, false);
  this.setCaseState(v2, h2, state1);
    }


    public void setDictionary(Dictionary dictionary) {
  this.dictionary = dictionary;
    }


    public void setWordPoints(int points) {
  this.points = points;
    }


    public int getWordPoints() {
  return this.points;
    }


    public void setWordLength(int length) {
  this.length = length;
    }


    public int getWordLength() {
  return this.length;
    }


    public List<String> getFormedWords() {
  return Collections.unmodifiableList(this.words);
    }


    public void saveTurn(Element root) {
  Element element = new Element("Board");
  root.addContent(element);

  Iterator<BoardCase> it = this.newCases.iterator();

  while (it.hasNext()) {
      BoardCase boardCase = it.next();
      boardCase.save(element);
  }
  this.newCases.clear();
    }


    public int getNumberOfDroppedLetters() {
  return this.droppedLetters;
    }


    public void save(Element root) {
  Element element = new Element("Board");
  root.addContent(element);

  for (int v = 0; v < VERT_DIM; v++) {
      for (int h = 0; h < HORI_DIM; h++) {
    this.getCase(v, h).save(element);
      }
  }
    }


    public void load(Element root) {
  int h, v = 0;
  if (root != null) {
      Element element = root.getChild("Board");
      @SuppressWarnings("unchecked")
      Iterator<Element> Eboard = element.getChildren().iterator();

      while (Eboard.hasNext()) {
    Element EboardCase = Eboard.next();
    h = Integer.parseInt(EboardCase.getAttributeValue("h"));
    v = Integer.parseInt(EboardCase.getAttributeValue("v"));
    this.getCase(v, h).load(EboardCase);
      }
  }
    }


    public void addObserver(Observer o) {
  this.listObs.add(o);
    }


    public void deleteObserver(Observer o) {
  this.listObs.remove(o);
    }


    public void deleteObservers() {
  this.listObs = new ArrayList<Observer>(1);
    }


    public void notifyObservers(Object arg) {
  for (Observer obs : this.listObs) {
      obs.update(this, arg);
  }
    }


    public void setData(boolean centerUsed, int points,
      int length, List<String> words) {

  this.centerUsed = centerUsed;
  this.points = points;
  this.length = length;

  this.words.clear();
  Iterator<String> itr = words.iterator();
  while (itr.hasNext()) {
      this.words.add(itr.next());
  }
    }


    public boolean isAutoSave() {
  return this.isAutoSave;
    }


    public void setAutoSave(boolean autoSave) {
  this.isAutoSave = autoSave;
    }


    public Board clone() {
  Board board = FACTORY.createBoard();
  board.setDictionary(this.dictionary);
  board.setData(this.centerUsed, this.points, this.length, this.words);

  for (int v = 0; v < VERT_DIM; v++) {
      for (int h = 0; h < HORI_DIM; h++) {
    BoardCase boardCase = this.getCase(v, h).clone();
    board.setCase(v, h, boardCase);
      }
  }

  return board;
    }


    public Board transpose() {
  Board trans = Factory.FACTORY.createBoard();
  for (int v=0; v < VERT_DIM ; v++)
      for (int h=0; h < HORI_DIM; h++)
    trans.setCase(h, VERT_DIM-v, this.getCase(v, h).clone());
  return trans;
    }


    public boolean isFree(int h, int v) {
  return this.getCase(v, h).getState() == BoardCaseState.FREE;
    }


    public int countLetter(char c)
    {
  int amount = 0;

  for (int i = 0; i < HORI_DIM; i++)
      for (int j = 0; j < VERT_DIM; j++)
    if (!isFree(j, i) && (this.getCase(i, j).getLetter().getName() == c))
        amount++;

  return amount;
    }

    @Override
    public void changeEnvironment(GameEnvironment env) {
  this.dictionary = env.getDictionary();
    }
}
TOP

Related Classes of pdp.scrabble.game.impl.BoardImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.