Package minesweeper.ai.games

Source Code of minesweeper.ai.games.BoardInfoHelper

package minesweeper.ai.games;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import minesweeper.ai.games.BoardConfiguration.Cell;
import minesweeper.ai.games.BoardConfiguration.Position;

/**
* This is a class that contains utility methods that help an AI easily get
* important information from a GameState
*
*/
public class BoardInfoHelper {
 
  private BoardConfiguration board;
 
  public BoardInfoHelper(BoardConfiguration board) {
    this.board = board;
  }
 
  /**
   * Returns a list of cells adjacent to the given position that has the given value
   * @param p The position of the cell
   * @param cellValue The cell value (ex. Cell.UNKNOWN or Cell.FLAG)
   * @return a list of Positions adjacent to the given position of cells that have the given value
   * @see GameState.Position
   */
  public List<Position> getAdjacentCellsByValue(Position p, int cellValue) {
        return getAdjacentCellsByValue(p.row, p.col, cellValue);
  }
 
  public List<Position> getAdjacentCells(Position p) {
        return getAdjacentCells(p.row,p.col);
  }
 
  public List<Position> getAdjacentCellsWithAdjacentBombs(Position p) {
        return getAdjacentCellsWithAdjacentBombs(p.row,p.col);
  }
 
  /**
   * Returns a list of cells adjacent to the given position that has the given value
   * @param row The row number of the cell
   * @param col The column number of the cell
   * @param cellValue The cell value (ex. Cell.UNKNOWN or Cell.FLAG)
   * @return a list of Positions adjacent to the given (row,col) of cells that have the given value
   * @see GameState.Position
   */
  public List<Position> getAdjacentCellsByValue(int row, int col, int cellValue) {
        return getAdjacentCells(row, col).stream().
                          filter(p->board.getCell(p)==cellValue).
                          collect(Collectors.toList());
  }
 
  public List<Position> getAdjacentCells(int row, int col) {
        List<Position> ans = new ArrayList<Position>();
        if(inBounds(row-1,col-1)) ans.add(Position.valueOf(row-1,col-1));
        if(inBounds(row-1,col)) ans.add(Position.valueOf(row-1,col));
        if(inBounds(row-1,col+1)) ans.add(Position.valueOf(row-1,col+1));
        if(inBounds(row,col-1)) ans.add(Position.valueOf(row,col-1));
        if(inBounds(row,col+1)) ans.add(Position.valueOf(row,col+1));
        if(inBounds(row+1,col-1)) ans.add(Position.valueOf(row+1,col-1));
        if(inBounds(row+1,col)) ans.add(Position.valueOf(row+1,col));
        if(inBounds(row+1,col+1)) ans.add(Position.valueOf(row+1,col+1));
        return ans;
  }
 
  /**
   * Returns a list of cell positions from the board that have the given board
   * @param cellValue The cell value (ex. Cell.UNKNOWN or Cell.FLAG)
   * @return a list of Positions of cells that have the given value
   */
  public List<Position> getCellsByValue(int cellValue) {
    return enumeratePositions().stream().
        filter(p->board.getCell(p) == cellValue).
        collect(Collectors.toList());
  }
 
  /**
   * Returns a list of cell positions from the board that have a positive value
   * @return a list of Positions of cells that have a value of 1,2,...,8
   */
  public List<Position> getCellsWithAdjacentBombs() {
    return enumeratePositions().stream().
                  filter(p->board.getCell(p) >= 1).
                  collect(Collectors.toList());
  }
 
  public List<Position> getAdjacentCellsWithAdjacentBombs(int row, int col) {
        return getAdjacentCells(row, col).stream()
                         .filter(p->board.getCell(p) > 0)
                         .collect(Collectors.toList());
  }
 
  /**
   * Returns cells that haven't been picked or flagged yet that are
   * bordering a cell that has been picked and has a positive value
   * @return a list of Positions of cells that are unknown border cells
   */
  public List<Position> getUnknownBorderCells() {
    Set<Position> ans = new HashSet<>();
    for(Position p : getCellsWithAdjacentBombs())
      ans.addAll(getAdjacentCellsByValue(p.row,p.col,Cell.UNKNOWN));
    List<Position> result = new ArrayList<>(ans);
    Collections.sort(result, (p1,p2) -> ((p1.row-p2.row)*board.getCols()+p1.col-p2.col));
    return result;
  }
  /**
   * Returns a list of Positions of cells that are unknown border
   * cells and that are all part of the same closed off region
   * @return
   */
  public List<List<Position>> getClosedUnknownBorderCells() {
    return partition(getUnknownBorderCells());
  }
 
  /**
   * @return A copy of the board as a 2 dimensional array of cells (ints)
   */
  public MutableBoard getBoard() {
    int[][] ans = new int[board.getRows()][board.getCols()];
    enumeratePositions().stream().forEach(p -> ans[p.row][p.col]=board.getCell(p));
    return new MutableBoard(ans, board.getBombs());
  }
 
  public boolean validate(int row, int col) {
    for(Position p : getAdjacentCellsWithAdjacentBombs(row, col)) {
      List<Position> unknown = getAdjacentCellsByValue(p, Cell.UNKNOWN);
      List<Position> flags = getAdjacentCellsByValue(p, Cell.FLAG);
      int cellValue = board.getCell(p);
      if(flags.size() > cellValue || cellValue > flags.size()+unknown.size())
        return false;
    }
    return true;
  }
 
  public boolean validateAll() {
    for(Position p : getCellsWithAdjacentBombs()) {
      int u = getAdjacentCellsByValue(p, Cell.UNKNOWN).size();
      int f = getAdjacentCellsByValue(p, Cell.FLAG).size();
      int c = board.getCell(p);
      if(f > c || u + f < c) return false;
    }
    return true;
  }
 
  public boolean validate(Position p) {
    return validate(p.row, p.col);
  }
 
  private boolean inBounds(int r, int c) {
    return r < board.getRows() && c < board.getCols() && r >= 0 && c >= 0;
  }
 
  public List<Position> enumeratePositions() {
    List<Position> result = new ArrayList<>();
    for(int r=0; r<board.getRows(); r++)
      for(int c=0; c<board.getCols(); c++)
        result.add(Position.valueOf(r,c));
    return result;
  }
 
    private boolean isAdjacent(Position p1, Position p2) {
        return Math.abs(p1.row-p2.row) <= 1 && Math.abs(p1.col-p2.col) <= 1;
    }
   
   
    /** Jacek's Code */

  private boolean sharesElement(List<Position> a, List<Position> b) {
        for (Position c : a)
            for (Position d : b)
                if (isAdjacent(c,d)) return true
          return false;
  }
 
  private List<List<Position>> partition(List<Position> input) {
    List<Position> data = new ArrayList<Position>(input);
    List<List<Position>> output = new ArrayList<List<Position>>();

    while (data.size() > 0) {
      Position first = data.get(0);
      List<Position> toadd = new ArrayList<Position>();
      output.add(toadd);

      Iterator<Position> it = data.iterator();

      while (it.hasNext()) {
        Position current = it.next();
        if (isAdjacent(first, current)) {
          it.remove();
          toadd.add(current);
        }
      }
    }

    boolean changeMade = true;
    while (changeMade) {

      changeMade = false;

      for (int i = 0; i < output.size(); i++) {

        List<Position> first = output.get(i);

        for (int j = 0; j < output.size(); j++) {
          if (i != j && sharesElement(first, output.get(j))) {
            changeMade = true;
            first.addAll(output.get(j));
            output.remove(j);
            if (i > j)
              i--;
            j--;
          }
        }

      }

    }

    for (List<Position> result : output) {
      Collections
          .sort(result,
              (p1, p2) -> ((p1.row - p2.row) * board.getCols()
                  + p1.col - p2.col));
    }

    Collections.sort(output, (a1, a2) -> a1.size() - a2.size());

    return output;

  }
}
TOP

Related Classes of minesweeper.ai.games.BoardInfoHelper

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.