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:
Woody Folsom
2012-04-08 17:25:10 -04:00
parent e0f42531e7
commit 9619f9a96d
13 changed files with 178 additions and 58 deletions

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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];
}

View File

@@ -1,13 +0,0 @@
package model;
public abstract class ComController {
protected Board board = null;
public ComController(Board brd) {
board = brd;
}
public abstract Move getMove();
}

View File

@@ -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;
}

View 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
View 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();
}

View File

@@ -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
}
}

View File

@@ -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() {

View File

@@ -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++) {

View File

@@ -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);

View File

@@ -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();