From c47326b7ade1a64a9af1aa4abf2e802926b2a49a Mon Sep 17 00:00:00 2001 From: Martin Goik <goik@hdm-stuttgart.de> Date: Fri, 18 Sep 2015 11:59:58 +0200 Subject: [PATCH] Human vs. computer --- P/Sd1/TicTacToe/V4/.gitignore | 5 + P/Sd1/TicTacToe/V4/pom.xml | 66 +++++ .../hdm_stuttgart/mi/sd1/tictactoe/Board.java | 271 ++++++++++++++++++ .../mi/sd1/tictactoe/Helper.java | 15 + .../mi/sd1/tictactoe/Player.java | 31 ++ .../mi/sd1/tictactoe/TicTacToe.java | 64 +++++ .../V4/src/main/resources/log4j2.xml | 21 ++ .../mi/sd1/connectfour/HelperTest.java | 66 +++++ .../mi/sd1/connectfour/PerfectMoveTest.java | 59 ++++ .../mi/sd1/connectfour/ScoreTest.java | 130 +++++++++ 10 files changed, 728 insertions(+) create mode 100644 P/Sd1/TicTacToe/V4/.gitignore create mode 100644 P/Sd1/TicTacToe/V4/pom.xml create mode 100644 P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Board.java create mode 100644 P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Helper.java create mode 100644 P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Player.java create mode 100644 P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/TicTacToe.java create mode 100644 P/Sd1/TicTacToe/V4/src/main/resources/log4j2.xml create mode 100644 P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/HelperTest.java create mode 100644 P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/PerfectMoveTest.java create mode 100644 P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/ScoreTest.java diff --git a/P/Sd1/TicTacToe/V4/.gitignore b/P/Sd1/TicTacToe/V4/.gitignore new file mode 100644 index 000000000..4ef0c0524 --- /dev/null +++ b/P/Sd1/TicTacToe/V4/.gitignore @@ -0,0 +1,5 @@ +/target/ +/.settings/ +A1.log +.classpath +.project diff --git a/P/Sd1/TicTacToe/V4/pom.xml b/P/Sd1/TicTacToe/V4/pom.xml new file mode 100644 index 000000000..6e9ef6fc9 --- /dev/null +++ b/P/Sd1/TicTacToe/V4/pom.xml @@ -0,0 +1,66 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>de.hdm-stuttgart.mi</groupId> + <artifactId>lecturenotes-pom</artifactId> + <version>1.0</version> + <relativePath>../../../pom.xml</relativePath> + </parent> + + + <groupId>de.hdm-stuttgart.mi.sd1</groupId> + <artifactId>tictactoe</artifactId> + <version>4.0</version> + <packaging>jar</packaging> + + <name>TicTacToe</name> + + <url>http://www.mi.hdm-stuttgart.de/freedocs</url> + + <build> + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.1</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10.1</version> + <configuration/> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>2.3</version> + <configuration> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <manifestEntries> + <Main-Class>de.hdm_stuttgart.mi.sd1.connectfour.App</Main-Class> + </manifestEntries> + </transformer> + </transformers> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> +</project> diff --git a/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Board.java b/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Board.java new file mode 100644 index 000000000..7d1982065 --- /dev/null +++ b/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Board.java @@ -0,0 +1,271 @@ +package de.hdm_stuttgart.mi.sd1.tictactoe; + +public class Board { + + static private int clearTerminalLineCount = 20; // Scroll down this many lines simulating terminal clear. + static private int fieldSize = 3; + static private int numberOfFields = fieldSize * fieldSize; // Each Tic-Tac-Toe board has got 3 x 3 = 9 fields + private short numberOfMoves = 0; // Game will be over after a maximum of 9 moves + + private Player currentActivePlayer; // Player about to start next move + + final Player[] board = new Player[numberOfFields]; // Allocating a one- dimensional array, yet empty. + + public Board(final Player startingPlayer) { + currentActivePlayer = startingPlayer; + for (int i = 0; i < numberOfFields; i++) { // Initialize board with null values. + board[i] = null; + } + } + + public Board(final Player activePlayer, Player[] initial) { // For unit testing purpose. + currentActivePlayer = activePlayer; + for (int i = 0; i < numberOfFields; i++) { // Initialize board with null values. + board[i] = initial[i]; + if (null != board[i]) { + numberOfMoves++; + } + } + } + + public void nextPerfectMove() { + final int[] freeFields = getFreeFields(); + + if (0 == freeFields.length) { + return; + } + + int drawOrLooseIndex = freeFields[0]; // Choose a candidate. If not confirmed, we're bound to loose anyway + + for (int i = 0; i < freeFields.length; i++) { + + final int freeFieldIndex = freeFields[i]; + + board[freeFieldIndex] = currentActivePlayer; // Set empty field to player. + final int score = getScore( + board, currentActivePlayer.getOtherPlayer(), + Helper.excludeIndex(freeFields, i)); + + if (currentActivePlayer.score == score) { + currentActivePlayer = currentActivePlayer.getOtherPlayer(); + numberOfMoves++; + return; // Leave current field occupied by active player. + } else { + if (0 == score) { + drawOrLooseIndex = freeFieldIndex; // Better off than loosing. + } + } + board[freeFieldIndex] = null; // Reset field to empty state, continue searching. + } + board[drawOrLooseIndex] = currentActivePlayer; + numberOfMoves++; + currentActivePlayer = currentActivePlayer.getOtherPlayer(); + } + + + public int[] getFreeFields() { + final int[] freeFields = new int[numberOfFields - numberOfMoves]; + + int index = 0; + for (int i = 0; i < numberOfFields; i++) { + if (null == board[i]) { + freeFields[index++] = i; + } + } + return freeFields; + } + + public int getScore() { // For unit testing purpose. + final int[] freeFields = getFreeFields(); + return getScore(board, currentActivePlayer, freeFields); + } + + private int getScore(final Player[] evalBoard, final Player activePlayer, final int[] freeFields) { + + { + final Player winner = getWinner(evalBoard); + + if (null != winner) { + return winner.score; // "Winning" end state. + } else if (0 == freeFields.length) { + return 0; // "Draw" end state: Board completely populated. + } + } + + boolean drawChildExists = false; + for(int i = 0; i < freeFields.length; i++) { + final int freeFieldIndex = freeFields[i]; + + evalBoard[freeFieldIndex] = activePlayer; // Set empty field to player. + final int score = getScore( + evalBoard, activePlayer.getOtherPlayer(), + Helper.excludeIndex(freeFields, i)); + evalBoard[freeFieldIndex] = null; // Reset field to empty state. + + if (activePlayer.score == score) { // Maximum or minimum (with respect to active player) has been reached. + return activePlayer.score; + } else if (0 == score) { + drawChildExists = true; // Continue searching for better (maximal or minimal) score. + } + } + + if (drawChildExists) { + return 0; // There is at least one "draw" child to choose from. + } else { + return activePlayer.getOtherPlayer().score; // All board children score to the active player's enemy + } + } + + public Player evaluateWinner(){ + return getWinner(board); + } + + /** + * Test whether one of our two players has won the game. + * + * @return The winner instance if a winner exists, null otherwise + */ + static public Player getWinner(Player[] evalBoard) { + + if (null != evalBoard[4] && ( // Check both diagonals + (evalBoard[4] == evalBoard[0] && evalBoard[4] == evalBoard[8]) || // + (evalBoard[4] == evalBoard[6] && evalBoard[4] == evalBoard[2]))) { // x x + return evalBoard[4]; // x + } // x x + + for (int i = 0; i < fieldSize; i++) { // Check all three columns + if (null != evalBoard[i] && // +-= + evalBoard[i] == evalBoard[i + fieldSize] && + evalBoard[i] == evalBoard[i + 2* fieldSize]) { // +-= + return evalBoard[i]; // +-= + } + } + + for (int i = 0; i < 2 * fieldSize + 1; i += fieldSize) { // Check all three rows + if (null != evalBoard[i] && // +++ + evalBoard[i] == evalBoard[i + 1] && evalBoard[i] == evalBoard[i + 2]) { // --- + return evalBoard[i]; // === + } + } + return null; + } + + /** + * Occupy the next field by player {@link #getCurrentActivePlayer()}. + * + * Fields are being numbered by: + * + * 1|2|3 + * -+-+- + * 4|5|6 + * -+-+- + * 7|8|9 + * + * @param field The field in question + * + * @return An error message indication either an occupied field or an index violation. + * null if everything is o.K. + */ + public String nextMove(final int field) { + + if (field < 1 || numberOfFields < field) { + return "Field index out of range [0 ..." + + numberOfFields + "]"; + } else { + final int fieldIndex = field - 1; // User to (computer) nerd point of view + final Player current = board[fieldIndex]; + if (current == null) { + board[fieldIndex] = currentActivePlayer; + currentActivePlayer = currentActivePlayer.getOtherPlayer(); + numberOfMoves++; + return null; + } else { + return "Field already occupied by " + current.nickname; + } + } + } + + static public void printNumberingHint() { + System.out.println("Numbering scheme:\n"); + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + System.out.print((char)('1' + x + y * fieldSize)); + if (x < fieldSize - 1) { + System.out.print('|'); + } + } + if (y < fieldSize - 1) { + System.out.println("\n-+-+-"); + } + } + } + + /** + * Get the player instance which will do the next move. See {@link #nextMove(short)} + * + * @return the currently active player. + */ + public Player getCurrentActivePlayer() { + return currentActivePlayer; + } + + /** + * After nine moves all fields will have been occupied. + * @return true if all possible moves have been completed, false otherwise. + */ + public boolean allMovesFinished() { + return numberOfFields <= numberOfMoves; + } + + public void print(boolean simulateClear, boolean printNumberingHints) { + print(board, simulateClear, printNumberingHints); + } + + /** + * Publish the current state to standard output using + * ASCII graphics. + */ + static private void print(final Player[] boardState, boolean simulateClear, boolean printNumberingHints) { + for (int clear = 0; simulateClear && clear < clearTerminalLineCount; clear++) { + System.out.println("\n"); + } + + System.out.println("\n\nPlayer " + Player.YOU.nickname + "(" + + Player.YOU.representation + ")" + "\nvs. " + Player.COM.nickname + + "(" + Player.COM.representation + ")" + " Free fields\n"); + + final String tableSeparator = " "; + for (int x = 0; x < fieldSize; x++) { + + // Print current values + for (int y = 0; y < fieldSize; y++) { + final int fieldIndex = y + fieldSize * x; + System.out.print(null == boardState[fieldIndex] ? " " : boardState[fieldIndex].representation); + if (y < fieldSize - 1) { + System.out.print('|' ); + } + } + if (printNumberingHints) { + System.out.print(tableSeparator); + + // print free field numbering hints. + for (int y = 0; y < fieldSize; y++) { + final int fieldIndex = y + fieldSize * x; + System.out.print(null == boardState[fieldIndex] ? fieldIndex + 1 : // Nerd to user perspective. + " "); + if (y < fieldSize - 1) { + System.out.print('|'); + } + } + } + + if (x < fieldSize - 1) { + System.out.print("\n-+-+-" + (printNumberingHints ? tableSeparator + "-+-+-" : "") ); + System.out.println(); + } + } + } + public Player[] getBoard() { + return board.clone(); + } +} diff --git a/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Helper.java b/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Helper.java new file mode 100644 index 000000000..025744917 --- /dev/null +++ b/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Helper.java @@ -0,0 +1,15 @@ +package de.hdm_stuttgart.mi.sd1.tictactoe; + +public class Helper { + + static public int[] excludeIndex(final int[] values, int excludeIndex) { + final int[] ret = new int[values.length - 1]; + for (int i = 0; i < excludeIndex; i++) { + ret[i] = values[i]; + } + for (int i = excludeIndex; i < values.length - 1; i++) { + ret[i] = values[i + 1]; + } + return ret; + } +} diff --git a/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Player.java b/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Player.java new file mode 100644 index 000000000..bd323a2fb --- /dev/null +++ b/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/Player.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.mi.sd1.tictactoe; + +public enum Player { + + YOU("You", 'O', 1), COM("Me (computer)", 'X', -1); + + public final String nickname; + public final char representation; + public int score; + private Player other; + + static { // For further explanation see + YOU.other = COM; // http://stackoverflow.com/questions/5678309/illegal-forward-reference-and-enums#5678375 + COM.other = YOU; + } + + public Player getOtherPlayer() { + return other; + } + + Player(final String nickname, final char representation, final int score) { + this.nickname = nickname; + this.representation = representation; + this.score = score; + } + + @Override + public String toString() { + return nickname + ", " + score + ", "+ representation; + } +} diff --git a/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/TicTacToe.java b/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/TicTacToe.java new file mode 100644 index 000000000..413b64d06 --- /dev/null +++ b/P/Sd1/TicTacToe/V4/src/main/java/de/hdm_stuttgart/mi/sd1/tictactoe/TicTacToe.java @@ -0,0 +1,64 @@ +package de.hdm_stuttgart.mi.sd1.tictactoe; + +import java.util.Scanner; + +/** + * Playing Tic-tac-toe with two players. + * + */ +public class TicTacToe { + + /** + * @param args + * Unused + */ + public static void main(String[] args) { + + final Scanner scan = new Scanner(System.in); + + Board.printNumberingHint(); + System.out.println("\n\n"); + + System.out.println("Who is going to start? " + + Player.YOU.ordinal() + " = " + Player.YOU.nickname + + ", other = " + Player.COM.nickname); + + final int firstPlayer = scan.nextShort(); + + final Board board; + if (Player.YOU.ordinal() == firstPlayer) { + board = new Board(Player.YOU); + } else { + board = new Board(Player.COM); + board.nextPerfectMove(); + } + board.print(true, true); + + Player winner; + do { + do { + System.out.print("\n\nPlease enter next field's number:"); + final short nextField = scan.nextShort(); + final String errorMessage = board.nextMove(nextField); + if (null == errorMessage) { + break; // o.K., quit loop for next move. + } else { + System.err.println(errorMessage); // Field already occupied? + } + } while (true); + board.nextPerfectMove(); + board.print(true, !board.allMovesFinished()); + } while (null == (winner = board.evaluateWinner()) && !board.allMovesFinished()); + + if (null == winner) { + System.out.println("\n\nGame over: draw"); + } else { + switch(winner) { + case YOU: System.out.println("\n\nCongratulations, you won!");break; + case COM: System.out.println("\n\nSorry, you lost!");break; + } + } + + scan.close(); + } +} diff --git a/P/Sd1/TicTacToe/V4/src/main/resources/log4j2.xml b/P/Sd1/TicTacToe/V4/src/main/resources/log4j2.xml new file mode 100644 index 000000000..52f0a47cb --- /dev/null +++ b/P/Sd1/TicTacToe/V4/src/main/resources/log4j2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="A1" fileName="A1.log" append="false"> + <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> + </Console> + </Appenders> + <Loggers> + + <!-- You my want to define class or package level per-logger rules --> + <Logger name="de.hdm_stuttgart.mi.sd1.connectfour.App" level="debug"> + <AppenderRef ref="A1"/> + </Logger> + <Root level="info"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/HelperTest.java b/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/HelperTest.java new file mode 100644 index 000000000..3b8ef79f6 --- /dev/null +++ b/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/HelperTest.java @@ -0,0 +1,66 @@ +package de.hdm_stuttgart.mi.sd1.connectfour; + +import org.junit.Assert; +import org.junit.Test; + +import de.hdm_stuttgart.mi.sd1.tictactoe.Helper; + +/** + * Testing Tic-tac-toe. + */ +public class HelperTest { + + @Test + public void testOneField() { + final int[] input = {9}, + result = Helper.excludeIndex(input, 0), + expectedResult = {}; + + Assert.assertArrayEquals(expectedResult, result); + } + + @Test + public void testTwoFields0() { + final int[] input = {0, 8}, + result = Helper.excludeIndex(input, 0), + expectedResult = {8}; + + Assert.assertArrayEquals(expectedResult, result); + } + + @Test + public void testTwoFields1() { + final int[] input = {0, 8}, + result = Helper.excludeIndex(input, 1), + expectedResult = {0}; + + Assert.assertArrayEquals(expectedResult, result); + } + + @Test + public void testArrayFields0() { + final int[] input = {1,2,3}, + result = Helper.excludeIndex(input, 0), + expectedResult = {2,3}; + + Assert.assertArrayEquals(expectedResult, result); + } + + @Test + public void testArrayFields2() { + final int[] input = {1,2,3}, + result = Helper.excludeIndex(input, 1), + expectedResult = {1,3}; + + Assert.assertArrayEquals(expectedResult, result); + } + + @Test + public void testThreeFields3() { + final int[] input = {1,2,3}, + result = Helper.excludeIndex(input, 2), + expectedResult = {1,2}; + + Assert.assertArrayEquals(expectedResult, result); + } +} \ No newline at end of file diff --git a/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/PerfectMoveTest.java b/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/PerfectMoveTest.java new file mode 100644 index 000000000..05d8167b1 --- /dev/null +++ b/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/PerfectMoveTest.java @@ -0,0 +1,59 @@ +package de.hdm_stuttgart.mi.sd1.connectfour; + +import static de.hdm_stuttgart.mi.sd1.tictactoe.Player.YOU; +import static de.hdm_stuttgart.mi.sd1.tictactoe.Player.COM; + +import org.junit.Assert; +import org.junit.Test; + +import de.hdm_stuttgart.mi.sd1.tictactoe.Board; +import de.hdm_stuttgart.mi.sd1.tictactoe.Player; +/** + * Testing Tic-tac-toe. + */ +public class PerfectMoveTest { + + @Test + public void testWinningMove() { + + final Board board = new Board( + COM, // active player. + + new Player[] { + null, COM, YOU, // |X|O + // -+-+- + null, COM, YOU, // |X|O + // -+-+- + null, null, null}); // | | + + board.nextPerfectMove(); + + final Player[] expected = new Player[] { + null, COM, YOU, // |X|O + // -+-+- + null, COM, YOU, // |X|O + // -+-+- + null, COM, null}; // |X| + + Assert.assertArrayEquals(expected, board.getBoard()); + } + + @Test + public void testStartPlayer() { + + final Board board = new Board(YOU); + + board.nextMove(1); + board.nextPerfectMove(); + board.print(false, true); + + board.nextMove(2); + board.print(false, true); + + board.nextPerfectMove(); + board.print(false, true); + } + + + +} diff --git a/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/ScoreTest.java b/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/ScoreTest.java new file mode 100644 index 000000000..4cf14dfe9 --- /dev/null +++ b/P/Sd1/TicTacToe/V4/src/test/java/de/hdm_stuttgart/mi/sd1/connectfour/ScoreTest.java @@ -0,0 +1,130 @@ +package de.hdm_stuttgart.mi.sd1.connectfour; + +import static de.hdm_stuttgart.mi.sd1.tictactoe.Player.YOU; +import static de.hdm_stuttgart.mi.sd1.tictactoe.Player.COM; + +import org.junit.Assert; +import org.junit.Test; + +import de.hdm_stuttgart.mi.sd1.tictactoe.Board; +import de.hdm_stuttgart.mi.sd1.tictactoe.Player; +/** + * Testing Tic-tac-toe. + */ +public class ScoreTest { + + @Test + public void testEmptyBoard() { + + final Board board = new Board( + COM, // active player. + + new Player[] { + null, null, null, // | | + // -+-+- + null, null, null, // | | + // -+-+- + null, null, null}); // | | + + Assert.assertEquals(0, board.getScore()); + } + + @Test + public void testDrawTwoEnd() { + + final Board board = new Board( + YOU, // active player. + + new Player[] { + YOU, COM, COM, // O|X|X + // -+-+- + COM, YOU, YOU, // X|O|O + // -+-+- + null, null, COM}); // | |X + + Assert.assertEquals(0, board.getScore()); + } + + @Test + public void testDraw1() { + + final Board board = new Board( + COM, // active player. + + new Player[] { + null, null, null, // | | + // -+-+- + null, YOU, null, // |O| + // -+-+- + YOU, null, COM}); // O| |X + + Assert.assertEquals(YOU.score, board.getScore()); + } + + + @Test + public void testDrawEnd() { + + final Board board = new Board( + COM, // active player. + + new Player[] { + YOU, COM, COM, // O|X|X + // -+-+- + COM, YOU, YOU, // X|O|O + // -+-+- + YOU, null, COM}); // O| |X + + Assert.assertEquals(0, board.getScore()); + } + + @Test + public void testWinOne1() { + + final Board board = new Board( + YOU, // active player. + + new Player[] { + null, null, null, // | | + // -+-+- + null, YOU, null, // |O| + // -+-+- + YOU, COM, COM}); // O|X|X + + Assert.assertEquals(YOU.score, board.getScore()); + } + + + + @Test + public void testWinTwoMoves() { + + final Board board = new Board( + COM, // active player. + + new Player[] { + null, YOU, COM, // |O|X + // -+-+- + COM, YOU, YOU, // X|O|O + // -+-+- + null, COM, null}); // |X| + + Assert.assertEquals(COM.score, board.getScore()); + } + + @Test + public void testLooseNextMove() { + + final Board board = new Board( + COM, // active player. + + new Player[] { + null, YOU, YOU, // |O|O + // -+-+- + null, COM, YOU, // |X|O + // -+-+- + COM, null, null}); // X| | + + Assert.assertEquals(YOU.score, board.getScore()); + } +} -- GitLab