| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Set;
- import java.util.stream.Collectors;
-
- final class MinesweeperBoard {
-
- private static final char MINE_CHAR = '*';
-
- private static final char SPACE_CHAR = ' ';
-
- private final List<String> rawRepresentation;
-
- private final int numberOfRows;
-
- private final int numberOfColumns;
-
- MinesweeperBoard(final List<String> rawRepresentation) {
- validateInputBoard(rawRepresentation);
- this.rawRepresentation = rawRepresentation;
- this.numberOfRows = rawRepresentation.size();
- this.numberOfColumns = rawRepresentation.isEmpty() ? 0 : rawRepresentation.get(0).length();
- }
-
- List<String> getAnnotatedRepresentation() throws IllegalArgumentException {
- final List<String> result = new ArrayList<>();
-
- for (int rowNumber = 0; rowNumber < numberOfRows; rowNumber++) {
- result.add(getAnnotatedRow(rowNumber));
- }
-
- return result;
- }
-
- private String getAnnotatedRow(final int rowNumber) {
- String result = "";
-
- for (int columnNumber = 0; columnNumber < numberOfColumns; columnNumber++) {
- result += getCellAnnotation(rowNumber, columnNumber);
- }
-
- return result;
- }
-
- private char getCellAnnotation(final int rowNumber, final int columnNumber) {
- // If (rowNumber, columnNumber) is a mine, we're done.
- if (rawRepresentation.get(rowNumber).charAt(columnNumber) == MINE_CHAR) {
- return MINE_CHAR;
- }
-
- final int mineCount = computeMineCountAround(rowNumber, columnNumber);
-
- // If computed count is positive, add it to the annotated row. Otherwise, add a blank space.
- return mineCount > 0 ? Character.forDigit(mineCount, 10) : SPACE_CHAR;
- }
-
- private int computeMineCountAround(final int rowNumber, final int columnNumber) {
- int result = 0;
-
- // Compute row and column ranges to inspect (respecting board edges).
- final int minRowToInspect = Math.max(rowNumber - 1, 0);
- final int maxRowToInspect = Math.min(rowNumber + 1, numberOfRows - 1);
- final int minColToInspect = Math.max(columnNumber - 1, 0);
- final int maxColToInspect = Math.min(columnNumber + 1, numberOfColumns - 1);
-
- // Count mines in the cells surrounding (row, col).
- for (int rowToInspect = minRowToInspect; rowToInspect <= maxRowToInspect; rowToInspect++) {
- for (int colToInspect = minColToInspect; colToInspect <= maxColToInspect; colToInspect++) {
- if (rawRepresentation.get(rowToInspect).charAt(colToInspect) == MINE_CHAR) {
- result += 1;
- }
- }
- }
-
- return result;
- }
-
- private void validateInputBoard(final List<String> inputBoard) throws IllegalArgumentException {
- validateInputBoardIsNotNull(inputBoard);
-
- if (inputBoard.isEmpty()) {
- return;
- }
-
- validateInputBoardCharacters(inputBoard);
- validateInputBoardColumnCounts(inputBoard);
- }
-
- private void validateInputBoardIsNotNull(final List<String> inputBoard) throws IllegalArgumentException {
- if (inputBoard == null) {
- throw new IllegalArgumentException("Input board may not be null.");
- }
- }
-
- private void validateInputBoardCharacters(final List<String> inputBoard) throws IllegalArgumentException {
- final String allBoardCharacters = String.join("", inputBoard);
-
- if (!allBoardCharacters.matches("^[ *]*$")) {
- throw new IllegalArgumentException("Input board can only contain the characters ' ' and '*'.");
- }
- }
-
- private void validateInputBoardColumnCounts(final List<String> inputBoard) throws IllegalArgumentException {
- final Set<Integer> setOfColumnCounts = inputBoard.stream().map(String::length).collect(Collectors.toSet());
-
- if (setOfColumnCounts.size() > 1) {
- throw new IllegalArgumentException("Input board rows must all have the same number of columns.");
- }
- }
-
- }
|