Commit 4fca81a3 authored by Stefano Cobelli's avatar Stefano Cobelli

AI Player ready to be tested

Controller ready to be tested
parent e8f58c0e
......@@ -21,7 +21,7 @@ import controller.TTTController;
public class TTTMainGame {
/**
* the maximum size I'll allow for a board to be. the actual max is around
* 42 for a lab linux machine, it just doesn't show up. Anything above 25 is
* 42 for a lab linux machine in the comp sci lab, it just doesn't show up. Anything above 25 is
* stupid anyway
*/
private final static int MAXSIZE = 25;
......
......@@ -12,8 +12,15 @@ import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import model.Board;
import model.Board.State;
import model.Game;
import model.Mark;
import model.player.AIPlayer;
import model.player.AutoPlayable;
import model.player.BlockerPlayer;
import model.player.Player;
import model.player.RandomPlayer;
import view.TTTBoardPanel;
import view.TTTControlPanel;
import view.TTTMainView;
......@@ -31,13 +38,16 @@ public class TTTController implements ActionListener {
private Game theGame;
/** an instance of the main view */
private TTTMainView theView;
/** an instance of the stats panel from the main veiw */
/** an instance of the stats panel from the main view */
private TTTStatsPanel statsPanel;
/** an instance of the board panel from the main veiw */
/** an instance of the board panel from the main view */
private TTTBoardPanel boardPanel;
/** an instance of the control panel from the main view */
private TTTControlPanel controlPanel;
/** an instance of the player panel from the main view */
private TTTPlayerPanel playerPanel;
/** an instance of an ai player. Not necessary as the hashtable is static */
private AIPlayer aiGuy;
/** */
/**
......@@ -71,52 +81,68 @@ public class TTTController implements ActionListener {
*/
@Override
public void actionPerformed(ActionEvent e) {
// checks all the buttons if it's the source
if (e.getSource() == controlPanel.getNewGameButton()) {
theGame.newGame();
clearGUI();
return;
newGame();
}
if (e.getSource() == controlPanel.getTrainAIButton()) {
for (int i)
else if (e.getSource() == controlPanel.getTrainAIButton()) {
int trainCount = 0;
try {
trainCount = Integer.parseInt(controlPanel.getTrainNumberField().getText());
}catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Please enter a valid number to train");
return;
}
Game aiGames = new Game(theGame.getSize());
Board aiBoard = new Board(theGame.getSize());
aiGuy = new AIPlayer(aiBoard, Mark.O);
RandomPlayer randGuy = new RandomPlayer(aiBoard, Mark.X);
aiGames.setPlayerX(aiGuy);
aiGames.setPlayerO(randGuy);
for (int i = 0; i < trainCount; i++) {
while(aiGames.isPlayable()) {
((AutoPlayable) aiGames.getCurPlayer()).decideMove();
aiGames.switchTurn();
}
}
}
for (int row = 0; row < boardPanel.getButtonBoard().length; row++) {
for (int col = 0; col < boardPanel.getButtonBoard().length; col++) {
if (e.getSource() == boardPanel.getButtonBoard()[row][col]) {
if (theGame.getCurPlayer().move(row, col)) {
// sets text on button if marked
boardPanel.getButtonBoard()[row][col].setText(theGame
.getPlayerTurn());
if (!theGame.isPlayable()) {
// performs relative actions if game is over
if (theGame.getState() == State.WIN) {
JOptionPane.showMessageDialog(null,
theGame.getPlayerTurn() + " wins!");
if (theGame.getPlayerTurn() == "X")
statsPanel.getXWins().setText(
incrementString(statsPanel
.getXWins().getText()));
else if (theGame.getPlayerTurn() == "O")
statsPanel.getOWins().setText(
incrementString(statsPanel
.getOWins().getText()));
theGame.newGame();
clearGUI();
} else if (theGame.getState() == State.DRAW) {
JOptionPane.showMessageDialog(null,
"The game's a draw!");
statsPanel.getDraws().setText(
incrementString(statsPanel.getDraws()
.getText()));
theGame.newGame();
clearGUI();
// checks all grid buttons if it's the source
else {
for (int row = 0; row < boardPanel.getButtonBoard().length; row++) {
for (int col = 0; col < boardPanel.getButtonBoard().length; col++) {
if (e.getSource() == boardPanel.getButtonBoard()[row][col]) {
if (theGame.getCurPlayer().move(row, col)) {
// sets text on button if marked
boardPanel.getButtonBoard()[row][col].setText(theGame
.getPlayerTurn());
if (!theGame.isPlayable()) {
// performs relative actions if game is over
if (theGame.getState() == State.WIN) {
JOptionPane.showMessageDialog(null,
theGame.getPlayerTurn() + " wins!");
if (theGame.getPlayerTurn() == "X")
statsPanel.getXWins().setText(
incrementString(statsPanel
.getXWins().getText()));
else if (theGame.getPlayerTurn() == "O")
statsPanel.getOWins().setText(
incrementString(statsPanel
.getOWins().getText()));
newGame();
} else if (theGame.getState() == State.DRAW) {
JOptionPane.showMessageDialog(null,
"The game's a draw!");
statsPanel.getDraws().setText(
incrementString(statsPanel.getDraws()
.getText()));
newGame();
}
} else {
// if the game is playable, switch the turn
theGame.switchTurn();
statsPanel.getPlayerTurn().setText(
theGame.getPlayerTurn());
}
} else {
// if the game is playable, switch the turn
theGame.switchTurn();
statsPanel.getPlayerTurn().setText(
theGame.getPlayerTurn());
}
}
}
......@@ -124,9 +150,33 @@ public class TTTController implements ActionListener {
}
}
/**
* clears the GUI to all ""
* sets up for a new game through the game object and gui. resets players according to the player pane.
*/
public void newGame() {
theGame.newGame();
if (playerPanel.getGameModeComboBox().getSelectedItem() == "Player vs. Player") {
theGame.setPlayerX(new Player(theGame.getBoard(), Mark.X));
theGame.setPlayerO(new Player(theGame.getBoard(), Mark.O));
}else {
theGame.setPlayerX(new Player(theGame.getBoard(), Mark.X));
if (playerPanel.getaIComboBox().getSelectedItem() == "Random") {
theGame.setPlayerO(new RandomPlayer(theGame.getBoard(), Mark.O));
}
else if (playerPanel.getaIComboBox().getSelectedItem() == "Blocker") {
theGame.setPlayerO(new BlockerPlayer(theGame.getBoard(), Mark.O));
}
else {
aiGuy.setMark(Mark.O);
theGame.setPlayerO(aiGuy);
}
}
clearGUI();
}
/**
* clears the GUI to all blanks ""
*/
public void clearGUI() {
for (int row = 0; row < boardPanel.getButtonBoard().length; row++) {
......
......@@ -282,4 +282,11 @@ public class Board {
public boolean isWinFor(Player player) {
return (updateBoardState() == player.getMark());
}
/**\
* @return board as a Mark[][]
*/
public Mark[][] getMarkArr() {
return board;
}
}
......@@ -98,16 +98,6 @@ public class Game {
}
public void trainAI(int times) {
for (int i = 0; i < times; i++) {
while (isPlayable()) {
// random move
// ai move
}
}
}
/**
* main method
*/
......@@ -187,4 +177,18 @@ public class Game {
theBoard.clear();
currentPlayer = 0;
}
/**
* @param player to set as X
*/
public void setPlayerX(Player player){
players[0] = player;
}
/**
* @param player to set as O
*/
public void setPlayerO(Player player){
players[0] = player;
}
}
......@@ -12,17 +12,24 @@ import java.util.Hashtable;
import model.Board;
import model.Mark;
import model.Board.State;
/**
* @author mjt023
* A player that learns from experience
*
* @author sjc032
*
*/
public class AIPlayer extends Player implements AutoPlayable {
private Hashtable<Mark[][], Boolean> hashBoards = new Hashtable<Mark[][], Boolean>();
private ArrayList<Mark[][]> boardStreak = new ArrayList<Mark[][]>();
/** a hashtable that stores moves done already. It stores the (potential) move by the ai,
* after the other player has gone, so the last mvoe done is always AIPlayer */
private static Hashtable<Mark[][], Boolean> hashBoards = new Hashtable<Mark[][], Boolean>();
/** the last board hashed */
private static Mark[][] prevBoard;
/**
* constructor for the aiplayer, just calls the super
* @param theBoard
* @param myMark
*/
......@@ -37,17 +44,61 @@ public class AIPlayer extends Player implements AutoPlayable {
*/
@Override
public boolean decideMove() {
Mark[][] curBoard = twoDArrayDeepCopy(theBoard.getMarkArr());
for (int row = 0; row < theBoard.getSize(); row++) {
for (int col = 0; col < theBoard.getSize(); col++) {
if (curBoard[row][col] == Mark.NONE) {
curBoard[row][col] = getMark();
//if the board is a win
if (hashBoards.get(curBoard) == true) {
return move(row,col);
}
//if the board might lead to a win
else if (hashBoards.get(curBoard) == null){
prevBoard = twoDArrayDeepCopy(curBoard);
boolean moveSuccess = move(row, col);
//if the boards a win, set all the other spots to false, so it knows to win
if (theBoard.getState() == State.WIN) {
hashBoards.put(curBoard,true);
curBoard[row][col] = Mark.NONE;
for (int row2 = 0; row < theBoard.getSize(); row++) {
for (int col2 = 0; col < theBoard.getSize(); col++) {
if(curBoard[row2][col2] == Mark.NONE && row2 != row && col2 != col){
curBoard[row2][col2] = getMark();
hashBoards.put(curBoard, false);
}
}
}
}
return moveSuccess;
}
//if the move is ineligible or leads to a loss
curBoard[row][col] = Mark.NONE;
}
}
}
//if all moves lead to a loss, forfeit
hashBoards.put(prevBoard, false);
for (int row = 0; row < theBoard.getSize(); row++) {
for (int col = 0; col < theBoard.getSize(); col++) {
if (curBoard[row][col] == Mark.NONE)
return move(row,col);
}
}
//board is finished
return false;
}
public Mark[][] turnBoard(Mark[][] boardToTurn) {
return boardToTurn;
}
public Mark[][] flipBoard(Mark[][] boardToFlip) {
return boardToFlip;
/**
* Makes a deep copy of a two dimensional Mark array
* @param board
* @return
*/
public static Mark[][] twoDArrayDeepCopy(Mark[][] board) {
Mark[][] newArray =(Mark[][]) board.clone();
//you have to clone all the
for(int row=0; row<board.length ;row++){
newArray[row]=(Mark[]) board[row].clone();
}
return newArray;
}
}
}
\ No newline at end of file
......@@ -8,6 +8,8 @@
package model.player;
/**
* an interface of an autoplayable player, such as BlockerPlayer
*
* @author sjc032
*
*/
......
......@@ -11,7 +11,9 @@ import model.Board;
import model.Mark;
/**
* @author mjt023
* A player that blocks when two of the other players marks line up
*
* @author sjc032
*
*/
public class BlockerPlayer extends Player implements AutoPlayable {
......
......@@ -57,4 +57,11 @@ public class Player {
public boolean move(int row, int col) {
return theBoard.setMark(row, col, myMark);
}
/**
* @param mark to be set for this player
*/
public void setMark(Mark mark) {
this.myMark = mark;
}
}
......@@ -15,6 +15,8 @@ import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
/**
* Bottom panel for the ai controls
*
* @author sjc032
*
*/
......
......@@ -17,6 +17,8 @@ import javax.swing.SwingConstants;
import javax.swing.border.EtchedBorder;
/**
* combo boxes of the possible ai and player combonations
*
* @author sjc032
*
*/
......@@ -25,6 +27,8 @@ public class TTTPlayerPanel extends JPanel {
private static final long serialVersionUID = 1L;
private JComboBox gameModeComboBox;
private JComboBox aIComboBox;
private String[] gameModeOptions = { "Player vs. Computer", "Player vs. Player" };
private String[] aIOptions = { "Random", "Blocker", "AI Player" };
public TTTPlayerPanel() {
this.setLayout(new GridLayout(2, 2, 5, 5));
......@@ -32,9 +36,7 @@ public class TTTPlayerPanel extends JPanel {
73, 178, 250)));
JLabel gameModeText = new JLabel("Game Mode:", SwingConstants.CENTER);
JLabel aIText = new JLabel("Computer Player:", SwingConstants.CENTER);
String[] gameModeOptions = { "Player vs. Computer", "Player vs. Player" };
this.gameModeComboBox = new JComboBox(gameModeOptions);
String[] aIOptions = { "Random", "Blocker", "AI Player" };
this.aIComboBox = new JComboBox(aIOptions);
this.add(gameModeText);
this.add(gameModeComboBox);
......@@ -55,5 +57,13 @@ public class TTTPlayerPanel extends JPanel {
public JComboBox getaIComboBox() {
return aIComboBox;
}
public String[] getGameModeOptions() {
return gameModeOptions;
}
public String[] getaIOptions() {
return aIOptions;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment