Introduce Model and ViewModel factories, Extract interfaces out of models
Replace some duplicated classnames with var keyword Fix a hierarchy violation in the view class
This commit is contained in:
parent
2cfa7130fc
commit
016d6db839
@ -1,7 +1,8 @@
|
||||
package de.icaotix.ultimatetictactoe;
|
||||
|
||||
import de.icaotix.ultimatetictactoe.model.ModelFactory;
|
||||
import de.icaotix.ultimatetictactoe.view.UltimateTicTacToeView;
|
||||
import de.icaotix.ultimatetictactoe.viewmodel.UltimateTicTacToePanelViewModel;
|
||||
import de.icaotix.ultimatetictactoe.viewmodel.ViewModelFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@ -9,7 +10,11 @@ public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
final UltimateTicTacToePanelViewModel ultimateTicTacToePanelViewModel = new UltimateTicTacToePanelViewModel();
|
||||
|
||||
ModelFactory modelFactory = new ModelFactory();
|
||||
ViewModelFactory viewModelFactory = new ViewModelFactory(modelFactory);
|
||||
|
||||
final var ultimateTicTacToePanelViewModel = viewModelFactory.getUltimateTicTacToePanelViewModel();
|
||||
new UltimateTicTacToeView(ultimateTicTacToePanelViewModel);
|
||||
ultimateTicTacToePanelViewModel.prepareNextMove();
|
||||
});
|
||||
|
@ -0,0 +1,18 @@
|
||||
package de.icaotix.ultimatetictactoe.model;
|
||||
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.CellState;
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.GameState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ITicTacToeGame {
|
||||
void setCellState(int cell, CellState state);
|
||||
|
||||
CellState[] getCells();
|
||||
|
||||
List<Integer> getAvailableFields();
|
||||
|
||||
boolean isFinished();
|
||||
|
||||
GameState getState();
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package de.icaotix.ultimatetictactoe.model;
|
||||
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.GameState;
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.Player;
|
||||
|
||||
public interface IUltimateTicTacToe {
|
||||
ITicTacToeGame getSubGame(int id);
|
||||
|
||||
int getActiveField();
|
||||
|
||||
Player getCurrentPlayer();
|
||||
|
||||
GameState getGameState();
|
||||
|
||||
void doPlayerMove(int cell);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package de.icaotix.ultimatetictactoe.model;
|
||||
|
||||
public class ModelFactory {
|
||||
|
||||
private final UltimateTicTacToe ultimateTicTacToe;
|
||||
|
||||
public ModelFactory() {
|
||||
this.ultimateTicTacToe = new UltimateTicTacToe();
|
||||
}
|
||||
|
||||
public IUltimateTicTacToe getUltimateTicTacToe() {
|
||||
return ultimateTicTacToe;
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package de.icaotix.ultimatetictactoe.model;
|
||||
|
||||
public enum Player {
|
||||
X,
|
||||
O
|
||||
}
|
@ -1,11 +1,14 @@
|
||||
package de.icaotix.ultimatetictactoe.model;
|
||||
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.CellState;
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.GameState;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class TicTacToeGame {
|
||||
public class TicTacToeGame implements ITicTacToeGame {
|
||||
|
||||
public static final Integer[][] winningCombinations = new Integer[][]{
|
||||
{0, 1, 2},
|
||||
@ -27,6 +30,22 @@ public class TicTacToeGame {
|
||||
this.state = GameState.RUNNING;
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
public static void printField(ITicTacToeGame game) {
|
||||
final var cells = game.getCells();
|
||||
System.out.println("--------------CURRENT STATE--------------");
|
||||
for (int i = 0; i < cells.length; i++) {
|
||||
System.out.print(cells[i] + " ");
|
||||
if ((i + 1) % 3 == 0) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
System.out.println("FREE: " + game.getAvailableFields());
|
||||
System.out.println("STATE: " + game.getState());
|
||||
System.out.println("IS FINISHED: " + game.isFinished());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCellState(int cell, CellState state) {
|
||||
if (this.state != GameState.RUNNING) return;
|
||||
if (this.cells[cell] == CellState.EMPTY) {
|
||||
@ -35,10 +54,12 @@ public class TicTacToeGame {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellState[] getCells() {
|
||||
return cells;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getAvailableFields() {
|
||||
final LinkedList<Integer> emptyFields = new LinkedList<>();
|
||||
for (int i = 0; i < this.cells.length; i++) {
|
||||
@ -49,17 +70,19 @@ public class TicTacToeGame {
|
||||
return emptyFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return this.state != GameState.RUNNING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
private void updateGameState() {
|
||||
for (Integer[] winningCombination : winningCombinations) {
|
||||
final HashSet<CellState> interestingStates = new HashSet<>();
|
||||
final var interestingStates = new HashSet<CellState>();
|
||||
interestingStates.add(this.cells[winningCombination[0]]);
|
||||
interestingStates.add(this.cells[winningCombination[1]]);
|
||||
interestingStates.add(this.cells[winningCombination[2]]);
|
||||
@ -77,19 +100,4 @@ public class TicTacToeGame {
|
||||
}
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
public static void printField(TicTacToeGame game) {
|
||||
final CellState[] cells = game.getCells();
|
||||
System.out.println("--------------CURRENT STATE--------------");
|
||||
for (int i = 0; i < cells.length; i++) {
|
||||
System.out.print(cells[i] + " ");
|
||||
if ((i + 1) % 3 == 0) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
System.out.println("FREE: " + game.getAvailableFields());
|
||||
System.out.println("STATE: " + game.getState());
|
||||
System.out.println("IS FINISHED: " + game.isFinished());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,18 +1,22 @@
|
||||
package de.icaotix.ultimatetictactoe.model;
|
||||
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.CellState;
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.GameState;
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class UltimateTicTacToe {
|
||||
public class UltimateTicTacToe implements IUltimateTicTacToe {
|
||||
|
||||
private final TicTacToeGame[] subGames;
|
||||
private final ITicTacToeGame[] subGames;
|
||||
private final GameState[] masterGameStates;
|
||||
private Player currentPlayer;
|
||||
private int activeField;
|
||||
private GameState gameState;
|
||||
|
||||
public UltimateTicTacToe() {
|
||||
this.subGames = new TicTacToeGame[9];
|
||||
this.subGames = new ITicTacToeGame[9];
|
||||
for (int i = 0; i < this.subGames.length; i++) {
|
||||
this.subGames[i] = new TicTacToeGame();
|
||||
}
|
||||
@ -25,26 +29,31 @@ public class UltimateTicTacToe {
|
||||
this.gameState = GameState.RUNNING;
|
||||
}
|
||||
|
||||
public TicTacToeGame getSubGame(int id) {
|
||||
@Override
|
||||
public ITicTacToeGame getSubGame(int id) {
|
||||
return this.subGames[id];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActiveField() {
|
||||
return activeField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getCurrentPlayer() {
|
||||
return this.currentPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameState getGameState() {
|
||||
return gameState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doPlayerMove(int cell) {
|
||||
if (!getSubGame(this.activeField).getAvailableFields().contains(cell)) return;
|
||||
|
||||
CellState nextCellState = this.currentPlayer == Player.X ? CellState.X : CellState.O;
|
||||
var nextCellState = this.currentPlayer == Player.X ? CellState.X : CellState.O;
|
||||
getSubGame(this.activeField).setCellState(cell, nextCellState);
|
||||
|
||||
this.masterGameStates[this.activeField] = getSubGame(this.activeField).getState();
|
||||
@ -60,7 +69,7 @@ public class UltimateTicTacToe {
|
||||
|
||||
private void updateGameState() {
|
||||
for (Integer[] winningCombination : TicTacToeGame.winningCombinations) {
|
||||
final HashSet<GameState> interestingStates = new HashSet<>();
|
||||
final var interestingStates = new HashSet<GameState>();
|
||||
interestingStates.add(this.masterGameStates[winningCombination[0]]);
|
||||
interestingStates.add(this.masterGameStates[winningCombination[1]]);
|
||||
interestingStates.add(this.masterGameStates[winningCombination[2]]);
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.icaotix.ultimatetictactoe.model;
|
||||
package de.icaotix.ultimatetictactoe.model.definitions;
|
||||
|
||||
public enum CellState {
|
||||
X("X"),
|
@ -1,4 +1,4 @@
|
||||
package de.icaotix.ultimatetictactoe.model;
|
||||
package de.icaotix.ultimatetictactoe.model.definitions;
|
||||
|
||||
public enum GameState {
|
||||
X_WON("X won"),
|
@ -0,0 +1,6 @@
|
||||
package de.icaotix.ultimatetictactoe.model.definitions;
|
||||
|
||||
public enum Player {
|
||||
X,
|
||||
O
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package de.icaotix.ultimatetictactoe.view;
|
||||
|
||||
import de.icaotix.ultimatetictactoe.model.Player;
|
||||
import de.icaotix.ultimatetictactoe.viewmodel.TicTacToePanelViewModel;
|
||||
import de.icaotix.ultimatetictactoe.viewmodel.UltimateTicTacToePanelViewModel;
|
||||
|
||||
@ -53,11 +52,7 @@ public class UltimateTicTacToeView extends JFrame {
|
||||
this.getContentPane().repaint();
|
||||
}
|
||||
|
||||
public void setCurrentPlayer(Player player) {
|
||||
if (player == Player.O) {
|
||||
this.currentPlayerLabel.setText("Current player: O");
|
||||
} else if (player == Player.X) {
|
||||
this.currentPlayerLabel.setText("Current player: X");
|
||||
}
|
||||
public void setCurrentPlayer(String playerText) {
|
||||
this.currentPlayerLabel.setText(playerText);
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,25 @@
|
||||
package de.icaotix.ultimatetictactoe.viewmodel;
|
||||
|
||||
|
||||
import de.icaotix.ultimatetictactoe.model.GameState;
|
||||
import de.icaotix.ultimatetictactoe.model.Player;
|
||||
import de.icaotix.ultimatetictactoe.model.TicTacToeGame;
|
||||
import de.icaotix.ultimatetictactoe.model.UltimateTicTacToe;
|
||||
import de.icaotix.ultimatetictactoe.model.IUltimateTicTacToe;
|
||||
import de.icaotix.ultimatetictactoe.model.ModelFactory;
|
||||
import de.icaotix.ultimatetictactoe.model.definitions.GameState;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class UltimateTicTacToePanelViewModel {
|
||||
|
||||
private final TicTacToePanelViewModel[] subGameViewModels;
|
||||
private final UltimateTicTacToe ultimateTicTacToe;
|
||||
private final IUltimateTicTacToe ultimateTicTacToe;
|
||||
private Consumer<String> gameResultCallback;
|
||||
private Consumer<Player> currentPlayerCallback;
|
||||
private Consumer<String> currentPlayerCallback;
|
||||
|
||||
public UltimateTicTacToePanelViewModel() {
|
||||
public UltimateTicTacToePanelViewModel(ModelFactory modelFactory, ViewModelFactory viewModelFactory) {
|
||||
this.subGameViewModels = new TicTacToePanelViewModel[9];
|
||||
for (int i = 0; i < this.subGameViewModels.length; i++) {
|
||||
this.subGameViewModels[i] = new TicTacToePanelViewModel(this);
|
||||
this.subGameViewModels[i] = viewModelFactory.getTicTacToePanelViewModel(this);
|
||||
}
|
||||
this.ultimateTicTacToe = new UltimateTicTacToe();
|
||||
this.ultimateTicTacToe = modelFactory.getUltimateTicTacToe();
|
||||
}
|
||||
|
||||
public void prepareNextMove() {
|
||||
@ -35,15 +33,16 @@ public class UltimateTicTacToePanelViewModel {
|
||||
}
|
||||
// Setup next move
|
||||
final int fieldId = this.ultimateTicTacToe.getActiveField();
|
||||
final List<Integer> availableFields = this.ultimateTicTacToe.getSubGame(fieldId).getAvailableFields();
|
||||
final var availableFields = this.ultimateTicTacToe.getSubGame(fieldId).getAvailableFields();
|
||||
this.subGameViewModels[fieldId].activate(availableFields);
|
||||
this.currentPlayerCallback.accept(this.ultimateTicTacToe.getCurrentPlayer());
|
||||
this.currentPlayerCallback.accept("Current player: "
|
||||
+ this.ultimateTicTacToe.getCurrentPlayer().name());
|
||||
}
|
||||
|
||||
public void onCellClicked(int cell) {
|
||||
final int oldActiveGameId = this.ultimateTicTacToe.getActiveField();
|
||||
final TicTacToePanelViewModel oldActiveGameViewModel = this.subGameViewModels[oldActiveGameId];
|
||||
final TicTacToeGame oldActiveGame = this.ultimateTicTacToe.getSubGame(oldActiveGameId);
|
||||
final var oldActiveGameViewModel = this.subGameViewModels[oldActiveGameId];
|
||||
final var oldActiveGame = this.ultimateTicTacToe.getSubGame(oldActiveGameId);
|
||||
oldActiveGameViewModel.deactivate();
|
||||
|
||||
this.ultimateTicTacToe.doPlayerMove(cell);
|
||||
@ -67,7 +66,7 @@ public class UltimateTicTacToePanelViewModel {
|
||||
this.gameResultCallback = gameResultCallback;
|
||||
}
|
||||
|
||||
public void setCurrentPlayerCallback(Consumer<Player> currentPlayerCallback) {
|
||||
public void setCurrentPlayerCallback(Consumer<String> currentPlayerCallback) {
|
||||
this.currentPlayerCallback = currentPlayerCallback;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package de.icaotix.ultimatetictactoe.viewmodel;
|
||||
|
||||
import de.icaotix.ultimatetictactoe.model.ModelFactory;
|
||||
|
||||
public class ViewModelFactory {
|
||||
|
||||
private final ModelFactory modelFactory;
|
||||
|
||||
public ViewModelFactory(ModelFactory modelFactory) {
|
||||
this.modelFactory = modelFactory;
|
||||
}
|
||||
|
||||
public UltimateTicTacToePanelViewModel getUltimateTicTacToePanelViewModel() {
|
||||
return new UltimateTicTacToePanelViewModel(this.modelFactory, this);
|
||||
}
|
||||
|
||||
public TicTacToePanelViewModel getTicTacToePanelViewModel(UltimateTicTacToePanelViewModel ultimateTicTacToePanelViewModel) {
|
||||
return new TicTacToePanelViewModel(ultimateTicTacToePanelViewModel);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user