Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Matt Tower
205_hw02
Commits
4fca81a3
Commit
4fca81a3
authored
Nov 13, 2014
by
Stefano Cobelli
Browse files
AI Player ready to be tested
Controller ready to be tested
parent
e8f58c0e
Changes
10
Hide whitespace changes
Inline
Side-by-side
src/TTTMainGame.java
View file @
4fca81a3
...
...
@@ -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
;
...
...
src/controller/TTTController.java
View file @
4fca81a3
...
...
@@ -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 v
e
iw */
/** an instance of the stats panel from the main vi
e
w */
private
TTTStatsPanel
statsPanel
;
/** an instance of the board panel from the main v
e
iw */
/** an instance of the board panel from the main vi
e
w */
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
++)
{
...
...
src/model/Board.java
View file @
4fca81a3
...
...
@@ -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
;
}
}
src/model/Game.java
View file @
4fca81a3
...
...
@@ -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
;
}
}
src/model/player/AIPlayer.java
View file @
4fca81a3
...
...
@@ -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
src/model/player/AutoPlayable.java
View file @
4fca81a3
...
...
@@ -8,6 +8,8 @@
package
model.player
;
/**
* an interface of an autoplayable player, such as BlockerPlayer
*
* @author sjc032
*
*/
...
...
src/model/player/BlockerPlayer.java
View file @
4fca81a3
...
...
@@ -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
{
...
...
src/model/player/Player.java
View file @
4fca81a3
...
...
@@ -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
;
}
}
src/view/TTTControlPanel.java
View file @
4fca81a3
...
...
@@ -15,6 +15,8 @@ import javax.swing.JTextField;
import
javax.swing.border.EmptyBorder
;
/**
* Bottom panel for the ai controls
*
* @author sjc032
*
*/
...
...
src/view/TTTPlayerPanel.java
View file @
4fca81a3
...
...
@@ -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
;
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment