From 9619f9a96db6bbaae92cea8e2171cfdeeff6a480 Mon Sep 17 00:00:00 2001 From: Woody Folsom Date: Sun, 8 Apr 2012 17:25:10 -0400 Subject: [PATCH] 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. --- src/controller/BoardPanelMouseListener.java | 14 ++--- src/controller/TSPMouseListener.java | 5 +- src/model/Board.java | 40 ++++++++++++++ src/model/ComController.java | 13 ----- .../HumanPlayer.java} | 13 ++--- src/model/MonteCarloComPlayer.java | 54 +++++++++++++++++++ src/model/Player.java | 20 +++++++ ...omController.java => RandomComPlayer.java} | 24 +++++---- src/model/Referee.java | 26 ++++----- src/view/BoardPanel.java | 2 +- src/view/MainFrame.java | 2 +- src/view/TileSelectionPanel.java | 6 +-- test/model/BoardTest.java | 17 ++++++ 13 files changed, 178 insertions(+), 58 deletions(-) delete mode 100644 src/model/ComController.java rename src/{controller/PlayerController.java => model/HumanPlayer.java} (91%) create mode 100644 src/model/MonteCarloComPlayer.java create mode 100644 src/model/Player.java rename src/model/{comController/RandomComController.java => RandomComPlayer.java} (66%) diff --git a/src/controller/BoardPanelMouseListener.java b/src/controller/BoardPanelMouseListener.java index cb64417..01c6512 100644 --- a/src/controller/BoardPanelMouseListener.java +++ b/src/controller/BoardPanelMouseListener.java @@ -5,17 +5,19 @@ import java.awt.event.MouseListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; +import model.HumanPlayer; + import view.BoardPanel; import view.Tile; import view.TileSelectionPanel; public class BoardPanelMouseListener implements MouseListener, MouseWheelListener { private final BoardPanel boardPanel; - private final PlayerController pc; + private final HumanPlayer humanPlayer; private final TileSelectionPanel tsp; - public BoardPanelMouseListener(BoardPanel boardPanel, TileSelectionPanel tsp, PlayerController pc) { - this.pc = pc; + public BoardPanelMouseListener(BoardPanel boardPanel, TileSelectionPanel tsp, HumanPlayer humanPlayer) { + this.humanPlayer = humanPlayer; this.boardPanel = boardPanel; this.tsp = tsp; } @@ -23,7 +25,7 @@ public class BoardPanelMouseListener implements MouseListener, MouseWheelListene @Override public void mouseClicked(MouseEvent e) { Tile tile = (Tile) e.getComponent(); - pc.setCell(tile.getRow(), tile.getCol()); + humanPlayer.setCell(tile.getRow(), tile.getCol()); boardPanel.updateIcons(); } @@ -50,9 +52,9 @@ public class BoardPanelMouseListener implements MouseListener, MouseWheelListene @Override public void mouseWheelMoved(MouseWheelEvent e) { if (e.getWheelRotation() > 0) { - pc.incrementColor(); + humanPlayer.incrementColor(); } else if (e.getWheelRotation() < 0) { - pc.decrementColor(); + humanPlayer.decrementColor(); } tsp.updateBorders(); } diff --git a/src/controller/TSPMouseListener.java b/src/controller/TSPMouseListener.java index 9e645ad..04b931e 100644 --- a/src/controller/TSPMouseListener.java +++ b/src/controller/TSPMouseListener.java @@ -5,14 +5,15 @@ import java.awt.event.MouseListener; import view.TileSelectionPanel; +import model.HumanPlayer; import model.Board.TileColor; public class TSPMouseListener implements MouseListener{ - private PlayerController pc; + private HumanPlayer pc; private TileColor tileColor; private TileSelectionPanel tsp; - public TSPMouseListener(PlayerController pc, TileSelectionPanel tsp, TileColor tileColor) { + public TSPMouseListener(HumanPlayer pc, TileSelectionPanel tsp, TileColor tileColor) { this.pc = pc; this.tileColor = tileColor; this.tsp = tsp; diff --git a/src/model/Board.java b/src/model/Board.java index df143db..3792878 100644 --- a/src/model/Board.java +++ b/src/model/Board.java @@ -1,6 +1,7 @@ package model; import java.util.ArrayList; +import java.util.Arrays; public class Board { public enum TileColor { @@ -13,6 +14,15 @@ public class 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() { board = new TileColor[NUM_ROWS][NUM_COLS]; 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) { return board[r][c]; } diff --git a/src/model/ComController.java b/src/model/ComController.java deleted file mode 100644 index c64ce00..0000000 --- a/src/model/ComController.java +++ /dev/null @@ -1,13 +0,0 @@ -package model; - - -public abstract class ComController { - - protected Board board = null; - - public ComController(Board brd) { - board = brd; - } - - public abstract Move getMove(); -} diff --git a/src/controller/PlayerController.java b/src/model/HumanPlayer.java similarity index 91% rename from src/controller/PlayerController.java rename to src/model/HumanPlayer.java index 58cbdf2..5119ab0 100644 --- a/src/controller/PlayerController.java +++ b/src/model/HumanPlayer.java @@ -1,16 +1,15 @@ -package controller; +package model; 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 boolean ready = false; private TileColor color = TileColor.BLUE; + @Override public void denyMove() { ready = false; } @@ -19,7 +18,8 @@ public class PlayerController { return color; } - public Move getMove() { + @Override + public Move getMove(Board board) { ready = false; return new Move(cell, color); @@ -63,6 +63,7 @@ public class PlayerController { color = colors[currentColor]; } + @Override public boolean isReady() { return ready; } diff --git a/src/model/MonteCarloComPlayer.java b/src/model/MonteCarloComPlayer.java new file mode 100644 index 0000000..d98f87a --- /dev/null +++ b/src/model/MonteCarloComPlayer.java @@ -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 + } +} diff --git a/src/model/Player.java b/src/model/Player.java new file mode 100644 index 0000000..f59d61b --- /dev/null +++ b/src/model/Player.java @@ -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(); +} diff --git a/src/model/comController/RandomComController.java b/src/model/RandomComPlayer.java similarity index 66% rename from src/model/comController/RandomComController.java rename to src/model/RandomComPlayer.java index b85a472..6143c20 100644 --- a/src/model/comController/RandomComController.java +++ b/src/model/RandomComPlayer.java @@ -1,23 +1,15 @@ -package model.comController; +package model; import java.util.Random; -import model.Board; 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(); - public RandomComController(Board brd) { - super(brd); - } - @Override - public Move getMove() { + public Move getMove(Board board) { TileColor tile = TileColor.BLUE; int r = -1; int c = -1; @@ -45,4 +37,14 @@ public class RandomComController extends ComController { 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 + } } diff --git a/src/model/Referee.java b/src/model/Referee.java index 5afa161..2c4fa80 100644 --- a/src/model/Referee.java +++ b/src/model/Referee.java @@ -1,8 +1,6 @@ package model; import model.Board.TileColor; -import model.comController.RandomComController; -import controller.PlayerController; public class Referee { @@ -34,35 +32,33 @@ public class Referee { } private final Board board; - - private final ComController cc; - - private final PlayerController pc = new PlayerController(); + private final HumanPlayer humanPlayer = new HumanPlayer(); + private final Player cc; private boolean playerTurn; private int score = 0; public Referee() { board = new Board(); - cc = new RandomComController(board); + cc = new RandomComPlayer(); playerTurn = true; } public void doSomething() { - if (playerTurn && pc.isReady()) { - Move mv = pc.getMove(); + if (playerTurn && humanPlayer.isReady()) { + Move mv = humanPlayer.getMove(board); if (board.getTile(mv.getCell().r, mv.getCell().c) == TileColor.NONE) { - playToken(pc.getMove()); + playToken(humanPlayer.getMove(board)); } else { - pc.denyMove(); + humanPlayer.denyMove(); } } else if (!playerTurn) { - Move mv = cc.getMove(); + Move mv = cc.getMove(board); playToken(mv); } } - public ComController getCom() { + public Player getCom() { return cc; } @@ -80,8 +76,8 @@ public class Referee { } } - public PlayerController getPlayer() { - return pc; + public HumanPlayer getHumanPlayer() { + return humanPlayer; } public int getScore() { diff --git a/src/view/BoardPanel.java b/src/view/BoardPanel.java index 843f6fb..69e66f0 100644 --- a/src/view/BoardPanel.java +++ b/src/view/BoardPanel.java @@ -35,7 +35,7 @@ public class BoardPanel extends JPanel { referee = ref; 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); for (int r = 0; r < Board.NUM_ROWS; r++) { for (int c = 0; c < Board.NUM_COLS; c++) { diff --git a/src/view/MainFrame.java b/src/view/MainFrame.java index 141f8ac..c77fcd9 100644 --- a/src/view/MainFrame.java +++ b/src/view/MainFrame.java @@ -38,7 +38,7 @@ public class MainFrame extends JFrame { private void init() { // Create objects. ScorePanel sp = new ScorePanel(game); - TileSelectionPanel tp = new TileSelectionPanel(game.getPlayer()); + TileSelectionPanel tp = new TileSelectionPanel(game.getHumanPlayer()); BoardPanel bp = new BoardPanel(game,tp); MessagePanel mp = new MessagePanel(game); diff --git a/src/view/TileSelectionPanel.java b/src/view/TileSelectionPanel.java index 51d492c..9dd8780 100644 --- a/src/view/TileSelectionPanel.java +++ b/src/view/TileSelectionPanel.java @@ -11,9 +11,9 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; -import controller.PlayerController; import controller.TSPMouseListener; +import model.HumanPlayer; import model.Board.TileColor; 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 yellow = new JLabel(new ImageIcon( BoardPanel.YELLOW_ICON)); - private final PlayerController pc; + private final HumanPlayer pc; - public TileSelectionPanel(PlayerController pc) { + public TileSelectionPanel(HumanPlayer pc) { this.pc = pc; initLayout(); diff --git a/test/model/BoardTest.java b/test/model/BoardTest.java index de23422..d713f71 100644 --- a/test/model/BoardTest.java +++ b/test/model/BoardTest.java @@ -1,5 +1,10 @@ package model; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import model.Board.TileColor; + import org.junit.Test; public class BoardTest { @@ -8,4 +13,16 @@ public class BoardTest { public void testConstructor() { 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)); + } }