Add a CLI entrypoint
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
package fr.uca.iut.clfreville2.morpion.cli;
|
||||
|
||||
import fr.uca.iut.clfreville2.morpion.game.*;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class AsciiBoardFormatter {
|
||||
|
||||
public void write(Board board, PrintStream stream) {
|
||||
for (int y = 0; y < board.height(); ++y) {
|
||||
stream.print("|");
|
||||
for (int x = 0; x < board.width(); ++x) {
|
||||
Tile tile = board.get(new Position(x, y));
|
||||
if (tile instanceof Placed placed) {
|
||||
stream.print(placed.x());
|
||||
} else {
|
||||
stream.print(' ');
|
||||
}
|
||||
stream.print("|");
|
||||
}
|
||||
stream.println();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
package fr.uca.iut.clfreville2.morpion.cli;
|
||||
|
||||
import fr.uca.iut.clfreville2.morpion.game.Game;
|
||||
import fr.uca.iut.clfreville2.morpion.game.Player;
|
||||
import fr.uca.iut.clfreville2.morpion.game.Position;
|
||||
import fr.uca.iut.clfreville2.morpion.win.CantPlace;
|
||||
import fr.uca.iut.clfreville2.morpion.win.MoveResult;
|
||||
|
||||
import java.util.InputMismatchException;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class CliPlay {
|
||||
|
||||
private Game game;
|
||||
private final Scanner scanner = new Scanner(System.in);
|
||||
|
||||
public void play() {
|
||||
System.out.print("Specify the number of players: ");
|
||||
final int playersCount = readInt();
|
||||
final List<Player> players = IntStream.rangeClosed(1, playersCount)
|
||||
.mapToObj(i -> new Player("Player" + i))
|
||||
.toList();
|
||||
game = new Game(players.toArray(Player[]::new));
|
||||
|
||||
final AsciiBoardFormatter formatter = new AsciiBoardFormatter();
|
||||
while (!isGameOver() && !game.board().isFull()) {
|
||||
formatter.write(game.board(), System.out);
|
||||
System.out.println("Player turn: " + game.currentPlayer().name());
|
||||
round();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isGameOver() {
|
||||
return game.players().stream().anyMatch(player -> player.score() > 0);
|
||||
}
|
||||
|
||||
private void round() {
|
||||
final Position pos = readPos();
|
||||
final MoveResult result = game.placeCurrent(pos);
|
||||
if (result instanceof CantPlace) {
|
||||
System.err.println("Tile already occupied!");
|
||||
round();
|
||||
}
|
||||
}
|
||||
|
||||
private Position readPos() {
|
||||
System.out.print("Indicate the coords (x, y) to play, separated by a whitespace: ");
|
||||
final int x = readInt();
|
||||
final int y = readInt();
|
||||
final Position pos = new Position(x, y);
|
||||
if (!game.board().isBound(pos)) {
|
||||
System.err.println("Out of bounds!");
|
||||
return readPos();
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private int readInt() {
|
||||
try {
|
||||
return scanner.nextInt();
|
||||
} catch (InputMismatchException ex) {
|
||||
System.err.println("Nah, it's not an int!");
|
||||
scanner.next();
|
||||
return readInt();
|
||||
}
|
||||
}
|
||||
}
|
10
src/main/java/fr/uca/iut/clfreville2/morpion/cli/Main.java
Normal file
10
src/main/java/fr/uca/iut/clfreville2/morpion/cli/Main.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package fr.uca.iut.clfreville2.morpion.cli;
|
||||
|
||||
public final class Main {
|
||||
|
||||
private Main() {}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new CliPlay().play();
|
||||
}
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
package fr.uca.iut.clfreville2.morpion.game;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Board {
|
||||
|
||||
private final int width, height;
|
||||
@@ -58,4 +60,8 @@ public class Board {
|
||||
public boolean isOutOfBound(Position relative) {
|
||||
return relative.x() < 0 || relative.y() < 0 || relative.x() >= width || relative.y() >= height;
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return Arrays.stream(tiles).allMatch(tile -> tile instanceof Placed);
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,13 @@
|
||||
package fr.uca.iut.clfreville2.morpion.game;
|
||||
|
||||
import fr.uca.iut.clfreville2.morpion.win.AlignmentWin;
|
||||
import fr.uca.iut.clfreville2.morpion.win.CantPlace;
|
||||
import fr.uca.iut.clfreville2.morpion.win.MoveResult;
|
||||
import fr.uca.iut.clfreville2.morpion.win.Result;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Game {
|
||||
|
||||
private boolean started;
|
||||
@@ -50,7 +55,10 @@ public class Game {
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
public Result placeCurrent(Position position) {
|
||||
public MoveResult placeCurrent(Position position) {
|
||||
if (board.isOccupied(position)) {
|
||||
return new CantPlace();
|
||||
}
|
||||
board.place(position, new Placed(switch (currentPlayer().name()) {
|
||||
case "Bob", "Blob" -> 'o';
|
||||
case "Cyril" -> 'p';
|
||||
@@ -87,4 +95,8 @@ public class Game {
|
||||
}
|
||||
player = playerB;*/
|
||||
}
|
||||
|
||||
public List<Player> players() {
|
||||
return Arrays.asList(players);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,4 @@
|
||||
package fr.uca.iut.clfreville2.morpion.win;
|
||||
|
||||
public record CantPlace() implements MoveResult {
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
package fr.uca.iut.clfreville2.morpion.win;
|
||||
|
||||
public sealed interface MoveResult permits CantPlace, Result {
|
||||
}
|
@@ -3,7 +3,7 @@ package fr.uca.iut.clfreville2.morpion.win;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public record Result(List<Win> wins) {
|
||||
public record Result(List<Win> wins) implements MoveResult {
|
||||
public Result(Win ...wins) {
|
||||
this(Arrays.asList(wins));
|
||||
}
|
||||
|
@@ -1,14 +1,12 @@
|
||||
package fr.uca.iut.clfreville2.morpion.game;
|
||||
|
||||
import fr.uca.iut.clfreville2.morpion.game.Board;
|
||||
import fr.uca.iut.clfreville2.morpion.game.Empty;
|
||||
import fr.uca.iut.clfreville2.morpion.game.Placed;
|
||||
import fr.uca.iut.clfreville2.morpion.game.Position;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
@@ -81,6 +79,38 @@ public class BoardTest {
|
||||
assertFalse(board.isBound(new Position(0, -1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isNotFull() {
|
||||
final Board board = new Board(2, 2);
|
||||
assertFalse(board.isFull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isNotVeryFull() {
|
||||
final Board board = new Board(2, 2);
|
||||
board.place(new Position(0, 1), new Placed('x'));
|
||||
assertFalse(board.isFull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isMaybeVeryFull() {
|
||||
final Random random = new Random();
|
||||
final Board board = new Board(2, 2);
|
||||
board.place(new Position(1, 1), new Placed('x'));
|
||||
board.place(new Position(random.nextInt(2), random.nextInt(2)), new Placed('x'));
|
||||
assertFalse(board.isFull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFull() {
|
||||
final Board board = new Board(2, 2);
|
||||
board.place(new Position(0, 0), new Placed('x'));
|
||||
board.place(new Position(1, 0), new Placed('p'));
|
||||
board.place(new Position(1, 1), new Placed('o'));
|
||||
board.place(new Position(0, 1), new Placed('o'));
|
||||
assertTrue(board.isFull());
|
||||
}
|
||||
|
||||
private static Stream<Arguments> provideAcceptSize() {
|
||||
return Stream.of(
|
||||
Arguments.of(0, 0),
|
||||
|
@@ -1,11 +1,14 @@
|
||||
package fr.uca.iut.clfreville2.morpion.game;
|
||||
|
||||
import fr.uca.iut.clfreville2.morpion.win.CantPlace;
|
||||
import fr.uca.iut.clfreville2.morpion.win.Result;
|
||||
import fr.uca.iut.clfreville2.morpion.win.Win;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class GameTest {
|
||||
@@ -134,4 +137,19 @@ public class GameTest {
|
||||
assertEquals(0, bob.score());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void exposePlayers() {
|
||||
final Player rami = new Player("Rami");
|
||||
final Player rami2 = new Player("Rami2");
|
||||
final Game game = new Game(rami, rami2);
|
||||
assertEquals(List.of(rami, rami2), game.players());
|
||||
}
|
||||
|
||||
@Test
|
||||
void cantPlaceTwoTimes() {
|
||||
final Game game = new Game(new Player("Alice"), new Player("Bob"));
|
||||
game.placeCurrent(new Position(0, 0));
|
||||
assertEquals(new CantPlace(), game.placeCurrent(new Position(0, 0)));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user