This commit is contained in:
Kristian Knarvik 2018-04-16 13:40:41 +02:00
commit e619971762
69 changed files with 2759 additions and 0 deletions

View File

@ -0,0 +1,11 @@
<component name="ArtifactManager">
<artifact type="jar" name="Four-In-A-Row">
<output-path>$PROJECT_DIR$/out/artifacts/Four_In_A_Row</output-path>
<root id="archive" name="Four-In-A-Row.jar">
<element id="directory" name="META-INF">
<element id="file-copy" path="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
</element>
<element id="module-output" name="Four-In-A-Row" />
</root>
</artifact>
</component>

View File

@ -0,0 +1,11 @@
<component name="libraryTable">
<library name="junit:junit:5.0-SNAPSHOT" type="repository">
<properties maven-id="junit:junit:5.0-SNAPSHOT" />
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/5.0-SNAPSHOT/junit-5.0-SNAPSHOT.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Four-In-A-Row.iml" filepath="$PROJECT_DIR$/Four-In-A-Row.iml" />
</modules>
</component>
</project>

124
.idea/uiDesigner.xml Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

1038
.idea/workspace.xml Normal file

File diff suppressed because it is too large Load Diff

13
Four-In-A-Row.iml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="junit:junit:5.0-SNAPSHOT" level="project" />
</component>
</module>

3
META-INF/MANIFEST.MF Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: Main

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,70 @@
Two dimensional array.
Render each subarray from bottom to top.
Place each piece in the start of the array.
Let user choose from a button above each row where to place a chip.
Keep count of player names and colors, maybe with some text input.
objects.Player has name and color.
Turn + Events
Width = 7, Height = 6
Check from each block of a color (maybe keep track of blocked pieces for effectiveness).
Maybe allow for custom combinations required to win.
Game
- Winning Conditions
- board.Board
- GameObjects
- Random events
- Input/Output
- Players
Players
Class with info about player <- passive
- name
- color (of token)
Interface for a player's actions <- active
- Methods for throwing token into column.
- +Info
Input/Output
- Input interface
* int getNextColumn(objects.Player p); //Retrieve user input
- Output interface
* void displayBoard(board.IBoard b);
* void displayMessage(String s);
Random Events
- Interface events.IRandomEvent
* void act(board.IBoard b);
* String announcement();
events.IRandomEvent
Abstract events.RandomEvent implements events.IRandomEvent (void flipCoin // Does something if heads)
Shuffle extends events.RandomEvent
objects.GameObject
objects.Token
Owner instanceof objects.Player
GameObjects(objects.Token, empty)
* One class
* getColor();
Winning Conditions
- Interface events.IWinCondition
* boolean hasWon(objects.Player p, board.IBoard board);
"Main" method (Game)
- Outer loop: "While the game has not been finished"
1) Determine who's turn
2) Get next input: int j = input.getNextColumn(p);
3) Execute move: p throws in column j.
4) Check if p has won.
5) Update view (output.displayBoard())
6) events.RandomEvent.act();

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

47
src/Main.java Normal file
View File

@ -0,0 +1,47 @@
import board.Board;
import events.FourInARow;
import events.IWinCondition;
import interfaces.FourInARowGUI;
import interfaces.NInARowGUI;
import interfaces.TicTacToeGUI;
import objects.Empty;
import javax.swing.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
class Main {
private static final int BOARD_WIDTH = 7;
private static final int BOARD_HEIGHT = 6;
private enum Gamemode {TICTACTOE, FOURINAROWCLASSIC, FOURINAROW}
public static void main(String[] args) {
HashMap<String, Gamemode> modeList = new HashMap<>();
modeList.put("Tic-Tac-Toe", Gamemode.TICTACTOE);
modeList.put("Four in a row classic", Gamemode.FOURINAROWCLASSIC);
modeList.put("Four in a row", Gamemode.FOURINAROW);
Object[] keys = modeList.keySet().toArray();
String selectedValue = (String)JOptionPane.showInputDialog(null, "Select a game from the list below:", "Car model...", JOptionPane.QUESTION_MESSAGE,null, keys, keys[0]);
if (selectedValue == null) {
System.exit(0);
}
List<IWinCondition> con = new ArrayList<>();
con.add(new FourInARow());
switch (modeList.get(selectedValue)) {
case TICTACTOE:
new TicTacToeGUI();
break;
case FOURINAROWCLASSIC:
new FourInARowGUI(BOARD_WIDTH, BOARD_HEIGHT, new Board(BOARD_WIDTH, BOARD_HEIGHT, new Empty(), con));
break;
case FOURINAROW:
new NInARowGUI(BOARD_WIDTH, BOARD_HEIGHT, new Board(BOARD_WIDTH, BOARD_HEIGHT, new Empty(), con));
break;
default:
System.exit(0);
}
}
}

70
src/Plan.txt Normal file
View File

@ -0,0 +1,70 @@
Two dimensional array.
Render each subarray from bottom to top.
Place each piece in the start of the array.
Let user choose from a button above each row where to place a chip.
Keep count of player names and colors, maybe with some text input.
objects.Player has name and color.
Turn + Events
Width = 7, Height = 6
Check from each block of a color (maybe keep track of blocked pieces for effectiveness).
Maybe allow for custom combinations required to win.
Game
- Winning Conditions
- board.Board
- GameObjects
- Random events
- Input/Output
- Players
Players
Class with info about player <- passive
- name
- color (of token)
Interface for a player's actions <- active
- Methods for throwing token into column.
- +Info
Input/Output
- Input interface
* int getNextColumn(objects.Player p); //Retrieve user input
- Output interface
* void displayBoard(board.IBoard b);
* void displayMessage(String s);
Random Events
- Interface events.IRandomEvent
* void act(board.IBoard b);
* String announcement();
events.IRandomEvent
Abstract events.RandomEvent implements events.IRandomEvent (void flipCoin // Does something if heads)
Shuffle extends events.RandomEvent
objects.GameObject
objects.Token
Owner instanceof objects.Player
GameObjects(objects.Token, empty)
* One class
* getColor();
Winning Conditions
- Interface events.IWinCondition
* boolean hasWon(objects.Player p, board.IBoard board);
"Main" method (Game)
- Outer loop: "While the game has not been finished"
1) Determine who's turn
2) Get next input: int j = input.getNextColumn(p);
3) Execute move: p throws in column j.
4) Check if p has won.
5) Update view (output.displayBoard())
6) events.RandomEvent.act();

149
src/board/Board.java Normal file
View File

@ -0,0 +1,149 @@
package board;
import events.IWinCondition;
import objects.GameObject;
import objects.Player;
import objects.Token;
import java.util.ArrayList;
import java.util.List;
public class Board implements IBoard{
private final Grid<GameObject> grid;
private final List<Player> players;
private int playersTurn = 0;
private final List<IWinCondition> conditionList;
private boolean won = false;
public Board(int width, int height, GameObject obj, List<IWinCondition> conditions) {
grid = new Grid<>(width, height, obj);
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<Player> 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;
}
/**
* Makes sure we don't have two equal players.
*
* @param player The new player to test
* @return True if the player is non-unique
*/
private boolean playerExists(Player player) {
for (Player p : players) {
if (player.equals(p)) {
return true;
}
}
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.
*
* @param x The x-coordinate of the last dropped object
* @param y The y-coordinate of the last dropped object
*/
private void checkWin(int x, int y) {
for (IWinCondition con : conditionList) {
if (con.hasWon(x, y, this)) {
won = true;
}
}
}
@Override
public boolean won() {
return won;
}
@Override
public void flush() {
grid.flush();
playersTurn = 0;
won = false;
}
@Override
public int getTopObject(int column) {
return grid.getTopObject(column);
}
@Override
public int getHeight() {
return grid.getHeight();
}
@Override
public int getWidth() {
return grid.getWidth();
}
@Override
public void set(int x, int y, GameObject element) {
grid.set(x, y, element);
if (element instanceof Token) {
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;
}
@Override
public GameObject get(int x, int y) { return grid.get(x, y); }
@Override
public IGrid<GameObject> copy() {
return grid.copy();
}
}

100
src/board/Grid.java Normal file
View File

@ -0,0 +1,100 @@
package board;
import objects.Token;
public class Grid<T> implements IGrid<T> {
private final T[][] grid;
private final int width;
private final int height;
private final T empty;
public Grid(int width, int height, T object) {
T[][] list = (T[][])new Object[width][height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
list[i][j] = object;
}
}
grid = list;
this.empty = object;
this.width = width;
this.height = height;
}
public void flush() {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
grid[i][j] = empty;
}
}
}
public boolean isFull() {
int empty = 0;
for (T[] list : grid) {
for (T item : list) {
if (this.empty.getClass().isInstance(item)) {
empty++;
}
}
}
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;
}
@Override
public int getHeight() {
return this.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;
}
@Override
public void set(int x, int y, T element) {
if (x > width || y > height || x < 0 || y < 0) {
throw new IllegalArgumentException("Index out of bounds.");
}
grid[x][y] = element;
}
@Override
public T get(int x, int y) {
if (y >= height || x >= width || x < 0 || y < 0) {
throw new IllegalArgumentException("Index out of bound.");
}
return grid[x][y];
}
@Override
public IGrid<T> copy() {
Grid<T> newGrid = new Grid<>(width, height, empty);
System.arraycopy(grid, 0, newGrid.grid, 0, width);
return newGrid;
}
}

50
src/board/IBoard.java Normal file
View File

@ -0,0 +1,50 @@
package board;
import objects.GameObject;
import objects.Player;
import java.util.List;
public interface IBoard extends IGrid<GameObject> {
/**
* Adds a new player to the board.
*
* @param p The player to add
* @return True if the player is valid
*/
boolean addPlayer(Player p);
/**
* Gets the next player from the board.
*
* @return A player
*/
Player nextPlayer();
/**
* Find out if someone has won.
*
* @return True if someone won
*/
boolean won();
/**
* Flushes all values in the board.
*/
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<Player> getPlayers();
}

70
src/board/IGrid.java Normal file
View File

@ -0,0 +1,70 @@
package board;
public interface IGrid<T> {
/**
* @return The height of the grid.
*/
int getHeight();
/**
* @return The width of the grid.
*/
int getWidth();
/**
*
* Set 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 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.
*/
T get(int x, int y);
/**
* Make a copy
*
* @return A fresh copy of the grid, with the same elements
*/
IGrid<T> copy();
/**
* Checks if the grid is absolutely full.
*
* @return True if it is full
*/
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
*/
int getTopObject(int column);
}

17
src/events/Block.java Normal file
View File

@ -0,0 +1,17 @@
package events;
import board.IBoard;
import objects.Immovable;
public class Block extends RandomEvent {
@Override
public void act(IBoard b) {
int x = random.nextInt(b.getWidth());
b.drop(x, new Immovable());
}
@Override
public String announcement() {
return "An immovable object was placed.";
}
}

47
src/events/Bomb.java Normal file
View File

@ -0,0 +1,47 @@
package events;
import board.IBoard;
import objects.Empty;
import objects.Token;
import java.util.ArrayList;
public class Bomb extends RandomEvent {
@Override
public void act(IBoard b) {
int x = random.nextInt(b.getWidth());
int y = b.getTopObject(x);
for (ArrayList<Integer> list : generateSquare(b, x, y, random.nextInt(2) + 1)) {
b.set(list.get(0), list.get(1), new Empty());
}
}
/**
* Gets all locations in a square a range from a point.
*
* @param b A board
* @param x The x index of the starting point
* @param y The y index of the starting point
* @param range The range of the square
* @return A list of lists of integers
*/
private ArrayList<ArrayList<Integer>> generateSquare(IBoard b, int x, int y, int range) {
ArrayList<ArrayList<Integer>> 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) {
ArrayList<Integer> coords = new ArrayList<>();
coords.add(i);
coords.add(j);
locations.add(coords);
}
}
}
return locations;
}
@Override
public String announcement() {
return "A bomb just exploded!";
}
}

View File

@ -0,0 +1,10 @@
package events;
import board.IBoard;
public class FourInARow extends InARow {
@Override
public boolean hasWon(int x, int y, IBoard board) {
return hasWon(x, y, board, 3);
}
}

View File

@ -0,0 +1,8 @@
package events;
import board.IBoard;
public interface IRandomEvent {
void act(IBoard b);
String announcement();
}

View File

@ -0,0 +1,18 @@
package events;
import board.IBoard;
/**
* A condition for winning the game.
*/
public interface IWinCondition {
/**
* Checks if someone has won according to the custom conditions.
*
* @param x The x-coordinate of the last placed element
* @param y The y-coordinate of the last placed element
* @param board The board to check
* @return True if someone has won
*/
boolean hasWon(int x, int y, IBoard board);
}

47
src/events/InARow.java Normal file
View File

@ -0,0 +1,47 @@
package events;
import board.IBoard;
import java.awt.*;
/**
* Contains methods for implementing any n in a row rules.
*/
abstract class InARow implements IWinCondition {
/**
* Checks if the supplied position has enough neighbours in a straight line of the same type
*
* @param x The x-coordinate of the start position
* @param y The y-coordinate of the start position
* @param board The board on which to perform the task
* @param t The number of elements in a row, which constitutes a win (excluding start position)
* @return True if x, y was a winning move
*/
static boolean hasWon(int x, int y, IBoard board, int t) {
return count(x, y, 1, 0, board) + count(x, y, -1, 0, board) >= t ||
count(x, y, 0, -1, board) + count(x, y, 0, 1, board) >= t ||
count(x, y, 1, 1, board) + count(x, y, -1, -1, board) >= t ||
count(x, y, 1, -1, board) + count(x, y, -1, 1, board) >= t;
}
/**
* Counts all elements from a start position in a set direction with a matching color.
*
* @param x The x-coordinate of the start position
* @param y The y-coordinate of the start position
* @param iX Step amount in x-direction
* @param iY Step amount in y-direction
* @param b The board on which to perform the task
* @return The number of elements found
*/
private static int count(int x, int y, int iX, int iY, IBoard b) {
int count = 0;
Color target = b.get(x, y).getColor();
while ((y + iY >= 0 && y + iY < b.getHeight()) && (x + iX >= 0 && x + iX < b.getWidth()) && b.get(x + iX, y + iY).getColor() == target) {
x += iX;
y += iY;
count++;
}
return count;
}
}

View File

@ -0,0 +1,43 @@
package events;
import board.IBoard;
import java.util.Random;
/**
* Contains basic probability methods usable by all random events.
*/
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) {
if (random.nextInt(2) > 0) {
act(b);
return true;
}
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) {
if (random.nextInt((int)Math.pow(6, n)) < 1) {
act(b);
return true;
}
return false;
}
public abstract void act(IBoard b);
}

View File

@ -0,0 +1,10 @@
package events;
import board.IBoard;
public class ThreeInARow extends InARow {
@Override
public boolean hasWon(int x, int y, IBoard board) {
return hasWon(x, y, board, 2);
}
}

View File

@ -0,0 +1,136 @@
package interfaces;
import board.IBoard;
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 FourInARowGUI extends GUI {
public FourInARowGUI(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;
for (int i = 0; i < 2; 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;
if (i == 0) {
color = Color.green;
} else {
color = Color.red;
}
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 + 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);
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()) {
if (board.isFull()) {
displayMessage("It's a draw");
} else {
this.currentPlayer = board.nextPlayer();
displayMessage("It's " + this.currentPlayer + "'s turn.");
}
} else {
GameObject winnerObject = this.board.get(i, this.board.getTopObject(i));
displayMessage(((Token)winnerObject).getOwner() + " won.");
}
} else {
displayMessage("That column is full.");
}
}
}
}
}
}

61
src/interfaces/GUI.java Normal file
View File

@ -0,0 +1,61 @@
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);
}
}

View File

@ -0,0 +1,6 @@
package interfaces;
interface IGameInterface {
void displayMessage(String s);
void displayBoard();
}

View File

@ -0,0 +1,181 @@
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("");
}
}
}

View File

@ -0,0 +1,151 @@
package interfaces;
import board.Board;
import events.IWinCondition;
import events.ThreeInARow;
import objects.Empty;
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;
import java.util.ArrayList;
import java.util.List;
public class TicTacToeGUI extends GUI {
private JButton[] gameGrid = new JButton[9];
public TicTacToeGUI() {
List<IWinCondition> conditions = new ArrayList<>();
conditions.add(new ThreeInARow());
this.board = new Board(3,3, new Empty(), conditions);
int playerNum = 2;
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);
}
if (playerName.length() > 10) {
JOptionPane.showMessageDialog(null, "Player name can't be longer than 10 characters.", "Error", JOptionPane.ERROR_MESSAGE);
playerName = "";
}
}
Player player;
if (i == 1) {
player = new Player(playerName, Color.BLACK);
} else {
player = new Player(playerName, Color.WHITE);
}
if (!this.board.addPlayer(player)) {
JOptionPane.showMessageDialog(null, "Player is not unique. Please try again.", "Error", JOptionPane.ERROR_MESSAGE);
i--;
}
}
initialize();
}
private void initialize() {
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) * 3;
int fullHeight = (TILE_HEIGHT) * 3;
this.frame = frame;
JPanel container = new JPanel();
container.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
container.setPreferredSize(new Dimension(fullWidth, fullHeight + 2 * BUTTON_HEIGHT));
frame.add(container);
JPanel panel2 = new JPanel();
this.mainPanel = panel2;
panel2.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
panel2.setPreferredSize(new Dimension(fullWidth, fullHeight));
readTiles();
container.add(panel2);
infoLabel = new JLabel();
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);
frame.validate();
frame.pack();
frame.setVisible(true);
currentPlayer = board.nextPlayer();
displayMessage("It's " + currentPlayer + "'s turn.");
}
public void displayBoard() {
for (JButton button : this.gameGrid) {
this.mainPanel.remove(button);
}
this.gameGrid = new JButton[this.board.getWidth() * this.board.getHeight()];
readTiles();
this.frame.validate();
}
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) {
button.setText("X");
} else if (obj.getColor() == Color.white) {
button.setText("O");
}
button.setPreferredSize(new Dimension(BUTTON_WIDTH, TILE_HEIGHT));
this.gameGrid[k++] = button;
mainPanel.add(button, BorderLayout.PAGE_START);
}
}
}
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 (!(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");
}
}
}
}
}
}
}

3
src/objects/Empty.java Normal file
View File

@ -0,0 +1,3 @@
package objects;
public class Empty extends GameObject {}

View File

@ -0,0 +1,11 @@
package objects;
import java.awt.*;
public abstract class GameObject {
Color color = Color.LIGHT_GRAY;
public Color getColor() {
return color;
}
}

View File

@ -0,0 +1,9 @@
package objects;
import java.awt.*;
public class Immovable extends GameObject {
public Immovable() {
this.color = Color.BLACK;
}
}

38
src/objects/Player.java Normal file
View File

@ -0,0 +1,38 @@
package objects;
import java.awt.*;
import java.util.Objects;
public class Player {
private final String name;
private final Color color;
public Player(String name, Color color) {
this.name = name;
this.color = color;
}
public Color getColor() {
return color;
}
@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);
}
@Override
public String toString() {
return name;
}
}

14
src/objects/Token.java Normal file
View File

@ -0,0 +1,14 @@
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;
}
}

63
test/FourInARowTest.java Normal file
View File

@ -0,0 +1,63 @@
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<IWinCondition> 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());
}
}

34
test/GridTest.java Normal file
View File

@ -0,0 +1,34 @@
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<GameObject> grid = new Grid<>(10, 11, empty);
assertEquals(10, grid.getWidth());
}
@Test
public void gridHeightTest() {
GameObject empty = new Empty();
Grid<GameObject> grid = new Grid<>(10, 11, empty);
assertEquals(11, grid.getHeight());
}
@Test
public void gridSetGetTest() {
GameObject empty = new Empty();
Grid<GameObject> 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));
}}

82
test/TicTacToeTest.java Normal file
View File

@ -0,0 +1,82 @@
import board.Board;
import events.IWinCondition;
import events.ThreeInARow;
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 TicTacToeTest {
private final List<IWinCondition> conditions = new ArrayList<>();
@Test
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));
board.set(0, 0, token);
board.set(1, 0, token);
board.set(2, 0, token);
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());
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());
}
@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));
board.set(0, 0, token);
assertFalse(board.won());
board.set(0, 1, token);
assertFalse(board.won());
board.set(0, 2, token);
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());
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());
}
@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));
board.set(0, 0, token);
assertFalse(board.won());
board.set(1, 1, token);
assertFalse(board.won());
board.set(2, 2, token);
assertTrue(board.won());
board = new Board(3, 3, new Empty(), conditions);
board.set(0, 2, token);
assertFalse(board.won());
board.set(1, 1, token);
assertFalse(board.won());
board.set(2, 0, token);
assertTrue(board.won());
}
}