APP_EXTRA_CREDITS = Arrays.asList(//
- /* "Graphics by Foo Bar" */
- );
- /**
- * Help text. Could be used for an in-game help page, perhaps.
- *
- * Use \n
for new lines, \f between pages (if multi-page).
- */
- public static final String APP_HELP = "Help:\n";
-}
diff --git a/src/interfaces/GUI.java b/src/interfaces/GUI.java
deleted file mode 100644
index a5ad078..0000000
--- a/src/interfaces/GUI.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package interfaces;
-
-import board.IBoard;
-import objects.GameObject;
-import objects.Player;
-import objects.Token;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionListener;
-
-public abstract class GUI implements ActionListener, IGameInterface {
- final int BUTTON_HEIGHT = 25;
- final int BUTTON_WIDTH = 50;
- final int TILE_HEIGHT = 50;
- final int HEIGHT_GAP = 10;
- final int WIDTH_GAP = 10;
-
- JButton[] dropButtons;
- JButton resetButton;
- JTextPane[] tiles;
- JLabel infoLabel;
- IBoard board;
- JPanel mainPanel;
- JFrame frame;
-
- Player currentPlayer;
-
- public void displayBoard() {
- for (JTextPane pane : this.tiles) {
- this.mainPanel.remove(pane);
- }
- this.tiles = new JTextPane[this.board.getWidth() * this.board.getHeight()];
- readTiles();
- this.frame.validate();
- }
-
- void readTiles() {
- int k = 0;
- for (int i = board.getHeight() - 1; i > -1; i--) {
- for (int j = 0; j < board.getWidth(); j++) {
- JTextPane textPane = new JTextPane();
- this.tiles[k++] = textPane;
- textPane.setEditable(false);
- textPane.setBackground(Color.BLUE);
- GameObject obj = board.get(j,i);
- textPane.setBorder(BorderFactory.createLineBorder(obj.getColor(), 50, true));
- textPane.setPreferredSize(new Dimension(BUTTON_WIDTH, TILE_HEIGHT));
- mainPanel.add(textPane, BorderLayout.PAGE_START);
- }
- }
- }
-
- boolean dropObject(int i) {
- return this.board.drop(i, new Token(currentPlayer));
- }
-
- public void displayMessage(String s) {
- infoLabel.setText(s);
- }
-}
diff --git a/src/interfaces/IGameInterface.java b/src/interfaces/IGameInterface.java
deleted file mode 100644
index 123bd64..0000000
--- a/src/interfaces/IGameInterface.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package interfaces;
-
-interface IGameInterface {
- void displayMessage(String s);
- void displayBoard();
-}
diff --git a/src/interfaces/NInARowGUI.java b/src/interfaces/NInARowGUI.java
deleted file mode 100644
index 53bd83d..0000000
--- a/src/interfaces/NInARowGUI.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package interfaces;
-
-import board.IBoard;
-import events.Block;
-import events.Bomb;
-import objects.GameObject;
-import objects.Player;
-import objects.Token;
-
-import javax.swing.*;
-import javax.swing.border.EmptyBorder;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-
-public class NInARowGUI extends GUI {
- private Bomb bomb = new Bomb();
- private Block block = new Block();
- private JLabel eventLabel;
-
- public NInARowGUI(int width, int height, IBoard board) {
- if (width < 3 || height < 3 || height > 50 || width > 50) {
- throw new IllegalArgumentException("Invalid game size.");
- }
- if (width != board.getWidth() || height != board.getHeight()) {
- throw new IllegalArgumentException("The board does not match the gui.");
- }
- this.board = board;
- int playerNum = 0;
- while (playerNum == 0) {
- try {
- String num = JOptionPane.showInputDialog("Number of players: ");
- if (num == null) {
- System.exit(0);
- }
- playerNum = Integer.parseInt(num);
- if (playerNum > width) {
- JOptionPane.showMessageDialog(null, "Number of players can't be higher than " + width, "Error", JOptionPane.ERROR_MESSAGE);
- playerNum = 0;
-
- }
- } catch (NumberFormatException e) {
- JOptionPane.showMessageDialog(null, "Invalid input.", "Error", JOptionPane.ERROR_MESSAGE);
- }
- }
- for (int i = 0; i < playerNum; i++) {
- String playerName = "";
- while (playerName.equals("")) {
- playerName = JOptionPane.showInputDialog(String.format("Name of player %d: ", i+1));
- if (playerName == null) {
- System.exit(0);
- }
- }
- Color color = null;
- while (color == null) {
- color = JColorChooser.showDialog(null, "Choose a color", Color.RED);
- if (color == null) {
- System.exit(0);
- }
- if (color == Color.lightGray || color == Color.blue || color == Color.black) {
- JOptionPane.showMessageDialog(null, "The chosen color is reserved. Please choose another color.", "Error", JOptionPane.ERROR_MESSAGE);
- color = null;
- }
- }
- Player player = new Player(playerName, color);
- if (!this.board.addPlayer(player)) {
- JOptionPane.showMessageDialog(null, "Player is not unique. Please try again.", "Error", JOptionPane.ERROR_MESSAGE);
- i--;
- }
- }
- initialize(width, height);
- }
-
- private void initialize(int width, int height) {
- JFrame frame = new JFrame("Four in a row");
- frame.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- System.exit(0);
- }
- });
- int fullWidth = BUTTON_WIDTH * width + (WIDTH_GAP + 1) * width;
- int fullHeight = BUTTON_HEIGHT + (TILE_HEIGHT * height) + HEIGHT_GAP * (height) + TILE_HEIGHT;
-
- this.frame = frame;
- JPanel container = new JPanel();
- container.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
- container.setPreferredSize(new Dimension(fullWidth, fullHeight + TILE_HEIGHT + 2 * BUTTON_HEIGHT));
- frame.add(container);
-
- JPanel panel3 = new JPanel();
- this.resetButton = new JButton("Reset");
- this.resetButton.addActionListener(this);
- panel3.add(this.resetButton);
- for (Player player : board.getPlayers()) {
- JLabel playerLabel = new JLabel(player.toString());
- playerLabel.setForeground(player.getColor());
- panel3.add(playerLabel);
- }
- container.add(panel3);
-
- JPanel panel2 = new JPanel();
- this.mainPanel = panel2;
- panel2.setBackground(Color.BLUE);
- panel2.setLayout(new FlowLayout(FlowLayout.CENTER, HEIGHT_GAP, WIDTH_GAP));
- panel2.setPreferredSize(new Dimension(fullWidth, fullHeight));
- dropButtons = new JButton[width];
- for (int i = 0; i < width; i++) {
- JButton button = new JButton();
- button.addActionListener(this);
- button.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
- dropButtons[i] = button;
- panel2.add(button, BorderLayout.PAGE_START);
- }
- tiles = new JTextPane[width * height];
- readTiles();
- container.add(panel2);
-
- infoLabel = new JLabel();
- infoLabel.setPreferredSize(new Dimension(fullWidth, BUTTON_HEIGHT));
- infoLabel.setBorder(new EmptyBorder(10, 10, 10, 10));
- container.add(infoLabel);
-
- eventLabel = new JLabel();
- eventLabel.setPreferredSize(new Dimension(fullWidth, BUTTON_HEIGHT));
- eventLabel.setBorder(new EmptyBorder(10, 10, 10, 10));
- container.add(eventLabel);
-
- frame.validate();
- frame.pack();
- frame.setVisible(true);
- this.currentPlayer = board.nextPlayer();
- displayMessage("It's " + this.currentPlayer + "'s turn.");
- }
-
- @Override
- public void actionPerformed(ActionEvent e) {
- if (e.getSource() == this.resetButton) {
- this.board.flush();
- displayBoard();
- this.currentPlayer = this.board.nextPlayer();
- displayMessage("It's " + this.currentPlayer + "'s turn.");
- }
- if (!(this.board.won() || this.board.isFull())) {
- for (int i = 0; i < this.dropButtons.length; i++) {
- if (e.getSource() == this.dropButtons[i]) {
- if (dropObject(i)) {
- displayBoard();
- if (this.board.won()) {
- GameObject winnerObject = this.board.get(i, this.board.getTopObject(i));
- displayMessage(((Token)winnerObject).getOwner() + " won.");
- } else {
- triggerEvents();
- if (board.isFull()) {
- displayMessage("It's a draw");
- } else {
- this.currentPlayer = board.nextPlayer();
- displayMessage("It's " + this.currentPlayer + "'s turn.");
- }
- }
- } else {
- displayMessage("That column is full.");
- }
- }
- }
- }
- }
-
- private void triggerEvents() {
- if (bomb.rollDie(this.board, 2)) {
- eventLabel.setText(bomb.announcement());
- displayBoard();
- } else if (block.rollDie(this.board, 1)) {
- eventLabel.setText(block.announcement());
- displayBoard();
- } else {
- eventLabel.setText("");
- }
- }
-}
diff --git a/src/main/java/inf101/v18/connectfour/Main.java b/src/main/java/inf101/v18/connectfour/Main.java
new file mode 100644
index 0000000..60b33c8
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/Main.java
@@ -0,0 +1,87 @@
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.interfaces.*;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * This is a "base" class, which lets the user choose a game.
+ */
+public class Main {
+ private static final int BOARD_WIDTH = 7;
+ private static final int BOARD_HEIGHT = 6;
+
+ public static void main(String[] args) {
+ ArrayList gamemodes = new ArrayList<>();
+ gamemodes.add("Connect Four");
+ gamemodes.add("Connect Four classic");
+ gamemodes.add("Tic-Tac-Toe");
+ if (System.console() != null) {
+ gamemodes.add("Connect Four CLI");
+ gamemodes.add("Tic-Tac-Toe CLI");
+ }
+
+ JOptionPane.showMessageDialog(
+ null,
+ "This software contains several games:\n" +
+ "* Connect Four is a custom version with customizable number of players.\n" +
+ "* Connect Four classic is a version closer to that of the original analogue version. Two human players are required.\n" +
+ "* Tic-Tac-Toe is a game built upon the same framework as Connect Four, but behaves quite differently. Two human players are required.\n" +
+ "* Connect Four CLI is a CLI implementation of connect four. It supports two players or one player and one ai.\n" +
+ "* Tic-Tac-Toe CLI is a CLI implementation of Tic-Tac-Toe. It supports two players or one player and one ai.",
+ "Game-types",
+ JOptionPane.INFORMATION_MESSAGE);
+ String selectedValue = (String)JOptionPane.showInputDialog(
+ null,
+ "Select a game from the list below:",
+ "Game type",
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ gamemodes.toArray(),
+ gamemodes.get(0));
+
+
+ if (selectedValue == null) {
+ System.exit(0);
+ }
+ boolean playAgain = true;
+ switch (selectedValue) {
+ case "Tic-Tac-Toe":
+ new TicTacToeGUI();
+ break;
+ case "Connect Four classic":
+ new ConnectFourClassicGUI(BOARD_WIDTH, BOARD_HEIGHT);
+ break;
+ case "Connect Four":
+ new ConnectFourGUI(BOARD_WIDTH, BOARD_HEIGHT);
+ break;
+ case "Connect Four CLI":
+ while (playAgain) {
+ playAgain = CLILoop(new ConnectFourCLI(7, 6));
+ }
+ break;
+ case "Tic-Tac-Toe CLI":
+ while (playAgain) {
+ playAgain = CLILoop(new TicTacToeCLI());
+ }
+ break;
+ default:
+ System.exit(0);
+ }
+ }
+
+ private static boolean CLILoop(IGameInterface gameInterface) {
+ Scanner in = new Scanner(System.in);
+ while (!gameInterface.hasWon() && !gameInterface.hasDrawn()) {
+ gameInterface.displayBoard();
+ gameInterface.doTurn();
+ }
+ if (gameInterface.hasDrawn() && !gameInterface.hasWon()) {
+ gameInterface.displayMessage("It's a draw.");
+ }
+ gameInterface.displayMessage("Do you want to play again? (y/n)");
+ return in.nextLine().toLowerCase().contains("y");
+ }
+}
diff --git a/src/board/Board.java b/src/main/java/inf101/v18/connectfour/board/Board.java
similarity index 53%
rename from src/board/Board.java
rename to src/main/java/inf101/v18/connectfour/board/Board.java
index 559854e..9f803b9 100644
--- a/src/board/Board.java
+++ b/src/main/java/inf101/v18/connectfour/board/Board.java
@@ -1,51 +1,29 @@
-package board;
+package inf101.v18.connectfour.board;
-import events.IWinCondition;
-import objects.GameObject;
-import objects.Player;
-import objects.Token;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.objects.IPlayerObject;
+import inf101.v18.connectfour.player.IPlayer;
import java.util.ArrayList;
import java.util.List;
-
+/**
+ * A board takes care of players, interacting with the grid and win-conditions.
+ */
public class Board implements IBoard{
- private final Grid grid;
- private final List players;
- private int playersTurn = 0;
- private final List conditionList;
- private boolean won = false;
+ IGrid grid;
+ List players;
+ int playersTurn = 0;
+ final List conditionList;
+ boolean won = false;
+ final IGameObject empty;
- public Board(int width, int height, GameObject obj, List conditions) {
- grid = new Grid<>(width, height, obj);
+ public Board(int width, int height, IGameObject empty, List conditions) {
+ grid = new Grid<>(width, height, empty);
players = new ArrayList<>();
conditionList = conditions;
- }
-
- @Override
- public boolean addPlayer(Player p) {
- if (!playerExists(p)) {
- players.add(p);
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public ArrayList getPlayers() {
- return new ArrayList<>(players);
- }
-
- /**
- * Gets the next player.
- *
- * @return A Player
- */
- public Player nextPlayer() {
- Player p = players.get(playersTurn);
- this.playersTurn = this.playersTurn + 2 > this.players.size() ? 0 : this.playersTurn + 1;
- return p;
+ this.empty = empty;
}
/**
@@ -54,8 +32,8 @@ public class Board implements IBoard{
* @param player The new player to test
* @return True if the player is non-unique
*/
- private boolean playerExists(Player player) {
- for (Player p : players) {
+ private boolean playerExists(IPlayer player) {
+ for (IPlayer p : players) {
if (player.equals(p)) {
return true;
}
@@ -63,24 +41,6 @@ public class Board implements IBoard{
return false;
}
- @Override
- public boolean isFull() {
- return grid.isFull();
- }
-
- /**
- * Checks if anyone has won.
- *
- * @param i The column of the last dropped object
- */
- private void checkWin(int i) {
- for (IWinCondition con : conditionList) {
- if (con.hasWon(i, getTopObject(i), this)) {
- won = true;
- }
- }
- }
-
/**
* Checks if anyone has won.
*
@@ -95,6 +55,36 @@ public class Board implements IBoard{
}
}
+ @Override
+ public boolean addPlayer(IPlayer p) {
+ if (!playerExists(p)) {
+ players.add(p);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public ArrayList getPlayers() {
+ return new ArrayList<>(players);
+ }
+
+ @Override
+ public IPlayer nextPlayer() {
+ if (players.isEmpty()) {
+ return null;
+ }
+ IPlayer p = players.get(playersTurn);
+ this.playersTurn = this.playersTurn + 2 > this.players.size() ? 0 : this.playersTurn + 1;
+ return p;
+ }
+
+ @Override
+ public boolean isFull() {
+ return grid.isFull();
+ }
+
@Override
public boolean won() {
return won;
@@ -107,11 +97,6 @@ public class Board implements IBoard{
won = false;
}
- @Override
- public int getTopObject(int column) {
- return grid.getTopObject(column);
- }
-
@Override
public int getHeight() {
return grid.getHeight();
@@ -123,27 +108,28 @@ public class Board implements IBoard{
}
@Override
- public void set(int x, int y, GameObject element) {
+ public void set(int x, int y, IGameObject element) {
grid.set(x, y, element);
- if (element instanceof Token) {
+ if (element instanceof IPlayerObject) {
checkWin(x, y);
}
}
@Override
- public boolean drop(int i, GameObject element) {
- boolean dropped = grid.drop(i, element);
- if (element instanceof Token) {
- checkWin(i);
- }
- return dropped;
- }
+ public IGameObject get(int x, int y) { return grid.get(x, y); }
@Override
- public GameObject get(int x, int y) { return grid.get(x, y); }
-
- @Override
- public IGrid copy() {
+ public IGrid copy() {
return grid.copy();
}
+
+ @Override
+ public IBoard copyAll() {
+ Board newBoard = new Board(getWidth(), getHeight(), empty, conditionList);
+ newBoard.players = new ArrayList<>(players);
+ newBoard.won = won;
+ newBoard.grid = copy();
+ newBoard.playersTurn = playersTurn;
+ return newBoard;
+ }
}
\ No newline at end of file
diff --git a/src/board/Grid.java b/src/main/java/inf101/v18/connectfour/board/Grid.java
similarity index 61%
rename from src/board/Grid.java
rename to src/main/java/inf101/v18/connectfour/board/Grid.java
index efe315d..92767de 100644
--- a/src/board/Grid.java
+++ b/src/main/java/inf101/v18/connectfour/board/Grid.java
@@ -1,14 +1,30 @@
-package board;
-
-import objects.Token;
+package inf101.v18.connectfour.board;
+/**
+ * An implementation of IGrid
+ *
+ * @param Can be anything
+ */
public class Grid implements IGrid {
private final T[][] grid;
private final int width;
private final int height;
private final T empty;
+ /**
+ * Creates a new grid.
+ *
+ * @param width The width of the new grid
+ * @param height The height of the new grid
+ * @param object The default object for all cells
+ */@SuppressWarnings("unchecked")
public Grid(int width, int height, T object) {
+ if (!(width > 0 && height > 0)) {
+ throw new IllegalArgumentException("Negative or zero height and/or width.");
+ }
+ if (object == null) {
+ throw new IllegalArgumentException("Grid can't be initialized with null");
+ }
T[][] list = (T[][])new Object[width][height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
@@ -21,6 +37,7 @@ public class Grid implements IGrid {
this.height = height;
}
+ @Override
public void flush() {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
@@ -29,57 +46,36 @@ public class Grid implements IGrid {
}
}
+ @Override
public boolean isFull() {
- int empty = 0;
for (T[] list : grid) {
for (T item : list) {
if (this.empty.getClass().isInstance(item)) {
- empty++;
+ return false;
}
}
}
- return empty < 1;
- }
-
- @Override
- public int getTopObject(int column) {
- for (int j = this.height - 1; j > -1; j--) {
- if (grid[column][j] instanceof Token) {
- return j;
- }
- }
- return -1;
+ return true;
}
@Override
public int getHeight() {
- return this.height;
+ return height;
}
@Override
public int getWidth() {
- return this.width;
- }
-
- @Override
- public boolean drop(int i, T element) {
- if (i > width || i < 0) {
- throw new IllegalArgumentException("Index out of bounds.");
- }
- for (int j = 0; j < this.height; j++) {
- if (this.empty.getClass().isInstance(grid[i][j])) {
- grid[i][j] = element;
- return true;
- }
- }
- return false;
+ return width;
}
@Override
public void set(int x, int y, T element) {
- if (x > width || y > height || x < 0 || y < 0) {
+ if (x >= width || y >= height || x < 0 || y < 0) {
throw new IllegalArgumentException("Index out of bounds.");
}
+ if (element == null) {
+ throw new IllegalArgumentException("This grid does not accept null.");
+ }
grid[x][y] = element;
}
@@ -94,7 +90,9 @@ public class Grid implements IGrid {
@Override
public IGrid copy() {
Grid newGrid = new Grid<>(width, height, empty);
- System.arraycopy(grid, 0, newGrid.grid, 0, width);
+ for (int i = 0; i < width; i++) {
+ System.arraycopy(grid[i], 0, newGrid.grid[i], 0, height);
+ }
return newGrid;
}
}
diff --git a/src/board/IBoard.java b/src/main/java/inf101/v18/connectfour/board/IBoard.java
similarity index 56%
rename from src/board/IBoard.java
rename to src/main/java/inf101/v18/connectfour/board/IBoard.java
index 0616d71..b088c7a 100644
--- a/src/board/IBoard.java
+++ b/src/main/java/inf101/v18/connectfour/board/IBoard.java
@@ -1,25 +1,28 @@
-package board;
+package inf101.v18.connectfour.board;
-import objects.GameObject;
-import objects.Player;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.player.IPlayer;
import java.util.List;
-public interface IBoard extends IGrid {
+/**
+ * An interface representing a game board.
+ */
+public interface IBoard extends IGrid {
/**
* Adds a new player to the board.
*
* @param p The player to add
* @return True if the player is valid
*/
- boolean addPlayer(Player p);
+ boolean addPlayer(IPlayer p);
/**
* Gets the next player from the board.
*
* @return A player
*/
- Player nextPlayer();
+ IPlayer nextPlayer();
/**
* Find out if someone has won.
@@ -33,18 +36,17 @@ public interface IBoard extends IGrid {
*/
void flush();
- /**
- * Gets the position of the topmost object in the board's grid.
- *
- * @param column The target column
- * @return A position or -1 if all rows are empty
- */
- int getTopObject(int column);
-
/**
* Gets a copy of the players list.
*
* @return A list of players
*/
- List getPlayers();
+ List getPlayers();
+
+ /**
+ * Makes a copy of the entire board.
+ *
+ * @return A new, but identical board
+ */
+ IBoard copyAll();
}
diff --git a/src/board/IGrid.java b/src/main/java/inf101/v18/connectfour/board/IGrid.java
similarity index 59%
rename from src/board/IGrid.java
rename to src/main/java/inf101/v18/connectfour/board/IGrid.java
index 561f137..3da3198 100644
--- a/src/board/IGrid.java
+++ b/src/main/java/inf101/v18/connectfour/board/IGrid.java
@@ -1,5 +1,10 @@
-package board;
+package inf101.v18.connectfour.board;
+/**
+ * An IGrid can store and retrieve anything of type T.
+ *
+ * @param
+ */
public interface IGrid {
/**
@@ -19,30 +24,20 @@ public interface IGrid {
* y must be greater than or equal to 0 and less than getHeight().
* x must be greater than or equal to 0 and less than getWidth().
*
- * @param x The column of the cell to change the contents of.
- * @param y The row of the cell to change the contents of.
- * @param element The contents the cell is to have.
+ * @param x The column of the cell to change the contents of
+ * @param y The row of the cell to change the contents of
+ * @param element The contents the cell is to have
*/
void set(int x, int y, T element);
/**
- * Drops an element into column i.
- *
- * @param i The target column
- * @param element The element to be dropped
- * @return True if the column had space for the element
- */
- boolean drop(int i, T element);
-
- /**
- *
* Get the contents of the cell in the given x,y location.
*
* y must be greater than or equal to 0 and less than getHeight().
* x must be greater than or equal to 0 and less than getWidth().
*
- * @param x The column of the cell to get the contents of.
- * @param y The row of the cell to get contents of.
+ * @param x The column of the cell to get the contents of
+ * @param y The row of the cell to get contents of
*/
T get(int x, int y);
@@ -61,10 +56,7 @@ public interface IGrid {
boolean isFull();
/**
- * Retrieves the position of the topmost element from a column.
- *
- * @param column The target column
- * @return The y-position of the top element
+ * Sets all spaces in the grid to the element representing an empty tile.
*/
- int getTopObject(int column);
+ void flush();
}
\ No newline at end of file
diff --git a/src/main/java/inf101/v18/connectfour/board/IVerticalBoard.java b/src/main/java/inf101/v18/connectfour/board/IVerticalBoard.java
new file mode 100644
index 0000000..c723325
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/board/IVerticalBoard.java
@@ -0,0 +1,55 @@
+package inf101.v18.connectfour.board;
+
+import inf101.v18.connectfour.objects.IGameObject;
+
+/**
+ * An IBoard with added methods for vertical interactions.
+ */
+public interface IVerticalBoard extends IBoard {
+ /**
+ * Retrieves the position of the "topmost" element in a column.
+ *
+ * Will return -1 if the column is empty.
+ *
+ * @param column The target column
+ * @return The y-position of the top element
+ */
+ int getTopObject(int column);
+
+ /**
+ * Retrieves the position of the "topmost" element of class clazz in a column.
+ *
+ * Will return -1 if the column is empty.
+ *
+ * @param column The target column
+ * @param clazz The target class
+ * @return The y-position of the top element
+ */
+ int getTopObject(int column, Class> clazz);
+
+ /**
+ * Drops an element into column i.
+ *
+ * i must be greater than or equal to 0 and less than getWidth.
+ *
+ * @param i The target column
+ * @param element The element to be dropped
+ * @return True if the column had space for the element
+ */
+ boolean drop(int i, IGameObject element);
+
+ /**
+ * Moves all floating elements one tile down.
+ */
+ void gravitate();
+
+ /**
+ * Tries to count the amount of steps required to gravitate all floating objects.
+ *
+ * @return An integer
+ */
+ int floatingObjects();
+
+ @Override
+ IVerticalBoard copyAll();
+}
diff --git a/src/main/java/inf101/v18/connectfour/board/VerticalBoard.java b/src/main/java/inf101/v18/connectfour/board/VerticalBoard.java
new file mode 100644
index 0000000..68ad6f6
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/board/VerticalBoard.java
@@ -0,0 +1,118 @@
+package inf101.v18.connectfour.board;
+
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.objects.IPlayerObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A board which supports dropping objects and gravity.
+ */
+public class VerticalBoard extends Board implements IVerticalBoard {
+ public VerticalBoard(int width, int height, IGameObject empty, List conditions) {
+ super(width, height, empty, conditions);
+ }
+
+ /**
+ * Checks if anyone has won.
+ *
+ * @param i The column of the last dropped object
+ */
+ private void checkWin(int i) {
+ for (IWinCondition con : conditionList) {
+ if (con.hasWon(i, getTopObject(i, IPlayerObject.class), this)) {
+ won = true;
+ }
+ }
+ }
+
+ @Override
+ public int floatingObjects() {
+ int maxFloat = 0;
+ for (int i = 0; i < getWidth(); i++) {
+ int topPos = -1;
+ int holes = 0;
+ for (int j = getHeight() - 1; j > -1; j--) {
+ if (!(empty.getClass().isInstance(grid.get(i, j)))) {
+ topPos = j;
+ } else if (topPos != -1) {
+ holes++;
+ }
+ }
+ if (holes > maxFloat) {
+ maxFloat = holes;
+ }
+ }
+ return maxFloat;
+ }
+
+ @Override
+ public void gravitate() {
+ for (int i = 0; i < getWidth(); i++) {
+ for (int j = 1; j < getHeight(); j++) {
+ if (!(empty.getClass().isInstance(grid.get(i, j))) && empty.getClass().isInstance(grid.get(i, j - 1))) {
+ grid.set(i, j - 1, grid.get(i, j));
+ grid.set(i, j, empty);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean drop(int i, IGameObject element) {
+ if (i >= getWidth() || i < 0) {
+ throw new IllegalArgumentException("Index out of bounds.");
+ }
+ if (element == null) {
+ throw new IllegalArgumentException("This grid does not accept null.");
+ }
+ for (int j = 0; j < getHeight(); j++) {
+ if (empty.getClass().isInstance(get(i, j))) {
+ set(i, j, element);
+ if (element instanceof IPlayerObject) {
+ checkWin(i);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getTopObject(int i) {
+ if (i < 0 || i >= getWidth()) {
+ throw new IllegalArgumentException("Index out of bounds.");
+ }
+ for (int j = getHeight() - 1; j > -1; j--) {
+ if (!(empty.getClass().isInstance(get(i, j)))) {
+ return j;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getTopObject(int i, Class> clazz) {
+ if (i < 0 || i >= getWidth()) {
+ throw new IllegalArgumentException("Index out of bounds.");
+ }
+ for (int j = getHeight() - 1; j > -1; j--) {
+ if (clazz.isInstance(get(i, j))) {
+ return j;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public IVerticalBoard copyAll() {
+ VerticalBoard newBoard = new VerticalBoard(getWidth(), getHeight(), empty, conditionList);
+ newBoard.players = new ArrayList<>(players);
+ newBoard.won = won;
+ newBoard.grid = copy();
+ newBoard.playersTurn = playersTurn;
+ return newBoard;
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/events/random/Block.java b/src/main/java/inf101/v18/connectfour/events/random/Block.java
new file mode 100644
index 0000000..209678b
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/events/random/Block.java
@@ -0,0 +1,24 @@
+package inf101.v18.connectfour.events.random;
+
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.Immovable;
+
+/**
+ * Blocks a random tile on the board
+ */
+public class Block extends RandomEvent {
+ @Override
+ void act(IVerticalBoard b) {
+ int i;
+ do {
+ i = random.nextInt(b.getWidth());
+ } while (!b.isFull() && !(b.get(i, b.getHeight()-1) instanceof Empty));
+ b.drop(i, new Immovable());
+ }
+
+ @Override
+ public String announcement() {
+ return "An immovable object was placed.";
+ }
+}
diff --git a/src/events/Bomb.java b/src/main/java/inf101/v18/connectfour/events/random/Bomb.java
similarity index 76%
rename from src/events/Bomb.java
rename to src/main/java/inf101/v18/connectfour/events/random/Bomb.java
index 53f899c..acb840d 100644
--- a/src/events/Bomb.java
+++ b/src/main/java/inf101/v18/connectfour/events/random/Bomb.java
@@ -1,16 +1,19 @@
-package events;
+package inf101.v18.connectfour.events.random;
-import board.IBoard;
-import objects.Empty;
-import objects.Token;
+import inf101.v18.connectfour.board.IBoard;
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.IPlayerObject;
import java.util.ArrayList;
+/**
+ * An event which removes objects from the board.
+ */
public class Bomb extends RandomEvent {
- @Override
- public void act(IBoard b) {
+ void act(IVerticalBoard b) {
int x = random.nextInt(b.getWidth());
- int y = b.getTopObject(x);
+ int y = b.getTopObject(x, IPlayerObject.class);
for (ArrayList list : generateSquare(b, x, y, random.nextInt(2) + 1)) {
b.set(list.get(0), list.get(1), new Empty());
}
@@ -29,7 +32,7 @@ public class Bomb extends RandomEvent {
ArrayList> locations = new ArrayList<>();
for (int i = x - range; i <= x + range; i++) {
for (int j = y - range; j <= y + range; j++) {
- if (i >= 0 && i < b.getWidth() && j >= 0 && j < b.getHeight() && b.get(i, j) instanceof Token) {
+ if (i >= 0 && i < b.getWidth() && j >= 0 && j < b.getHeight()) {
ArrayList coords = new ArrayList<>();
coords.add(i);
coords.add(j);
diff --git a/src/main/java/inf101/v18/connectfour/events/random/IRandomEvent.java b/src/main/java/inf101/v18/connectfour/events/random/IRandomEvent.java
new file mode 100644
index 0000000..288474d
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/events/random/IRandomEvent.java
@@ -0,0 +1,32 @@
+package inf101.v18.connectfour.events.random;
+
+import inf101.v18.connectfour.board.IVerticalBoard;
+
+/**
+ * A random event which can be run on an IVerticalBoard.
+ */
+public interface IRandomEvent {
+ /**
+ * Rolls n die, and acts if all die got a "6".
+ *
+ * @param b The board to act on
+ * @param n The number of die
+ * @return True if something happened. False otherwise
+ */
+ boolean rollDie(IVerticalBoard b, int n);
+
+ /**
+ * Flips a coin, and acts if it comes out as head.
+ *
+ * @param b The board to act on
+ * @return True if somehting happened. False otherwise
+ */
+ boolean flipCoin(IVerticalBoard b);
+
+ /**
+ * An announcement describing what just happened.
+ *
+ * @return An announcement string
+ */
+ String announcement();
+}
diff --git a/src/events/RandomEvent.java b/src/main/java/inf101/v18/connectfour/events/random/RandomEvent.java
similarity index 52%
rename from src/events/RandomEvent.java
rename to src/main/java/inf101/v18/connectfour/events/random/RandomEvent.java
index 4a035ff..741495a 100644
--- a/src/events/RandomEvent.java
+++ b/src/main/java/inf101/v18/connectfour/events/random/RandomEvent.java
@@ -1,6 +1,6 @@
-package events;
+package inf101.v18.connectfour.events.random;
-import board.IBoard;
+import inf101.v18.connectfour.board.IVerticalBoard;
import java.util.Random;
@@ -10,13 +10,8 @@ import java.util.Random;
public abstract class RandomEvent implements IRandomEvent {
final Random random = new Random();
- /**
- * Flips a coin, and acts if it comes out as head.
- *
- * @param b The board to act on
- * @return True if somehting happened. False otherwise
- */
- public boolean flipCoin(IBoard b) {
+ @Override
+ public boolean flipCoin(IVerticalBoard b) {
if (random.nextInt(2) > 0) {
act(b);
return true;
@@ -24,14 +19,8 @@ public abstract class RandomEvent implements IRandomEvent {
return false;
}
- /**
- * Rolls n die, and acts if all die got a "6".
- *
- * @param b The board to act on
- * @param n The number of die
- * @return True if something happened. False otherwise
- */
- public boolean rollDie(IBoard b, int n) {
+ @Override
+ public boolean rollDie(IVerticalBoard b, int n) {
if (random.nextInt((int)Math.pow(6, n)) < 1) {
act(b);
return true;
@@ -39,5 +28,10 @@ public abstract class RandomEvent implements IRandomEvent {
return false;
}
- public abstract void act(IBoard b);
+ /**
+ * Does something depending on the event.
+ *
+ * @param b The board to act on
+ */
+ abstract void act(IVerticalBoard b);
}
diff --git a/src/main/java/inf101/v18/connectfour/events/winning/FourInARow.java b/src/main/java/inf101/v18/connectfour/events/winning/FourInARow.java
new file mode 100644
index 0000000..a074810
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/events/winning/FourInARow.java
@@ -0,0 +1,13 @@
+package inf101.v18.connectfour.events.winning;
+
+import inf101.v18.connectfour.board.IBoard;
+
+/**
+ * A win condition used to check if a placed IPlayerObject caused four in a row.
+ */
+public class FourInARow extends InARow {
+ @Override
+ public boolean hasWon(int x, int y, IBoard board) {
+ return hasWon(x, y, board, 3);
+ }
+}
diff --git a/src/events/IWinCondition.java b/src/main/java/inf101/v18/connectfour/events/winning/IWinCondition.java
similarity index 82%
rename from src/events/IWinCondition.java
rename to src/main/java/inf101/v18/connectfour/events/winning/IWinCondition.java
index 1882628..87e3e0b 100644
--- a/src/events/IWinCondition.java
+++ b/src/main/java/inf101/v18/connectfour/events/winning/IWinCondition.java
@@ -1,6 +1,6 @@
-package events;
+package inf101.v18.connectfour.events.winning;
-import board.IBoard;
+import inf101.v18.connectfour.board.IBoard;
/**
* A condition for winning the game.
diff --git a/src/events/InARow.java b/src/main/java/inf101/v18/connectfour/events/winning/InARow.java
similarity index 95%
rename from src/events/InARow.java
rename to src/main/java/inf101/v18/connectfour/events/winning/InARow.java
index 8de9cc1..94170e2 100644
--- a/src/events/InARow.java
+++ b/src/main/java/inf101/v18/connectfour/events/winning/InARow.java
@@ -1,6 +1,6 @@
-package events;
+package inf101.v18.connectfour.events.winning;
-import board.IBoard;
+import inf101.v18.connectfour.board.IBoard;
import java.awt.*;
diff --git a/src/main/java/inf101/v18/connectfour/events/winning/ThreeInARow.java b/src/main/java/inf101/v18/connectfour/events/winning/ThreeInARow.java
new file mode 100644
index 0000000..9c88e1c
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/events/winning/ThreeInARow.java
@@ -0,0 +1,13 @@
+package inf101.v18.connectfour.events.winning;
+
+import inf101.v18.connectfour.board.IBoard;
+
+/**
+ * A win condition used to check if a placed IPlayerObject caused three in a row.
+ */
+public class ThreeInARow extends InARow {
+ @Override
+ public boolean hasWon(int x, int y, IBoard board) {
+ return hasWon(x, y, board, 2);
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/interfaces/CLI.java b/src/main/java/inf101/v18/connectfour/interfaces/CLI.java
new file mode 100644
index 0000000..63829d7
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/interfaces/CLI.java
@@ -0,0 +1,147 @@
+package inf101.v18.connectfour.interfaces;
+
+import inf101.v18.connectfour.board.IBoard;
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.player.IAI;
+import inf101.v18.connectfour.player.IPlayer;
+
+import java.awt.*;
+import java.util.InputMismatchException;
+import java.util.Scanner;
+
+/**
+ * An abstract class implementing methods common for all CLI interfaces.
+ */
+public abstract class CLI implements IGameInterface {
+ private final String ANSI_RESET = "\u001B[0m";
+ private final String ANSI_GREEN = "\u001B[92m";
+ private final String ANSI_RED = "\u001B[91m";
+ private final String ANSI_BLUE = "\u001B[94m";
+ private final String ANSI_YELLOW = "\u001B[93m";
+ private final String ANSI_MAGENTA = "\u001B[95m";
+ private final String ANSI_CYAN = "\u001B[96m";
+
+ IBoard board;
+ IPlayer currentPlayer;
+ private final Scanner in = new Scanner(System.in);
+
+ /**
+ * Converts a Color to an ansi colored string because CLI doesn't support RGB.
+ *
+ * @param color The color to convert
+ * @return An ansi colored O or an empty string
+ */
+ String colorToAnsi(Color color, char symbol) {
+ if (color == Color.green) {
+ return ANSI_GREEN + symbol + ANSI_RESET;
+ } else if (color == Color.red) {
+ return ANSI_RED + symbol + ANSI_RESET;
+ } else if (color == Color.blue) {
+ return ANSI_BLUE + symbol + ANSI_RESET;
+ } else if (color == Color.yellow) {
+ return ANSI_YELLOW + symbol + ANSI_RESET;
+ } else if (color == Color.magenta) {
+ return ANSI_MAGENTA + symbol + ANSI_RESET;
+ } else if (color == Color.cyan) {
+ return ANSI_CYAN + symbol + ANSI_RESET;
+ } else {
+ return ".";
+ }
+ }
+
+ /**
+ * Reads a name from the commandline.
+ *
+ * @param i An index representing the user being named
+ * @return A non-empty name
+ */
+ String readName(int i) {
+ String name;
+ do {
+ displayMessage("Name of player " + i + ":");
+ name = in.nextLine();
+ } while (name.equals(""));
+ return name;
+ }
+
+ /**
+ * Asks the user if they want to play alone against an AI, or with a friend.
+ *
+ * @return True if the player's input contains y
+ */
+ boolean playingAlone() {
+ displayMessage("Will you be playing alone? (y/n):");
+ return in.nextLine().toLowerCase().contains("y");
+ }
+
+ /**
+ * Gets the correct symbol for a player color
+ * @param color A color
+ * @return A symbol
+ */
+ char getSymbol(Color color) {
+ if (color == Color.red) {
+ return 'X';
+ } else if (color == Color.green) {
+ return 'O';
+ }
+ return 'O';
+ }
+
+ @Override
+ public void doTurn() {
+ boolean placed = false;
+ System.out.printf("%nIt's %s's turn (%s)%n", currentPlayer.getName(), colorToAnsi(currentPlayer.getColor(),
+ getSymbol(currentPlayer.getColor())));
+ if (currentPlayer instanceof IAI) {
+ if (board instanceof IVerticalBoard) {
+ placed = ((IVerticalGameInterface) this).dropObject(((IAI)currentPlayer).getColumn((IVerticalBoard) board));
+ } else {
+ int[] choice = ((IAI) currentPlayer).getXY(board);
+ try {
+ placed = placePlayerObject(choice[0], choice[1]);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace(); //If this happens, the AI is broken.
+ }
+ }
+ } else {
+ if (board instanceof IVerticalBoard) {
+ displayMessage("Drop token in (i):");
+ try {
+ int i = in.nextInt();
+ placed = ((IVerticalGameInterface)this).dropObject(i - 1);
+ } catch (InputMismatchException | IllegalArgumentException ignored) {
+ } finally {
+ in.nextLine();
+ }
+ } else {
+ displayMessage("Place token at (x,y):");
+ try {
+ String s = in.nextLine();
+ if (s.contains(",")) {
+ String[] numbers = s.split(",");
+ placed = placePlayerObject(Integer.parseInt(numbers[0]) - 1, Integer.parseInt(numbers[1]) - 1);
+ }
+ } catch (InputMismatchException | IllegalArgumentException | IllegalAccessException ignored) {}
+ }
+ }
+ if (!placed) {
+ displayMessage("Invalid input. Please try again.");
+ }
+ }
+
+ @Override
+ public boolean hasDrawn() {
+ return board.isFull();
+ }
+
+ @Override
+ public boolean hasWon() {
+ return board.won();
+ }
+
+ @Override
+ public void displayMessage(String s) {
+ System.out.println(s);
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/interfaces/ConnectFourCLI.java b/src/main/java/inf101/v18/connectfour/interfaces/ConnectFourCLI.java
new file mode 100644
index 0000000..c7130c9
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/interfaces/ConnectFourCLI.java
@@ -0,0 +1,69 @@
+package inf101.v18.connectfour.interfaces;
+
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.board.VerticalBoard;
+import inf101.v18.connectfour.events.winning.FourInARow;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.objects.Token;
+import inf101.v18.connectfour.player.AI;
+import inf101.v18.connectfour.player.Player;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A CLI implementation of connect four.
+ */
+public class ConnectFourCLI extends CLI implements IVerticalGameInterface {
+ public ConnectFourCLI(int width, int height) {
+ List con = new ArrayList<>();
+ con.add(new FourInARow());
+ board = new VerticalBoard(width, height, new Empty(), con);
+ board.addPlayer(new Player(readName(1), Color.green));
+ if (playingAlone()) {
+ board.addPlayer(new AI("AI", Color.red));
+ } else {
+ board.addPlayer(new Player(readName(2), Color.red));
+ }
+ currentPlayer = board.nextPlayer();
+ }
+
+ @Override
+ public void displayBoard() {
+ for (int i = 1; i <= board.getWidth(); i++) {
+ System.out.print(i + " ");
+ }
+ System.out.println();
+ for (int i = board.getHeight() - 1; i > -1; i--) {
+ for (int j = 0; j < board.getWidth(); j++) {
+ IGameObject obj = board.get(j,i);
+ System.out.print(colorToAnsi(obj.getColor(), 'O') + " ");
+ }
+ if (i > 0) {
+ System.out.println();
+ }
+ }
+ }
+
+ @Override
+ public boolean placePlayerObject(int x, int y) {
+ return false;
+ }
+
+ @Override
+ public boolean dropObject(int i) {
+ boolean hasDropped = ((IVerticalBoard)board).drop(i, new Token(currentPlayer));
+ if (!hasDropped) {
+ return false;
+ }
+ if (board.won()) {
+ displayBoard();
+ displayMessage("\n" + currentPlayer.getName() + " won");
+ }
+ currentPlayer = board.nextPlayer();
+ return true;
+ }
+}
diff --git a/src/interfaces/FourInARowGUI.java b/src/main/java/inf101/v18/connectfour/interfaces/ConnectFourClassicGUI.java
similarity index 58%
rename from src/interfaces/FourInARowGUI.java
rename to src/main/java/inf101/v18/connectfour/interfaces/ConnectFourClassicGUI.java
index 8e008db..6e8ae53 100644
--- a/src/interfaces/FourInARowGUI.java
+++ b/src/main/java/inf101/v18/connectfour/interfaces/ConnectFourClassicGUI.java
@@ -1,9 +1,14 @@
-package interfaces;
+package inf101.v18.connectfour.interfaces;
-import board.IBoard;
-import objects.GameObject;
-import objects.Player;
-import objects.Token;
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.board.VerticalBoard;
+import inf101.v18.connectfour.events.winning.FourInARow;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.objects.IPlayerObject;
+import inf101.v18.connectfour.player.IPlayer;
+import inf101.v18.connectfour.player.Player;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@@ -11,17 +16,20 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
+import java.util.ArrayList;
-public class FourInARowGUI extends GUI {
-
- public FourInARowGUI(int width, int height, IBoard board) {
- if (width < 3 || height < 3 || height > 50 || width > 50) {
+/**
+ * A GUI implementation of connect four.
+ * This implementation tries to closely replicate the "original" version.
+ */
+public class ConnectFourClassicGUI extends ConnectGUI {
+ public ConnectFourClassicGUI(int width, int height) {
+ if (width < 3 || height < 3) {
throw new IllegalArgumentException("Invalid game size.");
}
- if (width != board.getWidth() || height != board.getHeight()) {
- throw new IllegalArgumentException("The board does not match the gui.");
- }
- this.board = board;
+ ArrayList con = new ArrayList<>();
+ con.add(new FourInARow());
+ this.board = new VerticalBoard(width, height, new Empty(), con);
for (int i = 0; i < 2; i++) {
String playerName = "";
while (playerName.equals("")) {
@@ -32,9 +40,9 @@ public class FourInARowGUI extends GUI {
}
Color color;
if (i == 0) {
- color = Color.green;
+ color = new Color(0, 200, 0);
} else {
- color = Color.red;
+ color = new Color(200, 0, 0);
}
Player player = new Player(playerName, color);
if (!this.board.addPlayer(player)) {
@@ -45,6 +53,12 @@ public class FourInARowGUI extends GUI {
initialize(width, height);
}
+ /**
+ * Initialized the gui.
+ *
+ * @param width The width of the game grid
+ * @param height The height of the game grid
+ */
private void initialize(int width, int height) {
JFrame frame = new JFrame("Four in a row");
frame.addWindowListener(new WindowAdapter() {
@@ -66,8 +80,8 @@ public class FourInARowGUI extends GUI {
this.resetButton = new JButton("Reset");
this.resetButton.addActionListener(this);
panel3.add(this.resetButton);
- for (Player player : board.getPlayers()) {
- JLabel playerLabel = new JLabel(player.toString());
+ for (IPlayer player : board.getPlayers()) {
+ JLabel playerLabel = new JLabel(player.getName());
playerLabel.setForeground(player.getColor());
panel3.add(playerLabel);
}
@@ -75,17 +89,11 @@ public class FourInARowGUI extends GUI {
JPanel panel2 = new JPanel();
this.mainPanel = panel2;
- panel2.setBackground(Color.BLUE);
+ panel2.setBackground(new Color(0, 0, 200));
panel2.setLayout(new FlowLayout(FlowLayout.CENTER, HEIGHT_GAP, WIDTH_GAP));
panel2.setPreferredSize(new Dimension(fullWidth, fullHeight));
dropButtons = new JButton[width];
- for (int i = 0; i < width; i++) {
- JButton button = new JButton();
- button.addActionListener(this);
- button.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
- dropButtons[i] = button;
- panel2.add(button, BorderLayout.PAGE_START);
- }
+ initializeDropButtons(width, panel2);
tiles = new JTextPane[width * height];
readTiles();
container.add(panel2);
@@ -98,33 +106,28 @@ public class FourInARowGUI extends GUI {
frame.validate();
frame.pack();
frame.setVisible(true);
- this.currentPlayer = board.nextPlayer();
- displayMessage("It's " + this.currentPlayer + "'s turn.");
+ currentPlayer = board.nextPlayer();
+ displayMessage("It's " + currentPlayer.getName() + "'s turn.");
}
@Override
public void actionPerformed(ActionEvent e) {
- if (e.getSource() == this.resetButton) {
- this.board.flush();
- displayBoard();
- this.currentPlayer = this.board.nextPlayer();
- displayMessage("It's " + this.currentPlayer + "'s turn.");
- }
- if (!(this.board.won() || this.board.isFull())) {
- for (int i = 0; i < this.dropButtons.length; i++) {
- if (e.getSource() == this.dropButtons[i]) {
+ reset(e);
+ if (!(board.won() || board.isFull())) {
+ for (int i = 0; i < dropButtons.length; i++) {
+ if (e.getSource() == dropButtons[i]) {
if (dropObject(i)) {
displayBoard();
- if (!this.board.won()) {
+ if (!board.won()) {
if (board.isFull()) {
displayMessage("It's a draw");
} else {
- this.currentPlayer = board.nextPlayer();
- displayMessage("It's " + this.currentPlayer + "'s turn.");
+ currentPlayer = board.nextPlayer();
+ displayMessage("It's " + currentPlayer.getName() + "'s turn.");
}
} else {
- GameObject winnerObject = this.board.get(i, this.board.getTopObject(i));
- displayMessage(((Token)winnerObject).getOwner() + " won.");
+ IGameObject winnerObject = board.get(i, ((IVerticalBoard)board).getTopObject(i, IPlayerObject.class));
+ displayMessage(((IPlayerObject)winnerObject).getOwner().getName() + " won.");
}
} else {
displayMessage("That column is full.");
@@ -133,4 +136,9 @@ public class FourInARowGUI extends GUI {
}
}
}
+
+ @Override
+ public boolean placePlayerObject(int x, int y) throws IllegalAccessException {
+ throw new IllegalAccessException("Method not allowed in a vertical board.");
+ }
}
diff --git a/src/main/java/inf101/v18/connectfour/interfaces/ConnectFourGUI.java b/src/main/java/inf101/v18/connectfour/interfaces/ConnectFourGUI.java
new file mode 100644
index 0000000..348f8f9
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/interfaces/ConnectFourGUI.java
@@ -0,0 +1,247 @@
+package inf101.v18.connectfour.interfaces;
+
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.board.VerticalBoard;
+import inf101.v18.connectfour.events.random.Block;
+import inf101.v18.connectfour.events.random.Bomb;
+import inf101.v18.connectfour.events.random.IRandomEvent;
+import inf101.v18.connectfour.events.winning.FourInARow;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.objects.IPlayerObject;
+import inf101.v18.connectfour.player.AI;
+import inf101.v18.connectfour.player.IPlayer;
+import inf101.v18.connectfour.player.Player;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.ArrayList;
+
+/**
+ * A custom version of connect four.
+ */
+public class ConnectFourGUI extends ConnectGUI {
+ private final IRandomEvent bomb = new Bomb();
+ private final IRandomEvent block = new Block();
+ private JLabel eventLabel;
+
+ @Override
+ public boolean placePlayerObject(int x, int y) {
+ return false;
+ }
+
+ //A list of colors which can be used without conflict.
+ private enum Colors {GREEN, RED, BLUE, ORANGE, YELLOW, PINK, BROWN, TEAL}
+
+ public ConnectFourGUI(int width, int height) {
+ if (width < 3 || height < 3 || height > 50 || width > 50) {
+ throw new IllegalArgumentException("Invalid game size.");
+ }
+ ArrayList con = new ArrayList<>();
+ con.add(new FourInARow());
+ this.board = new VerticalBoard(width, height, new Empty(), con);
+ int playerNum = 0;
+ Colors[] colorValues = Colors.values();
+ while (playerNum == 0) {
+ try {
+ String num = JOptionPane.showInputDialog("Number of players: ");
+ if (num == null) {
+ System.exit(0);
+ }
+ playerNum = Integer.parseInt(num);
+ if (playerNum > colorValues.length) {
+ JOptionPane.showMessageDialog(null, "Number of players can't be higher than " + colorValues.length, "Error", JOptionPane.ERROR_MESSAGE);
+ playerNum = 0;
+
+ }
+ } catch (NumberFormatException e) {
+ JOptionPane.showMessageDialog(null, "Invalid input.", "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ int aiNum = -1;
+ while (aiNum == -1) {
+ try {
+ String num = JOptionPane.showInputDialog("Number of ai: ");
+ if (num == null) {
+ System.exit(0);
+ }
+ aiNum = Integer.parseInt(num);
+ if (aiNum + playerNum > colorValues.length) {
+ JOptionPane.showMessageDialog(null, "Number of ai + players can't be higher than " + colorValues.length, "Error", JOptionPane.ERROR_MESSAGE);
+ aiNum = 0;
+
+ }
+ } catch (NumberFormatException e) {
+ JOptionPane.showMessageDialog(null, "Invalid input.", "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ for (int i = 0; i < playerNum; i++) {
+ String playerName = "";
+ while (playerName.equals("")) {
+ playerName = JOptionPane.showInputDialog(String.format("Name of player %d: ", i + 1));
+ if (playerName == null) {
+ System.exit(0);
+ }
+ }
+ Color color = colorsToColor(Colors.values()[i]);
+ Player player = new Player(playerName, color);
+ if (!this.board.addPlayer(player)) {
+ JOptionPane.showMessageDialog(null, "Player is not unique. Please try again.", "Error", JOptionPane.ERROR_MESSAGE);
+ i--;
+ }
+ }
+ for (int i = 0; i < aiNum; i++) {
+ if (!this.board.addPlayer(new AI("AI" + (i + 1), colorsToColor(colorValues[playerNum + i])))) {
+ i--;
+ }
+ }
+ initialize(width, height);
+ }
+
+ /**
+ * Converts values in the Colors enum to actual colors.
+ *
+ * @param color An enum value
+ * @return An awt Color
+ */
+ private Color colorsToColor(Colors color) {
+ switch (color) {
+ case RED:
+ return new Color(209,17,65);
+ case GREEN:
+ return new Color(0,177,89);
+ case BLUE:
+ return new Color(0, 174, 219);
+ case ORANGE:
+ return new Color(243, 119, 53);
+ case YELLOW:
+ return new Color(255, 196, 37);
+ case PINK:
+ return new Color(255,0,101);
+ case BROWN:
+ return new Color(224,168,153);
+ case TEAL:
+ return new Color(102,178,178);
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Initializes the GUI.
+ *
+ * @param width The width of the board
+ * @param height The height of the board
+ */
+ private void initialize(int width, int height) {
+ JFrame frame = new JFrame("Four in a row");
+ frame.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ System.exit(0);
+ }
+ });
+ int fullWidth = BUTTON_WIDTH * width + (WIDTH_GAP + 1) * width;
+ int fullHeight = BUTTON_HEIGHT + (TILE_HEIGHT * height) + HEIGHT_GAP * (height) + TILE_HEIGHT;
+
+ this.frame = frame;
+ JPanel container = new JPanel();
+ container.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+ container.setPreferredSize(new Dimension(fullWidth, fullHeight + TILE_HEIGHT + 2 * BUTTON_HEIGHT));
+ frame.add(container);
+
+ JPanel panel3 = new JPanel();
+ this.resetButton = new JButton("Reset");
+ this.resetButton.addActionListener(this);
+ panel3.add(this.resetButton);
+ for (IPlayer player : board.getPlayers()) {
+ JLabel playerLabel = new JLabel(player.getName());
+ playerLabel.setForeground(player.getColor());
+ panel3.add(playerLabel);
+ }
+ container.add(panel3);
+
+ JPanel panel2 = new JPanel();
+ this.mainPanel = panel2;
+ panel2.setBackground(new Color(0, 0, 200));
+ panel2.setLayout(new FlowLayout(FlowLayout.CENTER, HEIGHT_GAP, WIDTH_GAP));
+ panel2.setPreferredSize(new Dimension(fullWidth, fullHeight));
+ dropButtons = new JButton[width];
+ initializeDropButtons(width, panel2);
+ tiles = new JTextPane[width * height];
+ readTiles();
+ container.add(panel2);
+
+ infoLabel = new JLabel();
+ infoLabel.setPreferredSize(new Dimension(fullWidth, BUTTON_HEIGHT));
+ infoLabel.setBorder(new EmptyBorder(10, 10, 10, 10));
+ container.add(infoLabel);
+
+ eventLabel = new JLabel();
+ eventLabel.setPreferredSize(new Dimension(fullWidth, BUTTON_HEIGHT));
+ eventLabel.setBorder(new EmptyBorder(10, 10, 10, 10));
+ container.add(eventLabel);
+
+ frame.validate();
+ frame.pack();
+ frame.setVisible(true);
+ currentPlayer = board.nextPlayer();
+ displayMessage("It's " + currentPlayer.getName() + "'s turn.");
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ reset(e);
+ if (!(board.won() || board.isFull())) {
+ for (int i = 0; i < dropButtons.length; i++) {
+ if (e.getSource() == dropButtons[i]) {
+ if (dropObject(i)) {
+ displayBoard();
+ if (board.won()) {
+ IGameObject winnerObject = board.get(i, ((IVerticalBoard)board).getTopObject(i, IPlayerObject.class));
+ displayMessage(((IPlayerObject)winnerObject).getOwner().getName() + " won.");
+ } else {
+ if (!board.isFull()) {
+ triggerEvents();
+ }
+ //This might look weird, but an event can fill up the board.
+ if (board.isFull()) {
+ displayMessage("It's a draw");
+ } else {
+ currentPlayer = board.nextPlayer();
+ displayMessage("It's " + currentPlayer.getName() + "'s turn.");
+ if (currentPlayer instanceof AI) {
+ dropButtons[((AI)currentPlayer).getColumn((VerticalBoard)board)].doClick();
+ }
+ }
+ }
+ } else {
+ displayMessage("That column is full.");
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Triggers a set of events after each player's turn.
+ */
+ private void triggerEvents() {
+ if (bomb.rollDie(((IVerticalBoard)board), 2)) {
+ eventLabel.setText(bomb.announcement());
+ } else if (block.rollDie(((IVerticalBoard)board), 1)) {
+ eventLabel.setText(block.announcement());
+ } else {
+ eventLabel.setText("");
+ }
+ while (((IVerticalBoard)board).floatingObjects() > 0) {
+ ((IVerticalBoard)board).gravitate();
+ }
+ displayBoard();
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/interfaces/ConnectGUI.java b/src/main/java/inf101/v18/connectfour/interfaces/ConnectGUI.java
new file mode 100644
index 0000000..311c8f4
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/interfaces/ConnectGUI.java
@@ -0,0 +1,66 @@
+package inf101.v18.connectfour.interfaces;
+
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.objects.Token;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Implements some methods specific for connect four.
+ */
+public abstract class ConnectGUI extends GUI implements IVerticalGameInterface {
+ JButton[] dropButtons;
+ JTextPane[] tiles;
+
+ @Override
+ public void displayBoard() {
+ for (JTextPane pane : this.tiles) {
+ this.mainPanel.remove(pane);
+ }
+ this.tiles = new JTextPane[this.board.getWidth() * this.board.getHeight()];
+ readTiles();
+ this.frame.validate();
+ }
+
+ /**
+ * Reads the values from board, and creates corresponding text panes.
+ */
+ void readTiles() {
+ int k = 0;
+ for (int i = board.getHeight() - 1; i > -1; i--) {
+ for (int j = 0; j < board.getWidth(); j++) {
+ JTextPane textPane = new JTextPane();
+ this.tiles[k++] = textPane;
+ textPane.setEditable(false);
+ textPane.setBackground(new Color(0, 0, 200));
+ IGameObject obj = board.get(j,i);
+ textPane.setBorder(BorderFactory.createLineBorder(obj.getColor(), 50, true));
+ textPane.setPreferredSize(new Dimension(BUTTON_WIDTH, TILE_HEIGHT));
+ mainPanel.add(textPane, BorderLayout.PAGE_START);
+ }
+ }
+ }
+
+ /**
+ * Creates a bunch of buttons.
+ *
+ * @param width The width of the game grid
+ * @param panel2 The panel the buttons should be attached to
+ */
+ void initializeDropButtons(int width, JPanel panel2) {
+ for (int i = 0; i < width; i++) {
+ JButton button = new JButton();
+ button.addActionListener(this);
+ button.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
+ dropButtons[i] = button;
+ panel2.add(button, BorderLayout.PAGE_START);
+ }
+ }
+
+ @Override
+ public boolean dropObject(int i) {
+ return ((IVerticalBoard)board).drop(i, new Token(currentPlayer));
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/interfaces/GUI.java b/src/main/java/inf101/v18/connectfour/interfaces/GUI.java
new file mode 100644
index 0000000..4e93aa9
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/interfaces/GUI.java
@@ -0,0 +1,54 @@
+package inf101.v18.connectfour.interfaces;
+
+import inf101.v18.connectfour.board.IBoard;
+import inf101.v18.connectfour.player.IPlayer;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * Implements common variables and methods for any GUI interface.
+ */
+public abstract class GUI implements ActionListener, IGameInterface {
+ final int BUTTON_HEIGHT = 25;
+ final int BUTTON_WIDTH = 50;
+ final int TILE_HEIGHT = 50;
+ final int HEIGHT_GAP = 10;
+ final int WIDTH_GAP = 10;
+
+ JButton resetButton;
+ JLabel infoLabel;
+ JPanel mainPanel;
+ JFrame frame;
+ IBoard board;
+
+ IPlayer currentPlayer;
+
+ void reset(ActionEvent e) {
+ if (e.getSource() == resetButton) {
+ board.flush();
+ displayBoard();
+ currentPlayer = board.nextPlayer();
+ displayMessage("It's " + currentPlayer.getName() + "'s turn.");
+ }
+ }
+
+ @Override
+ public boolean hasDrawn() {
+ return board.isFull();
+ }
+
+ @Override
+ public boolean hasWon() {
+ return board.won();
+ }
+
+ @Override
+ public void displayMessage(String s) {
+ infoLabel.setText(s);
+ }
+
+ @Override
+ public void doTurn() {}
+}
diff --git a/src/main/java/inf101/v18/connectfour/interfaces/IGameInterface.java b/src/main/java/inf101/v18/connectfour/interfaces/IGameInterface.java
new file mode 100644
index 0000000..528f8ff
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/interfaces/IGameInterface.java
@@ -0,0 +1,47 @@
+package inf101.v18.connectfour.interfaces;
+
+/**
+ * Provides an interface a user interface.
+ */
+public interface IGameInterface {
+ /**
+ * Displays a message to the player(s).
+ *
+ * @param s The massage to display
+ */
+ void displayMessage(String s);
+
+ /**
+ * Displays an updated board.
+ */
+ void displayBoard();
+
+ /**
+ * Checks if the game ended in someone winning.
+ *
+ * @return True if the game is over
+ */
+ boolean hasWon();
+
+ /**
+ * Checks if the game ended in a draw.
+ *
+ * @return True if the game is over
+ */
+ boolean hasDrawn();
+
+ /**
+ * Makes the interface place an object corresponding to the current player.
+ *
+ * @param x The x-coordinate of the object to place
+ * @param y The y-coordinate of the object to place
+ * @return True if the object was placed
+ * @throws IllegalAccessException If method is used from a vertical interface
+ */
+ boolean placePlayerObject(int x, int y) throws IllegalAccessException;
+
+ /**
+ * Makes the interface do whatever it wants to do for this turn.
+ */
+ void doTurn();
+}
diff --git a/src/main/java/inf101/v18/connectfour/interfaces/IVerticalGameInterface.java b/src/main/java/inf101/v18/connectfour/interfaces/IVerticalGameInterface.java
new file mode 100644
index 0000000..9205c9d
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/interfaces/IVerticalGameInterface.java
@@ -0,0 +1,26 @@
+package inf101.v18.connectfour.interfaces;
+
+/**
+ * An IVerticalGameInterface replaces IGameInterface's place method with a drop method.
+ */
+interface IVerticalGameInterface extends IGameInterface {
+ /**
+ * Drops an object onto the board at column i,
+ *
+ * @param i Target column
+ * @return True if the column had available space
+ */
+ boolean dropObject(int i);
+
+ /**
+ * Prevents manually placing a game piece, unless method is overwritten.
+ *
+ * @param x An integer which doesn't matter
+ * @param y An integer which doesn't matter
+ * @return Nothing
+ * @throws IllegalAccessException When method is used from a Vertical game
+ */
+ default boolean placePlayerObject(int x, int y) throws IllegalAccessException {
+ throw new IllegalAccessException("Method not allowed in a vertical board.");
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/interfaces/TicTacToeCLI.java b/src/main/java/inf101/v18/connectfour/interfaces/TicTacToeCLI.java
new file mode 100644
index 0000000..273b74a
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/interfaces/TicTacToeCLI.java
@@ -0,0 +1,67 @@
+package inf101.v18.connectfour.interfaces;
+
+import inf101.v18.connectfour.board.Board;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.events.winning.ThreeInARow;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.objects.IPlayerObject;
+import inf101.v18.connectfour.objects.Token;
+import inf101.v18.connectfour.player.AI;
+import inf101.v18.connectfour.player.Player;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A Tic-Tac-Toe implementation using a Command Line Interface.
+ */
+public class TicTacToeCLI extends CLI {
+ public TicTacToeCLI() {
+ List con = new ArrayList<>();
+ con.add(new ThreeInARow());
+ board = new Board(3, 3, new Empty(), con);
+ board.addPlayer(new Player(readName(1), Color.green));
+ if (playingAlone()) {
+ board.addPlayer(new AI("AI", Color.red));
+ } else {
+ board.addPlayer(new Player(readName(2), Color.red));
+ }
+ currentPlayer = board.nextPlayer();
+ }
+
+ @Override
+ public void displayBoard() {
+ for (int i = board.getHeight() - 1; i >= 0; i--) {
+ System.out.print((i + 1) + " ");
+ for (int j = 0; j < board.getWidth(); j++) {
+ IGameObject obj = board.get(j,i);
+ System.out.print(colorToAnsi(obj.getColor(), getSymbol(obj.getColor())) + " ");
+ }
+ System.out.println();
+ }
+ System.out.print(" ");
+ for (int i = 0; i < board.getWidth(); i++) {
+ System.out.print(" " + (i + 1));
+ }
+ }
+
+ @Override
+ public boolean placePlayerObject(int x, int y) {
+ if (board.get(x, y) instanceof IPlayerObject) {
+ return false;
+ }
+ try {
+ board.set(x, y, new Token(currentPlayer));
+ if (board.won()) {
+ displayBoard();
+ displayMessage("\n" + currentPlayer.getName() + " won");
+ }
+ currentPlayer = board.nextPlayer();
+ return true;
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+}
diff --git a/src/interfaces/TicTacToeGUI.java b/src/main/java/inf101/v18/connectfour/interfaces/TicTacToeGUI.java
similarity index 56%
rename from src/interfaces/TicTacToeGUI.java
rename to src/main/java/inf101/v18/connectfour/interfaces/TicTacToeGUI.java
index b38ebf3..0e29b79 100644
--- a/src/interfaces/TicTacToeGUI.java
+++ b/src/main/java/inf101/v18/connectfour/interfaces/TicTacToeGUI.java
@@ -1,12 +1,12 @@
-package interfaces;
+package inf101.v18.connectfour.interfaces;
-import board.Board;
-import events.IWinCondition;
-import events.ThreeInARow;
-import objects.Empty;
-import objects.GameObject;
-import objects.Player;
-import objects.Token;
+import inf101.v18.connectfour.board.Board;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.events.winning.ThreeInARow;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.IGameObject;
+import inf101.v18.connectfour.objects.Token;
+import inf101.v18.connectfour.player.Player;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@@ -17,6 +17,9 @@ import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
+/**
+ * A Tic-Tac-Toe implementation using a Graphical User Interface.
+ */
public class TicTacToeGUI extends GUI {
private JButton[] gameGrid = new JButton[9];
@@ -51,6 +54,9 @@ public class TicTacToeGUI extends GUI {
initialize();
}
+ /**
+ * Initializes the GUI.
+ */
private void initialize() {
JFrame frame = new JFrame("Four in a row");
frame.addWindowListener(new WindowAdapter() {
@@ -69,7 +75,7 @@ public class TicTacToeGUI extends GUI {
frame.add(container);
JPanel panel2 = new JPanel();
- this.mainPanel = panel2;
+ mainPanel = panel2;
panel2.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
panel2.setPreferredSize(new Dimension(fullWidth, fullHeight));
readTiles();
@@ -79,73 +85,106 @@ public class TicTacToeGUI extends GUI {
infoLabel.setPreferredSize(new Dimension(fullWidth, 15));
infoLabel.setBorder(new EmptyBorder(10, 10, 15, 10));
container.add(infoLabel);
- this.resetButton = new JButton("Reset");
- this.resetButton.addActionListener(this);
- container.add(this.resetButton);
+ resetButton = new JButton("Reset");
+ resetButton.addActionListener(this);
+ container.add(resetButton);
frame.validate();
frame.pack();
frame.setVisible(true);
currentPlayer = board.nextPlayer();
- displayMessage("It's " + currentPlayer + "'s turn.");
+ displayMessage("It's " + currentPlayer.getName() + "'s turn.");
}
+ @Override
public void displayBoard() {
- for (JButton button : this.gameGrid) {
- this.mainPanel.remove(button);
+ for (JButton button : gameGrid) {
+ mainPanel.remove(button);
}
- this.gameGrid = new JButton[this.board.getWidth() * this.board.getHeight()];
+ gameGrid = new JButton[board.getWidth() * board.getHeight()];
readTiles();
- this.frame.validate();
+ frame.validate();
}
- void readTiles() {
+ @Override
+ public boolean hasWon() {
+ return board.won();
+ }
+
+ @Override
+ public boolean placePlayerObject(int x, int y) {
+ if (!board.isFull()) {
+ try {
+ board.set(x, y, new Token(currentPlayer));
+ return true;
+ } catch (IllegalArgumentException ignored) {}
+ }
+ return false;
+ }
+
+ /**
+ * Converts the data contained in the board to buttons.
+ */
+ private void readTiles() {
int k = 0;
for (int i = 0; i < board.getHeight(); i++) {
for (int j = 0; j < board.getWidth(); j++) {
JButton button = new JButton();
button.addActionListener(this);
- GameObject obj = board.get(j,i);
- if (obj.getColor() == Color.black) {
+ IGameObject obj = board.get(j,i);
+ if (obj.getColor() == Color.black) { //This is a bit hacky, but prevents unnecessary changes,
button.setText("X");
} else if (obj.getColor() == Color.white) {
button.setText("O");
}
button.setPreferredSize(new Dimension(BUTTON_WIDTH, TILE_HEIGHT));
- this.gameGrid[k++] = button;
+ gameGrid[k++] = button;
mainPanel.add(button, BorderLayout.PAGE_START);
}
}
}
+ /**
+ * Handles all player input and output.
+ *
+ * @param e An event handler
+ */
+ @Override
public void actionPerformed(ActionEvent e) {
- if (e.getSource() == this.resetButton) {
+ if (e.getSource() == resetButton) {
this.board.flush();
displayBoard();
- this.currentPlayer = this.board.nextPlayer();
- displayMessage("It's " + this.currentPlayer + "'s turn.");
+ this.currentPlayer = board.nextPlayer();
+ displayMessage("It's " + currentPlayer.getName() + "'s turn.");
}
if (!(board.won() || board.isFull())) {
- for (int i = 0; i < this.gameGrid.length; i++) {
- if (e.getSource() == this.gameGrid[i]) {
- if (this.gameGrid[i].getText().equals("")) {
- int x = i % 3;
- int y = i / 3;
- this.board.set(x, y, new Token(currentPlayer));
- displayBoard();
- if (!board.won()) {
- currentPlayer = board.nextPlayer();
- displayMessage("It's " + currentPlayer + "'s turn.");
- } else {
- GameObject winnerObject = board.get(x, board.getTopObject(x));
- displayMessage(((Token)winnerObject).getOwner() + " won.");
- }
- if (board.isFull()) {
- displayMessage("It's a draw");
- }
- }
+ for (int i = 0; i < gameGrid.length; i++) {
+ if (e.getSource() == gameGrid[i] && gameGrid[i].getText().equals("")) {
+ doTurn(i);
}
}
}
}
+
+ /**
+ * Places a token, and prepares the board and itself for the next event.
+ *
+ * @param i The index of the button pushed
+ */
+ private void doTurn(int i) {
+ int x = i % 3;
+ int y = i / 3;
+ board.set(x, y, new Token(currentPlayer));
+ displayBoard();
+ if (board.won()) {
+ IGameObject winnerObject = board.get(x, y);
+ displayMessage(((Token)winnerObject).getOwner().getName() + " won.");
+ } else {
+ currentPlayer = board.nextPlayer();
+ displayMessage("It's " + currentPlayer.getName() + "'s turn.");
+ if (board.isFull()) {
+ displayMessage("It's a draw");
+ }
+ }
+ }
}
diff --git a/src/main/java/inf101/v18/connectfour/objects/Empty.java b/src/main/java/inf101/v18/connectfour/objects/Empty.java
new file mode 100644
index 0000000..94beba2
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/objects/Empty.java
@@ -0,0 +1,6 @@
+package inf101.v18.connectfour.objects;
+
+/**
+ * An object representing an empty tile.
+ */
+public class Empty extends GameObject {}
diff --git a/src/main/java/inf101/v18/connectfour/objects/GameObject.java b/src/main/java/inf101/v18/connectfour/objects/GameObject.java
new file mode 100644
index 0000000..7027d2c
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/objects/GameObject.java
@@ -0,0 +1,15 @@
+package inf101.v18.connectfour.objects;
+
+import java.awt.*;
+
+/**
+ * Implements necessary methods for every IGameObject.
+ */
+public abstract class GameObject implements IGameObject {
+ Color color = Color.LIGHT_GRAY;
+
+ @Override
+ public Color getColor() {
+ return color;
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/objects/IGameObject.java b/src/main/java/inf101/v18/connectfour/objects/IGameObject.java
new file mode 100644
index 0000000..4af65a0
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/objects/IGameObject.java
@@ -0,0 +1,16 @@
+package inf101.v18.connectfour.objects;
+
+import java.awt.*;
+
+/**
+ * An object which can be placed on/dropped into a board.
+ */
+public interface IGameObject {
+ /**
+ * Retrieves the color representing the object.
+ * To prevent conflicts, all colors should be easily extinguishable.
+ *
+ * @return A Color
+ */
+ Color getColor();
+}
diff --git a/src/main/java/inf101/v18/connectfour/objects/IPlayerObject.java b/src/main/java/inf101/v18/connectfour/objects/IPlayerObject.java
new file mode 100644
index 0000000..a1d51b3
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/objects/IPlayerObject.java
@@ -0,0 +1,10 @@
+package inf101.v18.connectfour.objects;
+
+import inf101.v18.connectfour.player.IPlayer;
+
+/**
+ * An object placed by an IPlayer.
+ */
+public interface IPlayerObject extends IGameObject {
+ IPlayer getOwner();
+}
diff --git a/src/objects/Immovable.java b/src/main/java/inf101/v18/connectfour/objects/Immovable.java
similarity index 51%
rename from src/objects/Immovable.java
rename to src/main/java/inf101/v18/connectfour/objects/Immovable.java
index c9e14ae..18a7913 100644
--- a/src/objects/Immovable.java
+++ b/src/main/java/inf101/v18/connectfour/objects/Immovable.java
@@ -1,7 +1,10 @@
-package objects;
+package inf101.v18.connectfour.objects;
import java.awt.*;
+/**
+ * An object representing an obstacle which does not represent any player.
+ */
public class Immovable extends GameObject {
public Immovable() {
this.color = Color.BLACK;
diff --git a/src/objects/Player.java b/src/main/java/inf101/v18/connectfour/objects/Player.java
similarity index 95%
rename from src/objects/Player.java
rename to src/main/java/inf101/v18/connectfour/objects/Player.java
index 8637dd9..68aef4a 100644
--- a/src/objects/Player.java
+++ b/src/main/java/inf101/v18/connectfour/objects/Player.java
@@ -1,4 +1,4 @@
-package objects;
+package inf101.v18.connectfour.objects;
import java.awt.*;
import java.util.Objects;
diff --git a/src/main/java/inf101/v18/connectfour/objects/Token.java b/src/main/java/inf101/v18/connectfour/objects/Token.java
new file mode 100644
index 0000000..41f047e
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/objects/Token.java
@@ -0,0 +1,24 @@
+package inf101.v18.connectfour.objects;
+
+import inf101.v18.connectfour.player.IPlayer;
+
+/**
+ * A token represents an object a player can place on a board.
+ */
+public class Token extends GameObject implements IPlayerObject {
+ private final IPlayer owner;
+
+ public Token(IPlayer owner) {
+ this.owner = owner;
+ this.color = owner.getColor();
+ }
+
+ /**
+ * Fetches the player associated with the token.
+ *
+ * @return A player
+ */
+ public IPlayer getOwner() {
+ return this.owner;
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/player/AI.java b/src/main/java/inf101/v18/connectfour/player/AI.java
new file mode 100644
index 0000000..aa84b39
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/player/AI.java
@@ -0,0 +1,136 @@
+package inf101.v18.connectfour.player;
+
+import inf101.v18.connectfour.board.IBoard;
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.Token;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * An AI is a Player which must be asked for input directly.
+ */
+public class AI extends Player implements IAI {
+ private final Random random = new Random();
+
+ public AI(String name, Color color) {
+ super(name, color);
+ }
+
+ @Override
+ public int getColumn(IVerticalBoard b) {
+ List topPositions = getTopElements(b);
+ IVerticalBoard copy = b.copyAll();
+ //Checks if the AI can win
+ int i = winRow(copy, topPositions, this)[0];
+ if (i != -1) {
+ return i;
+ }
+ IPlayer nextPlayer = copy.nextPlayer();
+ //Checks if the AI can prevent a winning move
+ while (nextPlayer != this) {
+ i = winRow(copy, topPositions, nextPlayer)[0];
+ if (i != -1) {
+ return i;
+ }
+ nextPlayer = copy.nextPlayer();
+ }
+ do {
+ i = random.nextInt(b.getWidth());
+ } while (!b.isFull() && !(b.get(i, b.getHeight()-1) instanceof Empty));
+ return i;
+ }
+
+ /**
+ * Retrieves a list of all possible drop locations.
+ *
+ * @param b A board
+ * @return A list of positions
+ */
+ private List getTopElements(IVerticalBoard b) {
+ List postitions = new ArrayList<>();
+ for (int x = 0; x < b.getWidth(); x++) {
+ int y = b.getTopObject(x);
+ if (y < b.getHeight() - 1 && b.get(x, y + 1) instanceof Empty) {
+ postitions.add(new int[]{x, y});
+ }
+ }
+ return postitions;
+ }
+
+ /**
+ * Retrieves a list of all empty locations.
+ *
+ * @param b A board
+ * @return A list of positions
+ */
+ private List getEmpty(IBoard b) {
+ List postitions = new ArrayList<>();
+ for (int i = 0; i < b.getWidth(); i++) {
+ for (int j = 0; j < b.getHeight(); j++) {
+ if (b.get(i, j) instanceof Empty) {
+ postitions.add(new int[]{i, j});
+ }
+ }
+ }
+ return postitions;
+ }
+
+ /**
+ * Tries to simulate all possible moves for a player, until it finds a winning move.
+ *
+ * @param b A board
+ * @param positions A list of positions on the board
+ * @param player The player to simulate
+ * @return A column index or -1 if the player can't win.
+ */
+ private int[] winRow(IBoard b, List positions, IPlayer player) {
+ for (int[] coords : positions) {
+ int x = coords[0];
+ int y = coords[1];
+ if (b instanceof IVerticalBoard) {
+ b.set(x, y + 1, new Token(player));
+ if (b.won()) {
+ return new int[]{x};
+ }
+ b.set(x, y + 1, new Empty());
+ } else {
+ b.set(x, y, new Token(player));
+ if (b.won()) {
+ return new int[]{x, y};
+ }
+ b.set(x, y, new Empty());
+ }
+ }
+ return new int[]{-1};
+ }
+
+ @Override
+ public int[] getXY(IBoard b) {
+ List emptyPositions = getEmpty(b);
+ IBoard copy = b.copyAll();
+ //Checks if the AI can win
+ int[] coords = winRow(copy, emptyPositions, this);
+ if (coords[0] != -1) {
+ return coords;
+ }
+ IPlayer nextPlayer = copy.nextPlayer();
+ //Checks if the AI can prevent a winning move
+ while (nextPlayer != this) {
+ coords = winRow(copy, emptyPositions, nextPlayer);
+ if (coords[0] != -1) {
+ return coords;
+ }
+ nextPlayer = copy.nextPlayer();
+ }
+ int x, y;
+ do {
+ x = random.nextInt(b.getWidth());
+ y = random.nextInt(b.getHeight());
+ } while (!b.isFull() && !(b.get(x, y) instanceof Empty));
+ return new int[]{x, y};
+ }
+}
diff --git a/src/main/java/inf101/v18/connectfour/player/IAI.java b/src/main/java/inf101/v18/connectfour/player/IAI.java
new file mode 100644
index 0000000..b8a5202
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/player/IAI.java
@@ -0,0 +1,25 @@
+package inf101.v18.connectfour.player;
+
+import inf101.v18.connectfour.board.IBoard;
+import inf101.v18.connectfour.board.IVerticalBoard;
+
+/**
+ * An IAI is an IPlayer with methods for retrieving its next move.
+ */
+public interface IAI extends IPlayer {
+ /**
+ * Gets the column where the AI wants to drop its token.
+ *
+ * @param b A board
+ * @return A valid column
+ */
+ int getColumn(IVerticalBoard b);
+
+ /**
+ * Gets the x and y coordinate of the board position where the AI wants to place its token.
+ *
+ * @param b A board
+ * @return An array of integers with length 2
+ */
+ int[] getXY(IBoard b);
+}
diff --git a/src/main/java/inf101/v18/connectfour/player/IPlayer.java b/src/main/java/inf101/v18/connectfour/player/IPlayer.java
new file mode 100644
index 0000000..3dfbb0f
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/player/IPlayer.java
@@ -0,0 +1,22 @@
+package inf101.v18.connectfour.player;
+
+import java.awt.*;
+
+/**
+ * An IPlayer is a representation of an actual player.
+ */
+public interface IPlayer {
+ /**
+ * Retrieves a color representing the player.
+ *
+ * @return A Color
+ */
+ Color getColor();
+
+ /**
+ * Retrieves a string representing the player.
+ *
+ * @return A String
+ */
+ String getName();
+}
diff --git a/src/main/java/inf101/v18/connectfour/player/Player.java b/src/main/java/inf101/v18/connectfour/player/Player.java
new file mode 100644
index 0000000..32fd603
--- /dev/null
+++ b/src/main/java/inf101/v18/connectfour/player/Player.java
@@ -0,0 +1,47 @@
+package inf101.v18.connectfour.player;
+
+import java.awt.*;
+import java.util.Objects;
+
+/**
+ * A class representing a player playing a game.
+ */
+public class Player implements IPlayer {
+ private final String name;
+ private final Color color;
+
+ public Player(String name, Color color) {
+ if (name == null || name.equals("")) {
+ throw new IllegalArgumentException("Player name is invalid.");
+ }
+ if (color == null) {
+ throw new IllegalArgumentException("Player color is invalid");
+ }
+ this.name = name;
+ this.color = color;
+ }
+
+ @Override
+ public Color getColor() {
+ return color;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Player player = (Player) o;
+ return Objects.equals(name, player.name) ||
+ Objects.equals(color, player.color);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, color);
+ }
+}
diff --git a/src/objects/Empty.java b/src/objects/Empty.java
deleted file mode 100644
index b614d4c..0000000
--- a/src/objects/Empty.java
+++ /dev/null
@@ -1,3 +0,0 @@
-package objects;
-
-public class Empty extends GameObject {}
diff --git a/src/objects/GameObject.java b/src/objects/GameObject.java
deleted file mode 100644
index 2da8c1c..0000000
--- a/src/objects/GameObject.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package objects;
-
-import java.awt.*;
-
-public abstract class GameObject {
- Color color = Color.LIGHT_GRAY;
-
- public Color getColor() {
- return color;
- }
-}
diff --git a/src/objects/Token.java b/src/objects/Token.java
deleted file mode 100644
index 5887556..0000000
--- a/src/objects/Token.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package objects;
-
-public class Token extends GameObject {
- private final Player owner;
-
- public Token(Player owner) {
- this.owner = owner;
- this.color = owner.getColor();
- }
-
- public Player getOwner() {
- return this.owner;
- }
-}
diff --git a/src/test/java/inf101/v18/connectfour/AITest.java b/src/test/java/inf101/v18/connectfour/AITest.java
new file mode 100644
index 0000000..03c8e4e
--- /dev/null
+++ b/src/test/java/inf101/v18/connectfour/AITest.java
@@ -0,0 +1,90 @@
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.board.Board;
+import inf101.v18.connectfour.board.IBoard;
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.board.VerticalBoard;
+import inf101.v18.connectfour.events.winning.FourInARow;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.objects.*;
+import inf101.v18.connectfour.player.AI;
+import inf101.v18.connectfour.player.IAI;
+import inf101.v18.connectfour.player.IPlayer;
+import inf101.v18.connectfour.player.Player;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.junit.Assert.assertEquals;
+
+public class AITest {
+ @Test
+ public void dropTest() {
+ try {
+ IVerticalBoard board = new VerticalBoard(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ IAI ai = new AI("AI", Color.yellow);
+ board.addPlayer(ai);
+ for (int i = 0; i < 5; i++) {
+ board.drop(1, new Immovable());
+ }
+ for (int i = 0; i < 20; i++) {
+ int choice = ai.getColumn(board);
+ Assert.assertNotEquals(1, choice);
+ board.drop(choice, token);
+ }
+ } catch (IllegalArgumentException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void placeTest() {
+ try {
+ IBoard board = new Board(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ IAI ai = new AI("AI", Color.yellow);
+ board.addPlayer(ai);
+ int[] choice = ai.getXY(board);
+ assertEquals(2, choice.length);
+ for (int i = 0; i < 5 * 5; i++) {
+ choice = ai.getXY(board);
+ board.set(choice[0], choice[1], token);
+ }
+ } catch (IllegalArgumentException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void winTest() {
+ List con = new ArrayList<>();
+ con.add(new FourInARow());
+ IVerticalBoard board = new VerticalBoard(5, 5, new Empty(), con);
+ IAI ai = new AI("AI", Color.red);
+ board.addPlayer(ai);
+ for (int i = 0; i < 3; i++) {
+ board.set(i, 0, new Token(ai));
+ }
+ assertEquals(3, ai.getColumn(board));
+ }
+
+ @Test
+ public void blockTest() {
+ List con = new ArrayList<>();
+ con.add(new FourInARow());
+ IVerticalBoard board = new VerticalBoard(5, 5, new Empty(), con);
+ IPlayer player = new Player("AAA", Color.green);
+ IAI ai = new AI("AI", Color.red);
+ board.addPlayer(player);
+ board.addPlayer(ai);
+ for (int i = 0; i < 3; i++) {
+ board.set(i, 0, new Token(player));
+ }
+ assertEquals(3, ai.getColumn(board));
+ }
+}
diff --git a/src/test/java/inf101/v18/connectfour/BoardTest.java b/src/test/java/inf101/v18/connectfour/BoardTest.java
new file mode 100644
index 0000000..2780312
--- /dev/null
+++ b/src/test/java/inf101/v18/connectfour/BoardTest.java
@@ -0,0 +1,154 @@
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.board.*;
+import inf101.v18.connectfour.events.winning.FourInARow;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.objects.*;
+import inf101.v18.connectfour.player.IPlayer;
+import inf101.v18.connectfour.player.Player;
+import org.junit.Test;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class BoardTest {
+ @Test
+ public void setGetTest() {
+ IBoard board = new Board(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ board.set(3, 3, token);
+ assertNotEquals(token, board.get(2, 3));
+ assertEquals(token, board.get(3, 3));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void heightTooBigTest() {
+ IBoard board = new Board(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ board.set(0, 5, token);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void widthTooSmallTest() {
+ IBoard board = new Board(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ board.set(-1, 1, token);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void heightTooSmallTest() {
+ IBoard board = new Board(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ board.set(0, -2, token);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void widthTooBigTest() {
+ IBoard board = new Board(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ board.set(5, 3, token);
+ }
+
+ @Test
+ public void heightWidthTest() {
+ IBoard board = new Board(5, 6, new Empty(), new ArrayList<>());
+ assertEquals(5, board.getWidth());
+ assertEquals(6, board.getHeight());
+ }
+
+ @Test
+ public void addPlayerTest() {
+ IBoard board = new Board(5, 6, new Empty(), new ArrayList<>());
+ IPlayer player = new Player("ppp", Color.yellow);
+ assertEquals(0, board.getPlayers().size());
+ assertTrue(board.addPlayer(player));
+ assertEquals(player, board.getPlayers().get(0));
+ assertFalse(board.addPlayer(new Player("ppp", Color.MAGENTA)));
+ assertFalse(board.addPlayer(new Player("asdaf", Color.yellow)));
+ }
+
+ @Test
+ public void nextPlayerTest() {
+ IBoard board = new Board(1, 1, new Empty(), new ArrayList<>());
+ IPlayer player1 = new Player("Nem", Color.yellow);
+ IPlayer player2 = new Player("Men", Color.ORANGE);
+ board.addPlayer(player1);
+ board.addPlayer(player2);
+ assertEquals(player1, board.nextPlayer());
+ assertEquals(player2, board.nextPlayer());
+ assertEquals(player1, board.nextPlayer());
+ }
+
+ @Test
+ public void onePlayerTest() {
+ IBoard board = new Board(1, 1, new Empty(), new ArrayList<>());
+ IPlayer player1 = new Player("Nem", Color.yellow);
+ board.addPlayer(player1);
+ assertNotNull(board.nextPlayer());
+ assertEquals(player1, board.nextPlayer());
+ assertEquals(player1, board.nextPlayer());
+ }
+
+ @Test
+ public void noPlayersTest() {
+ IBoard board = new Board(1, 1, new Empty(), new ArrayList<>());
+ assertNull(board.nextPlayer());
+ }
+
+ @Test
+ public void flushTest() {
+ IGameObject empty = new Empty();
+ List con = new ArrayList<>();
+ con.add(new FourInARow());
+ IBoard board = new Board(4, 5, empty, con);
+ IPlayer player1 = new Player("ÆÆÆ", Color.RED);
+ IPlayer player2 = new Player("asdÆ", Color.GREEN);
+ board.addPlayer(player1);
+ board.addPlayer(player2);
+ IPlayerObject token = new Token(player1);
+ board.set(0, 0, token);
+ board.set(1, 1, token);
+ board.set(2, 2, token);
+ board.set(3, 3, token);
+ assertTrue(board.won());
+ board.nextPlayer();
+ assertEquals(player2, board.nextPlayer());
+ board.flush();
+ assertFalse(board.won());
+ assertEquals(player1, board.nextPlayer());
+ assertEquals(empty, board.get(0, 0));
+ assertEquals(empty, board.get(1, 1));
+ assertEquals(empty, board.get(2, 2));
+ assertEquals(empty, board.get(3, 3));
+ }
+
+ @Test
+ public void isFullTest() {
+ IBoard board = new Board(5, 5, new Empty(), new ArrayList<>());
+ IGameObject token = new Token(new Player("Naem", Color.green));
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.set(0, i, token);
+ }
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.set(1, i, token);
+ }
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.set(2, i, token);
+ }
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.set(3, i, token);
+ }
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.set(4, i, token);
+ }
+ assertTrue(board.isFull());
+ }
+}
diff --git a/src/test/java/inf101/v18/connectfour/FourInARowTest.java b/src/test/java/inf101/v18/connectfour/FourInARowTest.java
new file mode 100644
index 0000000..2fe1f70
--- /dev/null
+++ b/src/test/java/inf101/v18/connectfour/FourInARowTest.java
@@ -0,0 +1,71 @@
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.board.VerticalBoard;
+import inf101.v18.connectfour.events.winning.FourInARow;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.IPlayerObject;
+import inf101.v18.connectfour.objects.Token;
+import inf101.v18.connectfour.player.Player;
+import org.junit.Test;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class FourInARowTest {
+ private final List conditions = new ArrayList<>();
+
+ @Test
+ public void horisontalTest() {
+ conditions.add(new FourInARow());
+ VerticalBoard board = new VerticalBoard(4, 1, new Empty(), conditions);
+ IPlayerObject token = new Token(new Player("Naem", Color.RED));
+ assertTrue(board.drop(0, token));
+ assertFalse(board.won());
+ assertTrue(board.drop(1, token));
+ assertFalse(board.won());
+ assertTrue(board.drop(2, token));
+ assertFalse(board.won());
+ assertTrue(board.drop(3, token));
+ assertTrue(board.won());
+ }
+
+ @Test
+ public void verticalTest() {
+ conditions.add(new FourInARow());
+ VerticalBoard board = new VerticalBoard(1, 4, new Empty(), conditions);
+ IPlayerObject token = new Token(new Player("Naem", Color.RED));
+ assertTrue(board.drop(0, token));
+ assertFalse(board.won());
+ assertTrue(board.drop(0, token));
+ assertFalse(board.won());
+ assertTrue(board.drop(0, token));
+ assertFalse(board.won());
+ assertTrue(board.drop(0, token));
+ assertTrue(board.won());
+ }
+
+ @Test
+ public void diagonalTest() {
+ conditions.add(new FourInARow());
+ VerticalBoard board = new VerticalBoard(10, 10, new Empty(), conditions);
+ IPlayerObject token1 = new Token(new Player("Naem", Color.RED));
+ IPlayerObject token2 = new Token(new Player("Name", Color.GREEN));
+ board.drop(0, token1);
+ board.drop(1, token2);
+ board.drop(1, token1);
+ board.drop(3, token2);
+ board.drop(3, token1);
+ board.drop(3, token2);
+ board.drop(3, token1);
+ board.drop(2, token2);
+ board.drop(2, token2);
+ assertFalse(board.won());
+ board.drop(2, token1);
+ assertTrue(board.won());
+ }
+}
diff --git a/src/test/java/inf101/v18/connectfour/GridTest.java b/src/test/java/inf101/v18/connectfour/GridTest.java
new file mode 100644
index 0000000..76ee955
--- /dev/null
+++ b/src/test/java/inf101/v18/connectfour/GridTest.java
@@ -0,0 +1,90 @@
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.board.*;
+import inf101.v18.connectfour.objects.*;
+import inf101.v18.connectfour.player.Player;
+import org.junit.Test;
+
+import java.awt.*;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class GridTest {
+ @Test(expected = IllegalArgumentException.class)
+ public void negativeWidthTest() {
+ new Grid<>(-1, 1, new Empty());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void negativeHeightTest() {
+ new Grid<>(1, -1, new Empty());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void zeroWidthTest() {
+ new Grid<>(0, 1, new Empty());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void zeroHeightTest() { new Grid<>(1, 0, new Empty()); }
+
+ @Test
+ public void gridWidthTest() {
+ IGrid grid = new Grid<>(10, 11, new Empty());
+ assertEquals(10, grid.getWidth());
+ grid = new Grid<>(3, 11, new Empty());
+ assertEquals(3, grid.getWidth());
+ }
+
+ @Test
+ public void gridHeightTest() {
+ IGrid grid = new Grid<>(10, 11, new Empty());
+ assertEquals(11, grid.getHeight());
+ grid = new Grid<>(10, 4, new Empty());
+ assertEquals(4, grid.getHeight());
+ }
+
+ @Test
+ public void gridSetGetTest() {
+ IGrid grid = new Grid<>(10, 11, new Empty());
+ IGameObject imm = new Immovable();
+ assertNotEquals(imm, grid.get(2, 2));
+ grid.set(2, 2, imm);
+ assertEquals(imm, grid.get(2, 2));
+ assertNotEquals(imm, grid.get(3, 2));
+ }
+
+ @Test
+ public void copyTest() {
+ IGrid grid = new Grid<>(5, 5, new Empty());
+ IPlayerObject token = new Token(new Player("Naem", Color.pink));
+ grid.set(0, 0, token);
+ IGrid gridCopy = grid.copy();
+ assertEquals(token, gridCopy.get(0, 0));
+ gridCopy.set(0, 3, token);
+
+ assertEquals(token, gridCopy.get(0, 3));
+ assertNotEquals(token, grid.get(0, 3));
+ }
+
+ @Test
+ public void flushTest() {
+ IGameObject empty = new Empty();
+ IPlayerObject token = new Token(new Player("AASD", Color.MAGENTA));
+ IGrid grid = new Grid<>(5, 5, empty);
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ assertEquals(empty, grid.get(i, j));
+ grid.set(i, j, token);
+ assertEquals(token, grid.get(i, j));
+ }
+ }
+ grid.flush();
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ assertEquals(empty, grid.get(i, j));
+ }
+ }
+ }
+}
diff --git a/src/test/java/inf101/v18/connectfour/PlayerTest.java b/src/test/java/inf101/v18/connectfour/PlayerTest.java
new file mode 100644
index 0000000..3b34265
--- /dev/null
+++ b/src/test/java/inf101/v18/connectfour/PlayerTest.java
@@ -0,0 +1,32 @@
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.player.IPlayer;
+import inf101.v18.connectfour.player.Player;
+import org.junit.Test;
+
+import java.awt.*;
+
+import static org.junit.Assert.assertEquals;
+
+public class PlayerTest {
+ @Test
+ public void nameTest() {
+ IPlayer player = new Player("AAAA", Color.green);
+ assertEquals("AAAA", player.getName());
+ player = new Player("Adsdfsdf", Color.green);
+ assertEquals("Adsdfsdf", player.getName());
+ }
+
+ @Test
+ public void colorTest() {
+ IPlayer player = new Player("AAAA", Color.green);
+ assertEquals(Color.green, player.getColor());
+ player = new Player("AAAA", Color.pink);
+ assertEquals(Color.pink, player.getColor());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void nameIsEmptyTest() {
+ new Player("", Color.RED);
+ }
+}
diff --git a/src/test/java/inf101/v18/connectfour/RandomEventTest.java b/src/test/java/inf101/v18/connectfour/RandomEventTest.java
new file mode 100644
index 0000000..625524b
--- /dev/null
+++ b/src/test/java/inf101/v18/connectfour/RandomEventTest.java
@@ -0,0 +1,44 @@
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.board.VerticalBoard;
+import inf101.v18.connectfour.events.random.Block;
+import inf101.v18.connectfour.events.random.Bomb;
+import inf101.v18.connectfour.events.random.IRandomEvent;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.Immovable;
+import inf101.v18.connectfour.objects.Token;
+import inf101.v18.connectfour.player.Player;
+import org.junit.Test;
+
+import java.awt.*;
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+
+public class RandomEventTest {
+ @Test
+ public void bombTest() {
+ IVerticalBoard board = new VerticalBoard(1, 1, new Empty(), new ArrayList<>());
+ IRandomEvent bomb = new Bomb();
+ board.drop(0, new Token(new Player("AAA", Color.MAGENTA)));
+ assertEquals(Token.class, board.get(0,0).getClass());
+ boolean flipped;
+ do {
+ flipped = bomb.flipCoin(board);
+ } while (!flipped);
+ assertEquals(Empty.class, board.get(0,0).getClass());
+ }
+
+ @Test
+ public void immovableTest() {
+ IVerticalBoard board = new VerticalBoard(1, 1, new Empty(), new ArrayList<>());
+ IRandomEvent immovable = new Block();
+ assertEquals(Empty.class, board.get(0,0).getClass());
+ boolean flipped;
+ do {
+ flipped = immovable.flipCoin(board);
+ } while (!flipped);
+ assertEquals(Immovable.class, board.get(0,0).getClass());
+ }
+}
\ No newline at end of file
diff --git a/test/TicTacToeTest.java b/src/test/java/inf101/v18/connectfour/TicTacToeTest.java
similarity index 58%
rename from test/TicTacToeTest.java
rename to src/test/java/inf101/v18/connectfour/TicTacToeTest.java
index 50e5ee1..20c9f4b 100644
--- a/test/TicTacToeTest.java
+++ b/src/test/java/inf101/v18/connectfour/TicTacToeTest.java
@@ -1,18 +1,19 @@
-import board.Board;
-import events.IWinCondition;
-import events.ThreeInARow;
-import objects.Empty;
-import objects.Player;
-import objects.Token;
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.board.Board;
+import inf101.v18.connectfour.events.winning.IWinCondition;
+import inf101.v18.connectfour.events.winning.ThreeInARow;
+import inf101.v18.connectfour.objects.Empty;
+import inf101.v18.connectfour.objects.IPlayerObject;
+import inf101.v18.connectfour.objects.Token;
+import inf101.v18.connectfour.player.Player;
+import org.junit.Assert;
import org.junit.Test;
-import java.awt.Color;
+import java.awt.*;
import java.util.ArrayList;
import java.util.List;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
public class TicTacToeTest {
private final List conditions = new ArrayList<>();
@@ -20,63 +21,63 @@ public class TicTacToeTest {
public void horisontalTest() {
conditions.add(new ThreeInARow());
Board board = new Board(3, 3, new Empty(), conditions);
- Token token = new Token(new Player("Naem", Color.WHITE));
+ IPlayerObject token = new Token(new Player("Naem", Color.WHITE));
board.set(0, 0, token);
board.set(1, 0, token);
board.set(2, 0, token);
- assertTrue(board.won());
+ Assert.assertTrue(board.won());
board = new Board(3, 3, new Empty(), conditions);
board.set(0, 1, token);
board.set(1, 1, token);
board.set(2, 1, token);
- assertTrue(board.won());
+ Assert.assertTrue(board.won());
board = new Board(3, 3, new Empty(), conditions);
board.set(0, 2, token);
board.set(1, 2, token);
board.set(2, 2, token);
- assertTrue(board.won());
+ Assert.assertTrue(board.won());
}
@Test
public void verticalTest() {
conditions.add(new ThreeInARow());
Board board = new Board(3, 3, new Empty(), conditions);
- Token token = new Token(new Player("Naem", Color.WHITE));
+ IPlayerObject token = new Token(new Player("Naem", Color.WHITE));
board.set(0, 0, token);
- assertFalse(board.won());
+ Assert.assertFalse(board.won());
board.set(0, 1, token);
- assertFalse(board.won());
+ Assert.assertFalse(board.won());
board.set(0, 2, token);
- assertTrue(board.won());
+ Assert.assertTrue(board.won());
board = new Board(3, 3, new Empty(), conditions);
board.set(1, 0, token);
board.set(1, 1, token);
board.set(1, 2, token);
- assertTrue(board.won());
+ Assert.assertTrue(board.won());
board = new Board(3, 3, new Empty(), conditions);
board.set(2, 0, token);
board.set(2, 1, token);
board.set(2, 2, token);
- assertTrue(board.won());
+ Assert.assertTrue(board.won());
}
@Test
public void diagonalTest() {
conditions.add(new ThreeInARow());
Board board = new Board(3, 3, new Empty(), conditions);
- Token token = new Token(new Player("Naem", Color.WHITE));
+ IPlayerObject token = new Token(new Player("Naem", Color.WHITE));
board.set(0, 0, token);
- assertFalse(board.won());
+ Assert.assertFalse(board.won());
board.set(1, 1, token);
- assertFalse(board.won());
+ Assert.assertFalse(board.won());
board.set(2, 2, token);
- assertTrue(board.won());
+ Assert.assertTrue(board.won());
board = new Board(3, 3, new Empty(), conditions);
board.set(0, 2, token);
- assertFalse(board.won());
+ Assert.assertFalse(board.won());
board.set(1, 1, token);
- assertFalse(board.won());
+ Assert.assertFalse(board.won());
board.set(2, 0, token);
- assertTrue(board.won());
+ Assert.assertTrue(board.won());
}
}
diff --git a/src/test/java/inf101/v18/connectfour/VerticalBoardTest.java b/src/test/java/inf101/v18/connectfour/VerticalBoardTest.java
new file mode 100644
index 0000000..15609f2
--- /dev/null
+++ b/src/test/java/inf101/v18/connectfour/VerticalBoardTest.java
@@ -0,0 +1,142 @@
+package inf101.v18.connectfour;
+
+import inf101.v18.connectfour.board.IVerticalBoard;
+import inf101.v18.connectfour.board.VerticalBoard;
+import inf101.v18.connectfour.objects.*;
+import inf101.v18.connectfour.player.Player;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.awt.*;
+import java.util.ArrayList;
+
+import static org.junit.Assert.*;
+
+public class VerticalBoardTest {
+ @Test
+ public void topObjectTest() {
+ IVerticalBoard board = new VerticalBoard(10, 11, new Empty(), new ArrayList<>());
+ assertEquals(-1, board.getTopObject(0));
+ assertEquals(-1, board.getTopObject(0, Token.class));
+ assertEquals(-1, board.getTopObject(0, Immovable.class));
+ assertEquals(10, board.getTopObject(0, Empty.class));
+ board.drop(0, new Token(new Player("Hello", Color.pink)));
+ assertEquals(0, board.getTopObject(0));
+ assertEquals(0, board.getTopObject(0, Token.class));
+ assertEquals(-1, board.getTopObject(0, Immovable.class));
+ assertEquals(10, board.getTopObject(0, Empty.class));
+ board.drop(1, new Immovable());
+ assertEquals(0, board.getTopObject(1));
+ assertEquals(-1, board.getTopObject(1, Token.class));
+ assertEquals(0, board.getTopObject(1, Immovable.class));
+ assertEquals(10, board.getTopObject(1, Empty.class));
+ }
+
+ @Test
+ public void dropTest1() {
+ IVerticalBoard board = new VerticalBoard(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ Assert.assertNotSame(board.get(0, 0), token);
+ board.drop(0, token);
+ assertEquals(token, board.get(0, 0));
+ }
+
+ @Test
+ public void dropTest2() {
+ IVerticalBoard board = new VerticalBoard(10, 11, new Empty(), new ArrayList<>());
+ IGameObject imm = new Immovable();
+ assertNotEquals(imm, board.get(5, 0));
+ board.drop(5, imm);
+ assertEquals(imm, board.get(5, 0));
+ assertEquals(imm, board.get(5, board.getTopObject(5)));
+ }
+
+ @Test
+ public void gravitateTest() {
+ IVerticalBoard board = new VerticalBoard(4, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("ÆÆÆ", Color.RED));
+ board.set(0, 4, token);
+ board.gravitate();
+ assertEquals(token, board.get(0, 3));
+ board.gravitate();
+ assertEquals(token, board.get(0, 2));
+ board.gravitate();
+ assertEquals(token, board.get(0, 1));
+ board.gravitate();
+ assertEquals(token, board.get(0, 0));
+ }
+
+ @Test
+ public void floatingObjectsEasyTest() {
+ IVerticalBoard board = new VerticalBoard(1, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("ÆÆÆ", Color.RED));
+ board.set(0, 4, token);
+ assertEquals(4, board.floatingObjects());
+ board.gravitate();
+ assertEquals(3, board.floatingObjects());
+ board.gravitate();
+ assertEquals(2, board.floatingObjects());
+ board.gravitate();
+ assertEquals(1, board.floatingObjects());
+ board.gravitate();
+ assertEquals(0, board.floatingObjects());
+ }
+
+ @Test
+ public void floatingObjectsComplicatedTest() {
+ VerticalBoard board = new VerticalBoard(4, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("ÆÆÆ", Color.RED));
+ assertEquals(0, board.floatingObjects());
+ board.set(0, 4, token);
+ assertEquals(4, board.floatingObjects());
+ board.set(0, 2, token);
+ assertEquals(3, board.floatingObjects());
+ board.set(1, 3, token);
+ assertEquals(3, board.floatingObjects());
+ board.set(3, 4, token);
+ assertEquals(4, board.floatingObjects());
+ board.set(3, 3, token);
+ assertEquals(3, board.floatingObjects());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void dropNegativeColumnTest() {
+ IVerticalBoard board = new VerticalBoard(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ board.drop(-1, token);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void dropOutOfBoundsTest() {
+ IVerticalBoard board = new VerticalBoard(5, 5, new Empty(), new ArrayList<>());
+ IPlayerObject token = new Token(new Player("Playa", Color.MAGENTA));
+ board.drop(5, token);
+ }
+
+ @Test
+ public void isFullTest() {
+ IVerticalBoard board = new VerticalBoard(5, 5, new Empty(), new ArrayList<>());
+ IGameObject token = new Token(new Player("Naem", Color.green));
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.drop(0, token);
+ }
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.drop(1, token);
+ }
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.drop(2, token);
+ }
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.drop(3, token);
+ }
+ assertFalse(board.isFull());
+ for (int i = 0; i < 5; i++) {
+ board.drop(4, token);
+ }
+ assertTrue(board.isFull());
+ }
+}
diff --git a/test/FourInARowTest.java b/test/FourInARowTest.java
deleted file mode 100644
index aa192b2..0000000
--- a/test/FourInARowTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-import board.Board;
-import events.FourInARow;
-import events.IWinCondition;
-import objects.Empty;
-import objects.Player;
-import objects.Token;
-import org.junit.Test;
-
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class FourInARowTest {
- private final List conditions = new ArrayList<>();
-
- @Test
- public void horisontalTest() {
- conditions.add(new FourInARow());
- Board board = new Board(4, 1, new Empty(), conditions);
- Token token = new Token(new Player("Naem", Color.RED));
- assertTrue(board.drop(0, token));
- assertFalse(board.won());
- assertTrue(board.drop(1, token));
- assertFalse(board.won());
- assertTrue(board.drop(2, token));
- assertFalse(board.won());
- assertTrue(board.drop(3, token));
- assertTrue(board.won());
- }
-
- @Test
- public void verticalTest() {
- conditions.add(new FourInARow());
- Board board = new Board(1, 4, new Empty(), conditions);
- Token token = new Token(new Player("Naem", Color.RED));
- assertTrue(board.drop(0, token));
- assertFalse(board.won());
- assertTrue(board.drop(0, token));
- assertFalse(board.won());
- assertTrue(board.drop(0, token));
- assertFalse(board.won());
- assertTrue(board.drop(0, token));
- assertTrue(board.won());
- }
-
- @Test
- public void diagonalTest() {
- conditions.add(new FourInARow());
- Board board = new Board(10, 10, new Empty(), conditions);
- Token token = new Token(new Player("Naem", Color.RED));
- board.set(0, 0, token);
- assertFalse(board.won());
- board.set(1, 1, token);
- assertFalse(board.won());
- board.set(2, 2, token);
- assertFalse(board.won());
- board.set(3, 3, token);
- assertTrue(board.won());
- }
-}
diff --git a/test/GridTest.java b/test/GridTest.java
deleted file mode 100644
index 3ec536c..0000000
--- a/test/GridTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-import static org.junit.Assert.*;
-
-import board.Grid;
-import objects.Empty;
-import objects.GameObject;
-import objects.Player;
-import objects.Token;
-import org.junit.Test;
-
-import java.awt.*;
-
-public class GridTest {
- @Test
- public void gridWidthTest() {
- GameObject empty = new Empty();
- Grid grid = new Grid<>(10, 11, empty);
- assertEquals(10, grid.getWidth());
- }
-
- @Test
- public void gridHeightTest() {
- GameObject empty = new Empty();
- Grid grid = new Grid<>(10, 11, empty);
- assertEquals(11, grid.getHeight());
- }
-
- @Test
- public void gridSetGetTest() {
- GameObject empty = new Empty();
- Grid grid = new Grid<>(10, 11, empty);
- Token token = new Token(new Player("Naem", Color.green));
- grid.set(7, 3, token);
- assertEquals(token, grid.get(7, 3));
- }}