Created
February 19, 2019 10:59
-
-
Save marvk/bd97e5e9540b8c9df3598cd0edb83f3c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.marvk.nuthello.game; | |
import javafx.beans.property.SimpleListProperty; | |
import javafx.collections.FXCollections; | |
import net.marvk.nuthello.player.Player; | |
import net.marvk.nuthello.player.PlayerFactory; | |
import java.util.List; | |
import java.util.NoSuchElementException; | |
import java.util.Optional; | |
public final class Game { | |
private final int sideLength; | |
private final PlayerFactory blackFactory; | |
private final Player black; | |
private final PlayerFactory whiteFactory; | |
private final Player white; | |
private Move lastMove; | |
private final SimpleListProperty<Move> history; | |
private Disc turn; | |
private GameResult result; | |
public Game(final int sideLength, final PlayerFactory blackFactory, final PlayerFactory whiteFactory) { | |
this.sideLength = sideLength; | |
this.lastMove = Move.of(Board.initialConfiguration(sideLength), null); | |
this.blackFactory = blackFactory; | |
this.whiteFactory = whiteFactory; | |
this.black = blackFactory.newInstance(Disc.BLACK); | |
this.white = whiteFactory.newInstance(Disc.WHITE); | |
this.turn = Disc.BLACK; | |
this.history = new SimpleListProperty<>(FXCollections.observableArrayList()); | |
history.add(lastMove); | |
} | |
public PlayerFactory getPlayerFactory(final Disc disc) { | |
return disc == Disc.BLACK ? blackFactory : whiteFactory; | |
} | |
private Player getPlayer(final Disc disc) { | |
return disc == Disc.BLACK ? black : white; | |
} | |
public Board getBoard() { | |
return lastMove.getBoard(); | |
} | |
public Optional<GameResult> getResult() { | |
return Optional.ofNullable(result); | |
} | |
public int getNumberOfDiscs(final Disc disc) { | |
return getBoard().discCount(disc); | |
} | |
public SimpleListProperty<Move> getHistory() { | |
return history; | |
} | |
public synchronized boolean hasNextMove() { | |
return result == null; | |
} | |
/** | |
* @return the board after the next move has been executed | |
* | |
* @throws NoSuchElementException if the game is finished ({@link Game#hasNextMove()} returns {@code false}) and no further move can be made | |
*/ | |
public synchronized Move nextMove() { | |
if (!hasNextMove()) { | |
throw new NoSuchElementException("can not perform next move, game has ended"); | |
} | |
final List<Move> validMoves = getBoard().getValidMoves(turn); | |
final Player player = getPlayer(turn); | |
final Point play = player.play(lastMove); | |
final Optional<Board> potentialNewBoard = validMoves.stream() | |
.filter(move -> move.getPoint().equals(play)) | |
.findAny() | |
.map(Move::getBoard); | |
if (potentialNewBoard.isPresent()) { | |
lastMove = Move.of(potentialNewBoard.get(), play); | |
history.add(lastMove); | |
turn = turn.opponent(); | |
final Optional<GameResult> gameResult = getBoard().findGameResult(blackFactory, whiteFactory); | |
gameResult.ifPresent(result -> this.result = result); | |
} else { | |
System.err.println(turn + " tried to play invalid move: " + play); | |
result = new GameResult( | |
getBoard().discCount(Disc.BLACK), | |
getBoard().discCount(Disc.WHITE), | |
blackFactory, | |
whiteFactory, | |
turn.opponent(), | |
getBoard(), | |
EndCondition.INVALID_PLAY | |
); | |
} | |
return lastMove; | |
} | |
public int getSideLength() { | |
return sideLength; | |
} | |
public Disc getTurn() { | |
return turn; | |
} | |
@Override | |
public String toString() { | |
return getBoard().toString(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment