Refactored and optimized project + bugs fix

This commit is contained in:
Quentin Legot 2021-04-10 15:05:02 +02:00
parent 0546fa73bc
commit 43ab7ebfa7
13 changed files with 171 additions and 123 deletions

View File

@ -3,6 +3,7 @@ package battleship;
import battleship.model.Game; import battleship.model.Game;
import battleship.model.player.AbstractPlayer; import battleship.model.player.AbstractPlayer;
import battleship.model.player.Human; import battleship.model.player.Human;
import battleship.model.player.Player;
import battleship.model.player.Random; import battleship.model.player.Random;
import battleship.utils.Pair; import battleship.utils.Pair;
import battleship.view.AbstractView; import battleship.view.AbstractView;
@ -35,7 +36,7 @@ public class Main {
} }
private static void parseArgs(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { private static void parseArgs(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
AbstractPlayer[] players = new AbstractPlayer[2]; Player[] players = new AbstractPlayer[2];
ArrayList<Pair<String, Class<? extends AbstractPlayer>>> playerClass = new ArrayList<>(2); ArrayList<Pair<String, Class<? extends AbstractPlayer>>> playerClass = new ArrayList<>(2);
playerClass.add(new Pair<>("human", Human.class)); playerClass.add(new Pair<>("human", Human.class));
playerClass.add(new Pair<>("random", Random.class)); playerClass.add(new Pair<>("random", Random.class));

View File

@ -1,7 +0,0 @@
package battleship.model;
// TODO: 10/04/2021
public class Board {
}

View File

@ -1,19 +1,16 @@
package battleship.model; package battleship.model;
import battleship.model.player.AbstractPlayer;
import battleship.model.player.Player; import battleship.model.player.Player;
import battleship.utils.Pair; import battleship.utils.Pair;
import battleship.utils.Triplet; import battleship.utils.Triplet;
import battleship.view.AbstractView; import battleship.view.AbstractView;
import java.util.Random;
public class Game { public class Game {
public Player[] players; public Player[] players;
public Player currentPlayer; public Player currentPlayer;
public Game(AbstractPlayer[] players) { public Game(Player[] players) {
this.players = players; this.players = players;
this.currentPlayer = players[0]; this.currentPlayer = players[0];
players[0].setId(1); players[0].setId(1);
@ -35,17 +32,17 @@ public class Game {
public void checkDrownedShips(){ public void checkDrownedShips(){
Player otherPlayer = getOtherPlayer(); Player otherPlayer = getOtherPlayer();
for(Ship ship : currentPlayer.ships){ for(Ship ship : otherPlayer.getShips()){
if(!ship.isDrown()) if(!ship.isDrown())
otherPlayer.updateIsDrown(ship); ship.updateIsDrown(currentPlayer);
} }
} }
public Player getWinner(){ public Player getWinner(){
Ship remainingShip = players[0].ships.parallelStream().filter(ship -> !ship.isDrown()).findFirst().orElse(null); Ship remainingShip = players[0].getShips().parallelStream().filter(ship -> !ship.isDrown()).findFirst().orElse(null);
if(remainingShip == null) if(remainingShip == null)
return players[1]; return players[1];
remainingShip = players[1].ships.parallelStream().filter(ship -> !ship.isDrown()).findFirst().orElse(null); remainingShip = players[1].getShips().parallelStream().filter(ship -> !ship.isDrown()).findFirst().orElse(null);
if(remainingShip == null) if(remainingShip == null)
return players[1]; return players[1];
return null; return null;
@ -54,13 +51,15 @@ public class Game {
public void move(Pair<Integer,Integer> move){ public void move(Pair<Integer,Integer> move){
boolean bool = false; boolean bool = false;
Player otherPlayer = getOtherPlayer(); Player otherPlayer = getOtherPlayer();
for (Ship ship : otherPlayer.ships) { for (Ship ship : otherPlayer.getShips()) {
for(Pair<Integer,Integer> pair : ship.getCoordsArray()){ for(Pair<Integer,Integer> coords : ship.getFullCoords()){
if ((pair.getRight().equals(move.getRight())) && (pair.getLeft().equals(move.getLeft()))) { if ((coords.getRight().equals(move.getRight())) && (coords.getLeft().equals(move.getLeft()))) {
bool = true; bool = true;
break; break;
} }
} }
if(bool)
break;
} }
currentPlayer.addMove(new Triplet<>(move, bool)); currentPlayer.addMove(new Triplet<>(move, bool));
} }
@ -70,24 +69,14 @@ public class Game {
view.setShips(players[1]); view.setShips(players[1]);
Player winner = null; Player winner = null;
while(winner == null) { while(winner == null) {
System.out.println("Au tour du joueur " + currentPlayer.getId());
view.displayBoard(); view.displayBoard();
move(currentPlayer.chooseMove()); move(view.chooseMove(currentPlayer));
changeCurrentPlayer();
checkDrownedShips(); checkDrownedShips();
changeCurrentPlayer();
winner = getWinner(); winner = getWinner();
} }
view.displayWinner(winner); view.displayWinner(winner);
} }
public void placeShipRandomly(Player player) {
Random rand = new Random();
for(int i : player.ShipSize) {
Ship ship = new Ship(new Pair<>(-1, -1), i, Direction.DEFAULT);
while(!player.setShips(ship)) {
ship = new Ship(new Pair<>(rand.nextInt(10), rand.nextInt(10)), i, Direction.values()[rand.nextInt(Direction.values().length)]);
}
}
}
} }

View File

@ -1,33 +1,41 @@
package battleship.model; package battleship.model;
import battleship.model.player.Player;
import battleship.utils.Pair; import battleship.utils.Pair;
import battleship.utils.Triplet;
import java.util.Arrays;
public class Ship { public class Ship {
private Pair<Integer, Integer> coords; private Pair<Integer, Integer> coords;
private final int size; private final int size;
Pair<Integer,Integer>[] fullCoords;
private Direction direction; // (0,-1) bas // (0,1) haut // (1,0) droite // (-1,0) gauche private Direction direction; // (0,-1) bas // (0,1) haut // (1,0) droite // (-1,0) gauche
private boolean isDrown; private boolean isDrown;
public Ship(Pair<Integer, Integer> coords, int size, Direction direction) { public Ship(Pair<Integer, Integer> coords, int size, Direction direction) {
this.coords = coords; this.coords = coords;
this.size = size; this.size = size;
this.fullCoords = new Pair[this.size];
this.direction = direction; this.direction = direction;
isDrown = false; isDrown = false;
recalculateFullCoords();
} }
public void setDirection(Direction d){ public void setDirection(Direction d){
this.direction = d; this.direction = d;
} }
public void setCoords(Pair<Integer,Integer> c){ public void setCoords(Pair<Integer,Integer> c){
this.coords = c; this.coords = c;
} }
public void setDrown(){ public void setDrown(){
isDrown = true; isDrown = true;
} }
public Boolean isDrown(){ public boolean isDrown(){
return isDrown; return isDrown;
} }
@ -43,21 +51,33 @@ public class Ship {
return this.coords; return this.coords;
} }
@SuppressWarnings("unchecked") public void recalculateFullCoords() {
public Pair<Integer, Integer>[] getCoordsArray(){ for(int i = 0; i < size; ++i){
Pair<Integer,Integer>[] tab = new Pair[size]; fullCoords[i] = new Pair<>(coords.getLeft() + i * direction.getDirection().getLeft(),coords.getRight() + i * direction.getDirection().getRight());
for(int i = 0; i<size;i++){
for(int y = 0;y<size;y++){
tab[i] = new Pair<>(coords.getLeft()+i* direction.getDirection().getLeft(),coords.getRight()+i * direction.getDirection().getRight());
}
} }
return tab; }
public Pair<Integer, Integer>[] getFullCoords(){
return fullCoords;
} }
@Override @Override
public String toString() { public String toString() {
return super.toString() + ", coords=" + coords.toString() + ", size=" + size + ", direction=" + direction.toString(); return super.toString() + ", coords=" + coords.toString() + ", size=" + size + ", direction=" + direction.toString();
} }
public void updateIsDrown(Player player) {
int cpt = 0;
for(Pair<Integer, Integer> coords : getFullCoords()) {
for(Triplet<Integer,Integer,Boolean> move : player.getMoves()) {
if(move.getRight() && move.getLeft().equals(coords.getLeft()) && move.getMiddle().equals(coords.getRight())){
++cpt;
break;
}
}
}
if(cpt == getSize()) {
setDrown();
}
}
} }

View File

@ -9,22 +9,19 @@ import java.util.ArrayList;
public abstract class AbstractPlayer implements Player { public abstract class AbstractPlayer implements Player {
ArrayList<Ship> ships = new ArrayList<>();
ArrayList<Triplet<Integer,Integer,Boolean>> moves = new ArrayList<>();
public int id; public int id;
public boolean setShips(Ship ship) { public boolean setShips(Ship ship) {
if(ship.getDirection() == Direction.DEFAULT) if(ship.getDirection() == Direction.DEFAULT)
return false; return false;
for(int i = 0; i < ship.getSize(); i++){ for(Pair<Integer, Integer> coords : ship.getFullCoords()) {
int x = ship.getCoords().getLeft() + i * ship.getDirection().getDirection().getLeft(); if(coords.getLeft() > 9 || coords.getLeft() < 0 || coords.getRight() > 9 || coords.getRight() < 0)
int y = ship.getCoords().getRight()+ i * ship.getDirection().getDirection().getRight();
if(x > 9 || x < 0 || y > 9 || y < 0)
return false; return false;
for(Ship ship1 : this.ships) { for(Ship ship1 : this.ships) {
for (int j = 0; j < ship1.getSize(); j++) { for (Pair<Integer, Integer> coords1 : ship1.getFullCoords()) {
int x1 = ship1.getCoords().getLeft() + i * ship1.getDirection().getDirection().getLeft(); if (coords1.getLeft().equals(coords.getLeft()) && coords1.getRight().equals(coords.getRight()))
int y1 = ship1.getCoords().getRight() + i * ship1.getDirection().getDirection().getRight();
if (x1 == x && y1 == y)
return false; return false;
} }
} }
@ -43,22 +40,6 @@ public abstract class AbstractPlayer implements Player {
return this; return this;
} }
public void updateIsDrown(Ship ship) {
int cpt = 0;
for(Triplet<Integer,Integer,Boolean> move : moves){
for(int i = 1; i <= ship.getSize(); i++){
int x = ship.getCoords().getLeft() + i * ship.getDirection().getDirection().getLeft();
int y = ship.getCoords().getRight()+ i * ship.getDirection().getDirection().getRight();
if(move.getLeft() == x && move.getMiddle() == y){
cpt += 1;
break;
}
}
}
if(cpt == ship.getSize())
ship.setDrown();
}
public ArrayList<Pair<Integer,Integer>> validMoves() { public ArrayList<Pair<Integer,Integer>> validMoves() {
ArrayList<Pair<Integer,Integer>> validMovesList = new ArrayList<>(); ArrayList<Pair<Integer,Integer>> validMovesList = new ArrayList<>();
for(int x = 0; x < 10; x++){ for(int x = 0; x < 10; x++){
@ -72,6 +53,18 @@ public abstract class AbstractPlayer implements Player {
return validMovesList; return validMovesList;
} }
public boolean areValid(int x, int y){
if(x <0 || x >10 || y <0 || y >10)
return false;
for(Triplet<Integer,Integer,Boolean> move : moves){
if((move.getLeft() == x) && (move.getMiddle() == y) )
return false;
}
return true;
}
@Override
public void setId(int i) { public void setId(int i) {
id = i; id = i;
} }
@ -79,4 +72,19 @@ public abstract class AbstractPlayer implements Player {
public int getId() { public int getId() {
return id; return id;
} }
@Override
public String toString() {
return getClass().getSimpleName() + " " + id;
}
@Override
public ArrayList<Ship> getShips() {
return ships;
}
@Override
public ArrayList<Triplet<Integer,Integer,Boolean>> getMoves() {
return moves;
}
} }

View File

@ -0,0 +1,23 @@
package battleship.model.player;
import battleship.model.Direction;
import battleship.model.Ship;
import battleship.utils.Pair;
import java.util.Random;
public abstract class Computer extends AbstractPlayer {
public void placeShipRandomly() {
java.util.Random rand = new Random();
for(int i : shipSize) {
Ship ship = new Ship(new Pair<>(-1, -1), i, Direction.DEFAULT);
while(!setShips(ship)) {
ship.setCoords(new Pair<>(rand.nextInt(10), rand.nextInt(10)));
ship.setDirection(Direction.values()[rand.nextInt(Direction.values().length)]);
ship.recalculateFullCoords();
}
}
}
}

View File

@ -1,40 +1,15 @@
package battleship.model.player; package battleship.model.player;
import battleship.utils.Pair; import battleship.utils.Pair;
import battleship.utils.Triplet;
import battleship.view.Terminal;
import java.util.Scanner;
public class Human extends AbstractPlayer { public class Human extends AbstractPlayer {
@Override @Override
public Pair<Integer,Integer> chooseMove() { public Pair<Integer,Integer> chooseMove() {
int x = -1, y = -1; return null;
Scanner scanner = Terminal.scanner;
while(!areValid(x,y)) {
System.out.println("Veuillez indiquer la coordonée x de votre coup");
x = scanner.nextInt();
System.out.println("Veuillez indiquer la coordonée y de votre coup");
y = scanner.nextInt();
}
return new Pair<>(x,y);
} }
public boolean areValid(int x, int y){
if(x <0 || x >10 || y <0 || y >10)
return false;
for(Triplet<Integer,Integer,Boolean> move : moves){
if((move.getLeft() == x) && (move.getMiddle() == y) )
return false;
}
return true;
}
@Override @Override
public String toString(){ public void placeShips() {}
return "Human " +id;
}
} }

View File

@ -8,9 +8,7 @@ import java.util.ArrayList;
public interface Player { public interface Player {
ArrayList<Ship> ships = new ArrayList<>(); int[] shipSize = { 5, 4, 3, 3, 2 };
ArrayList<Triplet<Integer,Integer,Boolean>> moves = new ArrayList<>();
int[] ShipSize = { 5, 4, 3, 3, 2};
Pair<Integer,Integer> chooseMove(); Pair<Integer,Integer> chooseMove();
@ -18,11 +16,18 @@ public interface Player {
int getId(); int getId();
void updateIsDrown(Ship ship);
Player addMove(Triplet<Integer,Integer,Boolean> move); Player addMove(Triplet<Integer,Integer,Boolean> move);
void setId(int i);
ArrayList<Pair<Integer,Integer>> validMoves();
void placeShips();
boolean areValid(int x, int y);
ArrayList<Ship> getShips();
ArrayList<Triplet<Integer,Integer,Boolean>> getMoves();
} }

View File

@ -2,15 +2,17 @@ package battleship.model.player;
import battleship.utils.Pair; import battleship.utils.Pair;
public class Random extends AbstractPlayer { public class Random extends Computer {
@Override @Override
public Pair<Integer,Integer> chooseMove() { public Pair<Integer,Integer> chooseMove() {
java.util.Random rand = new java.util.Random(); java.util.Random rand = new java.util.Random();
return validMoves().get(rand.nextInt(validMoves().size())); return validMoves().get(rand.nextInt(validMoves().size()));
} }
@Override @Override
public String toString(){ public void placeShips() {
return "Random " +id; placeShipRandomly();
} }
} }

View File

@ -23,8 +23,8 @@ public abstract class AbstractView implements View{
String chain = ""; String chain = "";
for(int u = 0; u < 2; ++u) { for(int u = 0; u < 2; ++u) {
Player player = game.players[u]; Player player = game.players[u];
ArrayList<Ship> ships = game.players[u].ships; ArrayList<Ship> ships = game.players[u].getShips();
chain += "Player " + (u + 1) + " :\n"; chain += "Joueur " + player.getId() + " :\n";
chain += "+ - - - - - - - - - - +\n"; chain += "+ - - - - - - - - - - +\n";
for(int x = 0; x < 10; ++x) { for(int x = 0; x < 10; ++x) {
chain += "|"; chain += "|";
@ -63,24 +63,16 @@ public abstract class AbstractView implements View{
} }
private boolean isShipPosition(Ship ship, Pair<Integer, Integer> boardsCoords) { private boolean isShipPosition(Ship ship, Pair<Integer, Integer> boardsCoords) {
if(ship.getCoords().equals(boardsCoords)) for(Pair<Integer, Integer> coords : ship.getFullCoords()) {
return true; if(boardsCoords.equals(coords))
for(int a = 0; a < ship.getSize(); ++a) {
if(new Pair<>(ship.getCoords().getLeft() + a * ship.getDirection().getDirection().getLeft(), ship.getCoords().getRight() + a * ship.getDirection().getDirection().getRight()).equals(boardsCoords)) {
return true; return true;
}
} }
return false; return false;
} }
@Override
private int isPositionDrowned(Player other, Pair<Integer, Integer> pair) { public void setShips(Player player) {
for(Triplet<Integer, Integer, Boolean> move : other.moves) { player.placeShips();
if(pair.getLeft().equals(move.getLeft()) && pair.getRight().equals(move.getMiddle())) {
return 2;
}
}
return 0;
} }
/** /**
@ -95,4 +87,18 @@ public abstract class AbstractView implements View{
return 1; return 1;
return isPositionDrowned(other, pair); return isPositionDrowned(other, pair);
} }
private int isPositionDrowned(Player other, Pair<Integer, Integer> pair) {
for(Triplet<Integer, Integer, Boolean> move : other.getMoves()) {
if(pair.getLeft().equals(move.getLeft()) && pair.getRight().equals(move.getMiddle())) {
return 2;
}
}
return 0;
}
@Override
public Pair<Integer, Integer> chooseMove(Player player) {
return player.chooseMove();
}
} }

View File

@ -50,14 +50,13 @@ public class Terminal extends AbstractView {
} }
} }
} }
ship.recalculateFullCoords();
} }
} }
} else { } else {
// Random super.setShips(player);
game.placeShipRandomly(player); // Computer
} }
} }
@Override @Override
@ -65,8 +64,25 @@ public class Terminal extends AbstractView {
System.out.println(toString()); System.out.println(toString());
} }
@Override
public Pair<Integer, Integer> chooseMove(Player player) {
if(player instanceof Human) {
int x = -1, y = -1;
while(!player.areValid(x, y)) {
System.out.println("Veuillez indiquer la coordonée x de votre coup");
x = scanner.nextInt();
System.out.println("Veuillez indiquer la coordonée y de votre coup");
y = scanner.nextInt();
}
return new Pair<>(x,y);
}
return super.chooseMove(player);
}
@Override @Override
public void displayWinner(Player winner) { public void displayWinner(Player winner) {
displayBoard();
System.out.println("Le joueur " + winner.getId() + " a gagné"); System.out.println("Le joueur " + winner.getId() + " a gagné");
} }

View File

@ -1,6 +1,7 @@
package battleship.view; package battleship.view;
import battleship.model.player.Player; import battleship.model.player.Player;
import battleship.utils.Pair;
public interface View { public interface View {
@ -10,5 +11,7 @@ public interface View {
void displayBoard(); void displayBoard();
Pair<Integer,Integer> chooseMove(Player player);
void displayWinner(Player winner); void displayWinner(Player winner);
} }

View File

@ -2,13 +2,14 @@ package battleship.view;
import battleship.model.Game; import battleship.model.Game;
import battleship.model.player.Player; import battleship.model.player.Player;
import battleship.utils.Pair;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
public class Window extends AbstractView { public class Window extends AbstractView {
private JFrame frame; private final JFrame frame;
private final int height = 600; private final int height = 600;
private final int width = 1200; private final int width = 1200;
@ -33,6 +34,12 @@ public class Window extends AbstractView {
frame.paintComponents(frame.getGraphics()); frame.paintComponents(frame.getGraphics());
} }
@Override
public Pair<Integer, Integer> chooseMove(Player player) {
return null;
}
@Override @Override
public void displayWinner(Player winner) { public void displayWinner(Player winner) {
// TODO: 07/04/2021 afficher un dialog // TODO: 07/04/2021 afficher un dialog