package de.lunarakai.minecleaner.game; import java.util.ArrayList; import org.joml.Vector2i; import de.lunarakai.minecleaner.MinecleanerPlugin; public class Game { public boolean gameover; private MinecleanerPlugin plugin; private int width; private int height; private int mineCount; private Cell[][] state; private Board board; private Tilemap tilemap; private ArrayList floodedCells; private int floodedFlaggedCellsCounter; private ArrayList explodedCells; public Game(MinecleanerPlugin plugin, int width, int mineCount) { this.plugin = plugin; this.width = width; this.height = width; this.mineCount = mineCount; this.floodedCells = new ArrayList<>(); this.explodedCells = new ArrayList<>(); floodedFlaggedCellsCounter = 0; } public void start() { board = new Board(); newGame(); } private void newGame() { state = new Cell[width][height]; Tile[][] tile = new Tile[width][height]; tilemap = new Tilemap(tile); gameover = false; generateCells(); //generateMines(); //generateNumbers(); board.draw(state, tilemap); } public void firstClick(int xFirst, int yFirst) { generateMines(xFirst, yFirst); generateNumbers(); } private void generateCells() { for (int x = 0; x < width; x ++) { for (int y = 0; y < height; y++) { Cell cell = new Cell(); cell.position = new Vector2i(x, y); cell.setType(Cell.CellType.Empty); state[x][y] = cell; } } } // Todo selten auch noch mine bei xFirst-1 private void generateMines(int xFirst, int yFirst) { for (int i = 0; i < mineCount; i++) { int x = (int) (Math.random() * width); int y = (int) (Math.random() * height); if(x == xFirst && y == yFirst) { i--; continue; } if(x == xFirst +1 && y == yFirst) { i--; continue; } if(x == xFirst -1 && y == yFirst) { i--; continue; } if(x == xFirst && y == yFirst +1) { i--; continue; } if(x == xFirst && y == yFirst -1) { i--; continue; } //Corners if(x == xFirst +1 && y == yFirst +1) { i--; continue; } if(x == xFirst +1 && y == yFirst -1) { i--; continue; } if(x == xFirst -1 && y == yFirst -1) { i--; continue; } if(x == xFirst -1 && y == yFirst +1) { i--; continue; } if (state[x][y].type == Cell.CellType.Mine) { i--; continue; } state[x][y].setType(Cell.CellType.Mine); } } private void generateNumbers() { for(int x = 0; x < width; x++) { for(int y = 0; y < height; y++) { Cell cell = state[x][y]; if(cell.getType() == Cell.CellType.Mine) { continue; } cell.number = countMines(x, y); if(cell.number > 0) { cell.setType(Cell.CellType.Number); } state[x][y] = cell; } } } public Tilemap getMinecleanerTilemap() { return tilemap; } private int countMines(int cellX, int cellY) { int count = 0; for (int adjacentX = -1; adjacentX <= 1; adjacentX++){ for (int adjacentY = -1; adjacentY <= 1; adjacentY++) { if(adjacentX == 0 && adjacentY == 0) { continue; } int x = cellX + adjacentX; int y = cellY + adjacentY; if (getCell(x,y).getType() == Cell.CellType.Mine) { count++; } } } return count; } public void flag(int x, int y) { Cell cell = getCell(x, y); if (cell.getType() == Cell.CellType.Invalid || cell.isRevealed()) { return; } cell.flagged = !cell.isFlagged(); state[x][y] = cell; board.draw(state, tilemap); } public void reveal(int x, int y) { Cell cell = getCell(x, y); if(cell.getType() == Cell.CellType.Invalid || cell.isRevealed() || cell.flagged) { return; } switch (cell.getType()) { case Mine: { explode(cell); break; } case Empty: { if(!floodedCells.isEmpty()) { floodedCells.clear(); } resetFloodedFlaggedCellCounter(); flood(cell); checkWinCondition(); break; } default: { resetFloodedFlaggedCellCounter(); cell.setRevealed(); state[x][y] = cell; checkWinCondition(); break; } } board.draw(state, tilemap); } private void resetFloodedFlaggedCellCounter() { if(floodedFlaggedCellsCounter > 0) { floodedFlaggedCellsCounter = 0; } } public void flood(Cell cell) { if(cell.isRevealed()) return; if(cell.getType() == Cell.CellType.Mine || cell.getType() == Cell.CellType.Invalid || cell.position == null) return; if(cell.isFlagged()) { cell.setFlaggedState(false); floodedFlaggedCellsCounter = floodedFlaggedCellsCounter + 1; } cell.setRevealed(); floodedCells.add(cell); state[cell.position.x][cell.position.y] = cell; if(cell.getType() == Cell.CellType.Empty) { if(isValid(cell.position.x -1, cell.position.y)) { flood(getCell(cell.position.x -1, cell.position.y)); } if(isValid(cell.position.x +1, cell.position.y)) { flood(getCell(cell.position.x +1, cell.position.y)); } if(isValid(cell.position.x, cell.position.y -1)) { flood(getCell(cell.position.x, cell.position.y -1)); } if(isValid(cell.position.x, cell.position.y +1)) { flood(getCell(cell.position.x, cell.position.y +1)); } // Corners if(isValid(cell.position.x + 1, cell.position.y +1)) { flood(getCell(cell.position.x +1, cell.position.y +1)); } if(isValid(cell.position.x + 1, cell.position.y -1)) { flood(getCell(cell.position.x +1, cell.position.y -1)); } if(isValid(cell.position.x - 1, cell.position.y +1)) { flood(getCell(cell.position.x -1, cell.position.y +1)); } if(isValid(cell.position.x - 1, cell.position.y - 1)) { flood(getCell(cell.position.x -1, cell.position.y -1)); } } } private void explode(Cell cell) { gameover = true; cell.revealed = true; cell.exploded = true; state[cell.position.x][cell.position.y] = cell; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { cell = state[x][y]; if(cell.getType() == Cell.CellType.Mine) { cell.revealed = true; state[x][y] = cell; explodedCells.add(cell); } } } } public void checkWinCondition() { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Cell cell = state[x][y]; if(cell.getType() != Cell.CellType.Mine && !cell.revealed) { return; } } } gameover = true; for(int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Cell cell = state[x][y]; if(cell.getType() == Cell.CellType.Mine) { cell.flagged = true; state[x][y] = cell; } } } } public Cell getCell(int x, int y) { if(isValid(x,y)) { return state[x][y]; } else { return new Cell(); } } private boolean isValid(int x, int y) { return x >= 0 && x < width && y >= 0 && y < height; } public ArrayList getfloodedCells() { return floodedCells; } public ArrayList getExplodedCells() { return explodedCells; } public int getFloodedFlaggedCells() { return floodedFlaggedCellsCounter; } }