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

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

@@ -0,0 +1,81 @@
package model;
import model.Board.TileColor;
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;
}
public TileColor getColor() {
return color;
}
@Override
public Move getMove(Board board) {
ready = false;
return new Move(cell, color);
}
public void decrementColor() {
TileColor[] colors = Board.TileColor.values();
int currentColor = -1;
for (int i = 0; i < colors.length; i++) {
if (colors[i] == color) {
currentColor = i;
break;
}
}
if (currentColor == -1) {
throw new RuntimeException("Color not found: " + color + "!");
}
currentColor = (currentColor + colors.length - 1) % colors.length;
if (colors[currentColor] == TileColor.NONE) {
currentColor = (currentColor + colors.length - 1) % colors.length;
}
color = colors[currentColor];
}
public void incrementColor() {
TileColor[] colors = Board.TileColor.values();
int currentColor = -1;
for (int i = 0; i < colors.length; i++) {
if (colors[i] == color) {
currentColor = i;
break;
}
}
if (currentColor == -1) {
throw new RuntimeException("Color not found: " + color + "!");
}
currentColor = (currentColor + 1) % colors.length;
if (colors[currentColor] == TileColor.NONE) {
currentColor = (currentColor + 1) % colors.length;
}
color = colors[currentColor];
}
@Override
public boolean isReady() {
return ready;
}
public void setCell(int row, int col) {
cell.r = row;
cell.c = col;
ready = true;
}
public void setColor(TileColor clr) {
color = clr;
}
}

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