Incremental updates. Work in progress to augment Board, Referee, add score for computer player, implement Monte-Carlo simulation.
Renamed Player implementations and changed Player to interface, with the goal of using abstraction to make the human and computer interactions with the game identical for ease of simulation.
This commit is contained in:
@@ -5,17 +5,19 @@ import java.awt.event.MouseListener;
|
|||||||
import java.awt.event.MouseWheelEvent;
|
import java.awt.event.MouseWheelEvent;
|
||||||
import java.awt.event.MouseWheelListener;
|
import java.awt.event.MouseWheelListener;
|
||||||
|
|
||||||
|
import model.HumanPlayer;
|
||||||
|
|
||||||
import view.BoardPanel;
|
import view.BoardPanel;
|
||||||
import view.Tile;
|
import view.Tile;
|
||||||
import view.TileSelectionPanel;
|
import view.TileSelectionPanel;
|
||||||
|
|
||||||
public class BoardPanelMouseListener implements MouseListener, MouseWheelListener {
|
public class BoardPanelMouseListener implements MouseListener, MouseWheelListener {
|
||||||
private final BoardPanel boardPanel;
|
private final BoardPanel boardPanel;
|
||||||
private final PlayerController pc;
|
private final HumanPlayer humanPlayer;
|
||||||
private final TileSelectionPanel tsp;
|
private final TileSelectionPanel tsp;
|
||||||
|
|
||||||
public BoardPanelMouseListener(BoardPanel boardPanel, TileSelectionPanel tsp, PlayerController pc) {
|
public BoardPanelMouseListener(BoardPanel boardPanel, TileSelectionPanel tsp, HumanPlayer humanPlayer) {
|
||||||
this.pc = pc;
|
this.humanPlayer = humanPlayer;
|
||||||
this.boardPanel = boardPanel;
|
this.boardPanel = boardPanel;
|
||||||
this.tsp = tsp;
|
this.tsp = tsp;
|
||||||
}
|
}
|
||||||
@@ -23,7 +25,7 @@ public class BoardPanelMouseListener implements MouseListener, MouseWheelListene
|
|||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
Tile tile = (Tile) e.getComponent();
|
Tile tile = (Tile) e.getComponent();
|
||||||
pc.setCell(tile.getRow(), tile.getCol());
|
humanPlayer.setCell(tile.getRow(), tile.getCol());
|
||||||
boardPanel.updateIcons();
|
boardPanel.updateIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,9 +52,9 @@ public class BoardPanelMouseListener implements MouseListener, MouseWheelListene
|
|||||||
@Override
|
@Override
|
||||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||||
if (e.getWheelRotation() > 0) {
|
if (e.getWheelRotation() > 0) {
|
||||||
pc.incrementColor();
|
humanPlayer.incrementColor();
|
||||||
} else if (e.getWheelRotation() < 0) {
|
} else if (e.getWheelRotation() < 0) {
|
||||||
pc.decrementColor();
|
humanPlayer.decrementColor();
|
||||||
}
|
}
|
||||||
tsp.updateBorders();
|
tsp.updateBorders();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ import java.awt.event.MouseListener;
|
|||||||
|
|
||||||
import view.TileSelectionPanel;
|
import view.TileSelectionPanel;
|
||||||
|
|
||||||
|
import model.HumanPlayer;
|
||||||
import model.Board.TileColor;
|
import model.Board.TileColor;
|
||||||
|
|
||||||
public class TSPMouseListener implements MouseListener{
|
public class TSPMouseListener implements MouseListener{
|
||||||
private PlayerController pc;
|
private HumanPlayer pc;
|
||||||
private TileColor tileColor;
|
private TileColor tileColor;
|
||||||
private TileSelectionPanel tsp;
|
private TileSelectionPanel tsp;
|
||||||
|
|
||||||
public TSPMouseListener(PlayerController pc, TileSelectionPanel tsp, TileColor tileColor) {
|
public TSPMouseListener(HumanPlayer pc, TileSelectionPanel tsp, TileColor tileColor) {
|
||||||
this.pc = pc;
|
this.pc = pc;
|
||||||
this.tileColor = tileColor;
|
this.tileColor = tileColor;
|
||||||
this.tsp = tsp;
|
this.tsp = tsp;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package model;
|
package model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class Board {
|
public class Board {
|
||||||
public enum TileColor {
|
public enum TileColor {
|
||||||
@@ -13,6 +14,15 @@ public class Board {
|
|||||||
|
|
||||||
private final TileColor[][] board;
|
private final TileColor[][] board;
|
||||||
|
|
||||||
|
public Board(Board that) {
|
||||||
|
this();
|
||||||
|
for (int i = 0; i < NUM_COLS; i++) {
|
||||||
|
for (int j = 0; j < NUM_ROWS; j++) {
|
||||||
|
this.board[j][i] = that.board[j][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Board() {
|
public Board() {
|
||||||
board = new TileColor[NUM_ROWS][NUM_COLS];
|
board = new TileColor[NUM_ROWS][NUM_COLS];
|
||||||
for (int r = 0; r < NUM_ROWS; r++) {
|
for (int r = 0; r < NUM_ROWS; r++) {
|
||||||
@@ -22,6 +32,36 @@ public class Board {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + Arrays.hashCode(board);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Board other = (Board) obj;
|
||||||
|
|
||||||
|
for (int r = 0; r < NUM_ROWS; r++) {
|
||||||
|
for (int c = 0; c < NUM_COLS; c++) {
|
||||||
|
if (this.board[r][c] != other.board[r][c]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public TileColor getTile(int r, int c) {
|
public TileColor getTile(int r, int c) {
|
||||||
return board[r][c];
|
return board[r][c];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
package model;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class ComController {
|
|
||||||
|
|
||||||
protected Board board = null;
|
|
||||||
|
|
||||||
public ComController(Board brd) {
|
|
||||||
board = brd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Move getMove();
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
package controller;
|
package model;
|
||||||
|
|
||||||
import model.Board.TileColor;
|
import model.Board.TileColor;
|
||||||
import model.Board;
|
|
||||||
import model.CellPointer;
|
|
||||||
import model.Move;
|
|
||||||
|
|
||||||
public class PlayerController {
|
|
||||||
|
public class HumanPlayer implements Player {
|
||||||
private final CellPointer cell = new CellPointer(0, 0);
|
private final CellPointer cell = new CellPointer(0, 0);
|
||||||
|
|
||||||
private boolean ready = false;
|
private boolean ready = false;
|
||||||
private TileColor color = TileColor.BLUE;
|
private TileColor color = TileColor.BLUE;
|
||||||
|
|
||||||
|
@Override
|
||||||
public void denyMove() {
|
public void denyMove() {
|
||||||
ready = false;
|
ready = false;
|
||||||
}
|
}
|
||||||
@@ -19,7 +18,8 @@ public class PlayerController {
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Move getMove() {
|
@Override
|
||||||
|
public Move getMove(Board board) {
|
||||||
ready = false;
|
ready = false;
|
||||||
return new Move(cell, color);
|
return new Move(cell, color);
|
||||||
|
|
||||||
@@ -63,6 +63,7 @@ public class PlayerController {
|
|||||||
color = colors[currentColor];
|
color = colors[currentColor];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isReady() {
|
public boolean isReady() {
|
||||||
return ready;
|
return ready;
|
||||||
}
|
}
|
||||||
54
src/model/MonteCarloComPlayer.java
Normal file
54
src/model/MonteCarloComPlayer.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package model;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import model.Board.TileColor;
|
||||||
|
|
||||||
|
|
||||||
|
public class MonteCarloComPlayer implements Player {
|
||||||
|
private final Random rand = new Random();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Move getMove(Board board) {
|
||||||
|
return getRandomMove(board,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Move getRandomMove(Board board, boolean isCompTurn) {
|
||||||
|
TileColor tile = TileColor.BLUE;
|
||||||
|
int r = -1;
|
||||||
|
int c = -1;
|
||||||
|
|
||||||
|
while (tile != TileColor.NONE) {
|
||||||
|
r = rand.nextInt(Board.NUM_ROWS);
|
||||||
|
c = rand.nextInt(Board.NUM_COLS);
|
||||||
|
|
||||||
|
tile = board.getTile(r, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (rand.nextInt(4)) {
|
||||||
|
case 0:
|
||||||
|
tile = TileColor.BLUE;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tile = TileColor.GREEN;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tile = TileColor.RED;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
tile = TileColor.YELLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Move(new CellPointer(r, c), tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void denyMove() {
|
||||||
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return true; // always ready to play a random valid move
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/model/Player.java
Normal file
20
src/model/Player.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package model;
|
||||||
|
|
||||||
|
|
||||||
|
public interface Player {
|
||||||
|
/**
|
||||||
|
* Instructs the Player to retract the last move.
|
||||||
|
*/
|
||||||
|
public void denyMove();
|
||||||
|
/**
|
||||||
|
* Gets the player's move given the board state. Blocks if player is not ready.
|
||||||
|
* @param board
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Move getMove(Board board);
|
||||||
|
/**
|
||||||
|
* Returns true if the player is ready to make a move (getMove() does not block).
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isReady();
|
||||||
|
}
|
||||||
@@ -1,23 +1,15 @@
|
|||||||
package model.comController;
|
package model;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import model.Board;
|
|
||||||
import model.Board.TileColor;
|
import model.Board.TileColor;
|
||||||
import model.CellPointer;
|
|
||||||
import model.ComController;
|
|
||||||
import model.Move;
|
|
||||||
|
|
||||||
public class RandomComController extends ComController {
|
|
||||||
|
|
||||||
|
public class RandomComPlayer implements Player {
|
||||||
private final Random rand = new Random();
|
private final Random rand = new Random();
|
||||||
|
|
||||||
public RandomComController(Board brd) {
|
|
||||||
super(brd);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Move getMove() {
|
public Move getMove(Board board) {
|
||||||
TileColor tile = TileColor.BLUE;
|
TileColor tile = TileColor.BLUE;
|
||||||
int r = -1;
|
int r = -1;
|
||||||
int c = -1;
|
int c = -1;
|
||||||
@@ -45,4 +37,14 @@ public class RandomComController extends ComController {
|
|||||||
|
|
||||||
return new Move(new CellPointer(r, c), tile);
|
return new Move(new CellPointer(r, c), tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void denyMove() {
|
||||||
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return true; // always ready to play a random valid move
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package model;
|
package model;
|
||||||
|
|
||||||
import model.Board.TileColor;
|
import model.Board.TileColor;
|
||||||
import model.comController.RandomComController;
|
|
||||||
import controller.PlayerController;
|
|
||||||
|
|
||||||
public class Referee {
|
public class Referee {
|
||||||
|
|
||||||
@@ -34,35 +32,33 @@ public class Referee {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Board board;
|
private final Board board;
|
||||||
|
private final HumanPlayer humanPlayer = new HumanPlayer();
|
||||||
private final ComController cc;
|
private final Player cc;
|
||||||
|
|
||||||
private final PlayerController pc = new PlayerController();
|
|
||||||
|
|
||||||
private boolean playerTurn;
|
private boolean playerTurn;
|
||||||
private int score = 0;
|
private int score = 0;
|
||||||
|
|
||||||
public Referee() {
|
public Referee() {
|
||||||
board = new Board();
|
board = new Board();
|
||||||
cc = new RandomComController(board);
|
cc = new RandomComPlayer();
|
||||||
playerTurn = true;
|
playerTurn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doSomething() {
|
public void doSomething() {
|
||||||
if (playerTurn && pc.isReady()) {
|
if (playerTurn && humanPlayer.isReady()) {
|
||||||
Move mv = pc.getMove();
|
Move mv = humanPlayer.getMove(board);
|
||||||
if (board.getTile(mv.getCell().r, mv.getCell().c) == TileColor.NONE) {
|
if (board.getTile(mv.getCell().r, mv.getCell().c) == TileColor.NONE) {
|
||||||
playToken(pc.getMove());
|
playToken(humanPlayer.getMove(board));
|
||||||
} else {
|
} else {
|
||||||
pc.denyMove();
|
humanPlayer.denyMove();
|
||||||
}
|
}
|
||||||
} else if (!playerTurn) {
|
} else if (!playerTurn) {
|
||||||
Move mv = cc.getMove();
|
Move mv = cc.getMove(board);
|
||||||
playToken(mv);
|
playToken(mv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComController getCom() {
|
public Player getCom() {
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +76,8 @@ public class Referee {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerController getPlayer() {
|
public HumanPlayer getHumanPlayer() {
|
||||||
return pc;
|
return humanPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getScore() {
|
public int getScore() {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class BoardPanel extends JPanel {
|
|||||||
referee = ref;
|
referee = ref;
|
||||||
setLayout(new GridLayout(Board.NUM_ROWS, Board.NUM_COLS));
|
setLayout(new GridLayout(Board.NUM_ROWS, Board.NUM_COLS));
|
||||||
|
|
||||||
BoardPanelMouseListener bpml = new BoardPanelMouseListener(this, tsp, referee.getPlayer());
|
BoardPanelMouseListener bpml = new BoardPanelMouseListener(this, tsp, referee.getHumanPlayer());
|
||||||
ImageIcon noneIcon = new ImageIcon(NONE_ICON);
|
ImageIcon noneIcon = new ImageIcon(NONE_ICON);
|
||||||
for (int r = 0; r < Board.NUM_ROWS; r++) {
|
for (int r = 0; r < Board.NUM_ROWS; r++) {
|
||||||
for (int c = 0; c < Board.NUM_COLS; c++) {
|
for (int c = 0; c < Board.NUM_COLS; c++) {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class MainFrame extends JFrame {
|
|||||||
private void init() {
|
private void init() {
|
||||||
// Create objects.
|
// Create objects.
|
||||||
ScorePanel sp = new ScorePanel(game);
|
ScorePanel sp = new ScorePanel(game);
|
||||||
TileSelectionPanel tp = new TileSelectionPanel(game.getPlayer());
|
TileSelectionPanel tp = new TileSelectionPanel(game.getHumanPlayer());
|
||||||
BoardPanel bp = new BoardPanel(game,tp);
|
BoardPanel bp = new BoardPanel(game,tp);
|
||||||
MessagePanel mp = new MessagePanel(game);
|
MessagePanel mp = new MessagePanel(game);
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
import controller.PlayerController;
|
|
||||||
import controller.TSPMouseListener;
|
import controller.TSPMouseListener;
|
||||||
|
|
||||||
|
import model.HumanPlayer;
|
||||||
import model.Board.TileColor;
|
import model.Board.TileColor;
|
||||||
|
|
||||||
public class TileSelectionPanel extends JPanel {
|
public class TileSelectionPanel extends JPanel {
|
||||||
@@ -26,9 +26,9 @@ public class TileSelectionPanel extends JPanel {
|
|||||||
private final JLabel red = new JLabel(new ImageIcon(BoardPanel.RED_ICON));
|
private final JLabel red = new JLabel(new ImageIcon(BoardPanel.RED_ICON));
|
||||||
private final JLabel yellow = new JLabel(new ImageIcon(
|
private final JLabel yellow = new JLabel(new ImageIcon(
|
||||||
BoardPanel.YELLOW_ICON));
|
BoardPanel.YELLOW_ICON));
|
||||||
private final PlayerController pc;
|
private final HumanPlayer pc;
|
||||||
|
|
||||||
public TileSelectionPanel(PlayerController pc) {
|
public TileSelectionPanel(HumanPlayer pc) {
|
||||||
this.pc = pc;
|
this.pc = pc;
|
||||||
|
|
||||||
initLayout();
|
initLayout();
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package model;
|
package model;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import model.Board.TileColor;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class BoardTest {
|
public class BoardTest {
|
||||||
@@ -8,4 +13,16 @@ public class BoardTest {
|
|||||||
public void testConstructor() {
|
public void testConstructor() {
|
||||||
new Board();
|
new Board();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyConstructor() {
|
||||||
|
Board board = new Board();
|
||||||
|
Board copy = new Board(board);
|
||||||
|
|
||||||
|
board.setTile(new CellPointer(1,2), TileColor.BLUE);
|
||||||
|
|
||||||
|
assertFalse(board.equals(copy));
|
||||||
|
copy.setTile(new CellPointer(1,2),TileColor.BLUE);
|
||||||
|
assertTrue(board.equals(copy));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user