Add a CLI entrypoint
continuous-integration/drone/push Build is passing Details

main
Clément FRÉVILLE 2 years ago
parent dfc82796ac
commit 6cf730d056

@ -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();
}
}
}

@ -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)));
}
}

Loading…
Cancel
Save