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
Johan Gustav Thrane-Nielsen
inf101.v20.sem2.losning
Commits
0a460a98
Commit
0a460a98
authored
May 07, 2020
by
mva021
Browse files
Updated the Game classes with comments and renamed the FourInRow class
parent
11a093a9
Changes
13
Hide whitespace changes
Inline
Side-by-side
src/main/java/inf101/v20/sem2/GUI/GUIMain.java
View file @
0a460a98
package
inf101.v20.sem2.GUI
;
import
inf101.v20.sem2.games.Game
;
import
inf101.v20.sem2.games.
Abstract
Game
;
import
inf101.v20.sem2.games.TicTacToe
;
public
class
GUIMain
{
public
static
void
main
(
String
[]
args
)
{
Game
game
=
new
TicTacToe
(
GameGUI
.
getPlayers
());
Abstract
Game
game
=
new
TicTacToe
(
GameGUI
.
getPlayers
());
MNKGameGUI
gameGUI
=
new
MNKGameGUI
(
game
);
GameGUI
gui
=
new
GameGUI
(
gameGUI
);
}
...
...
src/main/java/inf101/v20/sem2/GUI/GameGUI.java
View file @
0a460a98
...
...
@@ -10,8 +10,8 @@ import javax.swing.JFrame;
import
javax.swing.JOptionPane
;
import
javax.swing.JPanel
;
import
inf101.v20.sem2.games.Four
i
nRow
;
import
inf101.v20.sem2.games.Game
;
import
inf101.v20.sem2.games.Four
I
nRow
;
import
inf101.v20.sem2.games.
Abstract
Game
;
import
inf101.v20.sem2.games.MiniMaxPlayer
;
import
inf101.v20.sem2.games.Player
;
import
inf101.v20.sem2.games.TicTacToe
;
...
...
@@ -75,7 +75,7 @@ public class GameGUI implements ActionListener{
Iterable
<
Player
>
players
=
getPlayers
();
frame
.
remove
(
gameBoard
);
if
(
e
.
getSource
()
==
playConnectFourButton
)
{
this
.
gameBoard
=
new
MNKGameGUI
(
new
Four
i
nRow
(
players
));
this
.
gameBoard
=
new
MNKGameGUI
(
new
Four
I
nRow
(
players
));
}
if
(
e
.
getSource
()
==
playTicTacToeButton
)
{
this
.
gameBoard
=
new
MNKGameGUI
(
new
TicTacToe
(
players
));
...
...
@@ -87,14 +87,14 @@ public class GameGUI implements ActionListener{
public
static
Iterable
<
Player
>
getPlayers
()
{
ArrayList
<
Player
>
players
=
new
ArrayList
<
Player
>();
//add player1
players
.
add
(
new
GuiPlayer
(
Game
.
piece1
));
players
.
add
(
new
GuiPlayer
(
Abstract
Game
.
piece1
));
//add player2
if
(
promptMultiplayer
())
{
players
.
add
(
new
GuiPlayer
(
Game
.
piece2
));
players
.
add
(
new
GuiPlayer
(
Abstract
Game
.
piece2
));
}
else
{
//make AI
//TODO: prompt for level of intelligence in AI player
players
.
add
(
new
MiniMaxPlayer
(
Game
.
piece2
,
5
));
players
.
add
(
new
MiniMaxPlayer
(
Abstract
Game
.
piece2
,
5
));
}
...
...
src/main/java/inf101/v20/sem2/GUI/MNKGameGUI.java
View file @
0a460a98
...
...
@@ -9,7 +9,7 @@ import java.util.List;
import
javax.swing.JLabel
;
import
javax.swing.JPanel
;
import
inf101.v20.sem2.games.Game
;
import
inf101.v20.sem2.games.
Abstract
Game
;
/**
*
...
...
@@ -20,11 +20,11 @@ public class MNKGameGUI extends JPanel{
private
static
final
long
serialVersionUID
=
8755882090377973497L
;
// Fields
private
Game
game
;
//the game logic
private
Abstract
Game
game
;
//the game logic
private
ClickableGrid
clickablePanels
;
//clickable grid for user input
private
JLabel
statusMessage
;
//field for displaying message to user
public
MNKGameGUI
(
Game
game
)
{
public
MNKGameGUI
(
Abstract
Game
game
)
{
this
.
game
=
game
;
game
.
setGui
(
this
);
statusMessage
=
new
JLabel
();
...
...
@@ -44,7 +44,7 @@ public class MNKGameGUI extends JPanel{
validate
();
}
public
void
reset
(
Game
newGame
)
{
public
void
reset
(
Abstract
Game
newGame
)
{
this
.
game
=
newGame
;
this
.
game
.
setGui
(
this
);
//updateMessage();
...
...
src/main/java/inf101/v20/sem2/games/Game.java
→
src/main/java/inf101/v20/sem2/games/
Abstract
Game.java
View file @
0a460a98
...
...
@@ -10,10 +10,11 @@ import inf101.v20.sem2.grid.Location;
/**
* A game consists of a GameBoard, and 2 players which each has a piece.
* Pieces are then placed on the board until a winning, loosing or draw condition
* @author mva021
*
* @author Martin Vatshelle - martin.vatshelle@uib.no
*
*/
public
abstract
class
Game
implements
IGame
{
public
abstract
class
Abstract
Game
implements
IGame
{
GameBoard
board
;
PlayerList
players
;
...
...
@@ -28,7 +29,7 @@ public abstract class Game implements IGame {
* @param board - The board to play on
* @param players - The players to play the game
*/
public
Game
(
GameBoard
board
,
Iterable
<
Player
>
players
)
{
public
Abstract
Game
(
GameBoard
board
,
Iterable
<
Player
>
players
)
{
this
(
board
);
for
(
Player
p:
players
)
{
addPlayer
(
p
);
...
...
@@ -39,7 +40,7 @@ public abstract class Game implements IGame {
* Constructor which creates a game without players
* @param board
*/
public
Game
(
GameBoard
board
)
{
public
Abstract
Game
(
GameBoard
board
)
{
players
=
new
PlayerList
();
this
.
board
=
board
;
}
...
...
@@ -218,7 +219,7 @@ public abstract class Game implements IGame {
* This method checks if the game is over
* @return
*/
p
rotected
boolean
gameOver
()
{
p
ublic
boolean
gameOver
()
{
return
hasWinner
()
||
isDraw
();
}
...
...
@@ -240,11 +241,6 @@ public abstract class Game implements IGame {
}
return
moves
;
}
/**
* @return The name of the game
*/
public
abstract
String
getName
();
@Override
public
GameBoard
getGameBoard
()
{
...
...
@@ -271,13 +267,12 @@ public abstract class Game implements IGame {
}
/**
* This method is needed for the AI players to try out different moves without
* actually changing the game.
* Advances the PlayerList until currentPlayer equals the given player.
* This can be used for deciding who should be the first player.
* It is also used by the copy method.
*
* @
return
* @
param player the player which should be the current player
*/
public
abstract
Game
copy
();
public
void
setPlayer
(
Player
player
)
{
while
(
player
!=
getCurrentPlayer
())
{
players
.
nextPlayer
();
...
...
src/main/java/inf101/v20/sem2/games/Four
i
nRow.java
→
src/main/java/inf101/v20/sem2/games/Four
I
nRow.java
View file @
0a460a98
...
...
@@ -3,17 +3,25 @@ package inf101.v20.sem2.games;
import
inf101.v20.sem2.grid.GridDirection
;
import
inf101.v20.sem2.grid.Location
;
public
class
FourinRow
extends
Game
{
/**
* This game is played on a 6 x 7 board.
* The players select a column and the placement will be on the lowest
* available row of that column.
*
* @author Martin Vatshelle - martin.vatshelle@uib.no
*
*/
public
class
FourInRow
extends
AbstractGame
{
public
Four
i
nRow
()
{
public
Four
I
nRow
()
{
super
(
new
GameBoard
(
6
,
7
));
}
public
Four
i
nRow
(
Iterable
<
Player
>
players
)
{
public
Four
I
nRow
(
Iterable
<
Player
>
players
)
{
super
(
new
GameBoard
(
6
,
7
),
players
);
}
public
Four
i
nRow
(
GameBoard
board
,
Iterable
<
Player
>
players
)
{
public
Four
I
nRow
(
GameBoard
board
,
Iterable
<
Player
>
players
)
{
super
(
board
,
players
);
}
...
...
@@ -68,8 +76,8 @@ public class FourinRow extends Game {
return
loc
;
}
@Override
public
Game
copy
()
{
Game
newGame
=
new
Four
i
nRow
(
board
.
copy
(),
players
);
public
Abstract
Game
copy
()
{
Abstract
Game
newGame
=
new
Four
I
nRow
(
board
.
copy
(),
players
);
newGame
.
setPlayer
(
getCurrentPlayer
());
return
newGame
;
}
...
...
src/main/java/inf101/v20/sem2/games/IGame.java
View file @
0a460a98
...
...
@@ -4,6 +4,12 @@ import java.util.List;
import
inf101.v20.sem2.grid.Location
;
/**
* This Interface is used to describe what is needed for playing a Game
*
* @author Martin Vatshelle - martin.vatshelle@uib.no
*
*/
public
interface
IGame
{
/**
...
...
@@ -17,9 +23,18 @@ public interface IGame {
*/
public
Iterable
<
Player
>
players
();
/**
* @return The name of the game
*/
public
String
getName
();
/**
* The game has rules for where the players can place.
* In both TicTacToe and Connect4 it does not matter who the player is, but it might in other games.
*
* This is both used to verify that the move a Player returns is valid
* and for the AI to know where it can place.
*
* @param loc - where to place
* @param player - who wants to place
* @return true if it is a valid move, false otherwise.
...
...
@@ -48,6 +63,9 @@ public interface IGame {
/**
* Will find all the possible moves the current player can make
* This is mainly for the AI to more easily select a move.
* Did not need to be in the Interface, but it might be a handy method to have.
*
* @return list of all possible Locations for next move
*/
public
List
<
Location
>
possibleMoves
();
...
...
@@ -66,7 +84,33 @@ public interface IGame {
*/
public
boolean
isWinner
(
Player
p
);
/**
* Checks if the game is a draw
* @return true if the game is a draw, false otherwise
*/
public
boolean
isDraw
();
public
abstract
Game
copy
();
/**
* Creates a copy of the game.
*
* This method is needed for the AI players to try out different moves without
* actually changing the game.
*
* @return a copy of the game.
*/
public
IGame
copy
();
/**
* This method is used for testing and by the AI which simulates
* several moves ahead to find the best move.
* @param loc
* @return
*/
public
boolean
makeMove
(
Location
loc
);
/**
* This method
* @return
*/
public
boolean
gameOver
();
}
src/main/java/inf101/v20/sem2/games/MiniMaxPlayer.java
View file @
0a460a98
...
...
@@ -49,7 +49,7 @@ public class MiniMaxPlayer extends AbstractPlayer {
//try each possible strategy
for
(
Location
loc
:
game
.
possibleMoves
())
{
//make a copy of the game and try the move
Game
newGame
=
game
.
copy
();
I
Game
newGame
=
game
.
copy
();
newGame
.
makeMove
(
loc
);
//note that this changes the current player in the copy but not the real game
int
score
=
0
;
if
(
newGame
.
gameOver
()
||
depth
==
1
)
{
//No more moves can be made
...
...
@@ -81,7 +81,7 @@ public class MiniMaxPlayer extends AbstractPlayer {
* @param p
* @return
*/
private
int
score
(
Game
game
,
Player
p
)
{
private
int
score
(
I
Game
game
,
Player
p
)
{
if
(
game
.
isWinner
(
p
))
{
return
1
;
}
...
...
@@ -113,7 +113,8 @@ public class MiniMaxPlayer extends AbstractPlayer {
/**
* A inner class only to be used by MiniMax player
* This class keeps track of a move and a score associated with that move
* @author mva021
*
* @author Martin Vatshelle - martin.vatshelle@uib.no
*
*/
class
Strategy
{
...
...
src/main/java/inf101/v20/sem2/games/PlayerList.java
View file @
0a460a98
...
...
@@ -4,8 +4,11 @@ import java.util.ArrayList;
import
java.util.Iterator
;
/**
* This class keep track of players and who's turn it is.
* @author mva021
* This class keep track of players and who's turn it is.
* In this project that might be overkill since there are only 2 players.
* But I think the code becomes more readable when we have a PlayerList class
*
* @author Martin Vatshelle - martin.vatshelle@uib.no
*/
public
class
PlayerList
implements
Iterable
<
Player
>{
...
...
@@ -44,15 +47,23 @@ public class PlayerList implements Iterable<Player>{
updateIndex
();
}
/**
* Advances the index to the next in the list, if the end is reached
* the index restarts on the beginning.
*/
private
void
updateIndex
()
{
if
(
currentIndex
>=
players
.
size
()
||
currentIndex
<
0
)
currentIndex
=
0
;
}
/**
* This method removes a player from the list.
* In this project there is no need to remove a Player.
* But in general one might think of games with more players
* where those who loose the game is removed
*
* @param index
* @return
* @param index
The index to remove
* @return
The Player removed from the PlayerList
*/
public
Player
remove
(
int
index
)
{
Player
p
=
players
.
remove
(
index
);
...
...
src/main/java/inf101/v20/sem2/games/TicTacToe.java
View file @
0a460a98
package
inf101.v20.sem2.games
;
public
class
TicTacToe
extends
Game
{
/**
* This game is played on a n by n board, normally n = 3.
* The goal is to get 3 in a row.
*
* @author Martin Vatshelle - martin.vatshelle@uib.no
*
*/
public
class
TicTacToe
extends
AbstractGame
{
/**
* Constructor for normal 3x3 TicTacToe
*/
...
...
@@ -39,8 +46,8 @@ public class TicTacToe extends Game {
}
@Override
public
Gam
e
copy
()
{
Gam
e
newGame
=
new
TicTacToe
(
board
.
copy
(),
players
());
public
TicTacTo
e
copy
()
{
TicTacTo
e
newGame
=
new
TicTacToe
(
board
.
copy
(),
players
());
newGame
.
setPlayer
(
getCurrentPlayer
());
return
newGame
;
}
...
...
src/main/java/inf101/v20/sem2/terminal/ConsolePlayer.java
View file @
0a460a98
...
...
@@ -6,7 +6,7 @@ import java.util.Scanner;
import
inf101.v20.sem2.grid.Location
;
import
inf101.v20.sem2.games.AbstractPlayer
;
import
inf101.v20.sem2.games.Four
i
nRow
;
import
inf101.v20.sem2.games.Four
I
nRow
;
import
inf101.v20.sem2.games.IGame
;
/**
...
...
@@ -57,8 +57,8 @@ public class ConsolePlayer extends AbstractPlayer {
@Override
public
Location
getMove
(
IGame
game
)
{
game
.
getGameBoard
().
printBoard
();
if
(
game
instanceof
Four
i
nRow
)
{
return
getColumn
((
Four
i
nRow
)
game
);
if
(
game
instanceof
Four
I
nRow
)
{
return
getColumn
((
Four
I
nRow
)
game
);
}
else
return
getLocation
(
game
);
...
...
@@ -67,7 +67,7 @@ public class ConsolePlayer extends AbstractPlayer {
/**
* Reads input for the FourInARow game
*/
private
Location
getColumn
(
Four
i
nRow
game
)
{
private
Location
getColumn
(
Four
I
nRow
game
)
{
System
.
out
.
println
(
"Player "
+
this
.
toString
()+
" type [Col] to make a move."
);
boolean
done
=
false
;
int
col
=
0
;
...
...
src/main/java/inf101/v20/sem2/terminal/TerminalMenu.java
View file @
0a460a98
...
...
@@ -3,7 +3,7 @@ package inf101.v20.sem2.terminal;
import
java.util.ArrayList
;
import
java.util.Scanner
;
import
inf101.v20.sem2.games.Four
i
nRow
;
import
inf101.v20.sem2.games.Four
I
nRow
;
import
inf101.v20.sem2.games.IGame
;
import
inf101.v20.sem2.games.MiniMaxPlayer
;
import
inf101.v20.sem2.games.Player
;
...
...
@@ -42,7 +42,7 @@ public class TerminalMenu {
break
;
case
2
:
game
=
new
Four
i
nRow
(
players
);
game
=
new
Four
I
nRow
(
players
);
break
;
default
:
throw
new
IllegalArgumentException
(
"Unexpected value: "
+
choice
);
...
...
src/test/java/inf101/v20/sem2/games/FourinRowTest.java
View file @
0a460a98
...
...
@@ -14,7 +14,7 @@ class FourinRowTest {
public
final
static
Player
player1
=
new
ConsolePlayer
(
"X"
,
"Martin"
);
public
final
static
Player
player2
=
new
ConsolePlayer
(
"O"
,
"Laura"
);
public
Four
i
nRow
game
;
public
Four
I
nRow
game
;
public
final
Random
rand
=
new
Random
();
@BeforeEach
...
...
@@ -22,8 +22,8 @@ class FourinRowTest {
game
=
makeGame
();
}
public
static
Four
i
nRow
makeGame
()
{
Four
i
nRow
game
=
new
Four
i
nRow
();
public
static
Four
I
nRow
makeGame
()
{
Four
I
nRow
game
=
new
Four
I
nRow
();
game
.
addPlayer
(
player1
);
game
.
addPlayer
(
player2
);
return
game
;
...
...
@@ -64,7 +64,7 @@ class FourinRowTest {
@Test
void
testCopy
()
{
Game
newGame
=
game
.
copy
();
Abstract
Game
newGame
=
game
.
copy
();
for
(
Location
loc
:
game
.
getGameBoard
().
locations
())
{
assertTrue
(
game
.
getGameBoard
().
get
(
loc
)
==
newGame
.
getGameBoard
().
get
(
loc
));
}
...
...
src/test/java/inf101/v20/sem2/games/GameTest.java
View file @
0a460a98
...
...
@@ -12,13 +12,13 @@ public class GameTest {
@Test
void
TwoAICanPlay
()
{
playGame
(
new
TicTacToe
(
getMiniMaxPlayers
()));
playGame
(
new
Four
i
nRow
(
getMiniMaxPlayers
()));
playGame
(
new
Four
I
nRow
(
getMiniMaxPlayers
()));
}
@Test
void
TwoRandomCanPlay
()
{
playGame
(
new
TicTacToe
(
getRandomPlayers
()));
playGame
(
new
Four
i
nRow
(
getRandomPlayers
()));
playGame
(
new
Four
I
nRow
(
getRandomPlayers
()));
}
@Test
...
...
@@ -26,7 +26,7 @@ public class GameTest {
int
aiwins
=
0
;
int
randomwins
=
0
;
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
Game
game
=
new
TicTacToe
(
getTwoDifferentAI
());
Abstract
Game
game
=
new
TicTacToe
(
getTwoDifferentAI
());
int
result
=
AICanBeatRandom
(
game
);
if
(
result
==
1
)
aiwins
++;
...
...
@@ -41,7 +41,7 @@ public class GameTest {
int
aiwins
=
0
;
int
randomwins
=
0
;
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
Game
game
=
new
Four
i
nRow
(
getTwoDifferentAI
());
Abstract
Game
game
=
new
Four
I
nRow
(
getTwoDifferentAI
());
int
result
=
AICanBeatRandom
(
game
);
if
(
result
==
1
)
aiwins
++;
...
...
@@ -52,7 +52,7 @@ public class GameTest {
}
int
AICanBeatRandom
(
Game
game
)
{
int
AICanBeatRandom
(
Abstract
Game
game
)
{
playGame
(
game
);
for
(
Player
player
:
game
.
players
())
{
if
(
game
.
isWinner
(
player
))
{
...
...
@@ -87,7 +87,7 @@ public class GameTest {
return
players
;
}
void
playGame
(
Game
game
)
{
void
playGame
(
Abstract
Game
game
)
{
game
.
start
();
assertTrue
(
game
.
gameOver
());
}
...
...
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