Commit 0a460a98 authored by mva021's avatar mva021
Browse files

Updated the Game classes with comments and renamed the FourInRow class

parent 11a093a9
package inf101.v20.sem2.GUI;
import inf101.v20.sem2.games.Game;
import inf101.v20.sem2.games.AbstractGame;
import inf101.v20.sem2.games.TicTacToe;
public class GUIMain {
public static void main(String[] args) {
Game game = new TicTacToe(GameGUI.getPlayers());
AbstractGame game = new TicTacToe(GameGUI.getPlayers());
MNKGameGUI gameGUI = new MNKGameGUI(game);
GameGUI gui = new GameGUI(gameGUI);
}
......
......@@ -10,8 +10,8 @@ import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import inf101.v20.sem2.games.FourinRow;
import inf101.v20.sem2.games.Game;
import inf101.v20.sem2.games.FourInRow;
import inf101.v20.sem2.games.AbstractGame;
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 FourinRow(players));
this.gameBoard = new MNKGameGUI(new FourInRow(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(AbstractGame.piece1));
//add player2
if(promptMultiplayer()) {
players.add(new GuiPlayer(Game.piece2));
players.add(new GuiPlayer(AbstractGame.piece2));
}else {
//make AI
//TODO: prompt for level of intelligence in AI player
players.add(new MiniMaxPlayer(Game.piece2, 5));
players.add(new MiniMaxPlayer(AbstractGame.piece2, 5));
}
......
......@@ -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.AbstractGame;
/**
*
......@@ -20,11 +20,11 @@ public class MNKGameGUI extends JPanel{
private static final long serialVersionUID = 8755882090377973497L;
// Fields
private Game game; //the game logic
private AbstractGame 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(AbstractGame 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(AbstractGame newGame) {
this.game = newGame;
this.game.setGui(this);
//updateMessage();
......
......@@ -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 AbstractGame 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 AbstractGame(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 AbstractGame(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
*/
protected boolean gameOver() {
public 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();
......
......@@ -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 FourinRow() {
public FourInRow() {
super(new GameBoard(6, 7));
}
public FourinRow(Iterable<Player> players) {
public FourInRow(Iterable<Player> players) {
super(new GameBoard(6, 7),players);
}
public FourinRow(GameBoard board, Iterable<Player> players) {
public FourInRow(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 FourinRow(board.copy(),players);
public AbstractGame copy() {
AbstractGame newGame = new FourInRow(board.copy(),players);
newGame.setPlayer(getCurrentPlayer());
return newGame;
}
......
......@@ -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();
}
......@@ -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();
IGame 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(IGame 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{
......
......@@ -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);
......
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 Game copy() {
Game newGame = new TicTacToe(board.copy(),players());
public TicTacToe copy() {
TicTacToe newGame = new TicTacToe(board.copy(),players());
newGame.setPlayer(getCurrentPlayer());
return newGame;
}
......
......@@ -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.FourinRow;
import inf101.v20.sem2.games.FourInRow;
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 FourinRow) {
return getColumn((FourinRow) game);
if(game instanceof FourInRow) {
return getColumn((FourInRow) game);
}
else
return getLocation(game);
......@@ -67,7 +67,7 @@ public class ConsolePlayer extends AbstractPlayer {
/**
* Reads input for the FourInARow game
*/
private Location getColumn(FourinRow game) {
private Location getColumn(FourInRow game) {
System.out.println("Player "+this.toString()+" type [Col] to make a move.");
boolean done = false;
int col = 0;
......
......@@ -3,7 +3,7 @@ package inf101.v20.sem2.terminal;
import java.util.ArrayList;
import java.util.Scanner;
import inf101.v20.sem2.games.FourinRow;
import inf101.v20.sem2.games.FourInRow;
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 FourinRow(players);
game = new FourInRow(players);
break;
default:
throw new IllegalArgumentException("Unexpected value: " + choice);
......
......@@ -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 FourinRow game;
public FourInRow game;
public final Random rand = new Random();
@BeforeEach
......@@ -22,8 +22,8 @@ class FourinRowTest {
game = makeGame();
}
public static FourinRow makeGame() {
FourinRow game = new FourinRow();
public static FourInRow makeGame() {
FourInRow game = new FourInRow();
game.addPlayer(player1);
game.addPlayer(player2);
return game;
......@@ -64,7 +64,7 @@ class FourinRowTest {
@Test
void testCopy() {
Game newGame = game.copy();
AbstractGame newGame = game.copy();
for(Location loc : game.getGameBoard().locations()) {
assertTrue(game.getGameBoard().get(loc) == newGame.getGameBoard().get(loc));
}
......
......@@ -12,13 +12,13 @@ public class GameTest {
@Test
void TwoAICanPlay() {
playGame(new TicTacToe(getMiniMaxPlayers()));
playGame(new FourinRow(getMiniMaxPlayers()));
playGame(new FourInRow(getMiniMaxPlayers()));
}
@Test
void TwoRandomCanPlay() {
playGame(new TicTacToe(getRandomPlayers()));
playGame(new FourinRow(getRandomPlayers()));
playGame(new FourInRow(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());
AbstractGame 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 FourinRow(getTwoDifferentAI());
AbstractGame game = new FourInRow(getTwoDifferentAI());
int result = AICanBeatRandom(game);
if(result == 1)
aiwins++;
......@@ -52,7 +52,7 @@ public class GameTest {
}
int AICanBeatRandom(Game game) {
int AICanBeatRandom(AbstractGame 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(AbstractGame game) {
game.start();
assertTrue(game.gameOver());
}
......
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