package com.netbeetle.minesweeper; import java.util.Vector; /** * This class represents the minesweeper board. */ public class Board { private Cell[] cells; // the state of the board private int rows; // number of rows private int cols; // number of columns private int mines; // number of mines /** * Constructs a Board with the given number of rows and columns. * @param cols the number of columns. * @param rows the number of rows. * @param mines the number of mines. */ public Board(int cols, int rows, int mines) { cells = new Cell[cols * rows]; this.rows = rows; this.cols = cols; this.mines = mines; if (this.mines > rows * cols) this.mines = rows * cols; double probability = mines / (rows * cols); // set initial values for (int i = 0; i < mines && i < cells.length; i++) cells[i] = new Cell(true); for (int i = mines; i < cells.length; i++) cells[i] = new Cell(false); // scramble the board for (int i = cells.length - 1; i > 0; i--) { int random = (int) (Math.random() * (i + 1)); Cell temp = cells[random]; cells[random] = cells[i]; cells[i] = temp; } // set the cell neighbors int col; int row; int neighborCount; int rowAdjust; boolean left; boolean right; boolean top; boolean bottom; for (int i = 0; i < cells.length; i++) { neighborCount = 8; rowAdjust = 0; col = i % cols; row = i / cols; left = false; right = false; top = false; bottom = false; if (col == 0) { left = true; neighborCount -= 3; rowAdjust++; } if (col == cols - 1) { right = true; neighborCount -= 3; rowAdjust++; } if (row == 0) { top = true; neighborCount -= 3 - rowAdjust; } if (row == rows - 1) { bottom = true; neighborCount -= 3 - rowAdjust; } Cell[] neighbors = new Cell[neighborCount]; neighborCount = 0; if (!left && !top) { neighbors[neighborCount] = getCell(i - 1 - cols); neighborCount++; } if (!top) { neighbors[neighborCount] = getCell(i - cols); neighborCount++; } if (!right && !top) { neighbors[neighborCount] = getCell(i + 1 - cols); neighborCount++; } if (!left) { neighbors[neighborCount] = getCell(i - 1); neighborCount++; } if (!right) { neighbors[neighborCount] = getCell(i + 1); neighborCount++; } if (!left && !bottom) { neighbors[neighborCount] = getCell(i - 1 + cols); neighborCount++; } if (!bottom) { neighbors[neighborCount] = getCell(i + cols); neighborCount++; } if (!right && !bottom) { neighbors[neighborCount] = getCell(i + 1 + cols); } cells[i].setNeighbors(neighbors); } adjustNaiveProbabilities(); } public Cell getCell(int index) { if (index < 0 || index >= cells.length) return null; return cells[index]; } public void adjustProbabilities() { adjustNaiveProbabilities(); adjustKnownProbabilities(); } public void adjustNaiveProbabilities() { int minesUsed = 0; int cellsOpen = 0; for (int i = 0; i < cells.length; i++) { if (cells[i].isMine() || (cells[i].hasGuess() && cells[i].getGuess())) minesUsed++; else if (!cells[i].isKnown() && !cells[i].hasGuess()) cellsOpen++; } if (cellsOpen == 0) return; double probability = (double) (mines - minesUsed) / cellsOpen; for (int i = 0; i < cells.length; i++) { cells[i].setMineProbability(probability); } } public void adjustKnownProbabilities() { Vector cellsToChange = new Vector(); for (int i = 0; i < cells.length; i++) { if (!cells[i].isKnown() && cells[i].hasEmptyNeighbors() && !cells[i].hasGuess()) { cellsToChange.add(cells[i]); cells[i].setMineProbability(0); } } findSolutions(cellsToChange, 0); } public void findSolutions(Vector cellsToChange, int index) { if (index >= cellsToChange.size()) { useGuesses(cellsToChange); return; } Cell cell = (Cell) cellsToChange.get(index); cell.guess(true); if (cell.areNeighborsSatisfiable()) findSolutions(cellsToChange, index + 1); cell.guess(false); if (cell.areNeighborsSatisfiable()) findSolutions(cellsToChange, index + 1); cell.clearGuess(); } public void useGuesses(Vector cellsToChange) { for (int i = 0; i < cellsToChange.size(); i++) { Cell cell = (Cell) cellsToChange.get(i); cell.adjustMineProbability(cell.getGuess() ? 1 : 0); } } public void makeSureMoves() { for (int i = 0; i < cells.length; i++) { if (cells[i].isKnown() || cells[i].hasGuess()) continue; if (cells[i].getMineProbability() == 0) { cells[i].guess(false); cells[i].reveal(); } if (cells[i].getMineProbability() == 1) { cells[i].guess(true); } } } public void makeBestMove() { int best = -1; double bestProbability = 1; double probability; for (int i = 0; i < cells.length; i++) { if (cells[i].isKnown() || cells[i].hasGuess()) continue; probability = cells[i].getMineProbability(); if (probability < bestProbability) { bestProbability = probability; best = i; } } if (best == -1) return; cells[best].guess(false); cells[best].reveal(); } }