Files
Prog_1/Reversi/ReversiController.java
Felix Steghofer 3db4f94e6a init
2022-12-04 01:25:28 +01:00

237 lines
6.5 KiB
Java

package reversi.controller;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Stack;
import javax.swing.JComboBox;
import reversi.model.Board;
import reversi.model.Field;
import reversi.model.IllegalMoveException;
import reversi.model.Player;
import reversi.model.Reversi;
import reversi.view.ReversiField;
import reversi.view.ReversiView;
/**
* Controller has an instance of the board and handles the
* mouse and keyboard actions. Updates the gui if playBoard changes.
*/
public class ReversiController {
private Player human = new Player(true);
private Player bot = new Player(false);
private Reversi model;
private ReversiView view;
private MachineMoveThread machineMoveThread;
/**
* Stack for UndoMove method.
*/
private Stack<Reversi> pastMoves;
/**
* Create the model and the view.
*/
public ReversiController() {
this.model = new Reversi(human, bot, human);
this.view = new ReversiView();
addListener();
this.view.updatePlayField(this.model);
createStack();
}
/**
* View the gui.
*/
public final void showView() {
this.view.setVisible(true);
}
/**
* Opens a new reversi game.
*
* @param firstPlayer Player that starts
* @return new reversi board
*/
private Reversi newGame(Player firstPlayer) {
stopMachineMoveThread();
createStack();
Reversi model = new Reversi(this.human, this.bot, firstPlayer);
model.setLevel(this.view.getLevel());
if (firstPlayer == bot) {
performMachineMove(model);
} else {
this.view.updatePlayField(model);
this.view.setMovePossible(true);
}
return model;
}
/**
* Add all Listener in the gui.
*/
private void addListener() {
setPlayFieldListeners();
this.view.setNewGameListener(new NewGameListener());
this.view.setSwitchLevelListener(new SwitchLevelListener());
this.view.setSwitchGameListener(new SwitchGameListener());
this.view.setUndoMoveListener(new UndoMoveListener());
this.view.setQuitGameListener(new QuitGameListener());
}
/**
* Set the MouseListener for each PlayField.
*/
private void setPlayFieldListeners() {
for (int row = 0; row < Board.SIZE; row++) {
for (int col = 0; col < Board.SIZE; col++) {
this.view.setPlayFieldListener(
new FieldListener(), new Field(row, col));
}
}
}
/**
* Init Stack and disable Undo Button.
*/
private void createStack() {
this.pastMoves = new Stack<Reversi>();
view.setUndoButtonVisible(false);
}
/**
* Return to the state of the board before the last human and bot move.
*/
private void undoMove() {
stopMachineMoveThread();
this.model = pastMoves.pop();
this.view.updatePlayField(this.model);
if (pastMoves.isEmpty()) {
this.view.setUndoButtonVisible(false);
} else {
this.view.setMovePossible(true);
}
}
private void performMachineMove(Reversi model) {
this.view.setMovePossible(false);
machineMoveThread = new MachineMoveThread(model, this.view);
machineMoveThread.start();
}
private void performHumanMove(Field field) {
pastMoves.push(model.clone());
view.setUndoButtonVisible(true);
if (model.move(field.row(), field.col())) {
if (model.next() == human && !model.gameOver()) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public final void run() {
view.viewMessage("The bot has to miss a turn");
}
});
}
} else {
undoMove();
}
view.updatePlayField(model);
if (model.next() == bot) {
performMachineMove(model);
}
}
@SuppressWarnings("deprecation")
private void stopMachineMoveThread() {
if (machineMoveThread != null) {
machineMoveThread.stop();
}
}
/**
* Inner class FieldListener performs a move on click and starts the
* machine move. After every move, game over check is done.
*/
private class FieldListener extends MouseAdapter {
@Override
public void mousePressed(final MouseEvent event) {
if (!view.getMovePossible()) {
new IllegalMoveException("Machine Move is active");
return;
}
Field field = ((ReversiField) event.getComponent()).getField();
performHumanMove(field);
}
}
/**
* Create Listener for the level switch combobox.
*/
private class SwitchLevelListener implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
@SuppressWarnings("unchecked")
JComboBox<Integer> level = (JComboBox<Integer>) e.getSource();
model.setLevel((Integer) level.getSelectedItem());
}
}
/**
* Create Listener for the new game button.
*/
private class NewGameListener implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
model = newGame(model.getFirstPlayer());
}
}
/**
* Create Listener for the switch game button.
*/
private class SwitchGameListener implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
if (model.getFirstPlayer() == human) {
model = newGame(bot);
} else {
model = newGame(human);
}
}
}
/**
* Create Listener for the undo move button.
*/
private class UndoMoveListener implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
undoMove();
}
}
/**
* Create Listener for the quit game button.
*/
private class QuitGameListener implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
for (Frame frame : java.awt.Frame.getFrames()) {
frame.dispose();
}
stopMachineMoveThread();
}
}
}