237 lines
6.5 KiB
Java
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();
|
|
}
|
|
}
|
|
} |