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:
@@ -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];
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package model;
|
||||
|
||||
|
||||
public abstract class ComController {
|
||||
|
||||
protected Board board = null;
|
||||
|
||||
public ComController(Board brd) {
|
||||
board = brd;
|
||||
}
|
||||
|
||||
public abstract Move getMove();
|
||||
}
|
||||
81
src/model/HumanPlayer.java
Normal file
81
src/model/HumanPlayer.java
Normal 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;
|
||||
}
|
||||
}
|
||||
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 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
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user