diff --git a/app/src/main/java/fr/iutfbleau/sae/GameModel.java b/app/src/main/java/fr/iutfbleau/sae/GameModel.java new file mode 100644 index 0000000..b007479 --- /dev/null +++ b/app/src/main/java/fr/iutfbleau/sae/GameModel.java @@ -0,0 +1,317 @@ +package fr.iutfbleau.sae; + +import android.widget.TextView; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + + +public class GameModel { + + private final Map> cells; + + + private final Set lines; + + + private int size; + + + private boolean hardMode; + + + private int validLineCount; + + + private Cell inputLineStart; + + + private Cell inputLineEnd; + + + public GameModel(int size, boolean hardMode) { + this.cells = new HashMap>(); + this.lines = new HashSet(); + + this.reset(size); + + this.hardMode = hardMode; + } + + + private void resetGrid(int size) { + if ((size + 2) % 3 != 0) + throw new IllegalArgumentException("Invalid size."); + + this.size = size; + + this.cells.clear(); + this.lines.clear(); + + int side = (this.size + 2) / 3; + + this.fillCells(0, side - 1, side, 1); + this.fillCells(0, side - 1, 1, side); + this.fillCells(side - 1, 0, side, 1); + this.fillCells(side - 1, 0, 1, side); + this.fillCells(side * 2 - 2, 0, 1, side); + this.fillCells(side * 2 - 2, side - 1, side, 1); + this.fillCells(0, side * 2 - 2, side, 1); + this.fillCells(side * 3 - 3, side - 1, 1, side); + this.fillCells(side - 1, side * 3 - 3, side, 1); + this.fillCells(side - 1, side * 2 - 2, 1, side); + this.fillCells(side * 2 - 2, side * 2 - 2, side, 1); + this.fillCells(side * 2 - 2, side * 2 - 2, 1, side); + } + + + private void recountValidLines() { + this.validLineCount = 0; + + Set validLines = new HashSet(); + + for (Cell cell : this.cells.keySet()) + this.findValidLines(cell, validLines); + + this.validLineCount = validLines.size(); + } + + + public int getValidLineCount() { + return this.validLineCount; + } + + + public boolean isGameFinished() { + return this.validLineCount == 0; + } + + + public int getScore() { + return this.lines.size(); + } + + + public void reset(int size) { + this.resetGrid(size); + + this.recountValidLines(); + } + + + public void reset(int size, Set lines) { + this.resetGrid(size); + + for (Line line : lines) { + for (Cell cell : line) { + this.placeCell(cell); + + Set hits = this.cells.get(cell); + if (hits != null) + hits.add(line); + } + + this.lines.add(new Line(line)); + } + + this.recountValidLines(); + } + + + public int getSize() { + return this.size; + } + + + public Set getCells() { + Set cells = new HashSet(); + + for (Cell cell : this.cells.keySet()) + cells.add(new Cell(cell)); + + return cells; + } + + + public Set getLines() { + Set lines = new HashSet(); + + for (Line line : this.lines) + lines.add(new Line(line)); + + return lines; + } + + + public void startInputLine(Cell start) { + this.inputLineStart = new Cell(start); + this.inputLineEnd = new Cell(start); + } + + + public boolean moveInputLineEnd(Cell end) { + if (this.inputLineStart == null) + return false; + + boolean changed = !this.inputLineEnd.equals(end); + + this.inputLineEnd = new Cell(end); + + return changed; + } + + + public void endInputLine(Cell end) { + if (this.inputLineStart == null) + return; + + this.inputLineEnd = new Cell(end); + + if (!this.isLineValid(this.inputLineStart, this.inputLineEnd)) { + this.inputLineStart = null; + this.inputLineEnd = null; + return; + } + + Line line = new Line(this.inputLineStart, this.inputLineEnd); + + Set validLines = new HashSet(); + for (Cell cell : line) + this.findValidLines(cell, validLines); + + int startValidLineCount = validLines.size(); + + for (Cell cell : line) { + this.placeCell(cell); + + Set hits = this.cells.get(cell); + if (hits != null) + hits.add(line); + } + + this.lines.add(line); + + validLines.clear(); + for (Cell cell : line) + this.findValidLines(cell, validLines); + + int endValidLineCount = validLines.size(); + + this.validLineCount += endValidLineCount - startValidLineCount; + + this.inputLineStart = null; + this.inputLineEnd = null; + } + + + public boolean hasInputLine() { + return this.inputLineStart != null; + } + + + public boolean isInputLineValid() { + return this.isLineValid(this.inputLineStart, this.inputLineEnd); + } + + + public Cell getInputLineStart() { + return new Cell(this.inputLineStart); + } + + + public Cell getInputLineEnd() { + return new Cell(this.inputLineEnd); + } + + + public boolean isLineValid(Cell start, Cell end) { + if (!Line.isValid(start, end)) + return false; + + Line line = new Line(start, end); + + int count = 0; + + for (Cell cell : line) + if (this.cells.containsKey(cell)) + count++; + + if (count != 4) + return false; + + Set intersections = new HashSet(); + + for (Cell cell : line) { + Set lines = this.cells.get(cell); + + if (lines == null) + continue; + + for (Line hit : lines) + if (intersections.contains(hit)) + return false; + + intersections.addAll(lines); + } + + if (!hardMode) + return true; + + for (Line intersection : intersections) + if (intersection.extendsLine(line)) + return false; + + return true; + } + + + private void findValidLines(Cell cell, Set lines) { + for (int i = 0; i < 5; i++) { + Cell start = new Cell(cell.x - 4 + i, cell.y); + Cell end = new Cell(cell.x + i, cell.y); + + if (this.isLineValid(start, end)) + lines.add(new Line(start, end)); + + start = new Cell(cell.x - 4 + i, cell.y - 4 + i); + end = new Cell(cell.x + i, cell.y + i); + + if (this.isLineValid(start, end)) + lines.add(new Line(start, end)); + + start = new Cell(cell.x - 4 + i, cell.y + 4 - i); + end = new Cell(cell.x + i, cell.y - i); + + if (this.isLineValid(start, end)) + lines.add(new Line(start, end)); + + start = new Cell(cell.x, cell.y - 4 + i); + end = new Cell(cell.x, cell.y + i); + + if (this.isLineValid(start, end)) + lines.add(new Line(start, end)); + } + } + + + private void fillCells(int x, int y, int w, int h) { + for (int dx = 0; dx < w; dx++) + for (int dy = 0; dy < h; dy++) + this.placeCell(x + dx, y + dy); + } + + + private void placeCell(int x, int y) { + this.placeCell(new Cell(x, y)); + } + + + private void placeCell(Cell cell) { + if (this.cells.containsKey(cell)) + return; + + this.cells.put(cell, new HashSet()); + } +} \ No newline at end of file