ajout doc modele

This commit is contained in:
Hugo DIMITRIJEVIC 2024-04-03 20:54:46 +02:00
parent 18e84de927
commit 47fe1a7d47

View File

@ -7,30 +7,62 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
/**
* {@code GameModel} is a class that represents the state of the game.
*
* @autor Alexeï Kadir, Lyanis Souidi, Hugo Dimitrijevic
* @version 1.0
*/
public class GameModel { public class GameModel {
/**
* The {@code Map} of {@code Cell}s to the {@code Set} of {@code Line}s that
* intersect them.
*/
private final Map<Cell, Set<Line>> cells; private final Map<Cell, Set<Line>> cells;
/**
* The {@code Set} of {@code Line}s that have been drawn.
*/
private final Set<Line> lines; private final Set<Line> lines;
/**
* The size of the initial cross.
*/
private int size; private int size;
/**
* Whether the game is in hard mode. In hard mode, {@code Line}s cannot extend
* each other.
*/
private boolean hardMode; private boolean hardMode;
/**
* The number of unique valid {@code Line}s that can be drawn.
*/
private int validLineCount; private int validLineCount;
/**
* The start of the {@code Line} being drawn. If this is {@code null}, no
* {@code Line} is
* being drawn.
*/
private Cell inputLineStart; private Cell inputLineStart;
/**
* The end of the {@code Line} being drawn. If this is {@code null}, no
* {@code Line} is
* being drawn.
*/
private Cell inputLineEnd; private Cell inputLineEnd;
/**
* Constructs a new {@code GameModel} with the specified size, and whether the
* game is in
* hard mode.
*
* @param size The size of the initial cross.
* @param hardMode Whether the game is in hard mode.
*/
public GameModel(int size, boolean hardMode) { public GameModel(int size, boolean hardMode) {
this.cells = new HashMap<Cell, Set<Line>>(); this.cells = new HashMap<Cell, Set<Line>>();
this.lines = new HashSet<Line>(); this.lines = new HashSet<Line>();
@ -40,7 +72,14 @@ public class GameModel {
this.hardMode = hardMode; this.hardMode = hardMode;
} }
/**
* Resets the grid, and initializes a new game with a cross of the specified
* size. This call does not recount the number of valid {@code Line}s that can
* be
* drawn.
*
* @param size The size of the initial cross.
*/
private void resetGrid(int size) { private void resetGrid(int size) {
if ((size + 2) % 3 != 0) if ((size + 2) % 3 != 0)
throw new IllegalArgumentException("Invalid size."); throw new IllegalArgumentException("Invalid size.");
@ -66,7 +105,14 @@ public class GameModel {
this.fillCells(side * 2 - 2, side * 2 - 2, 1, side); this.fillCells(side * 2 - 2, side * 2 - 2, 1, side);
} }
/**
* Recounts the number of valid {@code Line}s that can be drawn. This call
* iterates over all
* {@code Cell}s in the grid, and finds all unique valid {@code Line}s that
* intersect them. This call is expensive, and should be used sparingly. The
* line count is updated when lines are added by the user, so this call is only
* necessary when the grid is reset.
*/
private void recountValidLines() { private void recountValidLines() {
this.validLineCount = 0; this.validLineCount = 0;
@ -78,29 +124,55 @@ public class GameModel {
this.validLineCount = validLines.size(); this.validLineCount = validLines.size();
} }
/**
* Returns the number of unique valid {@code Line}s that can be drawn.
*
* @return The number of unique valid {@code Line}s that can be drawn.
*/
public int getValidLineCount() { public int getValidLineCount() {
return this.validLineCount; return this.validLineCount;
} }
/**
* Returns whether the game is finished. The game is finished when all valid
* {@code Line}s have been drawn.
*
* @return {@code true} if the game is finished, {@code false} otherwise.
*/
public boolean isGameFinished() { public boolean isGameFinished() {
return this.validLineCount == 0; return this.validLineCount == 0;
} }
/**
* Returns the score of the game. The score is the number of {@code Line}s that
* have been drawn.
*
* @return The score of the game.
*/
public int getScore() { public int getScore() {
return this.lines.size(); return this.lines.size();
} }
/**
* Resets the grid, and initializes a new game with a cross of the specified
* size.
*
* @param size The size of the initial cross.
*/
public void reset(int size) { public void reset(int size) {
this.resetGrid(size); this.resetGrid(size);
this.recountValidLines(); this.recountValidLines();
} }
/**
* Resets the grid, and initializes a new game with a cross of the specified
* size, and the specified set of {@code Line}s. These {@code Line}s are added
* without checking for validity.
*
* @param size The size of the initial cross.
* @param lines The set of {@code Line}s to add to the grid.
*/
public void reset(int size, Set<Line> lines) { public void reset(int size, Set<Line> lines) {
this.resetGrid(size); this.resetGrid(size);
@ -119,12 +191,20 @@ public class GameModel {
this.recountValidLines(); this.recountValidLines();
} }
/**
* Returns the size of the cross.
*
* @return The size of the cross.
*/
public int getSize() { public int getSize() {
return this.size; return this.size;
} }
/**
* Returns a copy of the {@code Set} of {@code Cell}s in the grid.
*
* @return A copy of the {@code Set} of {@code Cell}s in the grid.
*/
public Set<Cell> getCells() { public Set<Cell> getCells() {
Set<Cell> cells = new HashSet<Cell>(); Set<Cell> cells = new HashSet<Cell>();
@ -134,7 +214,11 @@ public class GameModel {
return cells; return cells;
} }
/**
* Returns a copy of the {@code Set} of {@code Line}s that have been drawn.
*
* @return A copy of the {@code Set} of {@code Line}s that have been drawn.
*/
public Set<Line> getLines() { public Set<Line> getLines() {
Set<Line> lines = new HashSet<Line>(); Set<Line> lines = new HashSet<Line>();
@ -144,13 +228,23 @@ public class GameModel {
return lines; return lines;
} }
/**
* Starts drawing a {@code Line} at the specified {@code Cell}.
*
* @param start The {@code Cell} where the {@code Line} starts.
*/
public void startInputLine(Cell start) { public void startInputLine(Cell start) {
this.inputLineStart = new Cell(start); this.inputLineStart = new Cell(start);
this.inputLineEnd = new Cell(start); this.inputLineEnd = new Cell(start);
} }
/**
* Moves the end of the {@code Line} being drawn to the specified {@code Cell}.
*
* @param end The {@code Cell} where the {@code Line} ends.
* @return {@code true} if the end of the {@code Line} was moved, {@code false}
* otherwise.
*/
public boolean moveInputLineEnd(Cell end) { public boolean moveInputLineEnd(Cell end) {
if (this.inputLineStart == null) if (this.inputLineStart == null)
return false; return false;
@ -162,7 +256,15 @@ public class GameModel {
return changed; return changed;
} }
/**
* Ends drawing a {@code Line} at the specified {@code Cell}. If the
* {@code Line}
* is valid, it is added to the grid, and the {@code Cell}s it intersects are
* updated. If the {@code Line} is not valid, it is discarded. The number of
* unique valid {@code Line}s that can be drawn is updated as well.
*
* @param end The {@code Cell} where the {@code Line} ends.
*/
public void endInputLine(Cell end) { public void endInputLine(Cell end) {
if (this.inputLineStart == null) if (this.inputLineStart == null)
return; return;
@ -205,27 +307,54 @@ public class GameModel {
this.inputLineEnd = null; this.inputLineEnd = null;
} }
/**
* Returns whether a {@code Line} is being drawn.
*
* @return {@code true} if a {@code Line} is being drawn, {@code false}
* otherwise.
*/
public boolean hasInputLine() { public boolean hasInputLine() {
return this.inputLineStart != null; return this.inputLineStart != null;
} }
/**
* Returns whether the {@code Line} being drawn is valid.
*
* @return {@code true} if the {@code Line} being drawn is valid, {@code false}
* otherwise.
*/
public boolean isInputLineValid() { public boolean isInputLineValid() {
return this.isLineValid(this.inputLineStart, this.inputLineEnd); return this.isLineValid(this.inputLineStart, this.inputLineEnd);
} }
/**
* Returns the {@code Cell} where the {@code Line} being drawn starts.
*
* @return The {@code Cell} where the {@code Line} being drawn starts.
*/
public Cell getInputLineStart() { public Cell getInputLineStart() {
return new Cell(this.inputLineStart); return new Cell(this.inputLineStart);
} }
/**
* Returns the {@code Cell} where the {@code Line} being drawn ends.
*
* @return The {@code Cell} where the {@code Line} being drawn ends.
*/
public Cell getInputLineEnd() { public Cell getInputLineEnd() {
return new Cell(this.inputLineEnd); return new Cell(this.inputLineEnd);
} }
/**
* Returns whether the {@code Line} between the specified {@code Cell}s is
* valid. A {@code Line} is valid if it is horizontal, vertical, or diagonal,
* and intersects exactly four {@code Cell}s. In hard mode, {@code Line}s
* cannot extend each other.
*
* @param start The {@code Cell} where the {@code Line} starts.
* @param end The {@code Cell} where the {@code Line} ends.
* @return {@code true} if the {@code Line} is valid, {@code false} otherwise.
*/
public boolean isLineValid(Cell start, Cell end) { public boolean isLineValid(Cell start, Cell end) {
if (!Line.isValid(start, end)) if (!Line.isValid(start, end))
return false; return false;
@ -266,7 +395,14 @@ public class GameModel {
return true; return true;
} }
/**
* Finds all unique valid {@code Line}s that intersect the specified
* {@code Cell},
* and adds them to the specified {@code Set}.
*
* @param cell The {@code Cell} to check for intersections.
* @param lines The {@code Set} to add the valid {@code Line}s to.
*/
private void findValidLines(Cell cell, Set<Line> lines) { private void findValidLines(Cell cell, Set<Line> lines) {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
Cell start = new Cell(cell.x - 4 + i, cell.y); Cell start = new Cell(cell.x - 4 + i, cell.y);
@ -295,19 +431,35 @@ public class GameModel {
} }
} }
/**
* Fills the specified rectangle of {@code Cell}s.
*
* @param x The x-coordinate of the top-left corner of the rectangle.
* @param y The y-coordinate of the top-left corner of the rectangle.
* @param w The width of the rectangle.
* @param h The height of the rectangle.
*/
private void fillCells(int x, int y, int w, int h) { private void fillCells(int x, int y, int w, int h) {
for (int dx = 0; dx < w; dx++) for (int dx = 0; dx < w; dx++)
for (int dy = 0; dy < h; dy++) for (int dy = 0; dy < h; dy++)
this.placeCell(x + dx, y + dy); this.placeCell(x + dx, y + dy);
} }
/**
* Places a {@code Cell} in the grid.
*
* @param x The x-coordinate of the {@code Cell}.
* @param y The y-coordinate of the {@code Cell}.
*/
private void placeCell(int x, int y) { private void placeCell(int x, int y) {
this.placeCell(new Cell(x, y)); this.placeCell(new Cell(x, y));
} }
/**
* Places a {@code Cell} in the grid.
*
* @param cell The {@code Cell} to place.
*/
private void placeCell(Cell cell) { private void placeCell(Cell cell) {
if (this.cells.containsKey(cell)) if (this.cells.containsKey(cell))
return; return;