From e66525bb510dea0696a2c3843295c1bf4b922afd Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 7 Jul 2021 18:52:25 +0300 Subject: [PATCH 01/33] hometask_1 second commit --- src/main/java/lesson_2/Main.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/lesson_2/Main.java b/src/main/java/lesson_2/Main.java index 68371511..fe7b118c 100644 --- a/src/main/java/lesson_2/Main.java +++ b/src/main/java/lesson_2/Main.java @@ -2,10 +2,19 @@ public class Main { - public static void main(String[] args) { - System.out.println("Hello, World!"); + public static void main(String[] args) throws Exception { - System.out.println("Hello World2!"); + try { + for (String str : args) { + + if (str.equalsIgnoreCase("error")) { + System.out.println("\u001B[31m" + "Alarm!" + "\u001B[0m"); + throw new RuntimeException(); + } + System.out.println(str + " " + str.length() + " letters"); + } + } catch (Exception e) { + } } } From ef9907f19093e98fd213b4f41f734030949337cc Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Fri, 9 Jul 2021 15:55:23 +0300 Subject: [PATCH 02/33] commit without gradlew.bat --- src/main/java/lesson_2/Main.java | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/lesson_2/Main.java b/src/main/java/lesson_2/Main.java index fe7b118c..13e418bb 100644 --- a/src/main/java/lesson_2/Main.java +++ b/src/main/java/lesson_2/Main.java @@ -2,19 +2,20 @@ public class Main { - public static void main(String[] args) throws Exception { + public static void main(String[] args) throws Exception { - try { - for (String str : args) { - if (str.equalsIgnoreCase("error")) { - System.out.println("\u001B[31m" + "Alarm!" + "\u001B[0m"); - throw new RuntimeException(); + try { + for (String str : args) { + + if (str.equalsIgnoreCase("error")) { + System.out.println("\u001B[31m" + "Alarm!" + "\u001B[0m"); + throw new RuntimeException(); + } + System.out.println(str + " " + str.length() + " letters"); + } + } catch (Exception e) { } - System.out.println(str + " " + str.length() + " letters"); - } - } catch (Exception e) { } - } } From 6f861423cbba7da04db98c287bf20c78575dcdea Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Tue, 20 Jul 2021 14:32:44 +0300 Subject: [PATCH 03/33] First homework has been fixed --- src/main/java/homework_1/Main.java | 18 ++++++++++++++++++ src/main/java/lesson_2/Main.java | 21 --------------------- 2 files changed, 18 insertions(+), 21 deletions(-) create mode 100644 src/main/java/homework_1/Main.java delete mode 100644 src/main/java/lesson_2/Main.java diff --git a/src/main/java/homework_1/Main.java b/src/main/java/homework_1/Main.java new file mode 100644 index 00000000..5f18db59 --- /dev/null +++ b/src/main/java/homework_1/Main.java @@ -0,0 +1,18 @@ +package homework_1; + +public class Main { + + static final String RED = "\u001B[31m"; + static final String BLACK = "\u001B[0m"; + + public static void main(String[] args) throws Exception { + + for (String str : args) { + if (str.equals("error")) { + System.out.println(RED + "Alarm!" + BLACK); + return; + } + System.out.println(str + " " + str.length() + " letters"); + } + } +} diff --git a/src/main/java/lesson_2/Main.java b/src/main/java/lesson_2/Main.java deleted file mode 100644 index 13e418bb..00000000 --- a/src/main/java/lesson_2/Main.java +++ /dev/null @@ -1,21 +0,0 @@ -package lesson_2; - -public class Main { - - public static void main(String[] args) throws Exception { - - - try { - for (String str : args) { - - if (str.equalsIgnoreCase("error")) { - System.out.println("\u001B[31m" + "Alarm!" + "\u001B[0m"); - throw new RuntimeException(); - } - System.out.println(str + " " + str.length() + " letters"); - } - } catch (Exception e) { - } - } - -} From 79b46d522fd6f0911f27d92504f42333c17e8b29 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Tue, 20 Jul 2021 19:26:38 +0300 Subject: [PATCH 04/33] Second homework. ReadMe added. --- README.md | 14 +++ .../java/homework_2/pyramid_printer/Main.java | 9 ++ .../pyramid_printer/PyramidPrinter.java | 41 +++++++ .../homework_2/random_chars_table/Main.java | 9 ++ .../random_chars_table/RandomCharsTable.java | 104 ++++++++++++++++++ .../java/homework_2/traffic_light/Main.java | 9 ++ .../traffic_light/TrafficLight.java | 60 ++++++++++ .../java/homework_2/TrafficLightTest.java | 25 +++++ 8 files changed, 271 insertions(+) create mode 100644 README.md create mode 100644 src/main/java/homework_2/pyramid_printer/Main.java create mode 100644 src/main/java/homework_2/pyramid_printer/PyramidPrinter.java create mode 100644 src/main/java/homework_2/random_chars_table/Main.java create mode 100644 src/main/java/homework_2/random_chars_table/RandomCharsTable.java create mode 100644 src/main/java/homework_2/traffic_light/Main.java create mode 100644 src/main/java/homework_2/traffic_light/TrafficLight.java create mode 100644 src/test/java/homework_2/TrafficLightTest.java diff --git a/README.md b/README.md new file mode 100644 index 00000000..fb5b667f --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Java Core June 2021 + +## *Tom Shandrikov* + +| Number | Solution | Short description +| --- | --- | --- | +| HW1 | [Console printer](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_1) | This console app prints our words and number of letters until your input equals "error". | +| HW2.1 | [Traffic Light](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/traffic_light) | This console app reads an integer of seconds and prints a color of traffic light.| +| HW2.2 | [Pyramid Printer](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/pyramid_printer) | This console app prints a pyramid of "x". | +| HW2.3 | [Random Chars Table](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/random_chars_table) | This console app makes a table of chars from A to Z and shows evens/odds of them depending on the strategy we have chosen. | + +[Link to CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) + +[Link to markdown giude](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) diff --git a/src/main/java/homework_2/pyramid_printer/Main.java b/src/main/java/homework_2/pyramid_printer/Main.java new file mode 100644 index 00000000..04446884 --- /dev/null +++ b/src/main/java/homework_2/pyramid_printer/Main.java @@ -0,0 +1,9 @@ +package homework_2.pyramid_printer; + +public class Main { + + public static void main(String[] args) { + PyramidPrinter pyramidPrinter = new PyramidPrinter(); + pyramidPrinter.run(); + } +} diff --git a/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java b/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java new file mode 100644 index 00000000..eb3aca14 --- /dev/null +++ b/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java @@ -0,0 +1,41 @@ +package homework_2.pyramid_printer; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class PyramidPrinter { + + public static final String ERROR = "Only 1 non-negative integer is allowed as passed parameter"; + + public void run() { + System.out.println("Please, input a number:"); + int countX = bufferedReaderReadConsole(); + if (countX < 0) { + System.out.println(ERROR); + return; + } + + String s = "x"; + for (int i = 1; i <= countX; i++) { + System.out.println(s); + s = s + "x"; + } + } + + private int bufferedReaderReadConsole() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + int count = 0; + try { + count = Integer.parseInt(reader.readLine()); + } catch (NumberFormatException e) { + return -1; + } + return count; + } catch (IOException e) { + e.printStackTrace(); + } + // Что лучше возвращать в return? + return -1; + } +} diff --git a/src/main/java/homework_2/random_chars_table/Main.java b/src/main/java/homework_2/random_chars_table/Main.java new file mode 100644 index 00000000..e359a82c --- /dev/null +++ b/src/main/java/homework_2/random_chars_table/Main.java @@ -0,0 +1,9 @@ +package homework_2.random_chars_table; + +public class Main { + + public static void main(String[] args) { + RandomCharsTable randomCharsTable = new RandomCharsTable(); + randomCharsTable.run(); + } +} diff --git a/src/main/java/homework_2/random_chars_table/RandomCharsTable.java b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java new file mode 100644 index 00000000..f375042e --- /dev/null +++ b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java @@ -0,0 +1,104 @@ +package homework_2.random_chars_table; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class RandomCharsTable { + + public static final String ERROR = "Passed parameters should match the format [positive integer] [positive integer] [even|odd]"; + + private int length; + private int width; + private String strategy; + + private String strategyEven = "Even letters -"; + private String strategyOdd = "Odd letters -"; + + public void run() { + + System.out.println("[Input example: 2 3 odd]"); + System.out.println("Please, input 2 positive numbers and a strategy (even/odd)"); + + String inputFull = bufferedReaderReadConsole(); + try { + parseInput(inputFull); + validateInputData(length, width, strategy); + } catch (IllegalArgumentException e) { + System.out.println(ERROR); + return; + } + + char[][] table = new char[length][width]; + + for (int i = 0; i < length; i++) { + System.out.print("|"); + + for (int j = 0; j < width; j++) { + int x = (int) (Math.random() * 26 + 65); + table[i][j] = (char) x; + if (x % 2 == 0) { + strategyEven = strategyEven + " " + table[i][j] + ","; + } else { + strategyOdd = strategyOdd + " " + table[i][j] + ","; + } + System.out.print(" " + table[i][j] + " |"); + } + + System.out.println(); + } + + strategyOdd = deleteLastCommaInStrategy(strategyOdd); + strategyEven = deleteLastCommaInStrategy(strategyEven); + + if (strategy.equals("even")) { + System.out.print(strategyEven); + } + + if (strategy.equals("odd")) { + System.out.print(strategyOdd); + } + } + + private String bufferedReaderReadConsole() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + String input = reader.readLine(); + return input; + } catch (IOException e) { + e.printStackTrace(); + } + // Корректно ли здесь возвращать null или нет? + return null; + } + + private void parseInput(String s) { + + String[] array = s.split(" "); + + if (array.length != 3) { + throw new IllegalArgumentException(); + } + + try { + length = Integer.parseInt(array[0]); + width = Integer.parseInt(array[1]); + strategy = array[2]; + } catch (NumberFormatException e) { + throw new IllegalArgumentException(); + } + } + + private void validateInputData(int x, int y, String str) { + if (x < 1 || y < 1 || (!str.equals("odd") && !str.equals("even"))) { + throw new IllegalArgumentException(); + } + } + + private String deleteLastCommaInStrategy(String str) { + if (str.endsWith(",")) { + return str.substring(0, str.length() - 1); + } else { + return str; + } + } +} diff --git a/src/main/java/homework_2/traffic_light/Main.java b/src/main/java/homework_2/traffic_light/Main.java new file mode 100644 index 00000000..0b7b67da --- /dev/null +++ b/src/main/java/homework_2/traffic_light/Main.java @@ -0,0 +1,9 @@ +package homework_2.traffic_light; + +public class Main { + + public static void main(String[] args) { + TrafficLight trafficLight = new TrafficLight(); + trafficLight.run(); + } +} diff --git a/src/main/java/homework_2/traffic_light/TrafficLight.java b/src/main/java/homework_2/traffic_light/TrafficLight.java new file mode 100644 index 00000000..35fc72e9 --- /dev/null +++ b/src/main/java/homework_2/traffic_light/TrafficLight.java @@ -0,0 +1,60 @@ +package homework_2.traffic_light; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class TrafficLight { + + public static final String RESET = "\u001B[0m"; + public static final String RED = "\u001B[31m" + "RED" + RESET; + public static final String GREEN = "\u001B[32m" + "GREEN" + RESET; + public static final String YELLOW = "\u001B[33m" + "YELLOW" + RESET; + public static final String ERROR = "Only 1 non-negative integer is allowed as passed parameter"; + + public void run() { + System.out.println("Please, input a number of seconds:"); + int seconds = bufferedReaderReadConsole(); + + try { + validateInput(seconds); + } catch (IllegalArgumentException e) { + return; + } + + System.out.println(showLight(seconds)); + } + + private int bufferedReaderReadConsole() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + int secondsIn = Integer.parseInt(reader.readLine()); + return secondsIn; + } catch (IOException e) { + e.printStackTrace(); + } + // Что лучше возвращать в return? + return -1; + } + + // Как тестировать? + private void validateInput(int i) { + if (i < 0) { + System.out.println(ERROR); + throw new IllegalArgumentException(); + } else if (i > 86399) { + System.out.println("The day is over"); + throw new IllegalArgumentException(); + } + } + + // Можно ли здесь сделать метод статическим (для более короткого вызова метода в тестах), + // или это неправильно? + public static String showLight(int i) { + + int secondsMod = i % 60; + return secondsMod < 35 ? GREEN + : secondsMod < 40 ? YELLOW + : secondsMod < 55 ? RED + : YELLOW; + } +} diff --git a/src/test/java/homework_2/TrafficLightTest.java b/src/test/java/homework_2/TrafficLightTest.java new file mode 100644 index 00000000..417b1661 --- /dev/null +++ b/src/test/java/homework_2/TrafficLightTest.java @@ -0,0 +1,25 @@ +package homework_2; + +import org.junit.jupiter.api.Test; + +import static homework_2.traffic_light.TrafficLight.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TrafficLightTest { + + @Test + void given0(){ + final String expected = GREEN; + final String actual = showLight(0); + + assertEquals(expected, actual); + } + + @Test + void given119(){ + final String expected = YELLOW; + final String actual = showLight(119); + + assertEquals(expected, actual); + } +} From 3877a6b22b53cd4aed3373fd260bf8c50dd4834d Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 21 Jul 2021 15:40:45 +0300 Subject: [PATCH 05/33] Immutable class. --- README.md | 1 + src/main/java/homework_3/ImmutableClass.java | 50 ++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/main/java/homework_3/ImmutableClass.java diff --git a/README.md b/README.md index fb5b667f..f56cd78a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ | HW2.1 | [Traffic Light](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/traffic_light) | This console app reads an integer of seconds and prints a color of traffic light.| | HW2.2 | [Pyramid Printer](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/pyramid_printer) | This console app prints a pyramid of "x". | | HW2.3 | [Random Chars Table](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/random_chars_table) | This console app makes a table of chars from A to Z and shows evens/odds of them depending on the strategy we have chosen. | +| HW3 | [Immutable class](./src/main/java/homework_3) | This is an example of simple immutable class. | [Link to CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/homework_3/ImmutableClass.java b/src/main/java/homework_3/ImmutableClass.java new file mode 100644 index 00000000..79bc505c --- /dev/null +++ b/src/main/java/homework_3/ImmutableClass.java @@ -0,0 +1,50 @@ +package homework_3; + +import java.util.ArrayList; +/* +Class must be declared as final; +All members must be private; +There are no setters; +Getters must return copies of mutable objects; +Parameterized constructor must perform Deep Copy. + */ + +public final class ImmutableClass { + private final int age; + private final String name; + private final ArrayList hobbies; + + public int getAge() { + return age; + } + + public String getName() { + return name; + } + + public ArrayList getHobbies() { + return (ArrayList) hobbies.clone(); + } + + public ImmutableClass(int age, String name, ArrayList listHobbies) { + ArrayList tempList = new ArrayList<>(listHobbies); + this.age = age; + this.name = name; + this.hobbies = tempList; + } + + public static void main(String[] args) { + ArrayList listHobbies = new ArrayList<>(); + listHobbies.add("dances"); + listHobbies.add("travel"); + + int age = 27; + String name = "Tom"; + ImmutableClass immutableClass = new ImmutableClass(age, name, listHobbies); + + System.out.println(immutableClass.getAge()); + System.out.println(immutableClass.getName()); + System.out.println(immutableClass.getHobbies()); + } +} + From 7ef7cb3bde8634c07fb2b1c81d14ed6015a28a30 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 21 Jul 2021 16:46:01 +0300 Subject: [PATCH 06/33] Fixed secondHomework. --- README.md | 8 +- .../pyramid_printer/PyramidPrinter.java | 40 +++++---- .../random_chars_table/RandomCharsTable.java | 89 +++++++------------ .../traffic_light/TrafficLight.java | 32 +++---- 4 files changed, 71 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index f56cd78a..686db022 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ | Number | Solution | Short description | --- | --- | --- | -| HW1 | [Console printer](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_1) | This console app prints our words and number of letters until your input equals "error". | -| HW2.1 | [Traffic Light](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/traffic_light) | This console app reads an integer of seconds and prints a color of traffic light.| -| HW2.2 | [Pyramid Printer](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/pyramid_printer) | This console app prints a pyramid of "x". | -| HW2.3 | [Random Chars Table](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/TomShandrikov/src/main/java/homework_2/random_chars_table) | This console app makes a table of chars from A to Z and shows evens/odds of them depending on the strategy we have chosen. | +| HW1 | [Console printer](./src/main/java/homework_1) | This console app prints our words and number of letters until your input equals "error". | +| HW2.1 | [Traffic Light](./src/main/java/homework_2/traffic_light) | This console app reads an integer of seconds and prints a color of traffic light.| +| HW2.2 | [Pyramid Printer](./src/main/java/homework_2/pyramid_printer) | This console app prints a pyramid of "x". | +| HW2.3 | [Random Chars Table](./src/main/java/homework_2/random_chars_table) | This console app makes a table of chars from A to Z and shows evens/odds of them depending on the strategy we have chosen. | | HW3 | [Immutable class](./src/main/java/homework_3) | This is an example of simple immutable class. | [Link to CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java b/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java index eb3aca14..8b57cbb7 100644 --- a/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java +++ b/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java @@ -10,32 +10,36 @@ public class PyramidPrinter { public void run() { System.out.println("Please, input a number:"); - int countX = bufferedReaderReadConsole(); - if (countX < 0) { + + try { + int countX = bufferedReaderReadConsole(); + validateInput(countX); + printConsole(countX); + } catch (IOException | IllegalArgumentException e) { System.out.println(ERROR); - return; } + } - String s = "x"; + private void printConsole(int countX) { + StringBuilder result = new StringBuilder(""); for (int i = 1; i <= countX; i++) { - System.out.println(s); - s = s + "x"; + for (int j = 0; j < i; j++) { + result.append("x"); + } + result.append("\n"); } + System.out.println(result); } - private int bufferedReaderReadConsole() { + private int bufferedReaderReadConsole() throws IOException, NumberFormatException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { - int count = 0; - try { - count = Integer.parseInt(reader.readLine()); - } catch (NumberFormatException e) { - return -1; - } - return count; - } catch (IOException e) { - e.printStackTrace(); + return Integer.parseInt(reader.readLine()); + } + } + + private void validateInput(int i) { + if (i < 0) { + throw new IllegalArgumentException(); } - // Что лучше возвращать в return? - return -1; } } diff --git a/src/main/java/homework_2/random_chars_table/RandomCharsTable.java b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java index f375042e..07f54de6 100644 --- a/src/main/java/homework_2/random_chars_table/RandomCharsTable.java +++ b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java @@ -12,63 +12,26 @@ public class RandomCharsTable { private int width; private String strategy; - private String strategyEven = "Even letters -"; - private String strategyOdd = "Odd letters -"; - public void run() { System.out.println("[Input example: 2 3 odd]"); System.out.println("Please, input 2 positive numbers and a strategy (even/odd)"); - String inputFull = bufferedReaderReadConsole(); try { + String inputFull = bufferedReaderReadConsole(); parseInput(inputFull); validateInputData(length, width, strategy); - } catch (IllegalArgumentException e) { + String strategyRes = createCharTable(); + System.out.println(strategyRes); + } catch (IOException | IllegalArgumentException e) { System.out.println(ERROR); - return; - } - - char[][] table = new char[length][width]; - - for (int i = 0; i < length; i++) { - System.out.print("|"); - - for (int j = 0; j < width; j++) { - int x = (int) (Math.random() * 26 + 65); - table[i][j] = (char) x; - if (x % 2 == 0) { - strategyEven = strategyEven + " " + table[i][j] + ","; - } else { - strategyOdd = strategyOdd + " " + table[i][j] + ","; - } - System.out.print(" " + table[i][j] + " |"); - } - - System.out.println(); - } - - strategyOdd = deleteLastCommaInStrategy(strategyOdd); - strategyEven = deleteLastCommaInStrategy(strategyEven); - - if (strategy.equals("even")) { - System.out.print(strategyEven); - } - - if (strategy.equals("odd")) { - System.out.print(strategyOdd); } } - private String bufferedReaderReadConsole() { + private String bufferedReaderReadConsole() throws IOException, NumberFormatException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { - String input = reader.readLine(); - return input; - } catch (IOException e) { - e.printStackTrace(); + return reader.readLine(); } - // Корректно ли здесь возвращать null или нет? - return null; } private void parseInput(String s) { @@ -79,13 +42,9 @@ private void parseInput(String s) { throw new IllegalArgumentException(); } - try { - length = Integer.parseInt(array[0]); - width = Integer.parseInt(array[1]); - strategy = array[2]; - } catch (NumberFormatException e) { - throw new IllegalArgumentException(); - } + length = Integer.parseInt(array[0]); + width = Integer.parseInt(array[1]); + strategy = array[2]; } private void validateInputData(int x, int y, String str) { @@ -94,11 +53,31 @@ private void validateInputData(int x, int y, String str) { } } - private String deleteLastCommaInStrategy(String str) { - if (str.endsWith(",")) { - return str.substring(0, str.length() - 1); - } else { - return str; + private String createCharTable() { + + char[][] table = new char[length][width]; + StringBuilder strategyEven = new StringBuilder("Even letters -"); + StringBuilder strategyOdd = new StringBuilder("Odd letters -"); + + for (int i = 0; i < length; i++) { + System.out.print("|"); + + for (int j = 0; j < width; j++) { + int x = (int) (Math.random() * 26 + 65); + table[i][j] = (char) x; + if (x % 2 == 0) { + strategyEven.append(" " + table[i][j] + ","); + } else { + strategyOdd.append(" " + table[i][j] + ","); + } + System.out.print(" " + table[i][j] + " |"); + } + System.out.println(); } + + strategyOdd = strategyOdd.deleteCharAt(strategyOdd.length() - 1); + strategyEven = strategyEven.deleteCharAt(strategyEven.length() - 1); + + return "even".equals(strategy) ? strategyEven.toString() : strategyOdd.toString(); } } diff --git a/src/main/java/homework_2/traffic_light/TrafficLight.java b/src/main/java/homework_2/traffic_light/TrafficLight.java index 35fc72e9..70f4a76f 100644 --- a/src/main/java/homework_2/traffic_light/TrafficLight.java +++ b/src/main/java/homework_2/traffic_light/TrafficLight.java @@ -14,41 +14,31 @@ public class TrafficLight { public void run() { System.out.println("Please, input a number of seconds:"); - int seconds = bufferedReaderReadConsole(); - try { + int seconds = bufferedReaderReadConsole(); validateInput(seconds); - } catch (IllegalArgumentException e) { - return; + System.out.println(showLight(seconds)); + } catch (NumberFormatException | IOException ex) { + System.out.println(ERROR); + } catch (IllegalArgumentException ex) { + System.out.println(ex.getMessage()); } - - System.out.println(showLight(seconds)); } - private int bufferedReaderReadConsole() { + private int bufferedReaderReadConsole() throws IOException, NumberFormatException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { - int secondsIn = Integer.parseInt(reader.readLine()); - return secondsIn; - } catch (IOException e) { - e.printStackTrace(); + return Integer.parseInt(reader.readLine()); } - // Что лучше возвращать в return? - return -1; } - // Как тестировать? - private void validateInput(int i) { + private void validateInput(int i) throws IllegalArgumentException{ if (i < 0) { - System.out.println(ERROR); - throw new IllegalArgumentException(); + throw new IllegalArgumentException(ERROR); } else if (i > 86399) { - System.out.println("The day is over"); - throw new IllegalArgumentException(); + throw new IllegalArgumentException("The day is over"); } } - // Можно ли здесь сделать метод статическим (для более короткого вызова метода в тестах), - // или это неправильно? public static String showLight(int i) { int secondsMod = i % 60; From 68b209aca50d494308678672ef5af8e0e2beafd1 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Thu, 22 Jul 2021 13:42:19 +0300 Subject: [PATCH 07/33] Full third Homework. --- README.md | 9 +- build.gradle | 6 ++ .../random_chars_table/RandomCharsTable.java | 4 +- .../traffic_light/TrafficLight.java | 2 +- .../java/homework_2/PyramidPrinterTest.java | 55 ++++++++++++ .../java/homework_2/RandomCharsTableTest.java | 86 +++++++++++++++++++ .../java/homework_2/TrafficLightTest.java | 62 ++++++++++--- 7 files changed, 209 insertions(+), 15 deletions(-) create mode 100644 src/test/java/homework_2/PyramidPrinterTest.java create mode 100644 src/test/java/homework_2/RandomCharsTableTest.java diff --git a/README.md b/README.md index 686db022..d44251da 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,11 @@ | HW2.1 | [Traffic Light](./src/main/java/homework_2/traffic_light) | This console app reads an integer of seconds and prints a color of traffic light.| | HW2.2 | [Pyramid Printer](./src/main/java/homework_2/pyramid_printer) | This console app prints a pyramid of "x". | | HW2.3 | [Random Chars Table](./src/main/java/homework_2/random_chars_table) | This console app makes a table of chars from A to Z and shows evens/odds of them depending on the strategy we have chosen. | -| HW3 | [Immutable class](./src/main/java/homework_3) | This is an example of simple immutable class. | +| HW3.1 | [Immutable class](./src/main/java/homework_3) | This is an example of simple immutable class. | +| HW3.2 | [JUnit Tests](./src/test/java/homework_2) | Tests for homework2. | -[Link to CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) +[Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) + +[Link to markdown giude (article)](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)
+[Link to markdown giude (video)](https://www.youtube.com/watch?v=FFBTGdEMrQ4) -[Link to markdown giude](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) diff --git a/build.gradle b/build.gradle index b91dc843..c5b1cded 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,12 @@ repositories { } dependencies { + compileOnly 'org.projectlombok:lombok:1.18.20' + annotationProcessor 'org.projectlombok:lombok:1.18.20' + + testCompileOnly 'org.projectlombok:lombok:1.18.20' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.20' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' } diff --git a/src/main/java/homework_2/random_chars_table/RandomCharsTable.java b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java index 07f54de6..95198107 100644 --- a/src/main/java/homework_2/random_chars_table/RandomCharsTable.java +++ b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java @@ -3,6 +3,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Random; public class RandomCharsTable { @@ -63,7 +64,8 @@ private String createCharTable() { System.out.print("|"); for (int j = 0; j < width; j++) { - int x = (int) (Math.random() * 26 + 65); + Random r = new Random(); + int x = (r.nextInt(26) + 65); table[i][j] = (char) x; if (x % 2 == 0) { strategyEven.append(" " + table[i][j] + ","); diff --git a/src/main/java/homework_2/traffic_light/TrafficLight.java b/src/main/java/homework_2/traffic_light/TrafficLight.java index 70f4a76f..505bc407 100644 --- a/src/main/java/homework_2/traffic_light/TrafficLight.java +++ b/src/main/java/homework_2/traffic_light/TrafficLight.java @@ -39,7 +39,7 @@ private void validateInput(int i) throws IllegalArgumentException{ } } - public static String showLight(int i) { + private String showLight(int i) { int secondsMod = i % 60; return secondsMod < 35 ? GREEN diff --git a/src/test/java/homework_2/PyramidPrinterTest.java b/src/test/java/homework_2/PyramidPrinterTest.java new file mode 100644 index 00000000..a9d96309 --- /dev/null +++ b/src/test/java/homework_2/PyramidPrinterTest.java @@ -0,0 +1,55 @@ +package homework_2; + +import base.UnitBase; +import homework_2.pyramid_printer.PyramidPrinter; +import org.junit.jupiter.api.Test; + +import static homework_2.pyramid_printer.PyramidPrinter.ERROR; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class PyramidPrinterTest extends UnitBase { + + @Test + void given3_whenRun_then3linesOfX() { + setInput("3"); + runPrintRemoveFromOutput(); + + assertEquals("x", getOutputLines()[0]); + assertEquals("xx", getOutputLines()[1]); + assertEquals("xxx", getOutputLines()[2]); + } + + @Test + void given0_whenRun_thenEmpty() { + setInput("0"); + runPrintRemoveFromOutput(); + assertEquals("", getOutput()); + } + + @Test + void givenNegNumber_whenRun_thenERROR() { + setInput("-1"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + @Test + void givenNAN_whenRun_thenERROR() { + setInput("abc"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + @Test + void given2args_whenRun_thenERROR() { + setInput("2 3"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + private void runPrintRemoveFromOutput() { + new PyramidPrinter().run(); + printOut(); + removeFromOutput("Please, input a number:"); + } +} diff --git a/src/test/java/homework_2/RandomCharsTableTest.java b/src/test/java/homework_2/RandomCharsTableTest.java new file mode 100644 index 00000000..e329404c --- /dev/null +++ b/src/test/java/homework_2/RandomCharsTableTest.java @@ -0,0 +1,86 @@ +package homework_2; + +import base.UnitBase; +import homework_2.random_chars_table.RandomCharsTable; +import org.junit.jupiter.api.Test; + +import static homework_2.random_chars_table.RandomCharsTable.ERROR; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class RandomCharsTableTest extends UnitBase { + + @Test + void given22odd_whenRun_thenRandomOutput() { + setInput("2 2 odd"); + runPrintRemoveFromOutput(); + + boolean tableLine1 = getOutputLines()[0].matches("^[A-Z| ]{9}"); + boolean tableLine2 = getOutputLines()[1].matches("^[A-Z| ]{9}"); + boolean strategy = getOutputLines()[2].startsWith("Odd letters "); + String afterStrategy = getOutputLines()[2].substring(12); + boolean tableLine3 = afterStrategy.matches("^[A-Z, -]*"); + + assertTrue(tableLine1); + assertTrue(tableLine2); + assertTrue(strategy); + assertTrue(tableLine3); + } + + @Test + void given13even_whenRun_thenRandomOutput() { + setInput("1 3 even"); + runPrintRemoveFromOutput(); + + boolean tableLine1 = getOutputLines()[0].matches("^[A-Z| ]{13}"); + boolean strategy = getOutputLines()[1].startsWith("Even letters "); + String afterStrategy = getOutputLines()[1].substring(13); + boolean tableLine3 = afterStrategy.matches("^[A-Z, -]*"); + + assertTrue(tableLine1); + assertTrue(strategy); + assertTrue(tableLine3); + } + + @Test + void given2args_whenRun_thenERROR() { + setInput("2 3"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + @Test + void givenMistakeLetter_whenRun_thenERROR() { + setInput("2 3 ods"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + @Test + void given4args_whenRun_thenERROR() { + setInput("2 3 odd 2"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + @Test + void givenNegNumber_whenRun_thenERROR() { + setInput("2 -3 even"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + @Test + void givenOnly1number_whenRun_thenERROR() { + setInput("2 a odd"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + private void runPrintRemoveFromOutput() { + new RandomCharsTable().run(); + printOut(); + removeFromOutput("[Input example: 2 3 odd]"); + removeFromOutput("Please, input 2 positive numbers and a strategy (even/odd)"); + } +} diff --git a/src/test/java/homework_2/TrafficLightTest.java b/src/test/java/homework_2/TrafficLightTest.java index 417b1661..9ac0d4b2 100644 --- a/src/test/java/homework_2/TrafficLightTest.java +++ b/src/test/java/homework_2/TrafficLightTest.java @@ -1,25 +1,67 @@ package homework_2; +import base.UnitBase; +import homework_2.traffic_light.TrafficLight; import org.junit.jupiter.api.Test; -import static homework_2.traffic_light.TrafficLight.*; +import static homework_2.traffic_light.TrafficLight.ERROR; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; -public class TrafficLightTest { +public class TrafficLightTest extends UnitBase { @Test - void given0(){ - final String expected = GREEN; - final String actual = showLight(0); + void given2_whenRun_thenGreen() { + setInput("2"); + runPrintRemoveFromOutput(); + assertTrue(getOutput().contains("GREEN")); + } + + @Test + void given95_whenRun_thenYellow() { + setInput("95"); + runPrintRemoveFromOutput(); + assertTrue(getOutput().contains("YELLOW")); + } - assertEquals(expected, actual); + @Test + void given100_whenRun_thenRed() { + setInput("160"); + runPrintRemoveFromOutput(); + assertTrue(getOutput().contains("RED")); + } + + @Test + void givenNAN_whenRun_thenERROR() { + setInput("abc"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); } @Test - void given119(){ - final String expected = YELLOW; - final String actual = showLight(119); + void givenNegNumber_whenRun_thenERROR() { + setInput("-1"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + @Test + void given2args_whenRun_thenERROR() { + setInput("1 2"); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + @Test + void givenBigNumber_whenRun_thenDayIsOver() { + setInput("86400"); + runPrintRemoveFromOutput(); + assertEquals("The day is over", getOutput()); + } - assertEquals(expected, actual); + private void runPrintRemoveFromOutput() { + new TrafficLight().run(); + printOut(); + removeFromOutput("Please, input a number of seconds:"); } } From f5f87bdf23d9fe54ad2764f6e7e728226fbc0ca9 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Thu, 5 Aug 2021 11:53:29 +0300 Subject: [PATCH 08/33] Added parameterized tests at hw3. --- build.gradle | 2 + src/main/java/homework_1/Main.java | 6 +-- .../java/homework_2/pyramid_printer/Main.java | 3 +- .../pyramid_printer/PyramidPrinter.java | 2 +- .../homework_2/random_chars_table/Main.java | 3 +- .../random_chars_table/RandomCharsTable.java | 2 +- .../java/homework_2/traffic_light/Main.java | 3 +- .../traffic_light/TrafficLight.java | 10 ++--- .../java/homework_2/PyramidPrinterTest.java | 26 ++++------- .../java/homework_2/RandomCharsTableTest.java | 44 +++++-------------- .../java/homework_2/TrafficLightTest.java | 32 +++++--------- 11 files changed, 44 insertions(+), 89 deletions(-) diff --git a/build.gradle b/build.gradle index c5b1cded..820ef2b2 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,8 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' + + testCompile("org.junit.jupiter:junit-jupiter-params:5.7.0") } test { diff --git a/src/main/java/homework_1/Main.java b/src/main/java/homework_1/Main.java index 5f18db59..e2df3188 100644 --- a/src/main/java/homework_1/Main.java +++ b/src/main/java/homework_1/Main.java @@ -2,10 +2,10 @@ public class Main { - static final String RED = "\u001B[31m"; - static final String BLACK = "\u001B[0m"; + private static final String RED = "\u001B[31m"; + private static final String BLACK = "\u001B[0m"; - public static void main(String[] args) throws Exception { + public static void main(String[] args) { for (String str : args) { if (str.equals("error")) { diff --git a/src/main/java/homework_2/pyramid_printer/Main.java b/src/main/java/homework_2/pyramid_printer/Main.java index 04446884..71e33035 100644 --- a/src/main/java/homework_2/pyramid_printer/Main.java +++ b/src/main/java/homework_2/pyramid_printer/Main.java @@ -3,7 +3,6 @@ public class Main { public static void main(String[] args) { - PyramidPrinter pyramidPrinter = new PyramidPrinter(); - pyramidPrinter.run(); + new PyramidPrinter().run(); } } diff --git a/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java b/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java index 8b57cbb7..70ee7dbe 100644 --- a/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java +++ b/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java @@ -6,7 +6,7 @@ public class PyramidPrinter { - public static final String ERROR = "Only 1 non-negative integer is allowed as passed parameter"; + private static final String ERROR = "Only 1 non-negative integer is allowed as passed parameter"; public void run() { System.out.println("Please, input a number:"); diff --git a/src/main/java/homework_2/random_chars_table/Main.java b/src/main/java/homework_2/random_chars_table/Main.java index e359a82c..be586c4b 100644 --- a/src/main/java/homework_2/random_chars_table/Main.java +++ b/src/main/java/homework_2/random_chars_table/Main.java @@ -3,7 +3,6 @@ public class Main { public static void main(String[] args) { - RandomCharsTable randomCharsTable = new RandomCharsTable(); - randomCharsTable.run(); + new RandomCharsTable().run(); } } diff --git a/src/main/java/homework_2/random_chars_table/RandomCharsTable.java b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java index 95198107..0db0598c 100644 --- a/src/main/java/homework_2/random_chars_table/RandomCharsTable.java +++ b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java @@ -7,7 +7,7 @@ public class RandomCharsTable { - public static final String ERROR = "Passed parameters should match the format [positive integer] [positive integer] [even|odd]"; + private static final String ERROR = "Passed parameters should match the format [positive integer] [positive integer] [even|odd]"; private int length; private int width; diff --git a/src/main/java/homework_2/traffic_light/Main.java b/src/main/java/homework_2/traffic_light/Main.java index 0b7b67da..3ff7f428 100644 --- a/src/main/java/homework_2/traffic_light/Main.java +++ b/src/main/java/homework_2/traffic_light/Main.java @@ -3,7 +3,6 @@ public class Main { public static void main(String[] args) { - TrafficLight trafficLight = new TrafficLight(); - trafficLight.run(); + new TrafficLight().run(); } } diff --git a/src/main/java/homework_2/traffic_light/TrafficLight.java b/src/main/java/homework_2/traffic_light/TrafficLight.java index 505bc407..0c09df39 100644 --- a/src/main/java/homework_2/traffic_light/TrafficLight.java +++ b/src/main/java/homework_2/traffic_light/TrafficLight.java @@ -6,11 +6,11 @@ public class TrafficLight { - public static final String RESET = "\u001B[0m"; - public static final String RED = "\u001B[31m" + "RED" + RESET; - public static final String GREEN = "\u001B[32m" + "GREEN" + RESET; - public static final String YELLOW = "\u001B[33m" + "YELLOW" + RESET; - public static final String ERROR = "Only 1 non-negative integer is allowed as passed parameter"; + private static final String RESET = "\u001B[0m"; + private static final String RED = "\u001B[31m" + "RED" + RESET; + private static final String GREEN = "\u001B[32m" + "GREEN" + RESET; + private static final String YELLOW = "\u001B[33m" + "YELLOW" + RESET; + private static final String ERROR = "Only 1 non-negative integer is allowed as passed parameter"; public void run() { System.out.println("Please, input a number of seconds:"); diff --git a/src/test/java/homework_2/PyramidPrinterTest.java b/src/test/java/homework_2/PyramidPrinterTest.java index a9d96309..129f8e7f 100644 --- a/src/test/java/homework_2/PyramidPrinterTest.java +++ b/src/test/java/homework_2/PyramidPrinterTest.java @@ -3,12 +3,15 @@ import base.UnitBase; import homework_2.pyramid_printer.PyramidPrinter; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; -import static homework_2.pyramid_printer.PyramidPrinter.ERROR; import static org.junit.jupiter.api.Assertions.assertEquals; public class PyramidPrinterTest extends UnitBase { + private static final String ERROR = "Only 1 non-negative integer is allowed as passed parameter"; + @Test void given3_whenRun_then3linesOfX() { setInput("3"); @@ -26,23 +29,10 @@ void given0_whenRun_thenEmpty() { assertEquals("", getOutput()); } - @Test - void givenNegNumber_whenRun_thenERROR() { - setInput("-1"); - runPrintRemoveFromOutput(); - assertEquals(ERROR, getOutput()); - } - - @Test - void givenNAN_whenRun_thenERROR() { - setInput("abc"); - runPrintRemoveFromOutput(); - assertEquals(ERROR, getOutput()); - } - - @Test - void given2args_whenRun_thenERROR() { - setInput("2 3"); + @ParameterizedTest + @ValueSource(strings = {"2 3", "abc", "-1"}) + void givenERROR_whenRun_thenERROR(String input) { + setInput(input); runPrintRemoveFromOutput(); assertEquals(ERROR, getOutput()); } diff --git a/src/test/java/homework_2/RandomCharsTableTest.java b/src/test/java/homework_2/RandomCharsTableTest.java index e329404c..692eec62 100644 --- a/src/test/java/homework_2/RandomCharsTableTest.java +++ b/src/test/java/homework_2/RandomCharsTableTest.java @@ -3,13 +3,16 @@ import base.UnitBase; import homework_2.random_chars_table.RandomCharsTable; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; -import static homework_2.random_chars_table.RandomCharsTable.ERROR; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; public class RandomCharsTableTest extends UnitBase { + private static final String ERROR = "Passed parameters should match the format [positive integer] [positive integer] [even|odd]"; + @Test void given22odd_whenRun_thenRandomOutput() { setInput("2 2 odd"); @@ -19,7 +22,7 @@ void given22odd_whenRun_thenRandomOutput() { boolean tableLine2 = getOutputLines()[1].matches("^[A-Z| ]{9}"); boolean strategy = getOutputLines()[2].startsWith("Odd letters "); String afterStrategy = getOutputLines()[2].substring(12); - boolean tableLine3 = afterStrategy.matches("^[A-Z, -]*"); + boolean tableLine3 = afterStrategy.matches("^[ACEGIKMOQSUWY, -]*"); assertTrue(tableLine1); assertTrue(tableLine2); @@ -35,44 +38,17 @@ void given13even_whenRun_thenRandomOutput() { boolean tableLine1 = getOutputLines()[0].matches("^[A-Z| ]{13}"); boolean strategy = getOutputLines()[1].startsWith("Even letters "); String afterStrategy = getOutputLines()[1].substring(13); - boolean tableLine3 = afterStrategy.matches("^[A-Z, -]*"); + boolean tableLine3 = afterStrategy.matches("^[BDFHJLNPRTVXZ, -]*"); assertTrue(tableLine1); assertTrue(strategy); assertTrue(tableLine3); } - @Test - void given2args_whenRun_thenERROR() { - setInput("2 3"); - runPrintRemoveFromOutput(); - assertEquals(ERROR, getOutput()); - } - - @Test - void givenMistakeLetter_whenRun_thenERROR() { - setInput("2 3 ods"); - runPrintRemoveFromOutput(); - assertEquals(ERROR, getOutput()); - } - - @Test - void given4args_whenRun_thenERROR() { - setInput("2 3 odd 2"); - runPrintRemoveFromOutput(); - assertEquals(ERROR, getOutput()); - } - - @Test - void givenNegNumber_whenRun_thenERROR() { - setInput("2 -3 even"); - runPrintRemoveFromOutput(); - assertEquals(ERROR, getOutput()); - } - - @Test - void givenOnly1number_whenRun_thenERROR() { - setInput("2 a odd"); + @ParameterizedTest + @ValueSource(strings = {"2 a odd", "2 -3 even", "2 3 odd 2", "2 3 ods", "2 3"}) + void givenERROR_whenRun_thenERROR(String input) { + setInput(input); runPrintRemoveFromOutput(); assertEquals(ERROR, getOutput()); } diff --git a/src/test/java/homework_2/TrafficLightTest.java b/src/test/java/homework_2/TrafficLightTest.java index 9ac0d4b2..3438ea62 100644 --- a/src/test/java/homework_2/TrafficLightTest.java +++ b/src/test/java/homework_2/TrafficLightTest.java @@ -3,13 +3,16 @@ import base.UnitBase; import homework_2.traffic_light.TrafficLight; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; -import static homework_2.traffic_light.TrafficLight.ERROR; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; public class TrafficLightTest extends UnitBase { + private static final String ERROR = "Only 1 non-negative integer is allowed as passed parameter"; + @Test void given2_whenRun_thenGreen() { setInput("2"); @@ -32,33 +35,20 @@ void given100_whenRun_thenRed() { } @Test - void givenNAN_whenRun_thenERROR() { - setInput("abc"); - runPrintRemoveFromOutput(); - assertEquals(ERROR, getOutput()); - } - - @Test - void givenNegNumber_whenRun_thenERROR() { - setInput("-1"); + void givenBigNumber_whenRun_thenDayIsOver() { + setInput("86400"); runPrintRemoveFromOutput(); - assertEquals(ERROR, getOutput()); + assertEquals("The day is over", getOutput()); } - @Test - void given2args_whenRun_thenERROR() { - setInput("1 2"); + @ParameterizedTest + @ValueSource(strings = {"1 2", "-1", "abc"}) + void givenERROR_whenRun_thenERROR(String input) { + setInput(input); runPrintRemoveFromOutput(); assertEquals(ERROR, getOutput()); } - @Test - void givenBigNumber_whenRun_thenDayIsOver() { - setInput("86400"); - runPrintRemoveFromOutput(); - assertEquals("The day is over", getOutput()); - } - private void runPrintRemoveFromOutput() { new TrafficLight().run(); printOut(); From 0d7db0d80ff4ce9d2d83f56bd1176b1ab92e897b Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Tue, 10 Aug 2021 11:30:06 +0300 Subject: [PATCH 09/33] hw4. Singleton --- .../java/homework_4/Singleton/Circle.java | 24 +++++++++++++ src/main/java/homework_4/Singleton/Main.java | 20 +++++++++++ .../java/homework_4/Singleton/Singleton.java | 35 +++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/main/java/homework_4/Singleton/Circle.java create mode 100644 src/main/java/homework_4/Singleton/Main.java create mode 100644 src/main/java/homework_4/Singleton/Singleton.java diff --git a/src/main/java/homework_4/Singleton/Circle.java b/src/main/java/homework_4/Singleton/Circle.java new file mode 100644 index 00000000..f32ef7bf --- /dev/null +++ b/src/main/java/homework_4/Singleton/Circle.java @@ -0,0 +1,24 @@ +package homework_4.Singleton; + +import lombok.Data; + +/* + *Example of using Singleton + */ + +@Data +public class Circle { + + private static Circle uniqueCircle; + private String color; + + private Circle() { + } + + public static Circle getInstance() { + if (uniqueCircle == null) { + uniqueCircle = new Circle(); + } + return uniqueCircle; + } +} diff --git a/src/main/java/homework_4/Singleton/Main.java b/src/main/java/homework_4/Singleton/Main.java new file mode 100644 index 00000000..85a7d91a --- /dev/null +++ b/src/main/java/homework_4/Singleton/Main.java @@ -0,0 +1,20 @@ +package homework_4.Singleton; + +/* + *Example of using Singleton + */ + +public class Main { + public static void main(String[] args) { + + Circle myCircle = Circle.getInstance(); + myCircle.setColor("green"); + + Circle myCircle2 = Circle.getInstance(); + myCircle2.setColor("red"); + + System.out.println(myCircle.getColor()); // red + System.out.println(myCircle2.getColor()); // red + System.out.println(myCircle == myCircle2); // true + } +} diff --git a/src/main/java/homework_4/Singleton/Singleton.java b/src/main/java/homework_4/Singleton/Singleton.java new file mode 100644 index 00000000..ac141cfa --- /dev/null +++ b/src/main/java/homework_4/Singleton/Singleton.java @@ -0,0 +1,35 @@ +package homework_4.Singleton; + +//Basic Singleton + +public class Singleton { + private static Singleton uniqueInstance; + + private Singleton() { + } + + public static Singleton getInstance() { + if (uniqueInstance == null) { + uniqueInstance = new Singleton(); + } + return uniqueInstance; + } +} + +//Thread safe realization of Singleton + +class SingletonThreadSafe { + private static volatile SingletonThreadSafe uniqueInstance; + + private SingletonThreadSafe() { + } + + public static SingletonThreadSafe getInstance() { + if (uniqueInstance == null) { + synchronized (SingletonThreadSafe.class) { + uniqueInstance = new SingletonThreadSafe(); + } + } + return uniqueInstance; + } +} From e7dab2f2b0c9160fd627c3bbf5725ea7430c0209 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Tue, 10 Aug 2021 18:20:25 +0300 Subject: [PATCH 10/33] hw4. CustomFileReader + basic tests --- README.md | 2 + .../customFileReader/CustomFileReader.java | 89 +++++++++++++++++++ .../homework_4/customFileReader/Main.java | 10 +++ .../{Singleton => singleton}/Circle.java | 6 +- .../{Singleton => singleton}/Main.java | 6 +- .../{Singleton => singleton}/Singleton.java | 2 +- .../resources/custom_file_reader/file.txt | 4 + .../CustomFileReaderTest.java | 33 +++++++ .../homework_4/singleton/SingletonTest.java | 15 ++++ 9 files changed, 158 insertions(+), 9 deletions(-) create mode 100644 src/main/java/homework_4/customFileReader/CustomFileReader.java create mode 100644 src/main/java/homework_4/customFileReader/Main.java rename src/main/java/homework_4/{Singleton => singleton}/Circle.java (82%) rename src/main/java/homework_4/{Singleton => singleton}/Main.java (86%) rename src/main/java/homework_4/{Singleton => singleton}/Singleton.java (96%) create mode 100644 src/main/resources/custom_file_reader/file.txt create mode 100644 src/test/java/homework_4/customFileReader/CustomFileReaderTest.java create mode 100644 src/test/java/homework_4/singleton/SingletonTest.java diff --git a/README.md b/README.md index d44251da..acedabe4 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ | HW2.3 | [Random Chars Table](./src/main/java/homework_2/random_chars_table) | This console app makes a table of chars from A to Z and shows evens/odds of them depending on the strategy we have chosen. | | HW3.1 | [Immutable class](./src/main/java/homework_3) | This is an example of simple immutable class. | | HW3.2 | [JUnit Tests](./src/test/java/homework_2) | Tests for homework2. | +| HW4.1 | [CustomFileReader](./src/test/java/homework_2) | Here you can see 4 different ways to read text from file.txt. | +| HW4.2 | [Singleton](./src/test/java/homework_2) | Basic and Thread-safe examples of Singleton. | [Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/homework_4/customFileReader/CustomFileReader.java b/src/main/java/homework_4/customFileReader/CustomFileReader.java new file mode 100644 index 00000000..bce15568 --- /dev/null +++ b/src/main/java/homework_4/customFileReader/CustomFileReader.java @@ -0,0 +1,89 @@ +package homework_4.customFileReader; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Scanner; + +public class CustomFileReader { + + private static final String filename = "src/main/resources/custom_file_reader/file.txt"; + private final StringBuilder result = new StringBuilder(""); + + public String run1() { + + try(FileReader reader = new FileReader(filename)){ + int ch; + while ((ch = reader.read()) != -1){ + char x = (char)ch; + if (x == '.' || x == ',') { + continue; + } + result.append(x); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + System.out.println(result); + return result.toString(); + } + + public String run2() { + + try (BufferedReader reader = new BufferedReader(new FileReader(filename))){ + String line; + while ((line = reader.readLine()) != null) { + line = line.replaceAll("[,.]", ""); + result.append(line + "\n"); + + } + } catch (IOException e) { + e.printStackTrace(); + } + + System.out.println(result); + return result.toString(); + } + + public String run3(){ + + Path path = Paths.get(filename); + + try (Scanner scanner = new Scanner(path)){ + String line; + while (scanner.hasNextLine()){ + line = scanner.nextLine().replaceAll("[,.]", ""); + result.append(line + "\n"); + } + } catch (IOException e) { + e.printStackTrace(); + } + + System.out.println(result); + return result.toString(); + } + + public String run4(){ + + String content; + Path path = Paths.get(filename); + + try { + content = new String(Files.readAllBytes(path)); + content = content.replaceAll("[,.]", ""); + result.append(content); + } catch (IOException e) { + e.printStackTrace(); + } + + System.out.println(result); + return result.toString(); + } +} diff --git a/src/main/java/homework_4/customFileReader/Main.java b/src/main/java/homework_4/customFileReader/Main.java new file mode 100644 index 00000000..d0adde43 --- /dev/null +++ b/src/main/java/homework_4/customFileReader/Main.java @@ -0,0 +1,10 @@ +package homework_4.customFileReader; + +public class Main { + public static void main(String[] args) { + new CustomFileReader().run1(); + new CustomFileReader().run2(); + new CustomFileReader().run3(); + new CustomFileReader().run4(); + } +} diff --git a/src/main/java/homework_4/Singleton/Circle.java b/src/main/java/homework_4/singleton/Circle.java similarity index 82% rename from src/main/java/homework_4/Singleton/Circle.java rename to src/main/java/homework_4/singleton/Circle.java index f32ef7bf..e3730e4d 100644 --- a/src/main/java/homework_4/Singleton/Circle.java +++ b/src/main/java/homework_4/singleton/Circle.java @@ -1,10 +1,8 @@ -package homework_4.Singleton; +package homework_4.singleton; import lombok.Data; -/* - *Example of using Singleton - */ +//Example of using Singleton @Data public class Circle { diff --git a/src/main/java/homework_4/Singleton/Main.java b/src/main/java/homework_4/singleton/Main.java similarity index 86% rename from src/main/java/homework_4/Singleton/Main.java rename to src/main/java/homework_4/singleton/Main.java index 85a7d91a..eeb4092a 100644 --- a/src/main/java/homework_4/Singleton/Main.java +++ b/src/main/java/homework_4/singleton/Main.java @@ -1,8 +1,6 @@ -package homework_4.Singleton; +package homework_4.singleton; -/* - *Example of using Singleton - */ +//Example of using Singleton public class Main { public static void main(String[] args) { diff --git a/src/main/java/homework_4/Singleton/Singleton.java b/src/main/java/homework_4/singleton/Singleton.java similarity index 96% rename from src/main/java/homework_4/Singleton/Singleton.java rename to src/main/java/homework_4/singleton/Singleton.java index ac141cfa..f5b23f14 100644 --- a/src/main/java/homework_4/Singleton/Singleton.java +++ b/src/main/java/homework_4/singleton/Singleton.java @@ -1,4 +1,4 @@ -package homework_4.Singleton; +package homework_4.singleton; //Basic Singleton diff --git a/src/main/resources/custom_file_reader/file.txt b/src/main/resources/custom_file_reader/file.txt new file mode 100644 index 00000000..7cda6d00 --- /dev/null +++ b/src/main/resources/custom_file_reader/file.txt @@ -0,0 +1,4 @@ +Я вас любил: любовь еще, быть может, +В душе моей угасла не совсем; +Но пусть она вас больше не тревожит; +Я не хочу печалить вас ничем. \ No newline at end of file diff --git a/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java b/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java new file mode 100644 index 00000000..b7d8f8eb --- /dev/null +++ b/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java @@ -0,0 +1,33 @@ +package homework_4.customFileReader; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CustomFileReaderTest { + + private final String expected = "Я вас любил: любовь еще быть может\n" + + "В душе моей угасла не совсем;\n" + + "Но пусть она вас больше не тревожит;\n" + + "Я не хочу печалить вас ничем\n"; + + @Test + void run1() { + assertEquals(expected.trim(), new CustomFileReader().run1().replaceAll("\r", "")); + } + + @Test + void run2() { + assertEquals(expected, new CustomFileReader().run2()); + } + + @Test + void run3() { + assertEquals(expected, new CustomFileReader().run3()); + } + + @Test + void run4() { + assertEquals(expected.trim(), new CustomFileReader().run4().replaceAll("\r", "")); + } +} \ No newline at end of file diff --git a/src/test/java/homework_4/singleton/SingletonTest.java b/src/test/java/homework_4/singleton/SingletonTest.java new file mode 100644 index 00000000..d2f81d39 --- /dev/null +++ b/src/test/java/homework_4/singleton/SingletonTest.java @@ -0,0 +1,15 @@ +package homework_4.singleton; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class SingletonTest { + + @Test + void given2objects_whenRun_thenEquals() { + Singleton singleton = Singleton.getInstance(); + Singleton singleton2 = Singleton.getInstance(); + assertEquals(singleton, singleton2); + } +} \ No newline at end of file From 63b7ca4d8ec86bd588f3d5f2e2fdda9b898dd48e Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Tue, 10 Aug 2021 18:23:52 +0300 Subject: [PATCH 11/33] hw4. Readme fixed --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index acedabe4..4a4da6a9 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ | HW2.3 | [Random Chars Table](./src/main/java/homework_2/random_chars_table) | This console app makes a table of chars from A to Z and shows evens/odds of them depending on the strategy we have chosen. | | HW3.1 | [Immutable class](./src/main/java/homework_3) | This is an example of simple immutable class. | | HW3.2 | [JUnit Tests](./src/test/java/homework_2) | Tests for homework2. | -| HW4.1 | [CustomFileReader](./src/test/java/homework_2) | Here you can see 4 different ways to read text from file.txt. | -| HW4.2 | [Singleton](./src/test/java/homework_2) | Basic and Thread-safe examples of Singleton. | +| HW4.1 | [CustomFileReader](./src/main/java/homework_4/customFileReader) | Here you can see 4 different ways to read text from file.txt. | +| HW4.2 | [Singleton](./src/main/java/homework_4/singleton) | Basic and Thread-safe examples of Singleton. | [Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) From 2161b4570573a20ba4fe727c33b5703b3f8632ac Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 11 Aug 2021 15:22:20 +0300 Subject: [PATCH 12/33] hw4. +CustomAnnotations --- README.md | 1 + .../ClassCoffeeAnnotation.java | 33 +++++++++ .../homework_4/customAnnotation/Coffee.java | 39 +++++++++++ .../homework_4/customAnnotation/Main.java | 30 ++++++++ .../customFileReader/CustomFileReader.java | 68 +++++++------------ .../homework_4/customFileReader/Main.java | 18 +++-- .../customAnnotation/CoffeeTest.java | 44 ++++++++++++ .../CustomFileReaderTest.java | 56 +++++++++++---- 8 files changed, 228 insertions(+), 61 deletions(-) create mode 100644 src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java create mode 100644 src/main/java/homework_4/customAnnotation/Coffee.java create mode 100644 src/main/java/homework_4/customAnnotation/Main.java create mode 100644 src/test/java/homework_4/customAnnotation/CoffeeTest.java diff --git a/README.md b/README.md index 4a4da6a9..f1373aae 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ | HW3.2 | [JUnit Tests](./src/test/java/homework_2) | Tests for homework2. | | HW4.1 | [CustomFileReader](./src/main/java/homework_4/customFileReader) | Here you can see 4 different ways to read text from file.txt. | | HW4.2 | [Singleton](./src/main/java/homework_4/singleton) | Basic and Thread-safe examples of Singleton. | +| HW4.2 | [CustomAnnotation](./src/main/java/homework_4/customAnnotation) | This is an example of creating and using custom Annotations. | [Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java b/src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java new file mode 100644 index 00000000..5723a7a7 --- /dev/null +++ b/src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java @@ -0,0 +1,33 @@ +package homework_4.customAnnotation; + +import java.lang.annotation.*; + +import static java.lang.annotation.ElementType.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(TYPE) +@Inherited +public @interface ClassCoffeeAnnotation { + enum Size {SMALL, MEDIUM, BIG} + Size size() default Size.MEDIUM; + boolean hasMilk() default false; + int price(); + +} + +@Retention(RetentionPolicy.RUNTIME) +@Target(METHOD) +@interface AskForCoffeeAnnotation { + String value(); +} + +@Target(value= ElementType.METHOD) +@Retention(value= RetentionPolicy.RUNTIME) +@interface StartMakingCoffee { +} + +@Target(value=ElementType.METHOD) +@Retention(value= RetentionPolicy.RUNTIME) +@interface StopMakingCoffee { +} + diff --git a/src/main/java/homework_4/customAnnotation/Coffee.java b/src/main/java/homework_4/customAnnotation/Coffee.java new file mode 100644 index 00000000..46322712 --- /dev/null +++ b/src/main/java/homework_4/customAnnotation/Coffee.java @@ -0,0 +1,39 @@ +package homework_4.customAnnotation; + +import lombok.Data; +import lombok.SneakyThrows; + +@Data +@ClassCoffeeAnnotation(price = 100) +public class Coffee { + int price; + boolean hasMilk; + ClassCoffeeAnnotation.Size size; + + public Coffee() { + ClassCoffeeAnnotation annotation = this.getClass().getAnnotation(ClassCoffeeAnnotation.class); + + this.price = annotation.price(); + this.hasMilk = annotation.hasMilk(); + this.size = annotation.size(); + } + + @SneakyThrows + @AskForCoffeeAnnotation("Give me please this one!") + public void askForCoffee(){ + System.out.println(this.getClass().getMethod("askForCoffee").getDeclaredAnnotation(AskForCoffeeAnnotation.class).value()); + } + + @StartMakingCoffee + public void createCoffee(){ + //Some business logic + } + + @StopMakingCoffee + public void stopCoffee(){ + //Some business logic + } +} + + + diff --git a/src/main/java/homework_4/customAnnotation/Main.java b/src/main/java/homework_4/customAnnotation/Main.java new file mode 100644 index 00000000..532a742b --- /dev/null +++ b/src/main/java/homework_4/customAnnotation/Main.java @@ -0,0 +1,30 @@ +package homework_4.customAnnotation; + +import java.lang.reflect.Method; + +public class Main { + public static void main(String[] args) throws ClassNotFoundException { + + Coffee myCoffee = new Coffee(); + + System.out.println("Size: " + myCoffee.getSize()); + System.out.println("With milk: " + myCoffee.isHasMilk()); + System.out.println("Price: " + myCoffee.getPrice() + "₽"); + + myCoffee.askForCoffee(); + System.out.println(); + + boolean hasStart=false; + boolean hasStop=false; + + Method[] method = Class.forName("homework_4.customAnnotation.Coffee").getMethods(); + for(Method md: method){ + if(md.isAnnotationPresent(StartMakingCoffee.class)) {hasStart=true;} + if(md.isAnnotationPresent(StopMakingCoffee.class)) {hasStop=true;} + } + + System.out.println("Start making coffee - " + hasStart); + System.out.println("Making nice coffee..."); + System.out.println("Stop making coffee - " + hasStop); + } +} diff --git a/src/main/java/homework_4/customFileReader/CustomFileReader.java b/src/main/java/homework_4/customFileReader/CustomFileReader.java index bce15568..0aa635e1 100644 --- a/src/main/java/homework_4/customFileReader/CustomFileReader.java +++ b/src/main/java/homework_4/customFileReader/CustomFileReader.java @@ -1,89 +1,71 @@ package homework_4.customFileReader; import java.io.BufferedReader; -import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Scanner; public class CustomFileReader { - private static final String filename = "src/main/resources/custom_file_reader/file.txt"; - private final StringBuilder result = new StringBuilder(""); + private String filename; + private Path path; - public String run1() { + private final StringBuilder result = new StringBuilder(); - try(FileReader reader = new FileReader(filename)){ + public CustomFileReader(String filename) { + this.filename = filename; + } + + public CustomFileReader(Path path) { + this.path = path; + } + + public void run1() throws IOException { + + try (FileReader reader = new FileReader(filename)) { int ch; - while ((ch = reader.read()) != -1){ - char x = (char)ch; + while ((ch = reader.read()) != -1) { + char x = (char) ch; if (x == '.' || x == ',') { continue; } result.append(x); } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); } - System.out.println(result); - return result.toString(); } - public String run2() { + public void run2() throws IOException { - try (BufferedReader reader = new BufferedReader(new FileReader(filename))){ + try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { String line; while ((line = reader.readLine()) != null) { line = line.replaceAll("[,.]", ""); result.append(line + "\n"); - } - } catch (IOException e) { - e.printStackTrace(); } - System.out.println(result); - return result.toString(); } - public String run3(){ - - Path path = Paths.get(filename); + public void run3() throws IOException { - try (Scanner scanner = new Scanner(path)){ + try (Scanner scanner = new Scanner(path)) { String line; - while (scanner.hasNextLine()){ + while (scanner.hasNextLine()) { line = scanner.nextLine().replaceAll("[,.]", ""); result.append(line + "\n"); } - } catch (IOException e) { - e.printStackTrace(); } - System.out.println(result); - return result.toString(); } - public String run4(){ - - String content; - Path path = Paths.get(filename); - - try { - content = new String(Files.readAllBytes(path)); - content = content.replaceAll("[,.]", ""); - result.append(content); - } catch (IOException e) { - e.printStackTrace(); - } + public void run4() throws IOException { + String content = new String(Files.readAllBytes(path)); + content = content.replaceAll("[,.]", ""); + result.append(content); System.out.println(result); - return result.toString(); } } diff --git a/src/main/java/homework_4/customFileReader/Main.java b/src/main/java/homework_4/customFileReader/Main.java index d0adde43..7ff9594f 100644 --- a/src/main/java/homework_4/customFileReader/Main.java +++ b/src/main/java/homework_4/customFileReader/Main.java @@ -1,10 +1,18 @@ package homework_4.customFileReader; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + public class Main { - public static void main(String[] args) { - new CustomFileReader().run1(); - new CustomFileReader().run2(); - new CustomFileReader().run3(); - new CustomFileReader().run4(); + + private static String filename = "src/main/resources/custom_file_reader/file.txt"; + private static Path path = Paths.get(filename); + + public static void main(String[] args) throws IOException { + new CustomFileReader(filename).run1(); + new CustomFileReader(filename).run2(); + new CustomFileReader(path).run3(); + new CustomFileReader(path).run4(); } } diff --git a/src/test/java/homework_4/customAnnotation/CoffeeTest.java b/src/test/java/homework_4/customAnnotation/CoffeeTest.java new file mode 100644 index 00000000..a5ada225 --- /dev/null +++ b/src/test/java/homework_4/customAnnotation/CoffeeTest.java @@ -0,0 +1,44 @@ +package homework_4.customAnnotation; + +import base.UnitBase; +import org.junit.jupiter.api.Test; + +import static homework_4.customAnnotation.ClassCoffeeAnnotation.Size.SMALL; +import static org.junit.jupiter.api.Assertions.*; + +class CoffeeTest extends UnitBase { + + @Test + void givenDefault_whenMainRun_thenStandartOutput() throws ClassNotFoundException { + new Main().main(new String[]{}); + assertEquals("Size: MEDIUM", getOutputLines()[0]); + assertEquals("With milk: false", getOutputLines()[1]); + assertEquals("Price: 100₽", getOutputLines()[2]); + assertEquals("Give me please this one!", getOutputLines()[3]); + assertEquals("Start making coffee - true", getOutputLines()[5]); + assertEquals("Stop making coffee - true", getOutputLines()[7]); + } + + @Test + void givenNoParameters_whenCreateExistingCoffee_thenFieldsAreEqual() { + Coffee myCoffee = new Coffee(); + + assertFalse(myCoffee.hasMilk); + assertEquals(100, myCoffee.price); + assertEquals("MEDIUM", myCoffee.getSize().toString()); + } + + @Test + void givenAnnotaionParameters_whenExtendsCoffee_thenFieldsDiffer() { + + @ClassCoffeeAnnotation(price = 200, hasMilk = true, size = SMALL) + class NextCoffee extends Coffee {}; + + Coffee myCoffee = new NextCoffee(); + + assertTrue(myCoffee.hasMilk); + assertEquals(200, myCoffee.price); + assertEquals("SMALL", myCoffee.getSize().toString()); + } + +} \ No newline at end of file diff --git a/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java b/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java index b7d8f8eb..40d7b7cd 100644 --- a/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java +++ b/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java @@ -1,33 +1,63 @@ package homework_4.customFileReader; +import base.UnitBase; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + import static org.junit.jupiter.api.Assertions.*; -class CustomFileReaderTest { +class CustomFileReaderTest extends UnitBase { + + private final String[] expected = new String[] + {"Я вас любил: любовь еще быть может", + "В душе моей угасла не совсем;", + "Но пусть она вас больше не тревожит;", + "Я не хочу печалить вас ничем"}; - private final String expected = "Я вас любил: любовь еще быть может\n" + - "В душе моей угасла не совсем;\n" + - "Но пусть она вас больше не тревожит;\n" + - "Я не хочу печалить вас ничем\n"; + private String filename = "src/main/resources/custom_file_reader/file.txt"; + private Path path = Paths.get(filename); + + @Test + void givenTextFile_whenRun1_thenEquals() throws IOException { + new CustomFileReader(filename).run1(); + assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); + } @Test - void run1() { - assertEquals(expected.trim(), new CustomFileReader().run1().replaceAll("\r", "")); + void givenTextFile_whenRun2_thenEquals() throws IOException { + new CustomFileReader(filename).run2(); + assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); } @Test - void run2() { - assertEquals(expected, new CustomFileReader().run2()); + void givenTextFile_whenRun3_thenEquals() throws IOException { + new CustomFileReader(path).run3(); + assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); } @Test - void run3() { - assertEquals(expected, new CustomFileReader().run3()); + void givenTextFile_whenRun4_thenEquals() throws IOException { + new CustomFileReader(path).run4(); + assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); } @Test - void run4() { - assertEquals(expected.trim(), new CustomFileReader().run4().replaceAll("\r", "")); + void givenNotExistingFile_whenRun_thenException() { + + filename = "src/main/resources/custom_file_reader/fileX.txt"; + path = Paths.get("src/main/resources/custom_file_reader/fileX.txt"); + + Assertions.assertThrows(FileNotFoundException.class, () -> new CustomFileReader(filename).run1()); + Assertions.assertThrows(FileNotFoundException.class, () -> new CustomFileReader(filename).run2()); + + Assertions.assertThrows(NoSuchFileException.class, () -> new CustomFileReader(path).run3()); + Assertions.assertThrows(NoSuchFileException.class, () -> new CustomFileReader(path).run4()); } } \ No newline at end of file From 07344b246e4eac2f24a3225f9b5a20802845494b Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Fri, 13 Aug 2021 10:38:36 +0300 Subject: [PATCH 13/33] hw4. Bug Fixed --- .../ClassCoffeeAnnotation.java | 1 - .../homework_4/customAnnotation/Coffee.java | 8 ++----- .../homework_4/customAnnotation/Main.java | 9 ++++---- .../customFileReader/CustomFileReader.java | 19 ++++++++-------- .../homework_4/customFileReader/Main.java | 8 +++---- .../java/homework_4/singleton/Circle.java | 22 ------------------- src/main/java/homework_4/singleton/Main.java | 18 --------------- .../java/homework_4/singleton/Singleton.java | 2 ++ .../customAnnotation/CoffeeTest.java | 6 ++--- .../CustomFileReaderTest.java | 15 +++++-------- .../homework_4/singleton/SingletonTest.java | 1 + 11 files changed, 32 insertions(+), 77 deletions(-) delete mode 100644 src/main/java/homework_4/singleton/Circle.java delete mode 100644 src/main/java/homework_4/singleton/Main.java diff --git a/src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java b/src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java index 5723a7a7..30e1782f 100644 --- a/src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java +++ b/src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java @@ -12,7 +12,6 @@ enum Size {SMALL, MEDIUM, BIG} Size size() default Size.MEDIUM; boolean hasMilk() default false; int price(); - } @Retention(RetentionPolicy.RUNTIME) diff --git a/src/main/java/homework_4/customAnnotation/Coffee.java b/src/main/java/homework_4/customAnnotation/Coffee.java index 46322712..2ef376ce 100644 --- a/src/main/java/homework_4/customAnnotation/Coffee.java +++ b/src/main/java/homework_4/customAnnotation/Coffee.java @@ -1,9 +1,5 @@ package homework_4.customAnnotation; -import lombok.Data; -import lombok.SneakyThrows; - -@Data @ClassCoffeeAnnotation(price = 100) public class Coffee { int price; @@ -18,9 +14,8 @@ public Coffee() { this.size = annotation.size(); } - @SneakyThrows @AskForCoffeeAnnotation("Give me please this one!") - public void askForCoffee(){ + public void askForCoffee() throws NoSuchMethodException { System.out.println(this.getClass().getMethod("askForCoffee").getDeclaredAnnotation(AskForCoffeeAnnotation.class).value()); } @@ -33,6 +28,7 @@ public void createCoffee(){ public void stopCoffee(){ //Some business logic } + } diff --git a/src/main/java/homework_4/customAnnotation/Main.java b/src/main/java/homework_4/customAnnotation/Main.java index 532a742b..f801fd40 100644 --- a/src/main/java/homework_4/customAnnotation/Main.java +++ b/src/main/java/homework_4/customAnnotation/Main.java @@ -3,13 +3,13 @@ import java.lang.reflect.Method; public class Main { - public static void main(String[] args) throws ClassNotFoundException { + public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { Coffee myCoffee = new Coffee(); - System.out.println("Size: " + myCoffee.getSize()); - System.out.println("With milk: " + myCoffee.isHasMilk()); - System.out.println("Price: " + myCoffee.getPrice() + "₽"); + System.out.println("Size: " + myCoffee.size); + System.out.println("With milk: " + myCoffee.hasMilk); + System.out.println("Price: " + myCoffee.price + "₽"); myCoffee.askForCoffee(); System.out.println(); @@ -27,4 +27,5 @@ public static void main(String[] args) throws ClassNotFoundException { System.out.println("Making nice coffee..."); System.out.println("Stop making coffee - " + hasStop); } + } diff --git a/src/main/java/homework_4/customFileReader/CustomFileReader.java b/src/main/java/homework_4/customFileReader/CustomFileReader.java index 0aa635e1..49b20eb5 100644 --- a/src/main/java/homework_4/customFileReader/CustomFileReader.java +++ b/src/main/java/homework_4/customFileReader/CustomFileReader.java @@ -4,13 +4,12 @@ import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Scanner; public class CustomFileReader { - private String filename; - private Path path; + private final String filename; private final StringBuilder result = new StringBuilder(); @@ -18,10 +17,7 @@ public CustomFileReader(String filename) { this.filename = filename; } - public CustomFileReader(Path path) { - this.path = path; - } - + // using FileReader public void run1() throws IOException { try (FileReader reader = new FileReader(filename)) { @@ -37,6 +33,8 @@ public void run1() throws IOException { System.out.println(result); } + + // using BufferedReader public void run2() throws IOException { try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { @@ -49,9 +47,10 @@ public void run2() throws IOException { System.out.println(result); } + // using Scanner public void run3() throws IOException { - try (Scanner scanner = new Scanner(path)) { + try (Scanner scanner = new Scanner(Paths.get(filename))) { String line; while (scanner.hasNextLine()) { line = scanner.nextLine().replaceAll("[,.]", ""); @@ -61,11 +60,13 @@ public void run3() throws IOException { System.out.println(result); } + // using Files.readAllBytes public void run4() throws IOException { - String content = new String(Files.readAllBytes(path)); + String content = new String(Files.readAllBytes(Paths.get(filename))); content = content.replaceAll("[,.]", ""); result.append(content); System.out.println(result); } + } diff --git a/src/main/java/homework_4/customFileReader/Main.java b/src/main/java/homework_4/customFileReader/Main.java index 7ff9594f..dd4b4a7d 100644 --- a/src/main/java/homework_4/customFileReader/Main.java +++ b/src/main/java/homework_4/customFileReader/Main.java @@ -1,18 +1,16 @@ package homework_4.customFileReader; import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; public class Main { private static String filename = "src/main/resources/custom_file_reader/file.txt"; - private static Path path = Paths.get(filename); public static void main(String[] args) throws IOException { new CustomFileReader(filename).run1(); new CustomFileReader(filename).run2(); - new CustomFileReader(path).run3(); - new CustomFileReader(path).run4(); + new CustomFileReader(filename).run3(); + new CustomFileReader(filename).run4(); } + } diff --git a/src/main/java/homework_4/singleton/Circle.java b/src/main/java/homework_4/singleton/Circle.java deleted file mode 100644 index e3730e4d..00000000 --- a/src/main/java/homework_4/singleton/Circle.java +++ /dev/null @@ -1,22 +0,0 @@ -package homework_4.singleton; - -import lombok.Data; - -//Example of using Singleton - -@Data -public class Circle { - - private static Circle uniqueCircle; - private String color; - - private Circle() { - } - - public static Circle getInstance() { - if (uniqueCircle == null) { - uniqueCircle = new Circle(); - } - return uniqueCircle; - } -} diff --git a/src/main/java/homework_4/singleton/Main.java b/src/main/java/homework_4/singleton/Main.java deleted file mode 100644 index eeb4092a..00000000 --- a/src/main/java/homework_4/singleton/Main.java +++ /dev/null @@ -1,18 +0,0 @@ -package homework_4.singleton; - -//Example of using Singleton - -public class Main { - public static void main(String[] args) { - - Circle myCircle = Circle.getInstance(); - myCircle.setColor("green"); - - Circle myCircle2 = Circle.getInstance(); - myCircle2.setColor("red"); - - System.out.println(myCircle.getColor()); // red - System.out.println(myCircle2.getColor()); // red - System.out.println(myCircle == myCircle2); // true - } -} diff --git a/src/main/java/homework_4/singleton/Singleton.java b/src/main/java/homework_4/singleton/Singleton.java index f5b23f14..da06f6ba 100644 --- a/src/main/java/homework_4/singleton/Singleton.java +++ b/src/main/java/homework_4/singleton/Singleton.java @@ -14,6 +14,7 @@ public static Singleton getInstance() { } return uniqueInstance; } + } //Thread safe realization of Singleton @@ -32,4 +33,5 @@ public static SingletonThreadSafe getInstance() { } return uniqueInstance; } + } diff --git a/src/test/java/homework_4/customAnnotation/CoffeeTest.java b/src/test/java/homework_4/customAnnotation/CoffeeTest.java index a5ada225..595e4e87 100644 --- a/src/test/java/homework_4/customAnnotation/CoffeeTest.java +++ b/src/test/java/homework_4/customAnnotation/CoffeeTest.java @@ -9,7 +9,7 @@ class CoffeeTest extends UnitBase { @Test - void givenDefault_whenMainRun_thenStandartOutput() throws ClassNotFoundException { + void givenDefault_whenMainRun_thenStandartOutput() throws ClassNotFoundException, NoSuchMethodException { new Main().main(new String[]{}); assertEquals("Size: MEDIUM", getOutputLines()[0]); assertEquals("With milk: false", getOutputLines()[1]); @@ -25,7 +25,7 @@ void givenNoParameters_whenCreateExistingCoffee_thenFieldsAreEqual() { assertFalse(myCoffee.hasMilk); assertEquals(100, myCoffee.price); - assertEquals("MEDIUM", myCoffee.getSize().toString()); + assertEquals("MEDIUM", myCoffee.size.toString()); } @Test @@ -38,7 +38,7 @@ class NextCoffee extends Coffee {}; assertTrue(myCoffee.hasMilk); assertEquals(200, myCoffee.price); - assertEquals("SMALL", myCoffee.getSize().toString()); + assertEquals("SMALL", myCoffee.size.toString()); } } \ No newline at end of file diff --git a/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java b/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java index 40d7b7cd..8b4fc5eb 100644 --- a/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java +++ b/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java @@ -7,11 +7,9 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Arrays; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class CustomFileReaderTest extends UnitBase { @@ -22,7 +20,6 @@ class CustomFileReaderTest extends UnitBase { "Я не хочу печалить вас ничем"}; private String filename = "src/main/resources/custom_file_reader/file.txt"; - private Path path = Paths.get(filename); @Test void givenTextFile_whenRun1_thenEquals() throws IOException { @@ -38,13 +35,13 @@ void givenTextFile_whenRun2_thenEquals() throws IOException { @Test void givenTextFile_whenRun3_thenEquals() throws IOException { - new CustomFileReader(path).run3(); + new CustomFileReader(filename).run3(); assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); } @Test void givenTextFile_whenRun4_thenEquals() throws IOException { - new CustomFileReader(path).run4(); + new CustomFileReader(filename).run4(); assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); } @@ -52,12 +49,12 @@ void givenTextFile_whenRun4_thenEquals() throws IOException { void givenNotExistingFile_whenRun_thenException() { filename = "src/main/resources/custom_file_reader/fileX.txt"; - path = Paths.get("src/main/resources/custom_file_reader/fileX.txt"); Assertions.assertThrows(FileNotFoundException.class, () -> new CustomFileReader(filename).run1()); Assertions.assertThrows(FileNotFoundException.class, () -> new CustomFileReader(filename).run2()); - Assertions.assertThrows(NoSuchFileException.class, () -> new CustomFileReader(path).run3()); - Assertions.assertThrows(NoSuchFileException.class, () -> new CustomFileReader(path).run4()); + Assertions.assertThrows(NoSuchFileException.class, () -> new CustomFileReader(filename).run3()); + Assertions.assertThrows(NoSuchFileException.class, () -> new CustomFileReader(filename).run4()); } + } \ No newline at end of file diff --git a/src/test/java/homework_4/singleton/SingletonTest.java b/src/test/java/homework_4/singleton/SingletonTest.java index d2f81d39..b76a873a 100644 --- a/src/test/java/homework_4/singleton/SingletonTest.java +++ b/src/test/java/homework_4/singleton/SingletonTest.java @@ -12,4 +12,5 @@ void given2objects_whenRun_thenEquals() { Singleton singleton2 = Singleton.getInstance(); assertEquals(singleton, singleton2); } + } \ No newline at end of file From 2ef335e7f296f6dea4d5801b856c84368915223d Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Fri, 20 Aug 2021 13:43:51 +0300 Subject: [PATCH 14/33] hw5. Tests & ReadMe update are included --- README.md | 4 +- .../CustomRegexMatcher.java | 32 ++++++++++++ .../homework_5/customRegexMatcher/Main.java | 7 +++ .../java/homework_5/powerOfNumber/Main.java | 7 +++ .../powerOfNumber/PowerOfNumber.java | 51 +++++++++++++++++++ .../CustomRegexMatcherTest.java | 38 ++++++++++++++ .../powerOfNumber/PowerOfNumberTest.java | 49 ++++++++++++++++++ 7 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 src/main/java/homework_5/customRegexMatcher/CustomRegexMatcher.java create mode 100644 src/main/java/homework_5/customRegexMatcher/Main.java create mode 100644 src/main/java/homework_5/powerOfNumber/Main.java create mode 100644 src/main/java/homework_5/powerOfNumber/PowerOfNumber.java create mode 100644 src/test/java/homework_5/customRegexMatcher/CustomRegexMatcherTest.java create mode 100644 src/test/java/homework_5/powerOfNumber/PowerOfNumberTest.java diff --git a/README.md b/README.md index f1373aae..3209fbb2 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,10 @@ | HW3.1 | [Immutable class](./src/main/java/homework_3) | This is an example of simple immutable class. | | HW3.2 | [JUnit Tests](./src/test/java/homework_2) | Tests for homework2. | | HW4.1 | [CustomFileReader](./src/main/java/homework_4/customFileReader) | Here you can see 4 different ways to read text from file.txt. | -| HW4.2 | [Singleton](./src/main/java/homework_4/singleton) | Basic and Thread-safe examples of Singleton. | +| HW4.2 | [Singleton](./src/main/java/homework_4/singleton) | Here are Basic and Thread-safe examples of Singleton. | | HW4.2 | [CustomAnnotation](./src/main/java/homework_4/customAnnotation) | This is an example of creating and using custom Annotations. | +| HW5.1 | [PowerOfNumber](./src/main/java/homework_5/powerOfNumber) | This console app realizes Math.pow(int base, int n) method using recursion. | +| HW5.2 | [CustomRegexMatcher](./src/main/java/homework_5/customRegexMatcher) | This console app verifies custom email with regex. | [Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/homework_5/customRegexMatcher/CustomRegexMatcher.java b/src/main/java/homework_5/customRegexMatcher/CustomRegexMatcher.java new file mode 100644 index 00000000..2e0b7f6a --- /dev/null +++ b/src/main/java/homework_5/customRegexMatcher/CustomRegexMatcher.java @@ -0,0 +1,32 @@ +package homework_5.customRegexMatcher; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class CustomRegexMatcher { + + public void run() { + System.out.println("Please, input your Email"); + try { + String input = bufferedReaderReadConsole(); + System.out.println(regex(input)); + } catch (IOException | IllegalArgumentException ex) { + System.out.println(false); + } + } + + private String bufferedReaderReadConsole() throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + String str = reader.readLine(); + if (str == null) { + throw new IllegalArgumentException(); + } + return str; + } + } + + public boolean regex(String s) { + return s.matches("[\\w\\.\\-+!#%$&'*/=?`^{|}~]+@[\\w\\.]+\\.(com|ru|ua|kz|by)"); + } +} diff --git a/src/main/java/homework_5/customRegexMatcher/Main.java b/src/main/java/homework_5/customRegexMatcher/Main.java new file mode 100644 index 00000000..e6f903cb --- /dev/null +++ b/src/main/java/homework_5/customRegexMatcher/Main.java @@ -0,0 +1,7 @@ +package homework_5.customRegexMatcher; + +public class Main { + public static void main(String[] args) { + new CustomRegexMatcher().run(); + } +} diff --git a/src/main/java/homework_5/powerOfNumber/Main.java b/src/main/java/homework_5/powerOfNumber/Main.java new file mode 100644 index 00000000..3274a5f6 --- /dev/null +++ b/src/main/java/homework_5/powerOfNumber/Main.java @@ -0,0 +1,7 @@ +package homework_5.powerOfNumber; + +public class Main { + public static void main(String[] args) { + new PowerOfNumber().run(); + } +} diff --git a/src/main/java/homework_5/powerOfNumber/PowerOfNumber.java b/src/main/java/homework_5/powerOfNumber/PowerOfNumber.java new file mode 100644 index 00000000..b4e23378 --- /dev/null +++ b/src/main/java/homework_5/powerOfNumber/PowerOfNumber.java @@ -0,0 +1,51 @@ +package homework_5.powerOfNumber; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class PowerOfNumber { + private static final String ERROR = "Only 2 non-negative integers are allowed"; + + public void run() { + System.out.println("Please, input 2 non-negative numbers:"); + try { + String input = bufferedReaderReadConsole(); + int[] array = validateInput(input); + int i1 = array[0]; + int i2 = array[1]; + System.out.println(powerN(i1, i2)); + } catch (IOException | IllegalArgumentException ex) { + System.out.println(ERROR); + } + } + + private String bufferedReaderReadConsole() throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + String str = reader.readLine(); + if (str == null) { + throw new IllegalArgumentException(); + } + return str; + } + } + + private int[] validateInput(String s) { + String[] array = s.trim().replaceAll("( )+", " ").split(" "); + if (array.length != 2) { + throw new IllegalArgumentException(); + } + int i1 = Integer.parseInt(array[0]); + int i2 = Integer.parseInt(array[1]); + if (i1 < 0 || i2 < 0) { + throw new IllegalArgumentException(); + } + return new int[]{i1, i2}; + } + + public int powerN(int base, int n) { + if (n < 1) return 1; + return base * (powerN(base, n - 1)); + } +} + diff --git a/src/test/java/homework_5/customRegexMatcher/CustomRegexMatcherTest.java b/src/test/java/homework_5/customRegexMatcher/CustomRegexMatcherTest.java new file mode 100644 index 00000000..3897d131 --- /dev/null +++ b/src/test/java/homework_5/customRegexMatcher/CustomRegexMatcherTest.java @@ -0,0 +1,38 @@ +package homework_5.customRegexMatcher; + +import base.UnitBase; +import homework_5.powerOfNumber.PowerOfNumber; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +class CustomRegexMatcherTest extends UnitBase { + + @ParameterizedTest + @ValueSource(strings = {"ashandrikov@gmail.com", "123abc@yandex.ru", "r_n-13@mail.i.ua"}) + void givenCorrectEmail_whenRun_thenTrue(String input) { + setInput(input); + runPrintRemoveFromOutput(); + assertTrue(Boolean.parseBoolean(getOutput())); + } + + @ParameterizedTest + @ValueSource(strings = {"as.ua", "a@gmail.com a@gmail.com", "", "a@.ru"}) + void givenIncorrectEmail_whenRun_thenFalse(String input) { + setInput(input); + runPrintRemoveFromOutput(); + assertFalse(Boolean.parseBoolean(getOutput())); + } + + private void runPrintRemoveFromOutput() { + new CustomRegexMatcher().run(); + printOut(); + removeFromOutput("Please, input your Email"); + } +} \ No newline at end of file diff --git a/src/test/java/homework_5/powerOfNumber/PowerOfNumberTest.java b/src/test/java/homework_5/powerOfNumber/PowerOfNumberTest.java new file mode 100644 index 00000000..60d936b2 --- /dev/null +++ b/src/test/java/homework_5/powerOfNumber/PowerOfNumberTest.java @@ -0,0 +1,49 @@ +package homework_5.powerOfNumber; + +import base.UnitBase; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +class PowerOfNumberTest extends UnitBase { + private static final String ERROR = "Only 2 non-negative integers are allowed"; + + @ParameterizedTest + @MethodSource("testCases") + void givenCorrectInput_whenRun_thenCorrectOutput(String input, String expected) { + setInput(input); + runPrintRemoveFromOutput(); + assertEquals(expected, getOutput()); + } + + static Stream testCases() { + return Stream.of( + Arguments.of("1 2", "1"), + Arguments.of("2 0", "1"), + Arguments.of("3 3", "27"), + Arguments.of("0 0", "1"), + Arguments.of("0 5", "0"), + Arguments.of(" 3 3 ", "27") + ); + } + + @ParameterizedTest + @ValueSource(strings = {"2 -1", "abc abc", "1", " 1 2 3", "", "-1 1"}) + void givenERROR_whenRun_thenERROR(String input) { + setInput(input); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + private void runPrintRemoveFromOutput() { + new PowerOfNumber().run(); + printOut(); + removeFromOutput("Please, input 2 non-negative numbers:"); + } + +} \ No newline at end of file From eff024dd3ca31c165a91ccbca73189ed623b1fd9 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Sun, 29 Aug 2021 15:07:21 +0300 Subject: [PATCH 15/33] hw6. Tests are included. --- README.md | 1 + .../homework_6/mapProblemsGenerator/Cat.java | 26 ++++++++++ .../homework_6/mapProblemsGenerator/Dog.java | 32 +++++++++++++ .../homework_6/mapProblemsGenerator/Main.java | 10 ++++ .../MapProblemsGenerator.java | 48 +++++++++++++++++++ .../MapProblemsGeneratorTest.java | 25 ++++++++++ 6 files changed, 142 insertions(+) create mode 100644 src/main/java/homework_6/mapProblemsGenerator/Cat.java create mode 100644 src/main/java/homework_6/mapProblemsGenerator/Dog.java create mode 100644 src/main/java/homework_6/mapProblemsGenerator/Main.java create mode 100644 src/main/java/homework_6/mapProblemsGenerator/MapProblemsGenerator.java create mode 100644 src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java diff --git a/README.md b/README.md index 3209fbb2..d6a7060f 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ | HW4.2 | [CustomAnnotation](./src/main/java/homework_4/customAnnotation) | This is an example of creating and using custom Annotations. | | HW5.1 | [PowerOfNumber](./src/main/java/homework_5/powerOfNumber) | This console app realizes Math.pow(int base, int n) method using recursion. | | HW5.2 | [CustomRegexMatcher](./src/main/java/homework_5/customRegexMatcher) | This console app verifies custom email with regex. | +| HW6 | [MapProblemsGenerator](./src/main/java/homework_6/mapProblemsGenerator) | Here you can find example of incorrect hash method overriding and a case where we can loose information in our map. | [Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/homework_6/mapProblemsGenerator/Cat.java b/src/main/java/homework_6/mapProblemsGenerator/Cat.java new file mode 100644 index 00000000..a7e66a37 --- /dev/null +++ b/src/main/java/homework_6/mapProblemsGenerator/Cat.java @@ -0,0 +1,26 @@ +package homework_6.mapProblemsGenerator; + +import lombok.Data; + +/** + * Class Cat with incorrect hashCode() method that creates collisions every time. + */ + +@Data +public final class Cat { + final int age; + + @Override + public int hashCode() { + return 1; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Cat cat = (Cat) o; + return age == cat.age; + } + +} diff --git a/src/main/java/homework_6/mapProblemsGenerator/Dog.java b/src/main/java/homework_6/mapProblemsGenerator/Dog.java new file mode 100644 index 00000000..8df21c99 --- /dev/null +++ b/src/main/java/homework_6/mapProblemsGenerator/Dog.java @@ -0,0 +1,32 @@ +package homework_6.mapProblemsGenerator; + +import lombok.Data; + +import java.util.Objects; + +/** + * Class Dog with mutable field age. + */ + +@Data +public final class Dog { + int age; + + public Dog(int age) { + this.age = age; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Dog dog = (Dog) o; + return age == dog.age; + } + + @Override + public int hashCode() { + return Objects.hash(age); + } + +} diff --git a/src/main/java/homework_6/mapProblemsGenerator/Main.java b/src/main/java/homework_6/mapProblemsGenerator/Main.java new file mode 100644 index 00000000..057d5c0f --- /dev/null +++ b/src/main/java/homework_6/mapProblemsGenerator/Main.java @@ -0,0 +1,10 @@ +package homework_6.mapProblemsGenerator; + +public class Main { + public static void main(String[] args) { + + new MapProblemsGenerator().runCatIssue(); //Collisions + new MapProblemsGenerator().runDogIssue(); //Loosing information + } + +} diff --git a/src/main/java/homework_6/mapProblemsGenerator/MapProblemsGenerator.java b/src/main/java/homework_6/mapProblemsGenerator/MapProblemsGenerator.java new file mode 100644 index 00000000..c80047f5 --- /dev/null +++ b/src/main/java/homework_6/mapProblemsGenerator/MapProblemsGenerator.java @@ -0,0 +1,48 @@ +package homework_6.mapProblemsGenerator; + +import java.util.HashMap; +import java.util.Map; + +public class MapProblemsGenerator { + + public void runCatIssue() { + createCatsMapWithCollisionsInHashCode(); + } + + public void runDogIssue() { + createDogsMapWithLoosingDogs(); + } + + private void createCatsMapWithCollisionsInHashCode() { + Map map = new HashMap<>(); + Cat cat1 = new Cat(3); + Cat cat2 = new Cat(5); + map.put(cat1, "Snezhok"); + map.put(cat2, "Kris"); + catInfo(cat1, cat2); + } + + private static void catInfo(Cat cat1, Cat cat2) { + System.out.println("cat1.equals(cat2): " + cat1.equals(cat2)); + System.out.println("cat1.hashCode() == cat2.hashCode(): " + (cat1.hashCode() == cat2.hashCode())); + } + + private void createDogsMapWithLoosingDogs() { + Map map = new HashMap<>(); + Dog dog = new Dog(3); + map.put(dog, "Lapka"); + dogInfo(dog, map); + dogGrows(dog); + dogInfo(dog, map); + } + + private void dogGrows(Dog dog) { + System.out.println("dog grows..."); + dog.setAge(dog.getAge() + 1); + } + + private static void dogInfo(Dog dog, Map map) { + System.out.println("map.containsKey(dog) = " + map.containsKey(dog)); + } + +} diff --git a/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java b/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java new file mode 100644 index 00000000..6421cb25 --- /dev/null +++ b/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java @@ -0,0 +1,25 @@ +package homework_6.mapProblemsGenerator; + +import base.UnitBase; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MapProblemsGeneratorTest extends UnitBase { + + @Test + void given2cats_whenRunCatIssue_thenHashcodeCollision(){ + new MapProblemsGenerator().runCatIssue(); + assertEquals("cat1.equals(cat2): false", getOutputLines()[0]); + assertEquals("cat1.hashCode() == cat2.hashCode(): true", getOutputLines()[1]); + } + + @Test + void givenMutableDog_whenRunDogIssue_thenLooseDog(){ + new MapProblemsGenerator().runDogIssue(); + assertEquals("map.containsKey(dog) = true", getOutputLines()[0]); + assertEquals("dog grows...", getOutputLines()[1]); + assertEquals("map.containsKey(dog) = false", getOutputLines()[2]); + } + +} \ No newline at end of file From 2056e0c9f03b61769a34e5e1ab2d69f054ec0656 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Mon, 30 Aug 2021 22:30:44 +0300 Subject: [PATCH 16/33] hw6. Reduced the amount of code. --- .../homework_6/mapProblemsGenerator/Cat.java | 13 +++-- .../homework_6/mapProblemsGenerator/Dog.java | 13 +++-- .../homework_6/mapProblemsGenerator/Main.java | 10 ---- .../MapProblemsGenerator.java | 48 ------------------- .../MapProblemsGeneratorTest.java | 30 ++++++++---- 5 files changed, 38 insertions(+), 76 deletions(-) delete mode 100644 src/main/java/homework_6/mapProblemsGenerator/Main.java delete mode 100644 src/main/java/homework_6/mapProblemsGenerator/MapProblemsGenerator.java diff --git a/src/main/java/homework_6/mapProblemsGenerator/Cat.java b/src/main/java/homework_6/mapProblemsGenerator/Cat.java index a7e66a37..99928f4c 100644 --- a/src/main/java/homework_6/mapProblemsGenerator/Cat.java +++ b/src/main/java/homework_6/mapProblemsGenerator/Cat.java @@ -1,14 +1,19 @@ package homework_6.mapProblemsGenerator; -import lombok.Data; - /** * Class Cat with incorrect hashCode() method that creates collisions every time. */ -@Data public final class Cat { - final int age; + private final int age; + + public Cat(int age) { + this.age = age; + } + + public int getAge() { + return age; + } @Override public int hashCode() { diff --git a/src/main/java/homework_6/mapProblemsGenerator/Dog.java b/src/main/java/homework_6/mapProblemsGenerator/Dog.java index 8df21c99..f3831326 100644 --- a/src/main/java/homework_6/mapProblemsGenerator/Dog.java +++ b/src/main/java/homework_6/mapProblemsGenerator/Dog.java @@ -1,21 +1,26 @@ package homework_6.mapProblemsGenerator; -import lombok.Data; - import java.util.Objects; /** * Class Dog with mutable field age. */ -@Data public final class Dog { - int age; + private int age; public Dog(int age) { this.age = age; } + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/homework_6/mapProblemsGenerator/Main.java b/src/main/java/homework_6/mapProblemsGenerator/Main.java deleted file mode 100644 index 057d5c0f..00000000 --- a/src/main/java/homework_6/mapProblemsGenerator/Main.java +++ /dev/null @@ -1,10 +0,0 @@ -package homework_6.mapProblemsGenerator; - -public class Main { - public static void main(String[] args) { - - new MapProblemsGenerator().runCatIssue(); //Collisions - new MapProblemsGenerator().runDogIssue(); //Loosing information - } - -} diff --git a/src/main/java/homework_6/mapProblemsGenerator/MapProblemsGenerator.java b/src/main/java/homework_6/mapProblemsGenerator/MapProblemsGenerator.java deleted file mode 100644 index c80047f5..00000000 --- a/src/main/java/homework_6/mapProblemsGenerator/MapProblemsGenerator.java +++ /dev/null @@ -1,48 +0,0 @@ -package homework_6.mapProblemsGenerator; - -import java.util.HashMap; -import java.util.Map; - -public class MapProblemsGenerator { - - public void runCatIssue() { - createCatsMapWithCollisionsInHashCode(); - } - - public void runDogIssue() { - createDogsMapWithLoosingDogs(); - } - - private void createCatsMapWithCollisionsInHashCode() { - Map map = new HashMap<>(); - Cat cat1 = new Cat(3); - Cat cat2 = new Cat(5); - map.put(cat1, "Snezhok"); - map.put(cat2, "Kris"); - catInfo(cat1, cat2); - } - - private static void catInfo(Cat cat1, Cat cat2) { - System.out.println("cat1.equals(cat2): " + cat1.equals(cat2)); - System.out.println("cat1.hashCode() == cat2.hashCode(): " + (cat1.hashCode() == cat2.hashCode())); - } - - private void createDogsMapWithLoosingDogs() { - Map map = new HashMap<>(); - Dog dog = new Dog(3); - map.put(dog, "Lapka"); - dogInfo(dog, map); - dogGrows(dog); - dogInfo(dog, map); - } - - private void dogGrows(Dog dog) { - System.out.println("dog grows..."); - dog.setAge(dog.getAge() + 1); - } - - private static void dogInfo(Dog dog, Map map) { - System.out.println("map.containsKey(dog) = " + map.containsKey(dog)); - } - -} diff --git a/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java b/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java index 6421cb25..de2938b0 100644 --- a/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java +++ b/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java @@ -3,23 +3,33 @@ import base.UnitBase; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; class MapProblemsGeneratorTest extends UnitBase { @Test - void given2cats_whenRunCatIssue_thenHashcodeCollision(){ - new MapProblemsGenerator().runCatIssue(); - assertEquals("cat1.equals(cat2): false", getOutputLines()[0]); - assertEquals("cat1.hashCode() == cat2.hashCode(): true", getOutputLines()[1]); + void testCatClass() { + Cat cat1 = new Cat(3); + Cat cat2 = new Cat(4); + assertEquals(cat1.hashCode(), cat2.hashCode()); + assertNotEquals(cat1, cat2); } @Test - void givenMutableDog_whenRunDogIssue_thenLooseDog(){ - new MapProblemsGenerator().runDogIssue(); - assertEquals("map.containsKey(dog) = true", getOutputLines()[0]); - assertEquals("dog grows...", getOutputLines()[1]); - assertEquals("map.containsKey(dog) = false", getOutputLines()[2]); + void testDatClass() { + Dog dog1 = new Dog(3); + Dog dog2 = new Dog(3); + Dog dog3 = new Dog(4); + assertEquals(dog1, dog2); + assertNotEquals(dog1, dog3); + + Map map = new HashMap<>(); + map.put(dog1, "Gav"); + dog1.setAge(4); + assertFalse(map.containsKey(dog1)); } } \ No newline at end of file From a538113e7ce2e299e81eb8f0fa7f333f3df4b541 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Tue, 31 Aug 2021 15:52:55 +0300 Subject: [PATCH 17/33] hw6. Renamed classes. --- .../homework_6/mapProblemsGenerator/Cat.java | 31 ---------------- .../homework_6/mapProblemsGenerator/Dog.java | 37 ------------------- .../MapProblemsCollisionGenerator.java | 28 ++++++++++++++ .../MapProblemsMutableGenerator.java | 37 +++++++++++++++++++ .../MapProblemsGeneratorTest.java | 28 +++++++------- 5 files changed, 79 insertions(+), 82 deletions(-) delete mode 100644 src/main/java/homework_6/mapProblemsGenerator/Cat.java delete mode 100644 src/main/java/homework_6/mapProblemsGenerator/Dog.java create mode 100644 src/main/java/homework_6/mapProblemsGenerator/MapProblemsCollisionGenerator.java create mode 100644 src/main/java/homework_6/mapProblemsGenerator/MapProblemsMutableGenerator.java diff --git a/src/main/java/homework_6/mapProblemsGenerator/Cat.java b/src/main/java/homework_6/mapProblemsGenerator/Cat.java deleted file mode 100644 index 99928f4c..00000000 --- a/src/main/java/homework_6/mapProblemsGenerator/Cat.java +++ /dev/null @@ -1,31 +0,0 @@ -package homework_6.mapProblemsGenerator; - -/** - * Class Cat with incorrect hashCode() method that creates collisions every time. - */ - -public final class Cat { - private final int age; - - public Cat(int age) { - this.age = age; - } - - public int getAge() { - return age; - } - - @Override - public int hashCode() { - return 1; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Cat cat = (Cat) o; - return age == cat.age; - } - -} diff --git a/src/main/java/homework_6/mapProblemsGenerator/Dog.java b/src/main/java/homework_6/mapProblemsGenerator/Dog.java deleted file mode 100644 index f3831326..00000000 --- a/src/main/java/homework_6/mapProblemsGenerator/Dog.java +++ /dev/null @@ -1,37 +0,0 @@ -package homework_6.mapProblemsGenerator; - -import java.util.Objects; - -/** - * Class Dog with mutable field age. - */ - -public final class Dog { - private int age; - - public Dog(int age) { - this.age = age; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Dog dog = (Dog) o; - return age == dog.age; - } - - @Override - public int hashCode() { - return Objects.hash(age); - } - -} diff --git a/src/main/java/homework_6/mapProblemsGenerator/MapProblemsCollisionGenerator.java b/src/main/java/homework_6/mapProblemsGenerator/MapProblemsCollisionGenerator.java new file mode 100644 index 00000000..ea8f02a1 --- /dev/null +++ b/src/main/java/homework_6/mapProblemsGenerator/MapProblemsCollisionGenerator.java @@ -0,0 +1,28 @@ +package homework_6.mapProblemsGenerator; + +/** + * Class MapProblemsCollisionGenerator with incorrect hashCode() method that creates + * collisions every time. + */ + +public final class MapProblemsCollisionGenerator { + private final int someField; + + public MapProblemsCollisionGenerator(int n) { + this.someField = n; + } + + @Override + public int hashCode() { + return 1; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MapProblemsCollisionGenerator generator = (MapProblemsCollisionGenerator) o; + return someField == generator.someField; + } + +} diff --git a/src/main/java/homework_6/mapProblemsGenerator/MapProblemsMutableGenerator.java b/src/main/java/homework_6/mapProblemsGenerator/MapProblemsMutableGenerator.java new file mode 100644 index 00000000..1eeb3cce --- /dev/null +++ b/src/main/java/homework_6/mapProblemsGenerator/MapProblemsMutableGenerator.java @@ -0,0 +1,37 @@ +package homework_6.mapProblemsGenerator; + +import java.util.Objects; + +/** + * Class Dog with mutable field age. + */ + +public final class MapProblemsMutableGenerator { + private int someField; + + public MapProblemsMutableGenerator(int n) { + this.someField = n; + } + + public int getSomeField() { + return someField; + } + + public void setSomeField(int someField) { + this.someField = someField; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MapProblemsMutableGenerator generator = (MapProblemsMutableGenerator) o; + return someField == generator.someField; + } + + @Override + public int hashCode() { + return Objects.hash(someField); + } + +} diff --git a/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java b/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java index de2938b0..f114dda3 100644 --- a/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java +++ b/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java @@ -12,24 +12,24 @@ class MapProblemsGeneratorTest extends UnitBase { @Test void testCatClass() { - Cat cat1 = new Cat(3); - Cat cat2 = new Cat(4); - assertEquals(cat1.hashCode(), cat2.hashCode()); - assertNotEquals(cat1, cat2); + MapProblemsCollisionGenerator generator1 = new MapProblemsCollisionGenerator(3); + MapProblemsCollisionGenerator generator2 = new MapProblemsCollisionGenerator(4); + assertEquals(generator1.hashCode(), generator2.hashCode()); + assertNotEquals(generator1, generator2); } @Test void testDatClass() { - Dog dog1 = new Dog(3); - Dog dog2 = new Dog(3); - Dog dog3 = new Dog(4); - assertEquals(dog1, dog2); - assertNotEquals(dog1, dog3); - - Map map = new HashMap<>(); - map.put(dog1, "Gav"); - dog1.setAge(4); - assertFalse(map.containsKey(dog1)); + MapProblemsMutableGenerator generator1 = new MapProblemsMutableGenerator(3); + MapProblemsMutableGenerator generator2 = new MapProblemsMutableGenerator(3); + MapProblemsMutableGenerator generator3 = new MapProblemsMutableGenerator(4); + assertEquals(generator1, generator2); + assertNotEquals(generator1, generator3); + + Map map = new HashMap<>(); + map.put(generator1, "someString"); + generator1.setSomeField(4); + assertFalse(map.containsKey(generator1)); } } \ No newline at end of file From e8f7ba7d90d3e590d459f679c1e0d343f8aff7bc Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Mon, 13 Sep 2021 15:06:38 +0300 Subject: [PATCH 18/33] hw7. KittenToCat function --- README.md | 1 + .../homework_7/catToKittenFunction/Cat.java | 27 +++++++++++++++++++ .../catToKittenFunction/Kitten.java | 27 +++++++++++++++++++ .../KittenToCatFunction.java | 6 +++++ .../homework_7/catToKittenFunction/Main.java | 16 +++++++++++ 5 files changed, 77 insertions(+) create mode 100644 src/main/java/homework_7/catToKittenFunction/Cat.java create mode 100644 src/main/java/homework_7/catToKittenFunction/Kitten.java create mode 100644 src/main/java/homework_7/catToKittenFunction/KittenToCatFunction.java create mode 100644 src/main/java/homework_7/catToKittenFunction/Main.java diff --git a/README.md b/README.md index d6a7060f..4528500b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ | HW5.1 | [PowerOfNumber](./src/main/java/homework_5/powerOfNumber) | This console app realizes Math.pow(int base, int n) method using recursion. | | HW5.2 | [CustomRegexMatcher](./src/main/java/homework_5/customRegexMatcher) | This console app verifies custom email with regex. | | HW6 | [MapProblemsGenerator](./src/main/java/homework_6/mapProblemsGenerator) | Here you can find example of incorrect hash method overriding and a case where we can loose information in our map. | +| HW7 | [KittenToCatFunction](./src/main/java/homework_7/catToKittenFunction) | This is an example of realization my functional interface that takes a Kitty as a parameter and returns a Cat. | [Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/homework_7/catToKittenFunction/Cat.java b/src/main/java/homework_7/catToKittenFunction/Cat.java new file mode 100644 index 00000000..264cde78 --- /dev/null +++ b/src/main/java/homework_7/catToKittenFunction/Cat.java @@ -0,0 +1,27 @@ +package homework_7.catToKittenFunction; + +public class Cat { + private int age; + private String name; + + public Cat(int age, String name) { + this.age = age; + this.name = name; + } + + public int getAge() { + return age; + } + + public String getName() { + return name; + } + + public void setAge(int age) { + this.age = age; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/homework_7/catToKittenFunction/Kitten.java b/src/main/java/homework_7/catToKittenFunction/Kitten.java new file mode 100644 index 00000000..3ee719cd --- /dev/null +++ b/src/main/java/homework_7/catToKittenFunction/Kitten.java @@ -0,0 +1,27 @@ +package homework_7.catToKittenFunction; + +public class Kitten { + private int age; + private String name; + + public Kitten(int age, String name) { + this.age = age; + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/homework_7/catToKittenFunction/KittenToCatFunction.java b/src/main/java/homework_7/catToKittenFunction/KittenToCatFunction.java new file mode 100644 index 00000000..5c372548 --- /dev/null +++ b/src/main/java/homework_7/catToKittenFunction/KittenToCatFunction.java @@ -0,0 +1,6 @@ +package homework_7.catToKittenFunction; + +@FunctionalInterface +public interface KittenToCatFunction{ + Cat grow(Kitten k); +} diff --git a/src/main/java/homework_7/catToKittenFunction/Main.java b/src/main/java/homework_7/catToKittenFunction/Main.java new file mode 100644 index 00000000..8c5c064c --- /dev/null +++ b/src/main/java/homework_7/catToKittenFunction/Main.java @@ -0,0 +1,16 @@ +package homework_7.catToKittenFunction; + +public class Main { + + public static void main(String[] args) { + + Kitten smallCat = new Kitten(1, "Push"); + KittenToCatFunction function = x -> new Cat(x.getAge() + 2, x.getName()); + Cat oldCat = function.grow(smallCat); + + System.out.println("oldCat.getClass() = " + oldCat.getClass()); + System.out.println("oldCat.getAge() = " + oldCat.getAge()); + System.out.println("oldCat.getName() = " + oldCat.getName()); + } + +} From 716d62b6b7b227b470e5c7ee0a01eae286057df8 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Mon, 13 Sep 2021 21:18:16 +0300 Subject: [PATCH 19/33] hw7. Added Kitten to Cat' constructor --- .../java/homework_7/catToKittenFunction/Cat.java | 12 +++++++++++- .../java/homework_7/catToKittenFunction/Main.java | 10 +++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/homework_7/catToKittenFunction/Cat.java b/src/main/java/homework_7/catToKittenFunction/Cat.java index 264cde78..ed358eba 100644 --- a/src/main/java/homework_7/catToKittenFunction/Cat.java +++ b/src/main/java/homework_7/catToKittenFunction/Cat.java @@ -3,10 +3,20 @@ public class Cat { private int age; private String name; + private Kitten kitten; - public Cat(int age, String name) { + public Cat(int age, String name, Kitten kitten) { this.age = age; this.name = name; + this.kitten = kitten; + } + + public Kitten getKitten() { + return kitten; + } + + public void setKitten(Kitten kitten) { + this.kitten = kitten; } public int getAge() { diff --git a/src/main/java/homework_7/catToKittenFunction/Main.java b/src/main/java/homework_7/catToKittenFunction/Main.java index 8c5c064c..bab1a56a 100644 --- a/src/main/java/homework_7/catToKittenFunction/Main.java +++ b/src/main/java/homework_7/catToKittenFunction/Main.java @@ -5,12 +5,12 @@ public class Main { public static void main(String[] args) { Kitten smallCat = new Kitten(1, "Push"); - KittenToCatFunction function = x -> new Cat(x.getAge() + 2, x.getName()); - Cat oldCat = function.grow(smallCat); + KittenToCatFunction function = x -> new Cat(x.getAge() + 2, x.getName(), smallCat); + Cat bigCat = function.grow(smallCat); - System.out.println("oldCat.getClass() = " + oldCat.getClass()); - System.out.println("oldCat.getAge() = " + oldCat.getAge()); - System.out.println("oldCat.getName() = " + oldCat.getName()); + System.out.println("bigCat.getClass() = " + bigCat.getClass()); + System.out.println("bigCat.getAge() = " + bigCat.getAge()); + System.out.println("bigCat.getName() = " + bigCat.getName()); } } From b238f2d5c7656c3eeb15fa8ed3b55b7a7873b67c Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Sat, 18 Sep 2021 10:02:15 +0300 Subject: [PATCH 20/33] hw7. Added Kitten to Cat' constructor --- README.md | 2 +- .../{catToKittenFunction => kittenToCatFunction}/Cat.java | 2 +- .../{catToKittenFunction => kittenToCatFunction}/Kitten.java | 2 +- .../KittenToCatFunction.java | 2 +- .../{catToKittenFunction => kittenToCatFunction}/Main.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename src/main/java/homework_7/{catToKittenFunction => kittenToCatFunction}/Cat.java (93%) rename src/main/java/homework_7/{catToKittenFunction => kittenToCatFunction}/Kitten.java (91%) rename src/main/java/homework_7/{catToKittenFunction => kittenToCatFunction}/KittenToCatFunction.java (68%) rename src/main/java/homework_7/{catToKittenFunction => kittenToCatFunction}/Main.java (92%) diff --git a/README.md b/README.md index 4528500b..099f78ac 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ | HW5.1 | [PowerOfNumber](./src/main/java/homework_5/powerOfNumber) | This console app realizes Math.pow(int base, int n) method using recursion. | | HW5.2 | [CustomRegexMatcher](./src/main/java/homework_5/customRegexMatcher) | This console app verifies custom email with regex. | | HW6 | [MapProblemsGenerator](./src/main/java/homework_6/mapProblemsGenerator) | Here you can find example of incorrect hash method overriding and a case where we can loose information in our map. | -| HW7 | [KittenToCatFunction](./src/main/java/homework_7/catToKittenFunction) | This is an example of realization my functional interface that takes a Kitty as a parameter and returns a Cat. | +| HW7 | [KittenToCatFunction](./src/main/java/homework_7/kittenToCatFunction) | This is an example of realization my functional interface that takes a Kitty as a parameter and returns a Cat. | [Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/homework_7/catToKittenFunction/Cat.java b/src/main/java/homework_7/kittenToCatFunction/Cat.java similarity index 93% rename from src/main/java/homework_7/catToKittenFunction/Cat.java rename to src/main/java/homework_7/kittenToCatFunction/Cat.java index ed358eba..ed4de115 100644 --- a/src/main/java/homework_7/catToKittenFunction/Cat.java +++ b/src/main/java/homework_7/kittenToCatFunction/Cat.java @@ -1,4 +1,4 @@ -package homework_7.catToKittenFunction; +package homework_7.kittenToCatFunction; public class Cat { private int age; diff --git a/src/main/java/homework_7/catToKittenFunction/Kitten.java b/src/main/java/homework_7/kittenToCatFunction/Kitten.java similarity index 91% rename from src/main/java/homework_7/catToKittenFunction/Kitten.java rename to src/main/java/homework_7/kittenToCatFunction/Kitten.java index 3ee719cd..0daa3b81 100644 --- a/src/main/java/homework_7/catToKittenFunction/Kitten.java +++ b/src/main/java/homework_7/kittenToCatFunction/Kitten.java @@ -1,4 +1,4 @@ -package homework_7.catToKittenFunction; +package homework_7.kittenToCatFunction; public class Kitten { private int age; diff --git a/src/main/java/homework_7/catToKittenFunction/KittenToCatFunction.java b/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java similarity index 68% rename from src/main/java/homework_7/catToKittenFunction/KittenToCatFunction.java rename to src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java index 5c372548..606b410b 100644 --- a/src/main/java/homework_7/catToKittenFunction/KittenToCatFunction.java +++ b/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java @@ -1,4 +1,4 @@ -package homework_7.catToKittenFunction; +package homework_7.kittenToCatFunction; @FunctionalInterface public interface KittenToCatFunction{ diff --git a/src/main/java/homework_7/catToKittenFunction/Main.java b/src/main/java/homework_7/kittenToCatFunction/Main.java similarity index 92% rename from src/main/java/homework_7/catToKittenFunction/Main.java rename to src/main/java/homework_7/kittenToCatFunction/Main.java index bab1a56a..19b92f52 100644 --- a/src/main/java/homework_7/catToKittenFunction/Main.java +++ b/src/main/java/homework_7/kittenToCatFunction/Main.java @@ -1,4 +1,4 @@ -package homework_7.catToKittenFunction; +package homework_7.kittenToCatFunction; public class Main { From 6edc76c57e1bfc00e7ee5e96443995d969ae4634 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Mon, 20 Sep 2021 13:21:09 +0300 Subject: [PATCH 21/33] Course_project added. No tests yet. --- README.md | 1 + .../java/course_project/sea_battle/Game.java | 67 ++++++ .../java/course_project/sea_battle/Main.java | 7 + .../sea_battle/model/Player.java | 40 ++++ .../sea_battle/model/Point.java | 41 ++++ .../course_project/sea_battle/model/Ship.java | 44 ++++ .../course_project/sea_battle/model/Shot.java | 7 + .../sea_battle/model/boards/Board.java | 23 +++ .../sea_battle/model/boards/MyBoard.java | 17 ++ .../sea_battle/model/boards/MyShots.java | 4 + src/main/java/course_project/sea_battle/rules | 18 ++ .../sea_battle/service/Engine.java | 193 ++++++++++++++++++ .../sea_battle/service/InputReader.java | 131 ++++++++++++ .../sea_battle/service/NameSetter.java | 28 +++ .../sea_battle/service/ShipPlacer.java | 65 ++++++ .../sea_battle/view/BigSpace.java | 21 ++ .../sea_battle/view/BoardPrinter.java | 85 ++++++++ 17 files changed, 792 insertions(+) create mode 100644 src/main/java/course_project/sea_battle/Game.java create mode 100644 src/main/java/course_project/sea_battle/Main.java create mode 100644 src/main/java/course_project/sea_battle/model/Player.java create mode 100644 src/main/java/course_project/sea_battle/model/Point.java create mode 100644 src/main/java/course_project/sea_battle/model/Ship.java create mode 100644 src/main/java/course_project/sea_battle/model/Shot.java create mode 100644 src/main/java/course_project/sea_battle/model/boards/Board.java create mode 100644 src/main/java/course_project/sea_battle/model/boards/MyBoard.java create mode 100644 src/main/java/course_project/sea_battle/model/boards/MyShots.java create mode 100644 src/main/java/course_project/sea_battle/rules create mode 100644 src/main/java/course_project/sea_battle/service/Engine.java create mode 100644 src/main/java/course_project/sea_battle/service/InputReader.java create mode 100644 src/main/java/course_project/sea_battle/service/NameSetter.java create mode 100644 src/main/java/course_project/sea_battle/service/ShipPlacer.java create mode 100644 src/main/java/course_project/sea_battle/view/BigSpace.java create mode 100644 src/main/java/course_project/sea_battle/view/BoardPrinter.java diff --git a/README.md b/README.md index 099f78ac..cb6ee53b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ | HW5.2 | [CustomRegexMatcher](./src/main/java/homework_5/customRegexMatcher) | This console app verifies custom email with regex. | | HW6 | [MapProblemsGenerator](./src/main/java/homework_6/mapProblemsGenerator) | Here you can find example of incorrect hash method overriding and a case where we can loose information in our map. | | HW7 | [KittenToCatFunction](./src/main/java/homework_7/kittenToCatFunction) | This is an example of realization my functional interface that takes a Kitty as a parameter and returns a Cat. | +| course_project | [Sea Battle](./src/main/java/course_project/sea_battle) | Course project "Sea Battle Game" is here. You can find description and rules in file: rules.txt. | [Link to my CodingBat](https://codingbat.com/done?user=ashandrikov@gmail.com&tag=8115696431) diff --git a/src/main/java/course_project/sea_battle/Game.java b/src/main/java/course_project/sea_battle/Game.java new file mode 100644 index 00000000..c73fbfbd --- /dev/null +++ b/src/main/java/course_project/sea_battle/Game.java @@ -0,0 +1,67 @@ +package course_project.sea_battle; + +import course_project.sea_battle.model.Player; +import course_project.sea_battle.model.boards.MyBoard; +import course_project.sea_battle.model.boards.MyShots; +import course_project.sea_battle.service.Engine; +import course_project.sea_battle.service.ShipPlacer; + +import java.util.Scanner; + +import static course_project.sea_battle.service.NameSetter.setNames; + +public class Game { + private final Scanner scanner = new Scanner(System.in); + private final Player player1; + private final Player player2; + private static final String TIE = "Game over. It's a TIE!"; + private static final String GAMEOVER = "Game over. The winner is: "; + + public Game() { + MyBoard myBoard = new MyBoard(); + myBoard.setBasicGrids(); + MyShots enemyBoard = new MyShots(); + enemyBoard.setBasicGrids(); + + MyBoard myBoard2 = new MyBoard(); + myBoard2.setBasicGrids(); + MyShots enemyBoard2 = new MyShots(); + enemyBoard2.setBasicGrids(); + + this.player1 = new Player(myBoard, enemyBoard); + this.player2 = new Player(myBoard2, enemyBoard2); + } + + public void run() { + setNames(player1, player2); + setUpShips(); + startGame(); + } + + public void setUpShips() { + new ShipPlacer(scanner).placeShip(player1); + new ShipPlacer(scanner).placeShip(player2); + } + + public void startGame() { + while (!countShipsPlayers(player1, player2)) { + new Engine().checkPlayerShot(scanner, player1, player2); + new Engine().checkPlayerShot(scanner, player2, player1); + } + } + + public boolean countShipsPlayers(Player player1, Player player2) { + long p1ships = player1.getMyShips().stream().filter(e -> e.isAlive()).count(); + long p2ships = player2.getMyShips().stream().filter(e -> e.isAlive()).count(); + + if (p1ships == 0 && p2ships == 0) { + System.err.println(TIE); + } else if (p1ships == 0) { + System.err.println(GAMEOVER + player2.getName() + "!"); + } else if (p2ships == 0) { + System.err.println(GAMEOVER + player1.getName() + "!"); + } + return p1ships < 1 || p2ships < 1; + } + +} diff --git a/src/main/java/course_project/sea_battle/Main.java b/src/main/java/course_project/sea_battle/Main.java new file mode 100644 index 00000000..96d092fd --- /dev/null +++ b/src/main/java/course_project/sea_battle/Main.java @@ -0,0 +1,7 @@ +package course_project.sea_battle; + +public class Main { + public static void main(String[] args) { + new Game().run(); + } +} diff --git a/src/main/java/course_project/sea_battle/model/Player.java b/src/main/java/course_project/sea_battle/model/Player.java new file mode 100644 index 00000000..be1b46a8 --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/Player.java @@ -0,0 +1,40 @@ +package course_project.sea_battle.model; + +import course_project.sea_battle.model.boards.MyBoard; +import course_project.sea_battle.model.boards.MyShots; + +import java.util.ArrayList; +import java.util.List; + +public class Player { + private String name; + private MyBoard myBoard; + private MyShots myShots; + private final List myShips = new ArrayList<>(); + + public Player(MyBoard myBoard, MyShots enemyBoard) { + this.myBoard = myBoard; + this.myShots = enemyBoard; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getMyShips() { + return myShips; + } + + public MyBoard getMyBoard() { + return myBoard; + } + + public MyShots getMyShots() { + return myShots; + } + +} diff --git a/src/main/java/course_project/sea_battle/model/Point.java b/src/main/java/course_project/sea_battle/model/Point.java new file mode 100644 index 00000000..5acb270b --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/Point.java @@ -0,0 +1,41 @@ +package course_project.sea_battle.model; + +public class Point { + private final int x; + private final int y; + + public Point(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + + public int getY() { + return y; + } + + @Override + public String toString() { + return "Point{" + + "x=" + x + + ", y=" + y + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Point point = (Point) o; + return x == point.x && y == point.y; + } + + @Override + public int hashCode() { + return Integer.hashCode(x) + Integer.hashCode(y); + } +} diff --git a/src/main/java/course_project/sea_battle/model/Ship.java b/src/main/java/course_project/sea_battle/model/Ship.java new file mode 100644 index 00000000..9bea497d --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/Ship.java @@ -0,0 +1,44 @@ +package course_project.sea_battle.model; + +import java.util.List; + +public class Ship { + private final List coordinates; + private int lives; + private boolean isAlive; + + public Ship(List coordinates) { + this.coordinates = coordinates; + this.lives = coordinates.size(); + this.isAlive = true; + } + + public int getLives() { + return lives; + } + + public void setLives(int lives) { + this.lives = lives; + } + + public boolean isAlive() { + return isAlive; + } + + public void setAlive(boolean alive) { + this.isAlive = alive; + } + + public int getSize() { return coordinates.size(); } + + public List getCoordinates() { + return coordinates; + } + + @Override + public String toString() { + return "Ship{" + + "coordinates=" + coordinates + + '}'; + } +} diff --git a/src/main/java/course_project/sea_battle/model/Shot.java b/src/main/java/course_project/sea_battle/model/Shot.java new file mode 100644 index 00000000..f777e8cd --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/Shot.java @@ -0,0 +1,7 @@ +package course_project.sea_battle.model; + +public enum Shot { + MISS, + HIT, + KILLED +} diff --git a/src/main/java/course_project/sea_battle/model/boards/Board.java b/src/main/java/course_project/sea_battle/model/boards/Board.java new file mode 100644 index 00000000..963e3ed9 --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/boards/Board.java @@ -0,0 +1,23 @@ +package course_project.sea_battle.model.boards; + +abstract class Board { + + protected int[][] board; + + public void setBasicGrids() { + board = new int[10][10]; + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + board[i][j] = 0; + } + } + } + + public int[][] getBoard() { + return board; + } + + public void setBoard(int[][] board) { + this.board = board; + } +} diff --git a/src/main/java/course_project/sea_battle/model/boards/MyBoard.java b/src/main/java/course_project/sea_battle/model/boards/MyBoard.java new file mode 100644 index 00000000..5cf2a8d1 --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/boards/MyBoard.java @@ -0,0 +1,17 @@ +package course_project.sea_battle.model.boards; + +import course_project.sea_battle.model.Point; +import course_project.sea_battle.model.Ship; + +import java.util.List; + +public class MyBoard extends Board { + + public void placeShip(Ship ship) { + List coordinates = ship.getCoordinates(); + for (Point point : coordinates) { + board[point.getX()][point.getY()] = 1; + } + } + +} diff --git a/src/main/java/course_project/sea_battle/model/boards/MyShots.java b/src/main/java/course_project/sea_battle/model/boards/MyShots.java new file mode 100644 index 00000000..8daef2d0 --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/boards/MyShots.java @@ -0,0 +1,4 @@ +package course_project.sea_battle.model.boards; + +public class MyShots extends Board { +} diff --git a/src/main/java/course_project/sea_battle/rules b/src/main/java/course_project/sea_battle/rules new file mode 100644 index 00000000..edf0ddfc --- /dev/null +++ b/src/main/java/course_project/sea_battle/rules @@ -0,0 +1,18 @@ +GENERAL +Only 1 mode is available: player vs player. +Each player has 10 ships: 1*4deck, 2*3, 3*2, 4*1. + +SHIP PLACEMENT +You have to place ships manually. +It's not allowed to place ships close to each other (diagonal cells count as well). +You put a ship by pointing its topLeft point and with position ("v" - vertical, "h" - horizontal). + So your input should be like this: [A7 V] or [b1 h]. + +RULES +Shot format: [A7] or [b1]. +You cannot shoot out of board or cells that you have shooted before. +When you destroy ship all cells around fill automatically and you cannot shoot them (cause there are no ships). +Each player has same count of moves. +Game over when one of player (or both) don't have "alive" ships. + + diff --git a/src/main/java/course_project/sea_battle/service/Engine.java b/src/main/java/course_project/sea_battle/service/Engine.java new file mode 100644 index 00000000..6bd71917 --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/Engine.java @@ -0,0 +1,193 @@ +package course_project.sea_battle.service; + +import course_project.sea_battle.model.Player; +import course_project.sea_battle.model.Point; +import course_project.sea_battle.model.Ship; +import course_project.sea_battle.model.Shot; + +import java.util.*; +import java.util.stream.Collectors; + +import static course_project.sea_battle.view.BigSpace.bigSpace; +import static course_project.sea_battle.view.BoardPrinter.showBoards; + +public class Engine { + private int x; + private int y; + private boolean isGameOver = false; + private Shot shot; + private Ship currentShip; + + private static final String MAKESHOT = ", make your shot in format: [A6] or [b1]"; + private static final String INPUTERROR = "Input should be like this: [A7] or [b2]. Try again!"; + private static final String CHECKED = "Cell is checked. Make another shot!"; + private static final String KILLALL = ", you destroyed all enemy ships. Congratulations!"; + + public void checkPlayerShot(Scanner scanner, Player player1, Player player2) { + showBoards(player1); + System.out.println(player1.getName() + MAKESHOT); + + OUTER: + while (true) { + String input = scanner.nextLine(); + + if (!isValidInput(input)) continue; + if (isShooted(player2)) continue; + if (!checkCell(player2)) continue; + + putOnMyBoard(player1); + putOnEnemyBoard(player2); + + switch (shot) { + case KILLED: + fillCellsAroundDestroyedShip(currentShip, player1, player2); + showBoards(player1); + if (isGameOver) { + System.out.println(player1.getName() + KILLALL); + bigSpace(); + return; + } else { + System.out.println(player1.getName() + MAKESHOT); + } + break; + case HIT: + showBoards(player1); + System.out.println(player1.getName() + MAKESHOT); + break; + case MISS: + showBoards(player1); + bigSpace(); + break OUTER; + } + } + } + + public boolean isValidInput(String input) { + if (input.matches("[a-jA-J]([1-9]|10)")) { + y = Character.getNumericValue(input.charAt(0)) - 10; + x = Integer.parseInt(input.substring(1)) - 1; + return true; + } else { + System.out.println(INPUTERROR); + return false; + } + } + + public boolean isShooted(Player enemy) { + if (enemy.getMyBoard().getBoard()[x][y] == 3 || enemy.getMyBoard().getBoard()[x][y] == 4) { + System.out.println(CHECKED); + return true; + } + return false; + } + + public boolean checkCell(Player enemy) { + + if (enemy.getMyBoard().getBoard()[x][y] == 1) { + findOutHitOrKilled(enemy); + } else { + shot = Shot.MISS; + System.err.println("MISS"); + } + return true; + } + + public void findOutHitOrKilled(Player enemy) { + for (Ship ship : enemy.getMyShips()) { + if (ship.getCoordinates().contains(new Point(x, y))) { + ship.setLives(ship.getLives() - 1); + if (ship.getLives() == 0) { + System.err.println("KILLED!"); + shot = Shot.KILLED; + ship.setAlive(false); + System.out.println("Player " + enemy.getName() + " has " + countShips(enemy) + " ship(s) left."); + currentShip = ship; + if (countShips(enemy) == 0) { + isGameOver = true; + } + } else { + shot = Shot.HIT; + System.err.println("HIT!"); + } + break; + } + } + } + + public long countShips(Player player) { + return player.getMyShips().stream().filter(e -> e.isAlive()).count(); + } + + public void putOnMyBoard(Player player) { + int[][] tempBoard = player.getMyShots().getBoard(); + if (shot == Shot.MISS) { + tempBoard[x][y] = 2; + } else { + tempBoard[x][y] = 3; + } + player.getMyShots().setBoard(tempBoard); + } + + public void putOnEnemyBoard(Player player) { + int[][] tempBoard = player.getMyBoard().getBoard(); + if (shot == Shot.MISS) { + tempBoard[x][y] = 2; + } else { + tempBoard[x][y] = 3; + } + player.getMyBoard().setBoard(tempBoard); + } + + public void fillCellsAroundDestroyedShip(Ship ship, Player me, Player enemy) { + + List coordinatesOfTheShip = ship.getCoordinates(); + Set coordinatesAroundTheShip = new HashSet<>(); + + for (Point point : coordinatesOfTheShip) { + int x1 = point.getX(); + int y1 = point.getY(); + + if (x1 > 0) { + coordinatesAroundTheShip.add(new Point(x1 - 1, y1)); + } + if (y1 > 0) { + coordinatesAroundTheShip.add(new Point(x1, y1 - 1)); + } + if (x1 < 9) { + coordinatesAroundTheShip.add(new Point(x1 + 1, y1)); + } + if (y1 < 9) { + coordinatesAroundTheShip.add(new Point(x1, y1 + 1)); + } + if (x1 > 0 && y1 > 0) { + coordinatesAroundTheShip.add(new Point(x1 - 1, y1 - 1)); + } + if (x1 < 9 && y1 < 9) { + coordinatesAroundTheShip.add(new Point(x1 + 1, y1 + 1)); + } + if (x1 > 0 && y1 < 9) { + coordinatesAroundTheShip.add(new Point(x1 - 1, y1 + 1)); + } + if (x1 < 9 && y1 > 0) { + coordinatesAroundTheShip.add(new Point(x1 + 1, y1 - 1)); + } + } + + int[][] myShots = me.getMyShots().getBoard(); + int[][] enemyMainBoard = enemy.getMyBoard().getBoard(); + + Set filteredPointsAround = coordinatesAroundTheShip.stream() + .distinct() + .filter(e -> (enemyMainBoard[e.getX()][e.getY()] == 0)) + .collect(Collectors.toSet()); + + for (Point point : filteredPointsAround) { + myShots[point.getX()][point.getY()] = 4; + enemyMainBoard[point.getX()][point.getY()] = 4; + } + + me.getMyShots().setBoard(myShots); + enemy.getMyBoard().setBoard(enemyMainBoard); + } + +} diff --git a/src/main/java/course_project/sea_battle/service/InputReader.java b/src/main/java/course_project/sea_battle/service/InputReader.java new file mode 100644 index 00000000..ebc33cb0 --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/InputReader.java @@ -0,0 +1,131 @@ +package course_project.sea_battle.service; + +import course_project.sea_battle.model.boards.MyBoard; +import course_project.sea_battle.model.Point; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Scanner; + +public class InputReader { + private final Scanner scanner; + private int x; + private int y; + private String position; + private List coordinates; + + private static final String INPUTERROR = "Input should be like this: [A7 h] or [B2 h]. Try again!"; + private static final String OUTOFBOARD = "Impossible to place ship here because it is out of board!"; + private static final String SHIPSCROSS = "Impossible to place ship here because ship crosses with another one!"; + + public InputReader(Scanner scanner) { + this.scanner = scanner; + } + + public void getAndValidateInput(int shipSize, MyBoard board) { + while (true) { + String input = scanner.nextLine(); + if (!isValidInput(input)) continue; + Point topLeftPoint = getTopLeftPoint(); + if (!isShipWithinBoard(shipSize)) continue; + coordinates = findCoordinates(shipSize, topLeftPoint); + if (shipsDoNotCross(board, shipSize)) break; + } + } + + public boolean isValidInput(String input) { + if (input.matches("[a-jA-J]([1-9]|10) (v|h|V|H)")) { + String[] coords = input.split(" "); + y = Character.getNumericValue(coords[0].charAt(0)) - 10; + x = Integer.parseInt(coords[0].substring(1)) - 1; + position = coords[1].toLowerCase(); + return true; + } else { + System.out.println(INPUTERROR); + return false; + } + } + + public Point getTopLeftPoint() { + return new Point(x, y); + } + + private boolean isShipWithinBoard(int shipSize) { + Point rightBottomPoint = position.equalsIgnoreCase("v") + ? new Point(x + shipSize, y) + : new Point(x, y + shipSize); + if (rightBottomPoint.getX() > 10 || rightBottomPoint.getY() > 10) { + System.out.println(OUTOFBOARD); + return false; + } + return true; + } + + public List findCoordinates(int shipSize, Point topLeftPoint) { + coordinates = new ArrayList<>(); + + int x1 = topLeftPoint.getX(); + int y1 = topLeftPoint.getY(); + + for (int i = 0; i < shipSize; i++) { + coordinates.add(new Point(x1, y1)); + if (position.equals("v")) { + x1++; + } else if (position.equals("h")) { + y1++; + } + } + return coordinates; + } + + public boolean shipsDoNotCross(MyBoard board, int shipSize) { + HashSet allCoordinates = new HashSet<>(); + for (int i = 0; i < shipSize; i++) { + allCoordinates.add(new Point(x, y)); + if (x > 0) { + allCoordinates.add(new Point(x - 1, y)); + } + if (y > 0) { + allCoordinates.add(new Point(x, y - 1)); + } + if (x < 9) { + allCoordinates.add(new Point(x + 1, y)); + } + if (y < 9) { + allCoordinates.add(new Point(x, y + 1)); + } + if (x > 0 && y > 0) { + allCoordinates.add(new Point(x - 1, y - 1)); + } + if (x < 9 && y < 9) { + allCoordinates.add(new Point(x + 1, y + 1)); + } + if (x > 0 && y < 9) { + allCoordinates.add(new Point(x - 1, y + 1)); + } + if (x < 9 && y > 0) { + allCoordinates.add(new Point(x + 1, y - 1)); + } + if (position.equals("v")) { + x++; + } else { + y++; + } + } + long count = allCoordinates.stream() + .mapToInt(e -> board.getBoard()[e.getX()][e.getY()]) + .distinct() + .count(); + if (count > 1) { + System.out.println(SHIPSCROSS); + return false; + } + return true; + } + + public List getValidCoordinates() { + return coordinates; + } + +} diff --git a/src/main/java/course_project/sea_battle/service/NameSetter.java b/src/main/java/course_project/sea_battle/service/NameSetter.java new file mode 100644 index 00000000..8d393194 --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/NameSetter.java @@ -0,0 +1,28 @@ +package course_project.sea_battle.service; + +import course_project.sea_battle.model.Player; + +import java.util.Scanner; + +public class NameSetter { + + private NameSetter() { + } + + public static void setNames(Player player1, Player player2){ + Scanner scanner = new Scanner(System.in); + + System.out.println("Player 1, please, input your name"); + String player1Name = scanner.nextLine(); + player1.setName(player1Name); + System.out.println("Hello, " + player1Name + "!"); + + System.out.println("Player 2, please, input your name"); + String player2Name = scanner.nextLine(); + player2.setName(player2Name); + System.out.println("Hello, " + player2Name + "!"); + + System.out.println("Press ENTER to start the game"); + String str = scanner.nextLine(); + } +} diff --git a/src/main/java/course_project/sea_battle/service/ShipPlacer.java b/src/main/java/course_project/sea_battle/service/ShipPlacer.java new file mode 100644 index 00000000..3aa6feb8 --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/ShipPlacer.java @@ -0,0 +1,65 @@ +package course_project.sea_battle.service; + +import course_project.sea_battle.model.Player; +import course_project.sea_battle.model.Point; +import course_project.sea_battle.model.Ship; +import course_project.sea_battle.model.boards.MyBoard; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +import static course_project.sea_battle.view.BigSpace.bigSpace; +import static course_project.sea_battle.view.BoardPrinter.showBoards; + +public class ShipPlacer { + private final InputReader inputReader; + private static final String PLACED = "Ship is placed!"; + + public ShipPlacer(Scanner scanner) { + inputReader = new InputReader(scanner); + } + + public void placeShip(Player player) { + + MyBoard board = player.getMyBoard(); + showBoards(player); + + for (int shipSize = 4; shipSize >= 1; shipSize--) { + for (int shipNumber = 0; shipNumber <= 4 - shipSize; shipNumber++) { + System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); + + inputReader.getAndValidateInput(shipSize, board); + List coordinates = inputReader.getValidCoordinates(); + + Ship ship = new Ship(coordinates); + board.placeShip(ship); + + System.out.println(PLACED); + player.getMyShips().add(ship); + showBoards(player); + } + } + +// You can uncomment this block of code instead above for() (lines: 28-42) to place only 2 ships for every player. + +// for (int shipSize = 3; shipSize > 1; shipSize--) { +// for (int shipNumber = 0; shipNumber < 1; shipNumber++) { +// System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 H] or [a8 v]"); +// +// inputReader.getAndValidateInput(shipSize, board); +// List coordinates = inputReader.getValidCoordinates(); +// +// Ship ship = new Ship(coordinates); +// board.placeShip(ship); +// +// System.out.println(PLACED); +// player.getMyShips().add(ship); +// showBoards(player); +// } +// } + + bigSpace(); + } + +} diff --git a/src/main/java/course_project/sea_battle/view/BigSpace.java b/src/main/java/course_project/sea_battle/view/BigSpace.java new file mode 100644 index 00000000..5d1a8d6b --- /dev/null +++ b/src/main/java/course_project/sea_battle/view/BigSpace.java @@ -0,0 +1,21 @@ +package course_project.sea_battle.view; + +import java.util.Scanner; +import java.util.stream.Stream; + +public class BigSpace { + private static final String FINISH = "Press ENTER to finish your move"; + + private BigSpace() { + } + + public static void bigSpace() { + System.out.println(FINISH); + String str = new Scanner(System.in).nextLine(); + + Stream.generate(() -> ".") + .limit(5) + .forEach(System.out::println); + } + +} diff --git a/src/main/java/course_project/sea_battle/view/BoardPrinter.java b/src/main/java/course_project/sea_battle/view/BoardPrinter.java new file mode 100644 index 00000000..98e1d03b --- /dev/null +++ b/src/main/java/course_project/sea_battle/view/BoardPrinter.java @@ -0,0 +1,85 @@ +package course_project.sea_battle.view; + + +import course_project.sea_battle.model.Player; + +public class BoardPrinter { + private static final String RED = "\u001B[31m"; + private static final String GREEN = "\u001B[32m"; + private static final String RESET = "\u001B[0m"; + private static final String CYAN = "\u001B[36m"; + + private static final String MISS = GREEN + "0" + RESET; + private static final String HIT = RED + "X" + RESET; + private static final String WAVE = CYAN + "~" + RESET; + + private BoardPrinter() { + } + + public static void showBoards(Player player) { + int[][] myField = player.getMyBoard().getBoard(); + int[][] enemyField = player.getMyShots().getBoard(); + showHeader(player); + for (int i = 0; i < 10; i++) { + System.out.format("%3d", i + 1); + for (int j = 0; j < 23; j++) { + if (j < 10) { + switch (myField[i][j]) { + case 0: + System.out.printf(" %s", WAVE); + break; + case 1: + System.out.printf(" %s", "1"); + break; + case 3: + System.out.printf(" %s", HIT); + break; + case 2: + case 4: + System.out.printf(" %s", MISS); + break; + default: + System.out.printf(" %s", "?"); + } + } else if (j < 12) { + System.out.print("\t"); + } else if (j == 12) { + System.out.printf("%3d", i + 1); + } else { + switch (enemyField[i][j - 13]) { + case 0: + System.out.printf(" %s", WAVE); + break; + case 3: + System.out.printf(" %s", HIT); + break; + case 2: + case 4: + System.out.printf(" %s", MISS); + break; + default: + System.out.printf(" %s", "?"); + } + } + } + System.out.println(); + } + } + + public static void showHeader(Player player) { + System.out.println(); + System.out.println("\t\t\t\t\t\tMY BOARD (" + player.getName() + ") vs ENEMY BOARD"); + System.out.println(); + showHighLine(); + System.out.print("\t\t"); + showHighLine(); + System.out.println(); + } + + public static void showHighLine() { + System.out.print("\t"); + for (int i = 0; i < 10; i++) { + System.out.format("%3s", (char) (i + 65) + " "); + } + } +} From e84abaa0c6a56b51bb0471b65d0383e42d9b757a Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Mon, 20 Sep 2021 13:33:25 +0300 Subject: [PATCH 22/33] Course_project added. No tests yet. Small bug fixed. --- src/main/java/course_project/sea_battle/model/Player.java | 4 ++++ src/main/java/course_project/sea_battle/model/Ship.java | 3 +-- .../java/course_project/sea_battle/service/Engine.java | 8 ++------ .../course_project/sea_battle/service/ShipPlacer.java | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/course_project/sea_battle/model/Player.java b/src/main/java/course_project/sea_battle/model/Player.java index be1b46a8..416deee0 100644 --- a/src/main/java/course_project/sea_battle/model/Player.java +++ b/src/main/java/course_project/sea_battle/model/Player.java @@ -37,4 +37,8 @@ public MyShots getMyShots() { return myShots; } + public long countShips() { + return getMyShips().stream().filter(e -> e.isAlive()).count(); + } + } diff --git a/src/main/java/course_project/sea_battle/model/Ship.java b/src/main/java/course_project/sea_battle/model/Ship.java index 9bea497d..f8d46348 100644 --- a/src/main/java/course_project/sea_battle/model/Ship.java +++ b/src/main/java/course_project/sea_battle/model/Ship.java @@ -29,8 +29,6 @@ public void setAlive(boolean alive) { this.isAlive = alive; } - public int getSize() { return coordinates.size(); } - public List getCoordinates() { return coordinates; } @@ -41,4 +39,5 @@ public String toString() { "coordinates=" + coordinates + '}'; } + } diff --git a/src/main/java/course_project/sea_battle/service/Engine.java b/src/main/java/course_project/sea_battle/service/Engine.java index 6bd71917..221f7d64 100644 --- a/src/main/java/course_project/sea_battle/service/Engine.java +++ b/src/main/java/course_project/sea_battle/service/Engine.java @@ -100,9 +100,9 @@ public void findOutHitOrKilled(Player enemy) { System.err.println("KILLED!"); shot = Shot.KILLED; ship.setAlive(false); - System.out.println("Player " + enemy.getName() + " has " + countShips(enemy) + " ship(s) left."); + System.out.println(enemy.getName() + " has " + enemy.countShips() + " ship(s) left."); currentShip = ship; - if (countShips(enemy) == 0) { + if (enemy.countShips() == 0) { isGameOver = true; } } else { @@ -114,10 +114,6 @@ public void findOutHitOrKilled(Player enemy) { } } - public long countShips(Player player) { - return player.getMyShips().stream().filter(e -> e.isAlive()).count(); - } - public void putOnMyBoard(Player player) { int[][] tempBoard = player.getMyShots().getBoard(); if (shot == Shot.MISS) { diff --git a/src/main/java/course_project/sea_battle/service/ShipPlacer.java b/src/main/java/course_project/sea_battle/service/ShipPlacer.java index 3aa6feb8..faa871a3 100644 --- a/src/main/java/course_project/sea_battle/service/ShipPlacer.java +++ b/src/main/java/course_project/sea_battle/service/ShipPlacer.java @@ -5,7 +5,6 @@ import course_project.sea_battle.model.Ship; import course_project.sea_battle.model.boards.MyBoard; -import java.util.ArrayList; import java.util.List; import java.util.Scanner; From 021ab623a713036e361f08288377e1b410bd988e Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Mon, 20 Sep 2021 18:56:02 +0300 Subject: [PATCH 23/33] Few tests added. --- .../java/course_project/sea_battle/Game.java | 24 ++-- .../java/course_project/sea_battle/Main.java | 2 +- .../sea_battle/{model => }/boards/Board.java | 4 +- .../{model => }/boards/MyBoard.java | 2 +- .../sea_battle/boards/MyShots.java | 4 + .../course_project/sea_battle/gameProcess.png | Bin 0 -> 24123 bytes .../sea_battle/model/Player.java | 6 +- .../sea_battle/model/Point.java | 7 +- .../course_project/sea_battle/model/Ship.java | 9 +- .../sea_battle/model/boards/MyShots.java | 4 - .../sea_battle/service/Engine.java | 77 ++++++------ .../sea_battle/service/InputReader.java | 2 +- .../sea_battle/service/ShipPlacer.java | 44 +++---- .../sea_battle/view/BoardPrinter.java | 18 ++- .../course_project/sea_battle/ModelTest.java | 72 ++++++++++++ .../course_project/sea_battle/ViewTest.java | 111 ++++++++++++++++++ 16 files changed, 277 insertions(+), 109 deletions(-) rename src/main/java/course_project/sea_battle/{model => }/boards/Board.java (84%) rename src/main/java/course_project/sea_battle/{model => }/boards/MyBoard.java (88%) create mode 100644 src/main/java/course_project/sea_battle/boards/MyShots.java create mode 100644 src/main/java/course_project/sea_battle/gameProcess.png delete mode 100644 src/main/java/course_project/sea_battle/model/boards/MyShots.java create mode 100644 src/test/java/course_project/sea_battle/ModelTest.java create mode 100644 src/test/java/course_project/sea_battle/ViewTest.java diff --git a/src/main/java/course_project/sea_battle/Game.java b/src/main/java/course_project/sea_battle/Game.java index c73fbfbd..73ef3c26 100644 --- a/src/main/java/course_project/sea_battle/Game.java +++ b/src/main/java/course_project/sea_battle/Game.java @@ -1,8 +1,8 @@ package course_project.sea_battle; +import course_project.sea_battle.boards.MyBoard; +import course_project.sea_battle.boards.MyShots; import course_project.sea_battle.model.Player; -import course_project.sea_battle.model.boards.MyBoard; -import course_project.sea_battle.model.boards.MyShots; import course_project.sea_battle.service.Engine; import course_project.sea_battle.service.ShipPlacer; @@ -10,7 +10,7 @@ import static course_project.sea_battle.service.NameSetter.setNames; -public class Game { +public class Game extends Thread{ private final Scanner scanner = new Scanner(System.in); private final Player player1; private final Player player2; @@ -18,18 +18,8 @@ public class Game { private static final String GAMEOVER = "Game over. The winner is: "; public Game() { - MyBoard myBoard = new MyBoard(); - myBoard.setBasicGrids(); - MyShots enemyBoard = new MyShots(); - enemyBoard.setBasicGrids(); - - MyBoard myBoard2 = new MyBoard(); - myBoard2.setBasicGrids(); - MyShots enemyBoard2 = new MyShots(); - enemyBoard2.setBasicGrids(); - - this.player1 = new Player(myBoard, enemyBoard); - this.player2 = new Player(myBoard2, enemyBoard2); + this.player1 = new Player(new MyBoard(), new MyShots()); + this.player2 = new Player(new MyBoard(), new MyShots()); } public void run() { @@ -45,8 +35,8 @@ public void setUpShips() { public void startGame() { while (!countShipsPlayers(player1, player2)) { - new Engine().checkPlayerShot(scanner, player1, player2); - new Engine().checkPlayerShot(scanner, player2, player1); + new Engine(scanner).checkAndValidatePlayerShot(player1, player2); + new Engine(scanner).checkAndValidatePlayerShot(player2, player1); } } diff --git a/src/main/java/course_project/sea_battle/Main.java b/src/main/java/course_project/sea_battle/Main.java index 96d092fd..123db743 100644 --- a/src/main/java/course_project/sea_battle/Main.java +++ b/src/main/java/course_project/sea_battle/Main.java @@ -2,6 +2,6 @@ public class Main { public static void main(String[] args) { - new Game().run(); + new Game().start(); } } diff --git a/src/main/java/course_project/sea_battle/model/boards/Board.java b/src/main/java/course_project/sea_battle/boards/Board.java similarity index 84% rename from src/main/java/course_project/sea_battle/model/boards/Board.java rename to src/main/java/course_project/sea_battle/boards/Board.java index 963e3ed9..60b8e272 100644 --- a/src/main/java/course_project/sea_battle/model/boards/Board.java +++ b/src/main/java/course_project/sea_battle/boards/Board.java @@ -1,6 +1,6 @@ -package course_project.sea_battle.model.boards; +package course_project.sea_battle.boards; -abstract class Board { +public abstract class Board { protected int[][] board; diff --git a/src/main/java/course_project/sea_battle/model/boards/MyBoard.java b/src/main/java/course_project/sea_battle/boards/MyBoard.java similarity index 88% rename from src/main/java/course_project/sea_battle/model/boards/MyBoard.java rename to src/main/java/course_project/sea_battle/boards/MyBoard.java index 5cf2a8d1..836e0ae1 100644 --- a/src/main/java/course_project/sea_battle/model/boards/MyBoard.java +++ b/src/main/java/course_project/sea_battle/boards/MyBoard.java @@ -1,4 +1,4 @@ -package course_project.sea_battle.model.boards; +package course_project.sea_battle.boards; import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; diff --git a/src/main/java/course_project/sea_battle/boards/MyShots.java b/src/main/java/course_project/sea_battle/boards/MyShots.java new file mode 100644 index 00000000..b9e50f32 --- /dev/null +++ b/src/main/java/course_project/sea_battle/boards/MyShots.java @@ -0,0 +1,4 @@ +package course_project.sea_battle.boards; + +public class MyShots extends Board { +} diff --git a/src/main/java/course_project/sea_battle/gameProcess.png b/src/main/java/course_project/sea_battle/gameProcess.png new file mode 100644 index 0000000000000000000000000000000000000000..7423a675dade5589c085a4a535717afb431c25d7 GIT binary patch literal 24123 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 0; } public void setAlive(boolean alive) { @@ -33,11 +33,4 @@ public List getCoordinates() { return coordinates; } - @Override - public String toString() { - return "Ship{" + - "coordinates=" + coordinates + - '}'; - } - } diff --git a/src/main/java/course_project/sea_battle/model/boards/MyShots.java b/src/main/java/course_project/sea_battle/model/boards/MyShots.java deleted file mode 100644 index 8daef2d0..00000000 --- a/src/main/java/course_project/sea_battle/model/boards/MyShots.java +++ /dev/null @@ -1,4 +0,0 @@ -package course_project.sea_battle.model.boards; - -public class MyShots extends Board { -} diff --git a/src/main/java/course_project/sea_battle/service/Engine.java b/src/main/java/course_project/sea_battle/service/Engine.java index 221f7d64..a653f296 100644 --- a/src/main/java/course_project/sea_battle/service/Engine.java +++ b/src/main/java/course_project/sea_battle/service/Engine.java @@ -4,6 +4,7 @@ import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; import course_project.sea_battle.model.Shot; +import course_project.sea_battle.boards.Board; import java.util.*; import java.util.stream.Collectors; @@ -12,6 +13,7 @@ import static course_project.sea_battle.view.BoardPrinter.showBoards; public class Engine { + private final Scanner scanner; private int x; private int y; private boolean isGameOver = false; @@ -23,43 +25,47 @@ public class Engine { private static final String CHECKED = "Cell is checked. Make another shot!"; private static final String KILLALL = ", you destroyed all enemy ships. Congratulations!"; - public void checkPlayerShot(Scanner scanner, Player player1, Player player2) { + public Engine(Scanner scanner) { + this.scanner = scanner; + } + + public void checkAndValidatePlayerShot(Player player1, Player player2) { showBoards(player1); System.out.println(player1.getName() + MAKESHOT); - OUTER: - while (true) { + while (!isGameOver) { String input = scanner.nextLine(); if (!isValidInput(input)) continue; if (isShooted(player2)) continue; if (!checkCell(player2)) continue; - putOnMyBoard(player1); - putOnEnemyBoard(player2); - - switch (shot) { - case KILLED: - fillCellsAroundDestroyedShip(currentShip, player1, player2); - showBoards(player1); - if (isGameOver) { - System.out.println(player1.getName() + KILLALL); - bigSpace(); - return; - } else { - System.out.println(player1.getName() + MAKESHOT); - } - break; - case HIT: - showBoards(player1); - System.out.println(player1.getName() + MAKESHOT); - break; - case MISS: - showBoards(player1); - bigSpace(); - break OUTER; + putOnMyBoard(player1.getMyShots()); + putOnEnemyBoard(player2.getMyBoard()); + + if (!isGameContinue(player1, player2, shot)) break; + } + } + + public boolean isGameContinue(Player me, Player enemy, Shot shot) { + if (shot == Shot.KILLED) { + fillCellsAroundDestroyedShip(currentShip, me, enemy); + showBoards(me); + if (isGameOver) { + System.out.println(me.getName() + KILLALL); + bigSpace(); + } else { + System.out.println(me.getName() + MAKESHOT); } + } else if (shot == Shot.HIT) { + showBoards(me); + System.out.println(me.getName() + MAKESHOT); + } else if (shot == Shot.MISS) { + showBoards(me); + bigSpace(); + return false; } + return true; } public boolean isValidInput(String input) { @@ -74,7 +80,7 @@ public boolean isValidInput(String input) { } public boolean isShooted(Player enemy) { - if (enemy.getMyBoard().getBoard()[x][y] == 3 || enemy.getMyBoard().getBoard()[x][y] == 4) { + if (enemy.getMyBoard().getBoard()[x][y] == 3 || enemy.getMyBoard().getBoard()[x][y] == 2) { System.out.println(CHECKED); return true; } @@ -99,7 +105,6 @@ public void findOutHitOrKilled(Player enemy) { if (ship.getLives() == 0) { System.err.println("KILLED!"); shot = Shot.KILLED; - ship.setAlive(false); System.out.println(enemy.getName() + " has " + enemy.countShips() + " ship(s) left."); currentShip = ship; if (enemy.countShips() == 0) { @@ -114,24 +119,24 @@ public void findOutHitOrKilled(Player enemy) { } } - public void putOnMyBoard(Player player) { - int[][] tempBoard = player.getMyShots().getBoard(); + public void putOnMyBoard(Board board) { + int[][] tempBoard = board.getBoard(); if (shot == Shot.MISS) { tempBoard[x][y] = 2; } else { tempBoard[x][y] = 3; } - player.getMyShots().setBoard(tempBoard); + board.setBoard(tempBoard); } - public void putOnEnemyBoard(Player player) { - int[][] tempBoard = player.getMyBoard().getBoard(); + public void putOnEnemyBoard(Board board) { + int[][] tempBoard = board.getBoard(); if (shot == Shot.MISS) { tempBoard[x][y] = 2; } else { tempBoard[x][y] = 3; } - player.getMyBoard().setBoard(tempBoard); + board.setBoard(tempBoard); } public void fillCellsAroundDestroyedShip(Ship ship, Player me, Player enemy) { @@ -178,8 +183,8 @@ public void fillCellsAroundDestroyedShip(Ship ship, Player me, Player enemy) { .collect(Collectors.toSet()); for (Point point : filteredPointsAround) { - myShots[point.getX()][point.getY()] = 4; - enemyMainBoard[point.getX()][point.getY()] = 4; + myShots[point.getX()][point.getY()] = 2; + enemyMainBoard[point.getX()][point.getY()] = 2; } me.getMyShots().setBoard(myShots); diff --git a/src/main/java/course_project/sea_battle/service/InputReader.java b/src/main/java/course_project/sea_battle/service/InputReader.java index ebc33cb0..245fcd51 100644 --- a/src/main/java/course_project/sea_battle/service/InputReader.java +++ b/src/main/java/course_project/sea_battle/service/InputReader.java @@ -1,6 +1,6 @@ package course_project.sea_battle.service; -import course_project.sea_battle.model.boards.MyBoard; +import course_project.sea_battle.boards.MyBoard; import course_project.sea_battle.model.Point; import java.util.ArrayList; diff --git a/src/main/java/course_project/sea_battle/service/ShipPlacer.java b/src/main/java/course_project/sea_battle/service/ShipPlacer.java index faa871a3..3576a7fd 100644 --- a/src/main/java/course_project/sea_battle/service/ShipPlacer.java +++ b/src/main/java/course_project/sea_battle/service/ShipPlacer.java @@ -3,7 +3,7 @@ import course_project.sea_battle.model.Player; import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; -import course_project.sea_battle.model.boards.MyBoard; +import course_project.sea_battle.boards.MyBoard; import java.util.List; import java.util.Scanner; @@ -24,27 +24,9 @@ public void placeShip(Player player) { MyBoard board = player.getMyBoard(); showBoards(player); - for (int shipSize = 4; shipSize >= 1; shipSize--) { - for (int shipNumber = 0; shipNumber <= 4 - shipSize; shipNumber++) { - System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); - - inputReader.getAndValidateInput(shipSize, board); - List coordinates = inputReader.getValidCoordinates(); - - Ship ship = new Ship(coordinates); - board.placeShip(ship); - - System.out.println(PLACED); - player.getMyShips().add(ship); - showBoards(player); - } - } - -// You can uncomment this block of code instead above for() (lines: 28-42) to place only 2 ships for every player. - -// for (int shipSize = 3; shipSize > 1; shipSize--) { -// for (int shipNumber = 0; shipNumber < 1; shipNumber++) { -// System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 H] or [a8 v]"); +// for (int shipSize = 4; shipSize >= 1; shipSize--) { +// for (int shipNumber = 0; shipNumber <= 4 - shipSize; shipNumber++) { +// System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); // // inputReader.getAndValidateInput(shipSize, board); // List coordinates = inputReader.getValidCoordinates(); @@ -58,6 +40,24 @@ public void placeShip(Player player) { // } // } +// You can uncomment this block of code instead above for() (lines: 28-42) to place only 2 ships for every player. + + for (int shipSize = 3; shipSize > 1; shipSize--) { + for (int shipNumber = 0; shipNumber < 1; shipNumber++) { + System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 H] or [a8 v]"); + + inputReader.getAndValidateInput(shipSize, board); + List coordinates = inputReader.getValidCoordinates(); + + Ship ship = new Ship(coordinates); + board.placeShip(ship); + + System.out.println(PLACED); + player.getMyShips().add(ship); + showBoards(player); + } + } + bigSpace(); } diff --git a/src/main/java/course_project/sea_battle/view/BoardPrinter.java b/src/main/java/course_project/sea_battle/view/BoardPrinter.java index 98e1d03b..e451ef32 100644 --- a/src/main/java/course_project/sea_battle/view/BoardPrinter.java +++ b/src/main/java/course_project/sea_battle/view/BoardPrinter.java @@ -29,17 +29,15 @@ public static void showBoards(Player player) { System.out.printf(" %s", WAVE); break; case 1: - System.out.printf(" %s", "1"); - break; - case 3: - System.out.printf(" %s", HIT); + System.out.printf(" %s", "W"); break; case 2: - case 4: System.out.printf(" %s", MISS); break; + case 3: + System.out.printf(" %s", HIT); + break; default: - System.out.printf(" %s", "?"); } } else if (j < 12) { System.out.print("\t"); @@ -50,15 +48,13 @@ public static void showBoards(Player player) { case 0: System.out.printf(" %s", WAVE); break; - case 3: - System.out.printf(" %s", HIT); - break; case 2: - case 4: System.out.printf(" %s", MISS); break; + case 3: + System.out.printf(" %s", HIT); + break; default: - System.out.printf(" %s", "?"); } } } diff --git a/src/test/java/course_project/sea_battle/ModelTest.java b/src/test/java/course_project/sea_battle/ModelTest.java new file mode 100644 index 00000000..fcdc30b1 --- /dev/null +++ b/src/test/java/course_project/sea_battle/ModelTest.java @@ -0,0 +1,72 @@ +package course_project.sea_battle; + +import course_project.sea_battle.boards.MyBoard; +import course_project.sea_battle.boards.MyShots; +import course_project.sea_battle.model.Player; +import course_project.sea_battle.model.Point; +import course_project.sea_battle.model.Ship; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class ModelTest { + @Test + void testPoint() { + Point point1 = new Point(1, 2); + Point point2 = new Point(1, 2); + Point point3 = new Point(3, 3); + + assertEquals(1, point1.getX()); + assertEquals(2, point1.getY()); + assertEquals(point1, point2); + assertEquals(point1.hashCode(), point2.hashCode()); + assertNotEquals(point1, point3); + assertEquals("[1,2]", point1.toString()); + } + + @Test + void testShip() { + ArrayList shipCoordinates = new ArrayList<>(); + shipCoordinates.add(new Point(0, 0)); + shipCoordinates.add(new Point(0, 1)); + + Ship ship = new Ship(shipCoordinates); + + assertEquals(shipCoordinates, ship.getCoordinates()); + assertEquals(2, ship.getCoordinates().size()); + + assertTrue(ship.isAlive()); + assertEquals(2, ship.getLives()); + ship.setLives(0); + assertFalse(ship.isAlive()); + } + + @Test + void testBoard() { + int[][] myBoardTest = new int[10][10]; + + MyBoard myBoard = new MyBoard(); + MyShots myShots = new MyShots(); + + Player player = new Player(myBoard, myShots); + assertEquals(0, player.getMyShips().size()); + + List coordinates = new ArrayList<>(); + coordinates.add(new Point(0, 0)); + coordinates.add(new Point(0, 1)); + + Ship ship = new Ship(coordinates); + player.getMyBoard().placeShip(ship); + player.getMyShips().add(ship); + + assertEquals(1, player.getMyShips().size()); + + myBoardTest[0][0] = 1; + myBoardTest[0][1] = 1; + assertArrayEquals(myBoardTest, myBoard.getBoard()); + } + +} \ No newline at end of file diff --git a/src/test/java/course_project/sea_battle/ViewTest.java b/src/test/java/course_project/sea_battle/ViewTest.java new file mode 100644 index 00000000..5f2b9060 --- /dev/null +++ b/src/test/java/course_project/sea_battle/ViewTest.java @@ -0,0 +1,111 @@ +package course_project.sea_battle; + +import base.UnitBase; +import course_project.sea_battle.boards.MyBoard; +import course_project.sea_battle.boards.MyShots; +import course_project.sea_battle.model.Player; +import course_project.sea_battle.model.Point; +import course_project.sea_battle.model.Ship; +import course_project.sea_battle.model.Shot; +import course_project.sea_battle.service.Engine; +import course_project.sea_battle.service.ShipPlacer; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.*; + +import static course_project.sea_battle.view.BoardPrinter.showBoards; + +public class ViewTest extends UnitBase { + + private static final String CYAN = "\u001B[36m"; + private static final String RESET = "\u001B[0m"; + private static final String GREEN = "\u001B[32m"; + private static final String RED = "\u001B[31m"; + + private static final String MISS = GREEN + "0" + RESET; + private static final String HIT = RED + "X" + RESET; + private static final String WAVE = CYAN + "~" + RESET; + + private Shot shot; + + @Test + void testBoardPrinterMyBoard() { + MyBoard myBoard = new MyBoard(); + MyShots myShots = new MyShots(); + Player player1 = new Player(myBoard, myShots); + + Ship ship1 = new Ship(Arrays.asList(new Point(0, 1))); + myBoard.placeShip(ship1); + + showBoards(player1); + String expected1 = + " 1 ~ W ~ ~ ~ ~ ~ ~ ~ ~\t\t 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n"; + String expected2 = + " 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n"; ; + assertEquals(expected1.trim(), getOutputLines()[3].replace(WAVE,"~").trim()); + assertEquals(expected2.trim(), getOutputLines()[4].replace(WAVE,"~").trim()); + + + } + + @Test + void testBoardPrinterMyShotsIfMissed() { + + MyBoard myBoard2 = new MyBoard(); + MyShots myShots2 = new MyShots(); + Player player2 = new Player(myBoard2, myShots2); + + shot = Shot.KILLED; + new Engine(new Scanner("b1")).putOnEnemyBoard(player2.getMyBoard()); + showBoards(player2); + String expected2 = + " 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 1 0 ~ ~ ~ ~ ~ ~ ~ ~ ~\n"; + assertEquals(expected2.trim(), getOutputLines()[3] + .replace(WAVE, "~") + .replace(MISS, "0") + .replace(HIT, "X").trim()); + } + + @Test + void testUserShipPlacer() { + + MyBoard myBoard = new MyBoard(); + MyShots myShots = new MyShots(); + Player player = new Player(myBoard, myShots); + +// Ship ship = new Ship(Arrays.asList(new Point(0, 1))); +// myBoard.placeShip(ship); + + String input = "H1 hor\n" + + "A1 h\n"; + setInput(input); + +// PlayingField field = new PlayingField(); + ShipPlacer placer = new ShipPlacer(new Scanner(input)); + + placer.placeShip(player); +// myBoard.placeShip(); + + int actualSize = player.getMyShips().size(); + + assertEquals(10, actualSize); + } + + +// @Test +// void testUserShotInputReader() { +// String input = "A11\n" + +// "A10"; +// setInput(input); +// +// Coordinate expected = new Coordinate(9, 0); +// +// UserShotInputReader reader = new UserShotInputReader(new Scanner(System.in)); +// Coordinate pointFromReader = reader.getPointFromInput(); +// +// assertEquals(expected, pointFromReader); +// } +} From 36366f9b59fe14cc6b1ea3702e07e0d6fdb962e3 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Tue, 21 Sep 2021 17:21:13 +0300 Subject: [PATCH 24/33] Finished. --- .../java/course_project/sea_battle/Game.java | 68 ++++-- .../{gameProcess.png => gamePlay.png} | Bin .../sea_battle/model/Player.java | 8 +- .../course_project/sea_battle/model/Ship.java | 6 - .../sea_battle/service/NameSetter.java | 21 +- .../sea_battle/service/ShipPlacer.java | 62 ++--- .../{view => service/inputs}/BigSpace.java | 12 +- .../service/inputs/InputReader.java | 15 ++ .../InputShipReader.java} | 31 ++- .../InputShooterReader.java} | 107 ++++----- .../course_project/sea_battle/GameTest.java | 213 ++++++++++++++++++ .../course_project/sea_battle/ViewTest.java | 178 +++++++++------ 12 files changed, 503 insertions(+), 218 deletions(-) rename src/main/java/course_project/sea_battle/{gameProcess.png => gamePlay.png} (100%) rename src/main/java/course_project/sea_battle/{view => service/inputs}/BigSpace.java (57%) create mode 100644 src/main/java/course_project/sea_battle/service/inputs/InputReader.java rename src/main/java/course_project/sea_battle/service/{InputReader.java => inputs/InputShipReader.java} (88%) rename src/main/java/course_project/sea_battle/service/{Engine.java => inputs/InputShooterReader.java} (71%) create mode 100644 src/test/java/course_project/sea_battle/GameTest.java diff --git a/src/main/java/course_project/sea_battle/Game.java b/src/main/java/course_project/sea_battle/Game.java index 73ef3c26..5a22227c 100644 --- a/src/main/java/course_project/sea_battle/Game.java +++ b/src/main/java/course_project/sea_battle/Game.java @@ -3,55 +3,77 @@ import course_project.sea_battle.boards.MyBoard; import course_project.sea_battle.boards.MyShots; import course_project.sea_battle.model.Player; -import course_project.sea_battle.service.Engine; +import course_project.sea_battle.model.Ship; +import course_project.sea_battle.service.inputs.InputShipReader; +import course_project.sea_battle.service.NameSetter; +import course_project.sea_battle.service.inputs.InputShooterReader; import course_project.sea_battle.service.ShipPlacer; import java.util.Scanner; -import static course_project.sea_battle.service.NameSetter.setNames; - -public class Game extends Thread{ - private final Scanner scanner = new Scanner(System.in); - private final Player player1; - private final Player player2; +public class Game extends Thread { private static final String TIE = "Game over. It's a TIE!"; private static final String GAMEOVER = "Game over. The winner is: "; + private final Scanner scanner = new Scanner(System.in); + private final InputShipReader inputShipReader = new InputShipReader(scanner); + + private Player player1; + private Player player2; + public Game() { this.player1 = new Player(new MyBoard(), new MyShots()); this.player2 = new Player(new MyBoard(), new MyShots()); } + @Override public void run() { - setNames(player1, player2); + setUpNames(); setUpShips(); startGame(); + defineWinner(); + } + + public void setUpNames() { + new NameSetter(inputShipReader).setNames(player1, player2); } public void setUpShips() { - new ShipPlacer(scanner).placeShip(player1); - new ShipPlacer(scanner).placeShip(player2); + new ShipPlacer(inputShipReader).placeShip(player1); + new ShipPlacer(inputShipReader).placeShip(player2); } public void startGame() { - while (!countShipsPlayers(player1, player2)) { - new Engine(scanner).checkAndValidatePlayerShot(player1, player2); - new Engine(scanner).checkAndValidatePlayerShot(player2, player1); + while (bothPlayersHaveShips(player1, player2)) { + new InputShooterReader(scanner).checkAndValidatePlayerShot(player1, player2); + new InputShooterReader(scanner).checkAndValidatePlayerShot(player2, player1); } } - public boolean countShipsPlayers(Player player1, Player player2) { - long p1ships = player1.getMyShips().stream().filter(e -> e.isAlive()).count(); - long p2ships = player2.getMyShips().stream().filter(e -> e.isAlive()).count(); + public boolean bothPlayersHaveShips(Player player1, Player player2) { + return countShips(player1) > 0 && countShips(player2) > 0; + } + + public long countShips(Player player) { + return player.getMyShips().stream().filter(Ship::isAlive).count(); + } - if (p1ships == 0 && p2ships == 0) { - System.err.println(TIE); - } else if (p1ships == 0) { - System.err.println(GAMEOVER + player2.getName() + "!"); - } else if (p2ships == 0) { - System.err.println(GAMEOVER + player1.getName() + "!"); + public void defineWinner() { + if (countShips(player1) == 0 && countShips(player2) == 0) { + System.out.println(TIE); + } else if (countShips(player1) == 0) { + System.out.println(GAMEOVER + player2.getName() + "!"); + } else if (countShips(player2) == 0) { + System.out.println(GAMEOVER + player1.getName() + "!"); } - return p1ships < 1 || p2ships < 1; + } + + public Player getPlayer1() { + return player1; + } + + public Player getPlayer2() { + return player2; } } diff --git a/src/main/java/course_project/sea_battle/gameProcess.png b/src/main/java/course_project/sea_battle/gamePlay.png similarity index 100% rename from src/main/java/course_project/sea_battle/gameProcess.png rename to src/main/java/course_project/sea_battle/gamePlay.png diff --git a/src/main/java/course_project/sea_battle/model/Player.java b/src/main/java/course_project/sea_battle/model/Player.java index 7397e939..39385f22 100644 --- a/src/main/java/course_project/sea_battle/model/Player.java +++ b/src/main/java/course_project/sea_battle/model/Player.java @@ -19,6 +19,10 @@ public Player(MyBoard myBoard, MyShots enemyBoard) { myShots.setBasicGrids(); } + public long countShips() { + return getMyShips().stream().filter(Ship::isAlive).count(); + } + public String getName() { return name; } @@ -39,8 +43,4 @@ public MyShots getMyShots() { return myShots; } - public long countShips() { - return getMyShips().stream().filter(e -> e.isAlive()).count(); - } - } diff --git a/src/main/java/course_project/sea_battle/model/Ship.java b/src/main/java/course_project/sea_battle/model/Ship.java index b216e3be..36704528 100644 --- a/src/main/java/course_project/sea_battle/model/Ship.java +++ b/src/main/java/course_project/sea_battle/model/Ship.java @@ -5,12 +5,10 @@ public class Ship { private final List coordinates; private int lives; - private boolean isAlive; public Ship(List coordinates) { this.coordinates = coordinates; this.lives = coordinates.size(); - this.isAlive = true; } public int getLives() { @@ -25,10 +23,6 @@ public boolean isAlive() { return lives > 0; } - public void setAlive(boolean alive) { - this.isAlive = alive; - } - public List getCoordinates() { return coordinates; } diff --git a/src/main/java/course_project/sea_battle/service/NameSetter.java b/src/main/java/course_project/sea_battle/service/NameSetter.java index 8d393194..4ea3232e 100644 --- a/src/main/java/course_project/sea_battle/service/NameSetter.java +++ b/src/main/java/course_project/sea_battle/service/NameSetter.java @@ -1,28 +1,29 @@ package course_project.sea_battle.service; import course_project.sea_battle.model.Player; - -import java.util.Scanner; +import course_project.sea_battle.service.inputs.InputShipReader; public class NameSetter { + private final InputShipReader inputShipReader; - private NameSetter() { + public NameSetter(InputShipReader inputShipReader) { + this.inputShipReader = inputShipReader; } - public static void setNames(Player player1, Player player2){ - Scanner scanner = new Scanner(System.in); + public void setNames(Player player1, Player player2) { - System.out.println("Player 1, please, input your name"); - String player1Name = scanner.nextLine(); + System.out.println("Player 1, please, input your name:"); + String player1Name = inputShipReader.readLine(); player1.setName(player1Name); System.out.println("Hello, " + player1Name + "!"); - System.out.println("Player 2, please, input your name"); - String player2Name = scanner.nextLine(); + System.out.println("Player 2, please, input your name:"); + String player2Name = inputShipReader.readLine(); player2.setName(player2Name); System.out.println("Hello, " + player2Name + "!"); System.out.println("Press ENTER to start the game"); - String str = scanner.nextLine(); + inputShipReader.readLine(); } + } diff --git a/src/main/java/course_project/sea_battle/service/ShipPlacer.java b/src/main/java/course_project/sea_battle/service/ShipPlacer.java index 3576a7fd..066d9065 100644 --- a/src/main/java/course_project/sea_battle/service/ShipPlacer.java +++ b/src/main/java/course_project/sea_battle/service/ShipPlacer.java @@ -1,22 +1,24 @@ package course_project.sea_battle.service; +import course_project.sea_battle.boards.MyBoard; import course_project.sea_battle.model.Player; import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; -import course_project.sea_battle.boards.MyBoard; +import course_project.sea_battle.service.inputs.InputShipReader; +import course_project.sea_battle.service.inputs.BigSpace; import java.util.List; -import java.util.Scanner; -import static course_project.sea_battle.view.BigSpace.bigSpace; import static course_project.sea_battle.view.BoardPrinter.showBoards; public class ShipPlacer { - private final InputReader inputReader; + private final InputShipReader inputShipReader; private static final String PLACED = "Ship is placed!"; + private final BigSpace bigSpace; - public ShipPlacer(Scanner scanner) { - inputReader = new InputReader(scanner); + public ShipPlacer(InputShipReader inputShipReader) { + this.inputShipReader = inputShipReader; + this.bigSpace = new BigSpace(inputShipReader.getScanner()); } public void placeShip(Player player) { @@ -24,12 +26,30 @@ public void placeShip(Player player) { MyBoard board = player.getMyBoard(); showBoards(player); -// for (int shipSize = 4; shipSize >= 1; shipSize--) { -// for (int shipNumber = 0; shipNumber <= 4 - shipSize; shipNumber++) { -// System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); + for (int shipSize = 4; shipSize >= 1; shipSize--) { + for (int shipNumber = 0; shipNumber <= 4 - shipSize; shipNumber++) { + System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); + + inputShipReader.getAndValidateInput(shipSize, board); + List coordinates = inputShipReader.getValidCoordinates(); + + Ship ship = new Ship(coordinates); + board.placeShip(ship); + player.getMyShips().add(ship); + + System.out.println(PLACED); + showBoards(player); + } + } + +// You can uncomment this block of code instead above for() (lines: 28-42) to place only 2 ships for every player. + +// for (int shipSize = 3; shipSize > 2; shipSize--) { +// for (int shipNumber = 0; shipNumber < 1; shipNumber++) { +// System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 H] or [a8 v]"); // -// inputReader.getAndValidateInput(shipSize, board); -// List coordinates = inputReader.getValidCoordinates(); +// inputShipReader.getAndValidateInput(shipSize, board); +// List coordinates = inputShipReader.getValidCoordinates(); // // Ship ship = new Ship(coordinates); // board.placeShip(ship); @@ -40,25 +60,7 @@ public void placeShip(Player player) { // } // } -// You can uncomment this block of code instead above for() (lines: 28-42) to place only 2 ships for every player. - - for (int shipSize = 3; shipSize > 1; shipSize--) { - for (int shipNumber = 0; shipNumber < 1; shipNumber++) { - System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 H] or [a8 v]"); - - inputReader.getAndValidateInput(shipSize, board); - List coordinates = inputReader.getValidCoordinates(); - - Ship ship = new Ship(coordinates); - board.placeShip(ship); - - System.out.println(PLACED); - player.getMyShips().add(ship); - showBoards(player); - } - } - - bigSpace(); + bigSpace.printBigSpace(); } } diff --git a/src/main/java/course_project/sea_battle/view/BigSpace.java b/src/main/java/course_project/sea_battle/service/inputs/BigSpace.java similarity index 57% rename from src/main/java/course_project/sea_battle/view/BigSpace.java rename to src/main/java/course_project/sea_battle/service/inputs/BigSpace.java index 5d1a8d6b..1df6e42d 100644 --- a/src/main/java/course_project/sea_battle/view/BigSpace.java +++ b/src/main/java/course_project/sea_battle/service/inputs/BigSpace.java @@ -1,17 +1,19 @@ -package course_project.sea_battle.view; +package course_project.sea_battle.service.inputs; import java.util.Scanner; import java.util.stream.Stream; -public class BigSpace { +public class BigSpace extends InputReader { + private static final String FINISH = "Press ENTER to finish your move"; - private BigSpace() { + public BigSpace(Scanner scanner) { + this.scanner = scanner; } - public static void bigSpace() { + public void printBigSpace() { System.out.println(FINISH); - String str = new Scanner(System.in).nextLine(); + readLine(); Stream.generate(() -> ".") .limit(5) diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputReader.java new file mode 100644 index 00000000..f5961288 --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/inputs/InputReader.java @@ -0,0 +1,15 @@ +package course_project.sea_battle.service.inputs; + +import java.util.Scanner; + +public abstract class InputReader { + protected Scanner scanner; + + public String readLine() { + return scanner.nextLine(); + } + + public Scanner getScanner() { + return scanner; + } +} diff --git a/src/main/java/course_project/sea_battle/service/InputReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java similarity index 88% rename from src/main/java/course_project/sea_battle/service/InputReader.java rename to src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java index 245fcd51..783a0c64 100644 --- a/src/main/java/course_project/sea_battle/service/InputReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java @@ -1,4 +1,4 @@ -package course_project.sea_battle.service; +package course_project.sea_battle.service.inputs; import course_project.sea_battle.boards.MyBoard; import course_project.sea_battle.model.Point; @@ -8,10 +8,10 @@ import java.util.List; import java.util.Scanner; -public class InputReader { - private final Scanner scanner; +public class InputShipReader extends InputReader{ private int x; private int y; + private String position; private List coordinates; @@ -19,15 +19,16 @@ public class InputReader { private static final String OUTOFBOARD = "Impossible to place ship here because it is out of board!"; private static final String SHIPSCROSS = "Impossible to place ship here because ship crosses with another one!"; - public InputReader(Scanner scanner) { + public InputShipReader(Scanner scanner) { this.scanner = scanner; } public void getAndValidateInput(int shipSize, MyBoard board) { while (true) { - String input = scanner.nextLine(); + String input = readLine(); + if (!isValidInput(input)) continue; - Point topLeftPoint = getTopLeftPoint(); + Point topLeftPoint = new Point(x, y); if (!isShipWithinBoard(shipSize)) continue; coordinates = findCoordinates(shipSize, topLeftPoint); if (shipsDoNotCross(board, shipSize)) break; @@ -47,11 +48,7 @@ public boolean isValidInput(String input) { } } - public Point getTopLeftPoint() { - return new Point(x, y); - } - - private boolean isShipWithinBoard(int shipSize) { + public boolean isShipWithinBoard(int shipSize) { Point rightBottomPoint = position.equalsIgnoreCase("v") ? new Point(x + shipSize, y) : new Point(x, y + shipSize); @@ -128,4 +125,16 @@ public List getValidCoordinates() { return coordinates; } + public void setPosition(String position) { + this.position = position; + } + + public void setX(int x) { + this.x = x; + } + + public void setY(int y) { + this.y = y; + } + } diff --git a/src/main/java/course_project/sea_battle/service/Engine.java b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java similarity index 71% rename from src/main/java/course_project/sea_battle/service/Engine.java rename to src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java index a653f296..d27043fe 100644 --- a/src/main/java/course_project/sea_battle/service/Engine.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java @@ -1,73 +1,48 @@ -package course_project.sea_battle.service; +package course_project.sea_battle.service.inputs; -import course_project.sea_battle.model.Player; -import course_project.sea_battle.model.Point; -import course_project.sea_battle.model.Ship; -import course_project.sea_battle.model.Shot; import course_project.sea_battle.boards.Board; +import course_project.sea_battle.model.*; import java.util.*; import java.util.stream.Collectors; -import static course_project.sea_battle.view.BigSpace.bigSpace; import static course_project.sea_battle.view.BoardPrinter.showBoards; -public class Engine { - private final Scanner scanner; +public class InputShooterReader extends InputReader { private int x; private int y; - private boolean isGameOver = false; private Shot shot; private Ship currentShip; + private final BigSpace bigSpace; private static final String MAKESHOT = ", make your shot in format: [A6] or [b1]"; private static final String INPUTERROR = "Input should be like this: [A7] or [b2]. Try again!"; private static final String CHECKED = "Cell is checked. Make another shot!"; private static final String KILLALL = ", you destroyed all enemy ships. Congratulations!"; - public Engine(Scanner scanner) { + public InputShooterReader(Scanner scanner) { this.scanner = scanner; + this.bigSpace = new BigSpace(scanner); } public void checkAndValidatePlayerShot(Player player1, Player player2) { showBoards(player1); System.out.println(player1.getName() + MAKESHOT); - while (!isGameOver) { - String input = scanner.nextLine(); + while (true) { + String input = readLine(); if (!isValidInput(input)) continue; if (isShooted(player2)) continue; - if (!checkCell(player2)) continue; + getShotResult(player2); - putOnMyBoard(player1.getMyShots()); - putOnEnemyBoard(player2.getMyBoard()); + putOnBoard(player1.getMyShots(), new Point(x, y), shot); + putOnBoard(player2.getMyBoard(), new Point(x, y), shot); if (!isGameContinue(player1, player2, shot)) break; } } - public boolean isGameContinue(Player me, Player enemy, Shot shot) { - if (shot == Shot.KILLED) { - fillCellsAroundDestroyedShip(currentShip, me, enemy); - showBoards(me); - if (isGameOver) { - System.out.println(me.getName() + KILLALL); - bigSpace(); - } else { - System.out.println(me.getName() + MAKESHOT); - } - } else if (shot == Shot.HIT) { - showBoards(me); - System.out.println(me.getName() + MAKESHOT); - } else if (shot == Shot.MISS) { - showBoards(me); - bigSpace(); - return false; - } - return true; - } - public boolean isValidInput(String input) { if (input.matches("[a-jA-J]([1-9]|10)")) { y = Character.getNumericValue(input.charAt(0)) - 10; @@ -87,15 +62,12 @@ public boolean isShooted(Player enemy) { return false; } - public boolean checkCell(Player enemy) { - + public void getShotResult(Player enemy) { if (enemy.getMyBoard().getBoard()[x][y] == 1) { findOutHitOrKilled(enemy); } else { shot = Shot.MISS; - System.err.println("MISS"); } - return true; } public void findOutHitOrKilled(Player enemy) { @@ -103,47 +75,30 @@ public void findOutHitOrKilled(Player enemy) { if (ship.getCoordinates().contains(new Point(x, y))) { ship.setLives(ship.getLives() - 1); if (ship.getLives() == 0) { - System.err.println("KILLED!"); shot = Shot.KILLED; - System.out.println(enemy.getName() + " has " + enemy.countShips() + " ship(s) left."); currentShip = ship; - if (enemy.countShips() == 0) { - isGameOver = true; - } } else { shot = Shot.HIT; - System.err.println("HIT!"); } - break; } } } - public void putOnMyBoard(Board board) { + public static void putOnBoard(Board board, Point shotPoint, Shot shot) { int[][] tempBoard = board.getBoard(); if (shot == Shot.MISS) { - tempBoard[x][y] = 2; + tempBoard[shotPoint.getX()][shotPoint.getY()] = 2; } else { - tempBoard[x][y] = 3; + tempBoard[shotPoint.getX()][shotPoint.getY()] = 3; } board.setBoard(tempBoard); } - public void putOnEnemyBoard(Board board) { - int[][] tempBoard = board.getBoard(); - if (shot == Shot.MISS) { - tempBoard[x][y] = 2; - } else { - tempBoard[x][y] = 3; - } - board.setBoard(tempBoard); - } public void fillCellsAroundDestroyedShip(Ship ship, Player me, Player enemy) { List coordinatesOfTheShip = ship.getCoordinates(); Set coordinatesAroundTheShip = new HashSet<>(); - for (Point point : coordinatesOfTheShip) { int x1 = point.getX(); int y1 = point.getY(); @@ -174,7 +129,6 @@ public void fillCellsAroundDestroyedShip(Ship ship, Player me, Player enemy) { } } - int[][] myShots = me.getMyShots().getBoard(); int[][] enemyMainBoard = enemy.getMyBoard().getBoard(); Set filteredPointsAround = coordinatesAroundTheShip.stream() @@ -183,12 +137,35 @@ public void fillCellsAroundDestroyedShip(Ship ship, Player me, Player enemy) { .collect(Collectors.toSet()); for (Point point : filteredPointsAround) { - myShots[point.getX()][point.getY()] = 2; - enemyMainBoard[point.getX()][point.getY()] = 2; + putOnBoard(me.getMyShots(), point, Shot.MISS); + putOnBoard(enemy.getMyBoard(), point, Shot.MISS); } + } - me.getMyShots().setBoard(myShots); - enemy.getMyBoard().setBoard(enemyMainBoard); + public boolean isGameContinue(Player me, Player enemy, Shot shot) { + if (shot == Shot.KILLED) { + System.err.println("KILLED!"); + System.out.println(enemy.getName() + " has " + enemy.countShips() + " ship(s) left."); + fillCellsAroundDestroyedShip(currentShip, me, enemy); + showBoards(me); + if (enemy.countShips() == 0) { + System.out.println(me.getName() + KILLALL); + bigSpace.printBigSpace(); + return false; + } else { + System.out.println(me.getName() + MAKESHOT); + } + } else if (shot == Shot.HIT) { + System.err.println("HIT!"); + showBoards(me); + System.out.println(me.getName() + MAKESHOT); + } else if (shot == Shot.MISS) { + System.err.println("MISS!"); + showBoards(me); + bigSpace.printBigSpace(); + return false; + } + return true; } } diff --git a/src/test/java/course_project/sea_battle/GameTest.java b/src/test/java/course_project/sea_battle/GameTest.java new file mode 100644 index 00000000..e06212cd --- /dev/null +++ b/src/test/java/course_project/sea_battle/GameTest.java @@ -0,0 +1,213 @@ +package course_project.sea_battle; + +import base.UnitBase; +import course_project.sea_battle.model.Player; +import course_project.sea_battle.model.Point; +import course_project.sea_battle.model.Ship; +import course_project.sea_battle.service.inputs.InputShipReader; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.*; + +class GameTest extends UnitBase { + + private static final String INPUTSHIPERROR = "Input should be like this: [A7 h] or [B2 h]. Try again!"; + private static final String OUTOFBOARD = "Impossible to place ship here because it is out of board!"; + private static final String TIE = "Game over. It's a TIE!"; + private static final String GAMEOVER = "Game over. The winner is: "; + + @Test + void testNameSetter() { + String input = "Tom\n" + + "Vera\n" + + "\n"; + setInput(input); + + Game game = new Game(); + game.setUpNames(); + + Player player1 = game.getPlayer1(); + Player player2 = game.getPlayer2(); + + assertEquals("Tom", player1.getName()); + assertEquals("Vera", player2.getName()); + } + + @Test + void testValidCoordsShipPlacing() { + String input = "a1 h\n" + + "a3 h\n" + + "a5 h\n" + + "a7 h\n" + + "a9 h\n" + + "f1 h\n" + + "f3 h\n" + + "f5 h\n" + + "f7 h\n" + + "f9 h\n" + + "\n" + + "a1 h\n" + + "a3 h\n" + + "a5 h\n" + + "a7 h\n" + + "a9 h\n" + + "f1 h\n" + + "f3 h\n" + + "f5 h\n" + + "f7 h\n" + + "f9 h\n" + + "\n"; + setInput(input); + + Game game = new Game(); + game.setUpShips(); + + long numOfShips1 = game.getPlayer1().countShips(); + long numOfShips2 = game.getPlayer2().countShips(); + + assertEquals(10, numOfShips1); + assertEquals(10, numOfShips2); + } + + @Test + void testOnlyValidCoordsShipPlacing() { + String input = "a1 h\n" + + "a2 h\n" + + "a\n" + + "a6v\n" + + "a10 v\n" + + "a3 h\n" + + "a5 h\n" + + "a7 h\n" + + "a9 h\n" + + "f1 h\n" + + "f3 h\n" + + "f5 h\n" + + "f7 h\n" + + "f9 h\n" + + "\n" + + "a1 h\n" + + "a3 h\n" + + "a5 h\n" + + "a7 h\n" + + "a9 h\n" + + "f1 h\n" + + "f3 h\n" + + "f5 h\n" + + "f7 h\n" + + "f9 h\n" + + "\n"; + setInput(input); + + Game game = new Game(); + game.setUpShips(); + + long numOfShips1 = game.getPlayer1().countShips(); + long numOfShips2 = game.getPlayer2().countShips(); + + assertEquals(10, numOfShips1); + assertEquals(10, numOfShips2); + } + + @ParameterizedTest + @ValueSource(strings = {"a6", "d1 g", "d1 v 1", ""}) + void givenInvalidShipCoords_whenSetUpShips_ThenError(String input) { + setInput(input); + new InputShipReader(new Scanner(System.in)).isValidInput(input); + assertEquals(INPUTSHIPERROR, getOutput()); + } + + @Test + void givenOutOfBoardShipCoords_whenSetUpShips_ThenError() { + InputShipReader inputShipReader = new InputShipReader(new Scanner(System.in)); + inputShipReader.setX(7); + inputShipReader.setY(0); + inputShipReader.setPosition("v"); + + assertTrue(inputShipReader.isShipWithinBoard(3)); + assertFalse(inputShipReader.isShipWithinBoard(4)); + assertEquals(OUTOFBOARD, getOutput()); + } + + @Test + void testShooter() { + String input = "a1\n" + + "b1\n" + + "\n" + + "a10\n" + + "\n"; + setInput(input); + + List coordinates = new ArrayList<>(); + coordinates.add(new Point(0, 0)); + coordinates.add(new Point(0, 1)); + Ship ship = new Ship(coordinates); + + List coordinates2 = new ArrayList<>(); + coordinates.add(new Point(9, 9)); + Ship ship2 = new Ship(coordinates2); + + Game game = new Game(); + game.getPlayer1().getMyShips().add(ship); + game.getPlayer2().getMyShips().add(ship2); + + game.getPlayer1().getMyBoard().placeShip(ship); + game.getPlayer2().getMyBoard().placeShip(ship2); + + int numOfPlayer1AllShips = game.getPlayer1().getMyShips().size(); + int numOfPlayer2AllShips = game.getPlayer1().getMyShips().size(); + + assertEquals(1, numOfPlayer1AllShips); + assertEquals(1, numOfPlayer2AllShips); + + game.startGame(); + + long numOfPlayer1AliveShips = game.getPlayer1().getMyShips().stream() + .filter(Ship::isAlive) + .count(); + long numOfPlayer2AliveShips = game.getPlayer2().getMyShips().stream() + .filter(Ship::isAlive) + .count(); + + assertEquals(1, numOfPlayer1AliveShips); + assertEquals(0, numOfPlayer2AliveShips); + } + + @Test + void testDefineWinner() { + Game game = new Game(); + Player player1 = game.getPlayer1(); + Player player2 = game.getPlayer2(); + player1.setName("Tom"); + player2.setName("Vera"); + + Ship ship = new Ship(Arrays.asList(new Point(1, 1))); + List tomShips = game.getPlayer1().getMyShips(); + tomShips.add(ship); + + game.defineWinner(); + + assertEquals(GAMEOVER + "Tom!", getOutput()); + removeFromOutput(GAMEOVER + "Tom!"); + + List veraShips = game.getPlayer2().getMyShips(); + veraShips.add(ship); + tomShips.remove(0); + + game.defineWinner(); + assertEquals(GAMEOVER + "Vera!", getOutput()); + removeFromOutput(GAMEOVER + "Vera!"); + + veraShips.remove(0); + game.defineWinner(); + assertEquals(TIE, getOutput()); + } + +} \ No newline at end of file diff --git a/src/test/java/course_project/sea_battle/ViewTest.java b/src/test/java/course_project/sea_battle/ViewTest.java index 5f2b9060..4f07f3f0 100644 --- a/src/test/java/course_project/sea_battle/ViewTest.java +++ b/src/test/java/course_project/sea_battle/ViewTest.java @@ -7,18 +7,17 @@ import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; import course_project.sea_battle.model.Shot; -import course_project.sea_battle.service.Engine; -import course_project.sea_battle.service.ShipPlacer; +import course_project.sea_battle.service.inputs.BigSpace; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Scanner; -import static org.junit.jupiter.api.Assertions.*; - +import static course_project.sea_battle.service.inputs.InputShooterReader.putOnBoard; import static course_project.sea_battle.view.BoardPrinter.showBoards; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class ViewTest extends UnitBase { +class ViewTest extends UnitBase { private static final String CYAN = "\u001B[36m"; private static final String RESET = "\u001B[0m"; @@ -29,83 +28,134 @@ public class ViewTest extends UnitBase { private static final String HIT = RED + "X" + RESET; private static final String WAVE = CYAN + "~" + RESET; - private Shot shot; + MyBoard myBoard; + MyShots myShots; + Player player1; @Test - void testBoardPrinterMyBoard() { - MyBoard myBoard = new MyBoard(); - MyShots myShots = new MyShots(); - Player player1 = new Player(myBoard, myShots); - - Ship ship1 = new Ship(Arrays.asList(new Point(0, 1))); - myBoard.placeShip(ship1); + void testBigSpacePrinter() { + String input = "\n"; + setInput(input); - showBoards(player1); - String expected1 = - " 1 ~ W ~ ~ ~ ~ ~ ~ ~ ~\t\t 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n"; - String expected2 = - " 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n"; ; - assertEquals(expected1.trim(), getOutputLines()[3].replace(WAVE,"~").trim()); - assertEquals(expected2.trim(), getOutputLines()[4].replace(WAVE,"~").trim()); + new BigSpace(new Scanner(System.in)).printBigSpace(); + String expected = "Press ENTER to finish your move\n" + + ".\n" + + ".\n" + + ".\n" + + ".\n" + + "."; + assertEquals(expected, getOutput().replaceAll("\r", "")); + } + @Test + void testBoardPrinterEmptyBoard() { + createPlayers(); + player1.setName("Tom"); + showBoards(player1); + String expected = "MY BOARD (Tom) vs ENEMY BOARD\n" + "\n" + + "\t A B C D E F G H I J \t\t\t A B C D E F G H I J \n" + + " 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 3 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 3 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 5 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 5 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 6 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 6 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 8 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 8 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 9 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 9 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 10 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 10 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~"; + + assertEquals(expected, getOutput().replace(WAVE, "~").replaceAll("\r", "")); } @Test - void testBoardPrinterMyShotsIfMissed() { - - MyBoard myBoard2 = new MyBoard(); - MyShots myShots2 = new MyShots(); - Player player2 = new Player(myBoard2, myShots2); - - shot = Shot.KILLED; - new Engine(new Scanner("b1")).putOnEnemyBoard(player2.getMyBoard()); - showBoards(player2); - String expected2 = - " 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 1 0 ~ ~ ~ ~ ~ ~ ~ ~ ~\n"; - assertEquals(expected2.trim(), getOutputLines()[3] - .replace(WAVE, "~") - .replace(MISS, "0") - .replace(HIT, "X").trim()); + void testBoardPrinterShipPlacer() { + createPlayers(); + + Ship ship1 = new Ship(Arrays.asList(new Point(0, 1), new Point(1, 1))); + myBoard.placeShip(ship1); + + showBoards(player1); + String expected = "MY BOARD (null) vs ENEMY BOARD\n" + "\n" + + "\t A B C D E F G H I J \t\t\t A B C D E F G H I J \n" + + " 1 ~ W ~ ~ ~ ~ ~ ~ ~ ~\t\t 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 2 ~ W ~ ~ ~ ~ ~ ~ ~ ~\t\t 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 3 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 3 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 5 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 5 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 6 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 6 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 8 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 8 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 9 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 9 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 10 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 10 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~"; + + assertEquals(expected, getOutput().replace(WAVE, "~").replaceAll("\r", "")); } @Test - void testUserShipPlacer() { - - MyBoard myBoard = new MyBoard(); - MyShots myShots = new MyShots(); - Player player = new Player(myBoard, myShots); + void testBoardPrinterMyShots() { + createPlayers(); -// Ship ship = new Ship(Arrays.asList(new Point(0, 1))); -// myBoard.placeShip(ship); + putOnBoard(myShots, new Point(0,0), Shot.MISS); + putOnBoard(myShots, new Point(1,1), Shot.HIT); + putOnBoard(myShots, new Point(2,2), Shot.KILLED); - String input = "H1 hor\n" + - "A1 h\n"; - setInput(input); + showBoards(player1); + String expected = "MY BOARD (null) vs ENEMY BOARD\n" + "\n" + + "\t A B C D E F G H I J \t\t\t A B C D E F G H I J \n" + + " 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 1 0 ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 2 ~ X ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 3 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 3 ~ ~ X ~ ~ ~ ~ ~ ~ ~\n" + + " 4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 5 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 5 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 6 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 6 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 8 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 8 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 9 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 9 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 10 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 10 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~"; + + assertEquals(expected, getOutput() + .replace(WAVE, "~") + .replace(MISS, "0") + .replace(HIT, "X") + .replaceAll("\r", "")); -// PlayingField field = new PlayingField(); - ShipPlacer placer = new ShipPlacer(new Scanner(input)); + } - placer.placeShip(player); -// myBoard.placeShip(); + @Test + void testBoardPrinterEnemyShots() { + createPlayers(); - int actualSize = player.getMyShips().size(); + putOnBoard(myBoard, new Point(0,1), Shot.MISS); + putOnBoard(myBoard, new Point(0,2), Shot.HIT); + putOnBoard(myBoard, new Point(0,3), Shot.KILLED); - assertEquals(10, actualSize); + showBoards(player1); + String expected = "MY BOARD (null) vs ENEMY BOARD\n" + "\n" + + "\t A B C D E F G H I J \t\t\t A B C D E F G H I J \n" + + " 1 ~ 0 X X ~ ~ ~ ~ ~ ~\t\t 1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 2 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 3 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 3 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 4 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 5 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 5 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 6 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 6 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 8 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 8 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 9 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 9 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n" + + " 10 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\t\t 10 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~"; + + assertEquals(expected, getOutput() + .replace(WAVE, "~") + .replace(MISS, "0") + .replace(HIT, "X") + .replaceAll("\r", "")); } + private void createPlayers() { + myBoard = new MyBoard(); + myShots = new MyShots(); + player1 = new Player(myBoard, myShots); + } -// @Test -// void testUserShotInputReader() { -// String input = "A11\n" + -// "A10"; -// setInput(input); -// -// Coordinate expected = new Coordinate(9, 0); -// -// UserShotInputReader reader = new UserShotInputReader(new Scanner(System.in)); -// Coordinate pointFromReader = reader.getPointFromInput(); -// -// assertEquals(expected, pointFromReader); -// } } From 9d3d8359eef00393a955d851ca2495a6248aa82f Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Tue, 21 Sep 2021 17:24:04 +0300 Subject: [PATCH 25/33] Small bug fixed. --- .../homework_7/kittenToCatFunction/KittenToCatFunction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java b/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java index 606b410b..5c933421 100644 --- a/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java +++ b/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java @@ -1,6 +1,6 @@ package homework_7.kittenToCatFunction; @FunctionalInterface -public interface KittenToCatFunction{ +public interface KittenToCatFunction{ Cat grow(Kitten k); } From fc2f1030987426d52851967e79f49b122c4ea7cd Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 22 Sep 2021 11:49:56 +0300 Subject: [PATCH 26/33] Two classes are deleted. Added computer ship placement mode with its test. --- .../java/course_project/sea_battle/Game.java | 9 ++- .../course_project/sea_battle/GamePlayUpd.png | Bin 0 -> 44521 bytes .../sea_battle/boards/MyShots.java | 4 -- .../course_project/sea_battle/gamePlay.png | Bin 24123 -> 0 bytes .../sea_battle/model/Player.java | 7 +- src/main/java/course_project/sea_battle/rules | 2 +- .../sea_battle/service/NameSetter.java | 5 +- .../sea_battle/service/ShipPlacer.java | 65 +++++++++++------- .../sea_battle/service/inputs/BigSpace.java | 23 ------- .../service/inputs/InputShipReader.java | 36 ++++++---- .../service/inputs/InputShooterReader.java | 30 ++++++-- .../sea_battle/view/BoardPrinter.java | 5 +- .../course_project/sea_battle/GameTest.java | 35 ++++++++-- .../course_project/sea_battle/ModelTest.java | 3 +- .../course_project/sea_battle/ViewTest.java | 34 +++------ 15 files changed, 132 insertions(+), 126 deletions(-) create mode 100644 src/main/java/course_project/sea_battle/GamePlayUpd.png delete mode 100644 src/main/java/course_project/sea_battle/boards/MyShots.java delete mode 100644 src/main/java/course_project/sea_battle/gamePlay.png delete mode 100644 src/main/java/course_project/sea_battle/service/inputs/BigSpace.java diff --git a/src/main/java/course_project/sea_battle/Game.java b/src/main/java/course_project/sea_battle/Game.java index 5a22227c..ba8a031e 100644 --- a/src/main/java/course_project/sea_battle/Game.java +++ b/src/main/java/course_project/sea_battle/Game.java @@ -1,7 +1,6 @@ package course_project.sea_battle; import course_project.sea_battle.boards.MyBoard; -import course_project.sea_battle.boards.MyShots; import course_project.sea_battle.model.Player; import course_project.sea_battle.model.Ship; import course_project.sea_battle.service.inputs.InputShipReader; @@ -22,15 +21,15 @@ public class Game extends Thread { private Player player2; public Game() { - this.player1 = new Player(new MyBoard(), new MyShots()); - this.player2 = new Player(new MyBoard(), new MyShots()); + this.player1 = new Player(new MyBoard(), new MyBoard()); + this.player2 = new Player(new MyBoard(), new MyBoard()); } @Override public void run() { setUpNames(); setUpShips(); - startGame(); + play(); defineWinner(); } @@ -43,7 +42,7 @@ public void setUpShips() { new ShipPlacer(inputShipReader).placeShip(player2); } - public void startGame() { + public void play() { while (bothPlayersHaveShips(player1, player2)) { new InputShooterReader(scanner).checkAndValidatePlayerShot(player1, player2); new InputShooterReader(scanner).checkAndValidatePlayerShot(player2, player1); diff --git a/src/main/java/course_project/sea_battle/GamePlayUpd.png b/src/main/java/course_project/sea_battle/GamePlayUpd.png new file mode 100644 index 0000000000000000000000000000000000000000..3c8293271e370dec8113b8b475399c6ac82b15e2 GIT binary patch literal 44521 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 literal 0 HcmV?d00001 diff --git a/src/main/java/course_project/sea_battle/boards/MyShots.java b/src/main/java/course_project/sea_battle/boards/MyShots.java deleted file mode 100644 index b9e50f32..00000000 --- a/src/main/java/course_project/sea_battle/boards/MyShots.java +++ /dev/null @@ -1,4 +0,0 @@ -package course_project.sea_battle.boards; - -public class MyShots extends Board { -} diff --git a/src/main/java/course_project/sea_battle/gamePlay.png b/src/main/java/course_project/sea_battle/gamePlay.png deleted file mode 100644 index 7423a675dade5589c085a4a535717afb431c25d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24123 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 myShips = new ArrayList<>(); - public Player(MyBoard myBoard, MyShots enemyBoard) { + public Player(MyBoard myBoard, MyBoard enemyBoard) { this.myBoard = myBoard; this.myShots = enemyBoard; myBoard.setBasicGrids(); @@ -39,7 +38,7 @@ public MyBoard getMyBoard() { return myBoard; } - public MyShots getMyShots() { + public MyBoard getMyShots() { return myShots; } diff --git a/src/main/java/course_project/sea_battle/rules b/src/main/java/course_project/sea_battle/rules index edf0ddfc..a4bfa8fe 100644 --- a/src/main/java/course_project/sea_battle/rules +++ b/src/main/java/course_project/sea_battle/rules @@ -3,7 +3,7 @@ Only 1 mode is available: player vs player. Each player has 10 ships: 1*4deck, 2*3, 3*2, 4*1. SHIP PLACEMENT -You have to place ships manually. +You can choose how to place ships: manually or automatically. It's not allowed to place ships close to each other (diagonal cells count as well). You put a ship by pointing its topLeft point and with position ("v" - vertical, "h" - horizontal). So your input should be like this: [A7 V] or [b1 h]. diff --git a/src/main/java/course_project/sea_battle/service/NameSetter.java b/src/main/java/course_project/sea_battle/service/NameSetter.java index 4ea3232e..927b5071 100644 --- a/src/main/java/course_project/sea_battle/service/NameSetter.java +++ b/src/main/java/course_project/sea_battle/service/NameSetter.java @@ -2,6 +2,7 @@ import course_project.sea_battle.model.Player; import course_project.sea_battle.service.inputs.InputShipReader; +import lombok.SneakyThrows; public class NameSetter { private final InputShipReader inputShipReader; @@ -10,8 +11,8 @@ public NameSetter(InputShipReader inputShipReader) { this.inputShipReader = inputShipReader; } + @SneakyThrows public void setNames(Player player1, Player player2) { - System.out.println("Player 1, please, input your name:"); String player1Name = inputShipReader.readLine(); player1.setName(player1Name); @@ -22,8 +23,6 @@ public void setNames(Player player1, Player player2) { player2.setName(player2Name); System.out.println("Hello, " + player2Name + "!"); - System.out.println("Press ENTER to start the game"); - inputShipReader.readLine(); } } diff --git a/src/main/java/course_project/sea_battle/service/ShipPlacer.java b/src/main/java/course_project/sea_battle/service/ShipPlacer.java index 066d9065..c8026bdb 100644 --- a/src/main/java/course_project/sea_battle/service/ShipPlacer.java +++ b/src/main/java/course_project/sea_battle/service/ShipPlacer.java @@ -5,7 +5,7 @@ import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; import course_project.sea_battle.service.inputs.InputShipReader; -import course_project.sea_battle.service.inputs.BigSpace; +import lombok.SneakyThrows; import java.util.List; @@ -14,53 +14,66 @@ public class ShipPlacer { private final InputShipReader inputShipReader; private static final String PLACED = "Ship is placed!"; - private final BigSpace bigSpace; + private static final String GAMEMODE = ", please, choose ship placement mode: 1 - manual, 2 - automatic"; + private static final String NEXTMOVE = "Press ENTER to finish your move"; + private static final String DONE = "\nAll ships are placed!"; + private int gameMode; public ShipPlacer(InputShipReader inputShipReader) { this.inputShipReader = inputShipReader; - this.bigSpace = new BigSpace(inputShipReader.getScanner()); } + @SneakyThrows public void placeShip(Player player) { + defineGameMode(player.getName()); + MyBoard board = player.getMyBoard(); showBoards(player); for (int shipSize = 4; shipSize >= 1; shipSize--) { for (int shipNumber = 0; shipNumber <= 4 - shipSize; shipNumber++) { - System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); + if (gameMode == 1) { + System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); + } - inputShipReader.getAndValidateInput(shipSize, board); + inputShipReader.getAndValidateInput(shipSize, board, gameMode); List coordinates = inputShipReader.getValidCoordinates(); Ship ship = new Ship(coordinates); board.placeShip(ship); player.getMyShips().add(ship); - System.out.println(PLACED); - showBoards(player); + if (gameMode == 1) { + System.out.println(PLACED); + showBoards(player); + } + } + } + + if (gameMode == 2) { + System.out.println(DONE); + showBoards(player); + Thread.sleep(200); + } + printBigSpace(); + } + + public void defineGameMode(String name) { + while (true) { + System.out.println(name + GAMEMODE); + String gameModeInput = inputShipReader.readLine(); + if (gameModeInput.matches("[1]|[2]")) { + gameMode = Integer.parseInt(gameModeInput); + break; } } + } -// You can uncomment this block of code instead above for() (lines: 28-42) to place only 2 ships for every player. - -// for (int shipSize = 3; shipSize > 2; shipSize--) { -// for (int shipNumber = 0; shipNumber < 1; shipNumber++) { -// System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 H] or [a8 v]"); -// -// inputShipReader.getAndValidateInput(shipSize, board); -// List coordinates = inputShipReader.getValidCoordinates(); -// -// Ship ship = new Ship(coordinates); -// board.placeShip(ship); -// -// System.out.println(PLACED); -// player.getMyShips().add(ship); -// showBoards(player); -// } -// } - - bigSpace.printBigSpace(); + public void printBigSpace() { + System.out.println(NEXTMOVE); + inputShipReader.readLine(); + System.out.println("\n\n\n\n\n\n\n\n\n\n"); } } diff --git a/src/main/java/course_project/sea_battle/service/inputs/BigSpace.java b/src/main/java/course_project/sea_battle/service/inputs/BigSpace.java deleted file mode 100644 index 1df6e42d..00000000 --- a/src/main/java/course_project/sea_battle/service/inputs/BigSpace.java +++ /dev/null @@ -1,23 +0,0 @@ -package course_project.sea_battle.service.inputs; - -import java.util.Scanner; -import java.util.stream.Stream; - -public class BigSpace extends InputReader { - - private static final String FINISH = "Press ENTER to finish your move"; - - public BigSpace(Scanner scanner) { - this.scanner = scanner; - } - - public void printBigSpace() { - System.out.println(FINISH); - readLine(); - - Stream.generate(() -> ".") - .limit(5) - .forEach(System.out::println); - } - -} diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java index 783a0c64..98d47039 100644 --- a/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java @@ -3,12 +3,9 @@ import course_project.sea_battle.boards.MyBoard; import course_project.sea_battle.model.Point; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Scanner; +import java.util.*; -public class InputShipReader extends InputReader{ +public class InputShipReader extends InputReader { private int x; private int y; @@ -23,18 +20,29 @@ public InputShipReader(Scanner scanner) { this.scanner = scanner; } - public void getAndValidateInput(int shipSize, MyBoard board) { + public void getAndValidateInput(int shipSize, MyBoard board, int gameMode) { while (true) { - String input = readLine(); + if (gameMode == 1) { + String input = readLine(); + if (!isValidInput(input)) continue; + } else if (gameMode == 2) { + getAutomaticCoordinates(); + } - if (!isValidInput(input)) continue; Point topLeftPoint = new Point(x, y); - if (!isShipWithinBoard(shipSize)) continue; + if (!isShipWithinBoard(shipSize, gameMode)) continue; coordinates = findCoordinates(shipSize, topLeftPoint); - if (shipsDoNotCross(board, shipSize)) break; + if (shipsDoNotCross(board, shipSize, gameMode)) break; } } + public void getAutomaticCoordinates() { + Random random = new Random(); + x = random.nextInt(10); + y = random.nextInt(10); + position = random.nextInt(2) == 0 ? "v" : "h"; + } + public boolean isValidInput(String input) { if (input.matches("[a-jA-J]([1-9]|10) (v|h|V|H)")) { String[] coords = input.split(" "); @@ -48,12 +56,12 @@ public boolean isValidInput(String input) { } } - public boolean isShipWithinBoard(int shipSize) { + public boolean isShipWithinBoard(int shipSize, int gameMode) { Point rightBottomPoint = position.equalsIgnoreCase("v") ? new Point(x + shipSize, y) : new Point(x, y + shipSize); if (rightBottomPoint.getX() > 10 || rightBottomPoint.getY() > 10) { - System.out.println(OUTOFBOARD); + if (gameMode == 1) System.out.println(OUTOFBOARD); return false; } return true; @@ -76,7 +84,7 @@ public List findCoordinates(int shipSize, Point topLeftPoint) { return coordinates; } - public boolean shipsDoNotCross(MyBoard board, int shipSize) { + public boolean shipsDoNotCross(MyBoard board, int shipSize, int gameMode) { HashSet allCoordinates = new HashSet<>(); for (int i = 0; i < shipSize; i++) { allCoordinates.add(new Point(x, y)); @@ -115,7 +123,7 @@ public boolean shipsDoNotCross(MyBoard board, int shipSize) { .distinct() .count(); if (count > 1) { - System.out.println(SHIPSCROSS); + if (gameMode == 1) System.out.println(SHIPSCROSS); return false; } return true; diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java index d27043fe..bd98157c 100644 --- a/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java @@ -1,9 +1,16 @@ package course_project.sea_battle.service.inputs; import course_project.sea_battle.boards.Board; -import course_project.sea_battle.model.*; - -import java.util.*; +import course_project.sea_battle.model.Player; +import course_project.sea_battle.model.Point; +import course_project.sea_battle.model.Ship; +import course_project.sea_battle.model.Shot; +import lombok.SneakyThrows; + +import java.util.HashSet; +import java.util.List; +import java.util.Scanner; +import java.util.Set; import java.util.stream.Collectors; import static course_project.sea_battle.view.BoardPrinter.showBoards; @@ -13,16 +20,15 @@ public class InputShooterReader extends InputReader { private int y; private Shot shot; private Ship currentShip; - private final BigSpace bigSpace; private static final String MAKESHOT = ", make your shot in format: [A6] or [b1]"; private static final String INPUTERROR = "Input should be like this: [A7] or [b2]. Try again!"; private static final String CHECKED = "Cell is checked. Make another shot!"; private static final String KILLALL = ", you destroyed all enemy ships. Congratulations!"; + private static final String NEXTMOVE = "Press ENTER to finish your move"; public InputShooterReader(Scanner scanner) { this.scanner = scanner; - this.bigSpace = new BigSpace(scanner); } public void checkAndValidatePlayerShot(Player player1, Player player2) { @@ -142,30 +148,40 @@ public void fillCellsAroundDestroyedShip(Ship ship, Player me, Player enemy) { } } + @SneakyThrows public boolean isGameContinue(Player me, Player enemy, Shot shot) { if (shot == Shot.KILLED) { System.err.println("KILLED!"); System.out.println(enemy.getName() + " has " + enemy.countShips() + " ship(s) left."); fillCellsAroundDestroyedShip(currentShip, me, enemy); + Thread.sleep(100); showBoards(me); if (enemy.countShips() == 0) { System.out.println(me.getName() + KILLALL); - bigSpace.printBigSpace(); + printBigSpace(); return false; } else { System.out.println(me.getName() + MAKESHOT); } } else if (shot == Shot.HIT) { System.err.println("HIT!"); + Thread.sleep(100); showBoards(me); System.out.println(me.getName() + MAKESHOT); } else if (shot == Shot.MISS) { System.err.println("MISS!"); + Thread.sleep(100); showBoards(me); - bigSpace.printBigSpace(); + printBigSpace(); return false; } return true; } + public void printBigSpace() { + System.out.println(NEXTMOVE); + readLine(); + System.out.println("\n\n\n\n\n\n\n\n\n\n"); + } + } diff --git a/src/main/java/course_project/sea_battle/view/BoardPrinter.java b/src/main/java/course_project/sea_battle/view/BoardPrinter.java index e451ef32..ab305f40 100644 --- a/src/main/java/course_project/sea_battle/view/BoardPrinter.java +++ b/src/main/java/course_project/sea_battle/view/BoardPrinter.java @@ -13,10 +13,7 @@ public class BoardPrinter { private static final String HIT = RED + "X" + RESET; private static final String WAVE = CYAN + "~" + RESET; - private BoardPrinter() { - } - - public static void showBoards(Player player) { + public static synchronized void showBoards(Player player) { int[][] myField = player.getMyBoard().getBoard(); int[][] enemyField = player.getMyShots().getBoard(); showHeader(player); diff --git a/src/test/java/course_project/sea_battle/GameTest.java b/src/test/java/course_project/sea_battle/GameTest.java index e06212cd..cd12af68 100644 --- a/src/test/java/course_project/sea_battle/GameTest.java +++ b/src/test/java/course_project/sea_battle/GameTest.java @@ -26,8 +26,7 @@ class GameTest extends UnitBase { @Test void testNameSetter() { String input = "Tom\n" + - "Vera\n" + - "\n"; + "Vera\n"; setInput(input); Game game = new Game(); @@ -42,7 +41,8 @@ void testNameSetter() { @Test void testValidCoordsShipPlacing() { - String input = "a1 h\n" + + String input = "1\n" + + "a1 h\n" + "a3 h\n" + "a5 h\n" + "a7 h\n" + @@ -53,6 +53,7 @@ void testValidCoordsShipPlacing() { "f7 h\n" + "f9 h\n" + "\n" + + "1\n" + "a1 h\n" + "a3 h\n" + "a5 h\n" + @@ -78,7 +79,8 @@ void testValidCoordsShipPlacing() { @Test void testOnlyValidCoordsShipPlacing() { - String input = "a1 h\n" + + String input = "1\n" + + "a1 h\n" + "a2 h\n" + "a\n" + "a6v\n" + @@ -93,6 +95,7 @@ void testOnlyValidCoordsShipPlacing() { "f7 h\n" + "f9 h\n" + "\n" + + "1\n" + "a1 h\n" + "a3 h\n" + "a5 h\n" + @@ -116,6 +119,24 @@ void testOnlyValidCoordsShipPlacing() { assertEquals(10, numOfShips2); } + @Test + void testComputerShipPlacing() { + String input = "2\n" + + "\n" + + "2\n" + + "\n"; + setInput(input); + + Game game = new Game(); + game.setUpShips(); + + long numOfShips1 = game.getPlayer1().countShips(); + long numOfShips2 = game.getPlayer2().countShips(); + + assertEquals(10, numOfShips1); + assertEquals(10, numOfShips2); + } + @ParameterizedTest @ValueSource(strings = {"a6", "d1 g", "d1 v 1", ""}) void givenInvalidShipCoords_whenSetUpShips_ThenError(String input) { @@ -131,8 +152,8 @@ void givenOutOfBoardShipCoords_whenSetUpShips_ThenError() { inputShipReader.setY(0); inputShipReader.setPosition("v"); - assertTrue(inputShipReader.isShipWithinBoard(3)); - assertFalse(inputShipReader.isShipWithinBoard(4)); + assertTrue(inputShipReader.isShipWithinBoard(3, 1)); + assertFalse(inputShipReader.isShipWithinBoard(4, 1)); assertEquals(OUTOFBOARD, getOutput()); } @@ -167,7 +188,7 @@ void testShooter() { assertEquals(1, numOfPlayer1AllShips); assertEquals(1, numOfPlayer2AllShips); - game.startGame(); + game.play(); long numOfPlayer1AliveShips = game.getPlayer1().getMyShips().stream() .filter(Ship::isAlive) diff --git a/src/test/java/course_project/sea_battle/ModelTest.java b/src/test/java/course_project/sea_battle/ModelTest.java index fcdc30b1..296edb6c 100644 --- a/src/test/java/course_project/sea_battle/ModelTest.java +++ b/src/test/java/course_project/sea_battle/ModelTest.java @@ -1,7 +1,6 @@ package course_project.sea_battle; import course_project.sea_battle.boards.MyBoard; -import course_project.sea_battle.boards.MyShots; import course_project.sea_battle.model.Player; import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; @@ -49,7 +48,7 @@ void testBoard() { int[][] myBoardTest = new int[10][10]; MyBoard myBoard = new MyBoard(); - MyShots myShots = new MyShots(); + MyBoard myShots = new MyBoard(); Player player = new Player(myBoard, myShots); assertEquals(0, player.getMyShips().size()); diff --git a/src/test/java/course_project/sea_battle/ViewTest.java b/src/test/java/course_project/sea_battle/ViewTest.java index 4f07f3f0..18dea7e1 100644 --- a/src/test/java/course_project/sea_battle/ViewTest.java +++ b/src/test/java/course_project/sea_battle/ViewTest.java @@ -2,16 +2,13 @@ import base.UnitBase; import course_project.sea_battle.boards.MyBoard; -import course_project.sea_battle.boards.MyShots; import course_project.sea_battle.model.Player; import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; import course_project.sea_battle.model.Shot; -import course_project.sea_battle.service.inputs.BigSpace; import org.junit.jupiter.api.Test; import java.util.Arrays; -import java.util.Scanner; import static course_project.sea_battle.service.inputs.InputShooterReader.putOnBoard; import static course_project.sea_battle.view.BoardPrinter.showBoards; @@ -29,24 +26,9 @@ class ViewTest extends UnitBase { private static final String WAVE = CYAN + "~" + RESET; MyBoard myBoard; - MyShots myShots; + MyBoard myShots; Player player1; - @Test - void testBigSpacePrinter() { - String input = "\n"; - setInput(input); - - new BigSpace(new Scanner(System.in)).printBigSpace(); - String expected = "Press ENTER to finish your move\n" + - ".\n" + - ".\n" + - ".\n" + - ".\n" + - "."; - assertEquals(expected, getOutput().replaceAll("\r", "")); - } - @Test void testBoardPrinterEmptyBoard() { createPlayers(); @@ -97,9 +79,9 @@ void testBoardPrinterShipPlacer() { void testBoardPrinterMyShots() { createPlayers(); - putOnBoard(myShots, new Point(0,0), Shot.MISS); - putOnBoard(myShots, new Point(1,1), Shot.HIT); - putOnBoard(myShots, new Point(2,2), Shot.KILLED); + putOnBoard(myShots, new Point(0, 0), Shot.MISS); + putOnBoard(myShots, new Point(1, 1), Shot.HIT); + putOnBoard(myShots, new Point(2, 2), Shot.KILLED); showBoards(player1); String expected = "MY BOARD (null) vs ENEMY BOARD\n" + "\n" + @@ -127,9 +109,9 @@ void testBoardPrinterMyShots() { void testBoardPrinterEnemyShots() { createPlayers(); - putOnBoard(myBoard, new Point(0,1), Shot.MISS); - putOnBoard(myBoard, new Point(0,2), Shot.HIT); - putOnBoard(myBoard, new Point(0,3), Shot.KILLED); + putOnBoard(myBoard, new Point(0, 1), Shot.MISS); + putOnBoard(myBoard, new Point(0, 2), Shot.HIT); + putOnBoard(myBoard, new Point(0, 3), Shot.KILLED); showBoards(player1); String expected = "MY BOARD (null) vs ENEMY BOARD\n" + "\n" + @@ -154,7 +136,7 @@ void testBoardPrinterEnemyShots() { private void createPlayers() { myBoard = new MyBoard(); - myShots = new MyShots(); + myShots = new MyBoard(); player1 = new Player(myBoard, myShots); } From f546077ac26475da423d04cadc41f3deda779464 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 22 Sep 2021 13:11:51 +0300 Subject: [PATCH 27/33] Added game mode Player vs Computer(easy). --- .../java/course_project/sea_battle/Game.java | 8 +- .../sea_battle/model/Player.java | 8 ++ src/main/java/course_project/sea_battle/rules | 6 +- .../service/GameModeAndNameSetter.java | 50 +++++++++++ .../sea_battle/service/NameSetter.java | 28 ------- .../sea_battle/service/ShipPlacer.java | 50 ++++++----- .../service/inputs/InputShipReader.java | 2 +- .../service/inputs/InputShooterReader.java | 82 +++++++++++++------ .../course_project/sea_battle/GameTest.java | 3 +- 9 files changed, 154 insertions(+), 83 deletions(-) create mode 100644 src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java delete mode 100644 src/main/java/course_project/sea_battle/service/NameSetter.java diff --git a/src/main/java/course_project/sea_battle/Game.java b/src/main/java/course_project/sea_battle/Game.java index ba8a031e..7ea3ed3d 100644 --- a/src/main/java/course_project/sea_battle/Game.java +++ b/src/main/java/course_project/sea_battle/Game.java @@ -4,7 +4,7 @@ import course_project.sea_battle.model.Player; import course_project.sea_battle.model.Ship; import course_project.sea_battle.service.inputs.InputShipReader; -import course_project.sea_battle.service.NameSetter; +import course_project.sea_battle.service.GameModeAndNameSetter; import course_project.sea_battle.service.inputs.InputShooterReader; import course_project.sea_battle.service.ShipPlacer; @@ -34,12 +34,12 @@ public void run() { } public void setUpNames() { - new NameSetter(inputShipReader).setNames(player1, player2); + new GameModeAndNameSetter(inputShipReader).setNames(player1, player2); } public void setUpShips() { - new ShipPlacer(inputShipReader).placeShip(player1); - new ShipPlacer(inputShipReader).placeShip(player2); + new ShipPlacer(inputShipReader).placeShip(player1, player2); + new ShipPlacer(inputShipReader).placeShip(player2, player1); } public void play() { diff --git a/src/main/java/course_project/sea_battle/model/Player.java b/src/main/java/course_project/sea_battle/model/Player.java index b1246a49..096cdf60 100644 --- a/src/main/java/course_project/sea_battle/model/Player.java +++ b/src/main/java/course_project/sea_battle/model/Player.java @@ -7,6 +7,7 @@ public class Player { private String name; + private boolean isComputer; private MyBoard myBoard; private MyBoard myShots; private final List myShips = new ArrayList<>(); @@ -42,4 +43,11 @@ public MyBoard getMyShots() { return myShots; } + public boolean isComputer() { + return isComputer; + } + + public void setComputer(boolean computer) { + isComputer = computer; + } } diff --git a/src/main/java/course_project/sea_battle/rules b/src/main/java/course_project/sea_battle/rules index a4bfa8fe..2f3cb65d 100644 --- a/src/main/java/course_project/sea_battle/rules +++ b/src/main/java/course_project/sea_battle/rules @@ -1,5 +1,5 @@ GENERAL -Only 1 mode is available: player vs player. +2 game modes are available: Player vs Player and Player vs Computer (very easy). Each player has 10 ships: 1*4deck, 2*3, 3*2, 4*1. SHIP PLACEMENT @@ -10,8 +10,8 @@ You put a ship by pointing its topLeft point and with position ("v" - vertical, RULES Shot format: [A7] or [b1]. -You cannot shoot out of board or cells that you have shooted before. -When you destroy ship all cells around fill automatically and you cannot shoot them (cause there are no ships). +You cannot shoot out of board or cells that you have shot before. +When you destroy a ship all cells around are filled automatically and you cannot shoot them anymore (cause there are no ships). Each player has same count of moves. Game over when one of player (or both) don't have "alive" ships. diff --git a/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java b/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java new file mode 100644 index 00000000..7e07de2c --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java @@ -0,0 +1,50 @@ +package course_project.sea_battle.service; + +import course_project.sea_battle.model.Player; +import course_project.sea_battle.service.inputs.InputShipReader; +import lombok.SneakyThrows; + +public class GameModeAndNameSetter { + private final InputShipReader inputShipReader; + private static final String SHOOSEGAMEMODE = "Please, choose game mode:\n1: player vs player\n2: player vs computer"; + private static final String PL1 = "Player 1, please, input your name:"; + private static final String PL2 = "Player 2, please, input your name:"; + private int gameMode; + + public GameModeAndNameSetter(InputShipReader inputShipReader) { + this.inputShipReader = inputShipReader; + } + + @SneakyThrows + public void setNames(Player player1, Player player2) { + + defineGameMode(); + + System.out.println(PL1); + String player1Name = inputShipReader.readLine(); + player1.setName(player1Name); + System.out.println("Hello, " + player1Name + "!"); + + if (gameMode == 1) { + System.out.println(PL2); + String player2Name = inputShipReader.readLine(); + player2.setName(player2Name); + System.out.println("Hello, " + player2Name + "!"); + } else if (gameMode == 2) { + player2.setName("Computer"); + player2.setComputer(true); + } + } + + private void defineGameMode() { + while (true) { + System.out.println(SHOOSEGAMEMODE); + String gameModeInput = inputShipReader.readLine(); + if (gameModeInput.matches("[1]|[2]")) { + gameMode = Integer.parseInt(gameModeInput); + break; + } + } + } + +} diff --git a/src/main/java/course_project/sea_battle/service/NameSetter.java b/src/main/java/course_project/sea_battle/service/NameSetter.java deleted file mode 100644 index 927b5071..00000000 --- a/src/main/java/course_project/sea_battle/service/NameSetter.java +++ /dev/null @@ -1,28 +0,0 @@ -package course_project.sea_battle.service; - -import course_project.sea_battle.model.Player; -import course_project.sea_battle.service.inputs.InputShipReader; -import lombok.SneakyThrows; - -public class NameSetter { - private final InputShipReader inputShipReader; - - public NameSetter(InputShipReader inputShipReader) { - this.inputShipReader = inputShipReader; - } - - @SneakyThrows - public void setNames(Player player1, Player player2) { - System.out.println("Player 1, please, input your name:"); - String player1Name = inputShipReader.readLine(); - player1.setName(player1Name); - System.out.println("Hello, " + player1Name + "!"); - - System.out.println("Player 2, please, input your name:"); - String player2Name = inputShipReader.readLine(); - player2.setName(player2Name); - System.out.println("Hello, " + player2Name + "!"); - - } - -} diff --git a/src/main/java/course_project/sea_battle/service/ShipPlacer.java b/src/main/java/course_project/sea_battle/service/ShipPlacer.java index c8026bdb..048290d5 100644 --- a/src/main/java/course_project/sea_battle/service/ShipPlacer.java +++ b/src/main/java/course_project/sea_battle/service/ShipPlacer.java @@ -14,58 +14,64 @@ public class ShipPlacer { private final InputShipReader inputShipReader; private static final String PLACED = "Ship is placed!"; - private static final String GAMEMODE = ", please, choose ship placement mode: 1 - manual, 2 - automatic"; + private static final String CHOOSESHIPPLACEMENTMODE = ", please, choose ship placement mode:\n1: manual\n2: automatic"; private static final String NEXTMOVE = "Press ENTER to finish your move"; private static final String DONE = "\nAll ships are placed!"; - private int gameMode; + private int shipPlacementMode; public ShipPlacer(InputShipReader inputShipReader) { this.inputShipReader = inputShipReader; } @SneakyThrows - public void placeShip(Player player) { + public void placeShip(Player player1, Player player2) { - defineGameMode(player.getName()); + defineShipPlacementMode(player1); - MyBoard board = player.getMyBoard(); - showBoards(player); + MyBoard board = player1.getMyBoard(); + if (!player1.isComputer()) { + showBoards(player1); + } for (int shipSize = 4; shipSize >= 1; shipSize--) { for (int shipNumber = 0; shipNumber <= 4 - shipSize; shipNumber++) { - if (gameMode == 1) { - System.out.println(player.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); + if (shipPlacementMode == 1) { + System.out.println(player1.getName() + ", please, input top left coordinate for the ship (" + shipSize + " points) and orientation. Example: [A5 h] or [A8 v]"); } - inputShipReader.getAndValidateInput(shipSize, board, gameMode); + inputShipReader.getAndValidateInput(shipSize, board, shipPlacementMode); List coordinates = inputShipReader.getValidCoordinates(); Ship ship = new Ship(coordinates); board.placeShip(ship); - player.getMyShips().add(ship); + player1.getMyShips().add(ship); - if (gameMode == 1) { + if (shipPlacementMode == 1) { System.out.println(PLACED); - showBoards(player); + showBoards(player1); } } } - if (gameMode == 2) { + if (shipPlacementMode == 2 && !player1.isComputer()) { System.out.println(DONE); - showBoards(player); + showBoards(player1); Thread.sleep(200); } - printBigSpace(); + if (!player1.isComputer() && !player2.isComputer()) {printBigSpace();} } - public void defineGameMode(String name) { - while (true) { - System.out.println(name + GAMEMODE); - String gameModeInput = inputShipReader.readLine(); - if (gameModeInput.matches("[1]|[2]")) { - gameMode = Integer.parseInt(gameModeInput); - break; + public void defineShipPlacementMode(Player player) { + if (player.isComputer()) { + shipPlacementMode = 2; + } else { + while (true) { + System.out.println(player.getName() + CHOOSESHIPPLACEMENTMODE); + String gameModeInput = inputShipReader.readLine(); + if (gameModeInput.matches("[1]|[2]")) { + shipPlacementMode = Integer.parseInt(gameModeInput); + break; + } } } } diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java index 98d47039..fd86f6ad 100644 --- a/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java @@ -8,6 +8,7 @@ public class InputShipReader extends InputReader { private int x; private int y; + private Random random = new Random(); private String position; private List coordinates; @@ -37,7 +38,6 @@ public void getAndValidateInput(int shipSize, MyBoard board, int gameMode) { } public void getAutomaticCoordinates() { - Random random = new Random(); x = random.nextInt(10); y = random.nextInt(10); position = random.nextInt(2) == 0 ? "v" : "h"; diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java index bd98157c..73655713 100644 --- a/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java @@ -7,10 +7,7 @@ import course_project.sea_battle.model.Shot; import lombok.SneakyThrows; -import java.util.HashSet; -import java.util.List; -import java.util.Scanner; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import static course_project.sea_battle.view.BoardPrinter.showBoards; @@ -20,28 +17,44 @@ public class InputShooterReader extends InputReader { private int y; private Shot shot; private Ship currentShip; + private Random random = new Random(); private static final String MAKESHOT = ", make your shot in format: [A6] or [b1]"; private static final String INPUTERROR = "Input should be like this: [A7] or [b2]. Try again!"; private static final String CHECKED = "Cell is checked. Make another shot!"; private static final String KILLALL = ", you destroyed all enemy ships. Congratulations!"; private static final String NEXTMOVE = "Press ENTER to finish your move"; + private static final String COMPUTERMOVE = "Computer is thinking..."; public InputShooterReader(Scanner scanner) { this.scanner = scanner; } + @SneakyThrows public void checkAndValidatePlayerShot(Player player1, Player player2) { - showBoards(player1); - System.out.println(player1.getName() + MAKESHOT); + if (!player1.isComputer()) { + if (!player2.isComputer()) { + showBoards(player1); + } + System.out.println(player1.getName() + MAKESHOT); + } while (true) { - String input = readLine(); - if (!isValidInput(input)) continue; + if (!player1.isComputer()) { + String input = readLine(); + if (!isValidInput(input)) continue; + } else { + defineShot(); + } if (isShooted(player2)) continue; - getShotResult(player2); + if (player1.isComputer()) { + System.out.println(COMPUTERMOVE); + Thread.sleep(2000); + } + + getShotResult(player2); putOnBoard(player1.getMyShots(), new Point(x, y), shot); putOnBoard(player2.getMyBoard(), new Point(x, y), shot); @@ -49,6 +62,11 @@ public void checkAndValidatePlayerShot(Player player1, Player player2) { } } + public void defineShot() { + x = random.nextInt(10); + y = random.nextInt(10); + } + public boolean isValidInput(String input) { if (input.matches("[a-jA-J]([1-9]|10)")) { y = Character.getNumericValue(input.charAt(0)) - 10; @@ -100,7 +118,6 @@ public static void putOnBoard(Board board, Point shotPoint, Shot shot) { board.setBoard(tempBoard); } - public void fillCellsAroundDestroyedShip(Ship ship, Player me, Player enemy) { List coordinatesOfTheShip = ship.getCoordinates(); @@ -154,34 +171,51 @@ public boolean isGameContinue(Player me, Player enemy, Shot shot) { System.err.println("KILLED!"); System.out.println(enemy.getName() + " has " + enemy.countShips() + " ship(s) left."); fillCellsAroundDestroyedShip(currentShip, me, enemy); - Thread.sleep(100); - showBoards(me); + Thread.sleep(500); + if (!me.isComputer()) { + showBoards(me); + } else { + showBoards(enemy); + } if (enemy.countShips() == 0) { System.out.println(me.getName() + KILLALL); - printBigSpace(); + printBigSpace(!me.isComputer() && !enemy.isComputer()); return false; } else { - System.out.println(me.getName() + MAKESHOT); + if (!me.isComputer()) { + System.out.println(me.getName() + MAKESHOT); + } } } else if (shot == Shot.HIT) { System.err.println("HIT!"); - Thread.sleep(100); - showBoards(me); - System.out.println(me.getName() + MAKESHOT); + Thread.sleep(500); + if (!me.isComputer()) { + showBoards(me); + System.out.println(me.getName() + MAKESHOT); + } else { + showBoards(enemy); + } + } else if (shot == Shot.MISS) { System.err.println("MISS!"); - Thread.sleep(100); - showBoards(me); - printBigSpace(); + Thread.sleep(500); + if (!me.isComputer()) { + showBoards(me); + } else { + showBoards(enemy); + } + printBigSpace(!me.isComputer() && !enemy.isComputer()); return false; } return true; } - public void printBigSpace() { - System.out.println(NEXTMOVE); - readLine(); - System.out.println("\n\n\n\n\n\n\n\n\n\n"); + public void printBigSpace(boolean hasSence) { + if (hasSence) { + System.out.println(NEXTMOVE); + readLine(); + System.out.println("\n\n\n\n\n\n\n\n\n\n"); + } } } diff --git a/src/test/java/course_project/sea_battle/GameTest.java b/src/test/java/course_project/sea_battle/GameTest.java index cd12af68..94f6ff80 100644 --- a/src/test/java/course_project/sea_battle/GameTest.java +++ b/src/test/java/course_project/sea_battle/GameTest.java @@ -25,7 +25,8 @@ class GameTest extends UnitBase { @Test void testNameSetter() { - String input = "Tom\n" + + String input = "1\n" + + "Tom\n" + "Vera\n"; setInput(input); From e9a861d3b42fe10489c36d2386a27cf3db79fc17 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 22 Sep 2021 13:31:54 +0300 Subject: [PATCH 28/33] hw3 fixed. --- src/main/java/homework_3/ImmutableClass.java | 50 -------------- src/main/java/homework_3/Person.java | 73 ++++++++++++++++++++ 2 files changed, 73 insertions(+), 50 deletions(-) delete mode 100644 src/main/java/homework_3/ImmutableClass.java create mode 100644 src/main/java/homework_3/Person.java diff --git a/src/main/java/homework_3/ImmutableClass.java b/src/main/java/homework_3/ImmutableClass.java deleted file mode 100644 index 79bc505c..00000000 --- a/src/main/java/homework_3/ImmutableClass.java +++ /dev/null @@ -1,50 +0,0 @@ -package homework_3; - -import java.util.ArrayList; -/* -Class must be declared as final; -All members must be private; -There are no setters; -Getters must return copies of mutable objects; -Parameterized constructor must perform Deep Copy. - */ - -public final class ImmutableClass { - private final int age; - private final String name; - private final ArrayList hobbies; - - public int getAge() { - return age; - } - - public String getName() { - return name; - } - - public ArrayList getHobbies() { - return (ArrayList) hobbies.clone(); - } - - public ImmutableClass(int age, String name, ArrayList listHobbies) { - ArrayList tempList = new ArrayList<>(listHobbies); - this.age = age; - this.name = name; - this.hobbies = tempList; - } - - public static void main(String[] args) { - ArrayList listHobbies = new ArrayList<>(); - listHobbies.add("dances"); - listHobbies.add("travel"); - - int age = 27; - String name = "Tom"; - ImmutableClass immutableClass = new ImmutableClass(age, name, listHobbies); - - System.out.println(immutableClass.getAge()); - System.out.println(immutableClass.getName()); - System.out.println(immutableClass.getHobbies()); - } -} - diff --git a/src/main/java/homework_3/Person.java b/src/main/java/homework_3/Person.java new file mode 100644 index 00000000..3e3d5b8b --- /dev/null +++ b/src/main/java/homework_3/Person.java @@ -0,0 +1,73 @@ +package homework_3; + +import java.util.ArrayList; +import java.util.List; +/* +Class must be declared as final; +All members must be private; +There are no setters; +Getters must return copies of mutable objects; +Parameterized constructor must perform Deep Copy. + */ + +public final class Person { + private final int age; + private final String name; + private final ArrayList hobbies; + + public int getAge() { + return age; + } + + public String getName() { + return name; + } + + public List getHobbies() { + if (hobbies != null){ + return new ArrayList<>(hobbies); + } + return new ArrayList<>(); + } + + public Person(int age, String name, List listHobbies) { + this.age = age; + this.name = name; + this.hobbies = new ArrayList<>(listHobbies); + } + + public Person(int age, String name) { + this.hobbies = null; + this.age = age; + this.name = name; + } + + public Person addNewHobby (String hobby){ + List updatedHobbyList = getHobbies(); + updatedHobbyList.add(hobby); + return new Person(age, name, updatedHobbyList); + } + + public static void main(String[] args) { + ArrayList listHobbies = new ArrayList<>(); + listHobbies.add("Dancing"); + listHobbies.add("Travelling"); + + Person me = new Person(27, "Tom", listHobbies); + System.out.println("Me before changes = " + me); + + me = me.addNewHobby("Painting"); + System.out.println("Me after changes = " + me); + } + + @Override + public String toString() { + return "Person{" + + "age=" + age + + ", name='" + name + '\'' + + ", hobbies=" + hobbies + + '}'; + } + +} + From d3224251c9a415921f76b0893197dd9cafed3269 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 22 Sep 2021 14:33:06 +0300 Subject: [PATCH 29/33] hw7 fixed. --- .../homework_7/kittenToCatFunction/Cat.java | 2 +- .../kittenToCatFunction/EgyptCat.java | 7 +++++++ .../kittenToCatFunction/EgyptKitten.java | 7 +++++++ .../kittenToCatFunction/Kitten.java | 2 +- .../KittenToCatFunction.java | 2 +- .../homework_7/kittenToCatFunction/Main.java | 20 +++++++++++++------ .../kittenToCatFunction/SomeCat.java | 7 +++++++ 7 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 src/main/java/homework_7/kittenToCatFunction/EgyptCat.java create mode 100644 src/main/java/homework_7/kittenToCatFunction/EgyptKitten.java create mode 100644 src/main/java/homework_7/kittenToCatFunction/SomeCat.java diff --git a/src/main/java/homework_7/kittenToCatFunction/Cat.java b/src/main/java/homework_7/kittenToCatFunction/Cat.java index ed4de115..01d79ad1 100644 --- a/src/main/java/homework_7/kittenToCatFunction/Cat.java +++ b/src/main/java/homework_7/kittenToCatFunction/Cat.java @@ -1,6 +1,6 @@ package homework_7.kittenToCatFunction; -public class Cat { +public abstract class Cat { private int age; private String name; private Kitten kitten; diff --git a/src/main/java/homework_7/kittenToCatFunction/EgyptCat.java b/src/main/java/homework_7/kittenToCatFunction/EgyptCat.java new file mode 100644 index 00000000..6f69c7a7 --- /dev/null +++ b/src/main/java/homework_7/kittenToCatFunction/EgyptCat.java @@ -0,0 +1,7 @@ +package homework_7.kittenToCatFunction; + +public class EgyptCat extends Cat { + public EgyptCat(int age, String name, Kitten kitten) { + super(age, name, kitten); + } +} diff --git a/src/main/java/homework_7/kittenToCatFunction/EgyptKitten.java b/src/main/java/homework_7/kittenToCatFunction/EgyptKitten.java new file mode 100644 index 00000000..9b9e49fa --- /dev/null +++ b/src/main/java/homework_7/kittenToCatFunction/EgyptKitten.java @@ -0,0 +1,7 @@ +package homework_7.kittenToCatFunction; + +public class EgyptKitten extends Kitten { + public EgyptKitten(int age, String name) { + super(age, name); + } +} diff --git a/src/main/java/homework_7/kittenToCatFunction/Kitten.java b/src/main/java/homework_7/kittenToCatFunction/Kitten.java index 0daa3b81..b6b37052 100644 --- a/src/main/java/homework_7/kittenToCatFunction/Kitten.java +++ b/src/main/java/homework_7/kittenToCatFunction/Kitten.java @@ -1,6 +1,6 @@ package homework_7.kittenToCatFunction; -public class Kitten { +public abstract class Kitten { private int age; private String name; diff --git a/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java b/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java index 5c933421..1d29e024 100644 --- a/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java +++ b/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java @@ -1,6 +1,6 @@ package homework_7.kittenToCatFunction; @FunctionalInterface -public interface KittenToCatFunction{ +public interface KittenToCatFunction { Cat grow(Kitten k); } diff --git a/src/main/java/homework_7/kittenToCatFunction/Main.java b/src/main/java/homework_7/kittenToCatFunction/Main.java index 19b92f52..466a5338 100644 --- a/src/main/java/homework_7/kittenToCatFunction/Main.java +++ b/src/main/java/homework_7/kittenToCatFunction/Main.java @@ -4,13 +4,21 @@ public class Main { public static void main(String[] args) { - Kitten smallCat = new Kitten(1, "Push"); - KittenToCatFunction function = x -> new Cat(x.getAge() + 2, x.getName(), smallCat); - Cat bigCat = function.grow(smallCat); + Kitten kitten = new EgyptKitten(1, "Push"); - System.out.println("bigCat.getClass() = " + bigCat.getClass()); - System.out.println("bigCat.getAge() = " + bigCat.getAge()); - System.out.println("bigCat.getName() = " + bigCat.getName()); + KittenToCatFunction function = x -> { + if (x instanceof EgyptKitten) { + return new EgyptCat(x.getAge() + 3, x.getName(), x); + } else { + return new SomeCat(x.getAge() + 3, x.getName(), x); + } + }; + + Cat cat = function.grow(kitten); + + System.out.println("bigCat.getClass() = " + cat.getClass()); + System.out.println("bigCat.getAge() = " + cat.getAge()); + System.out.println("bigCat.getName() = " + cat.getName()); } } diff --git a/src/main/java/homework_7/kittenToCatFunction/SomeCat.java b/src/main/java/homework_7/kittenToCatFunction/SomeCat.java new file mode 100644 index 00000000..ad54436d --- /dev/null +++ b/src/main/java/homework_7/kittenToCatFunction/SomeCat.java @@ -0,0 +1,7 @@ +package homework_7.kittenToCatFunction; + +public class SomeCat extends Cat{ + public SomeCat(int age, String name, Kitten kitten) { + super(age, name, kitten); + } +} From 33e175b956678767f5166db17c23939a5d966746 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 22 Sep 2021 15:31:08 +0300 Subject: [PATCH 30/33] course_project. Small bugs fixed. --- .../course_project/sea_battle/model/Player.java | 2 +- .../sea_battle/service/GameModeAndNameSetter.java | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/course_project/sea_battle/model/Player.java b/src/main/java/course_project/sea_battle/model/Player.java index 096cdf60..fe489abb 100644 --- a/src/main/java/course_project/sea_battle/model/Player.java +++ b/src/main/java/course_project/sea_battle/model/Player.java @@ -7,9 +7,9 @@ public class Player { private String name; - private boolean isComputer; private MyBoard myBoard; private MyBoard myShots; + private boolean isComputer; private final List myShips = new ArrayList<>(); public Player(MyBoard myBoard, MyBoard enemyBoard) { diff --git a/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java b/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java index 7e07de2c..ba650d89 100644 --- a/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java +++ b/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java @@ -1,18 +1,18 @@ package course_project.sea_battle.service; import course_project.sea_battle.model.Player; -import course_project.sea_battle.service.inputs.InputShipReader; +import course_project.sea_battle.service.inputs.InputReader; import lombok.SneakyThrows; public class GameModeAndNameSetter { - private final InputShipReader inputShipReader; + private final InputReader inputReader; private static final String SHOOSEGAMEMODE = "Please, choose game mode:\n1: player vs player\n2: player vs computer"; private static final String PL1 = "Player 1, please, input your name:"; private static final String PL2 = "Player 2, please, input your name:"; private int gameMode; - public GameModeAndNameSetter(InputShipReader inputShipReader) { - this.inputShipReader = inputShipReader; + public GameModeAndNameSetter(InputReader inputReader) { + this.inputReader = inputReader; } @SneakyThrows @@ -21,13 +21,13 @@ public void setNames(Player player1, Player player2) { defineGameMode(); System.out.println(PL1); - String player1Name = inputShipReader.readLine(); + String player1Name = inputReader.readLine(); player1.setName(player1Name); System.out.println("Hello, " + player1Name + "!"); if (gameMode == 1) { System.out.println(PL2); - String player2Name = inputShipReader.readLine(); + String player2Name = inputReader.readLine(); player2.setName(player2Name); System.out.println("Hello, " + player2Name + "!"); } else if (gameMode == 2) { @@ -39,7 +39,7 @@ public void setNames(Player player1, Player player2) { private void defineGameMode() { while (true) { System.out.println(SHOOSEGAMEMODE); - String gameModeInput = inputShipReader.readLine(); + String gameModeInput = inputReader.readLine(); if (gameModeInput.matches("[1]|[2]")) { gameMode = Integer.parseInt(gameModeInput); break; From 37642d1fca3d8c451b4e9f55a92ab31e2a37f2c7 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Wed, 22 Sep 2021 17:57:31 +0300 Subject: [PATCH 31/33] course_project. Small bugs fixed. --- .../sea_battle/service/inputs/InputShooterReader.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java index 73655713..3b190caa 100644 --- a/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java @@ -47,7 +47,7 @@ public void checkAndValidatePlayerShot(Player player1, Player player2) { } else { defineShot(); } - if (isShooted(player2)) continue; + if (isShooted(player1, player2)) continue; if (player1.isComputer()) { System.out.println(COMPUTERMOVE); @@ -78,9 +78,11 @@ public boolean isValidInput(String input) { } } - public boolean isShooted(Player enemy) { + public boolean isShooted(Player me, Player enemy) { if (enemy.getMyBoard().getBoard()[x][y] == 3 || enemy.getMyBoard().getBoard()[x][y] == 2) { - System.out.println(CHECKED); + if (!me.isComputer()) { + System.out.println(CHECKED); + } return true; } return false; From 6b82bebda0cdd987ebbcdb4cd21e0e69e4eb5917 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Thu, 23 Sep 2021 08:26:57 +0300 Subject: [PATCH 32/33] course_project. Rearranged some methods and added utils and controller folders. --- .../java/course_project/sea_battle/Main.java | 4 +- .../sea_battle/boards/Board.java | 1 + .../GameController.java} | 6 +- .../sea_battle/model/Point.java | 17 +---- src/main/java/course_project/sea_battle/rules | 2 +- .../service/GameModeAndNameSetter.java | 6 +- .../sea_battle/service/ShipPlacer.java | 15 ++-- .../service/inputs/InputReader.java | 17 ++++- .../service/inputs/InputShipReader.java | 8 +-- .../service/inputs/InputShooterReader.java | 22 ++---- .../sea_battle/utils/Constants.java | 23 ++++++ ...{GameTest.java => GameControllerTest.java} | 71 ++++++++++--------- 12 files changed, 99 insertions(+), 93 deletions(-) rename src/main/java/course_project/sea_battle/{Game.java => controller/GameController.java} (95%) create mode 100644 src/main/java/course_project/sea_battle/utils/Constants.java rename src/test/java/course_project/sea_battle/{GameTest.java => GameControllerTest.java} (71%) diff --git a/src/main/java/course_project/sea_battle/Main.java b/src/main/java/course_project/sea_battle/Main.java index 123db743..56a1518a 100644 --- a/src/main/java/course_project/sea_battle/Main.java +++ b/src/main/java/course_project/sea_battle/Main.java @@ -1,7 +1,9 @@ package course_project.sea_battle; +import course_project.sea_battle.controller.GameController; + public class Main { public static void main(String[] args) { - new Game().start(); + new GameController().start(); } } diff --git a/src/main/java/course_project/sea_battle/boards/Board.java b/src/main/java/course_project/sea_battle/boards/Board.java index 60b8e272..b4c65744 100644 --- a/src/main/java/course_project/sea_battle/boards/Board.java +++ b/src/main/java/course_project/sea_battle/boards/Board.java @@ -20,4 +20,5 @@ public int[][] getBoard() { public void setBoard(int[][] board) { this.board = board; } + } diff --git a/src/main/java/course_project/sea_battle/Game.java b/src/main/java/course_project/sea_battle/controller/GameController.java similarity index 95% rename from src/main/java/course_project/sea_battle/Game.java rename to src/main/java/course_project/sea_battle/controller/GameController.java index 7ea3ed3d..325d9511 100644 --- a/src/main/java/course_project/sea_battle/Game.java +++ b/src/main/java/course_project/sea_battle/controller/GameController.java @@ -1,4 +1,4 @@ -package course_project.sea_battle; +package course_project.sea_battle.controller; import course_project.sea_battle.boards.MyBoard; import course_project.sea_battle.model.Player; @@ -10,7 +10,7 @@ import java.util.Scanner; -public class Game extends Thread { +public class GameController extends Thread { private static final String TIE = "Game over. It's a TIE!"; private static final String GAMEOVER = "Game over. The winner is: "; @@ -20,7 +20,7 @@ public class Game extends Thread { private Player player1; private Player player2; - public Game() { + public GameController() { this.player1 = new Player(new MyBoard(), new MyBoard()); this.player2 = new Player(new MyBoard(), new MyBoard()); } diff --git a/src/main/java/course_project/sea_battle/model/Point.java b/src/main/java/course_project/sea_battle/model/Point.java index 5c849713..ab58e2da 100644 --- a/src/main/java/course_project/sea_battle/model/Point.java +++ b/src/main/java/course_project/sea_battle/model/Point.java @@ -1,23 +1,12 @@ package course_project.sea_battle.model; +import lombok.Data; + +@Data public class Point { private final int x; private final int y; - public Point(int x, int y) { - this.x = x; - this.y = y; - } - - public int getX() { - return x; - } - - - public int getY() { - return y; - } - @Override public String toString() { return "[" + x + diff --git a/src/main/java/course_project/sea_battle/rules b/src/main/java/course_project/sea_battle/rules index 2f3cb65d..47a9b54e 100644 --- a/src/main/java/course_project/sea_battle/rules +++ b/src/main/java/course_project/sea_battle/rules @@ -1,5 +1,5 @@ GENERAL -2 game modes are available: Player vs Player and Player vs Computer (very easy). +2 gameController modes are available: Player vs Player and Player vs Computer (very easy). Each player has 10 ships: 1*4deck, 2*3, 3*2, 4*1. SHIP PLACEMENT diff --git a/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java b/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java index ba650d89..1bee0499 100644 --- a/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java +++ b/src/main/java/course_project/sea_battle/service/GameModeAndNameSetter.java @@ -4,11 +4,11 @@ import course_project.sea_battle.service.inputs.InputReader; import lombok.SneakyThrows; +import static course_project.sea_battle.utils.Constants.*; + public class GameModeAndNameSetter { private final InputReader inputReader; - private static final String SHOOSEGAMEMODE = "Please, choose game mode:\n1: player vs player\n2: player vs computer"; - private static final String PL1 = "Player 1, please, input your name:"; - private static final String PL2 = "Player 2, please, input your name:"; + private int gameMode; public GameModeAndNameSetter(InputReader inputReader) { diff --git a/src/main/java/course_project/sea_battle/service/ShipPlacer.java b/src/main/java/course_project/sea_battle/service/ShipPlacer.java index 048290d5..37d630e5 100644 --- a/src/main/java/course_project/sea_battle/service/ShipPlacer.java +++ b/src/main/java/course_project/sea_battle/service/ShipPlacer.java @@ -10,13 +10,10 @@ import java.util.List; import static course_project.sea_battle.view.BoardPrinter.showBoards; +import static course_project.sea_battle.utils.Constants.*; public class ShipPlacer { private final InputShipReader inputShipReader; - private static final String PLACED = "Ship is placed!"; - private static final String CHOOSESHIPPLACEMENTMODE = ", please, choose ship placement mode:\n1: manual\n2: automatic"; - private static final String NEXTMOVE = "Press ENTER to finish your move"; - private static final String DONE = "\nAll ships are placed!"; private int shipPlacementMode; public ShipPlacer(InputShipReader inputShipReader) { @@ -58,7 +55,9 @@ public void placeShip(Player player1, Player player2) { showBoards(player1); Thread.sleep(200); } - if (!player1.isComputer() && !player2.isComputer()) {printBigSpace();} + if (!player1.isComputer() && !player2.isComputer()) { + inputShipReader.printBigSpace(); + } } public void defineShipPlacementMode(Player player) { @@ -76,10 +75,4 @@ public void defineShipPlacementMode(Player player) { } } - public void printBigSpace() { - System.out.println(NEXTMOVE); - inputShipReader.readLine(); - System.out.println("\n\n\n\n\n\n\n\n\n\n"); - } - } diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputReader.java index f5961288..1493a9b4 100644 --- a/src/main/java/course_project/sea_battle/service/inputs/InputReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputReader.java @@ -2,6 +2,9 @@ import java.util.Scanner; +import static course_project.sea_battle.utils.Constants.NEXTMOVE; +import static course_project.sea_battle.utils.Constants.NEXTMOVE2; + public abstract class InputReader { protected Scanner scanner; @@ -9,7 +12,17 @@ public String readLine() { return scanner.nextLine(); } - public Scanner getScanner() { - return scanner; + public void printBigSpace() { + System.out.println(NEXTMOVE); + readLine(); + System.out.println("\n\n\n\n\n\n\n\n\n\n"); + } + + public void printBigSpaceInShooter(boolean hasSence) { + if (hasSence) { + System.out.println(NEXTMOVE2); + readLine(); + System.out.println("\n\n\n\n\n\n\n\n\n\n"); + } } } diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java index fd86f6ad..c3df2c4e 100644 --- a/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java @@ -5,6 +5,8 @@ import java.util.*; +import static course_project.sea_battle.utils.Constants.*; + public class InputShipReader extends InputReader { private int x; private int y; @@ -13,10 +15,6 @@ public class InputShipReader extends InputReader { private String position; private List coordinates; - private static final String INPUTERROR = "Input should be like this: [A7 h] or [B2 h]. Try again!"; - private static final String OUTOFBOARD = "Impossible to place ship here because it is out of board!"; - private static final String SHIPSCROSS = "Impossible to place ship here because ship crosses with another one!"; - public InputShipReader(Scanner scanner) { this.scanner = scanner; } @@ -51,7 +49,7 @@ public boolean isValidInput(String input) { position = coords[1].toLowerCase(); return true; } else { - System.out.println(INPUTERROR); + System.out.println(INPUTSHIPERROR); return false; } } diff --git a/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java index 3b190caa..9ec52f6c 100644 --- a/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java @@ -10,6 +10,7 @@ import java.util.*; import java.util.stream.Collectors; +import static course_project.sea_battle.utils.Constants.*; import static course_project.sea_battle.view.BoardPrinter.showBoards; public class InputShooterReader extends InputReader { @@ -19,13 +20,6 @@ public class InputShooterReader extends InputReader { private Ship currentShip; private Random random = new Random(); - private static final String MAKESHOT = ", make your shot in format: [A6] or [b1]"; - private static final String INPUTERROR = "Input should be like this: [A7] or [b2]. Try again!"; - private static final String CHECKED = "Cell is checked. Make another shot!"; - private static final String KILLALL = ", you destroyed all enemy ships. Congratulations!"; - private static final String NEXTMOVE = "Press ENTER to finish your move"; - private static final String COMPUTERMOVE = "Computer is thinking..."; - public InputShooterReader(Scanner scanner) { this.scanner = scanner; } @@ -73,7 +67,7 @@ public boolean isValidInput(String input) { x = Integer.parseInt(input.substring(1)) - 1; return true; } else { - System.out.println(INPUTERROR); + System.out.println(INPUTSHOTERROR); return false; } } @@ -181,7 +175,7 @@ public boolean isGameContinue(Player me, Player enemy, Shot shot) { } if (enemy.countShips() == 0) { System.out.println(me.getName() + KILLALL); - printBigSpace(!me.isComputer() && !enemy.isComputer()); + printBigSpaceInShooter(!me.isComputer() && !enemy.isComputer()); return false; } else { if (!me.isComputer()) { @@ -206,18 +200,10 @@ public boolean isGameContinue(Player me, Player enemy, Shot shot) { } else { showBoards(enemy); } - printBigSpace(!me.isComputer() && !enemy.isComputer()); + printBigSpaceInShooter(!me.isComputer() && !enemy.isComputer()); return false; } return true; } - public void printBigSpace(boolean hasSence) { - if (hasSence) { - System.out.println(NEXTMOVE); - readLine(); - System.out.println("\n\n\n\n\n\n\n\n\n\n"); - } - } - } diff --git a/src/main/java/course_project/sea_battle/utils/Constants.java b/src/main/java/course_project/sea_battle/utils/Constants.java new file mode 100644 index 00000000..a03a6390 --- /dev/null +++ b/src/main/java/course_project/sea_battle/utils/Constants.java @@ -0,0 +1,23 @@ +package course_project.sea_battle.utils; + +public class Constants { + public static final String SHOOSEGAMEMODE = "Please, choose game mode:\n1: player vs player\n2: player vs computer"; + public static final String PL1 = "Player 1, please, input your name:"; + public static final String PL2 = "Player 2, please, input your name:"; + + public static final String PLACED = "Ship is placed!"; + public static final String CHOOSESHIPPLACEMENTMODE = ", please, choose ship placement mode:\n1: manual\n2: automatic"; + public static final String NEXTMOVE = "Press ENTER to finish your move"; + public static final String DONE = "\nAll ships are placed!"; + + public static final String INPUTSHIPERROR = "Input should be like this: [A7 h] or [B2 h]. Try again!"; + public static final String OUTOFBOARD = "Impossible to place ship here because it is out of board!"; + public static final String SHIPSCROSS = "Impossible to place ship here because ship crosses with another one!"; + + public static final String MAKESHOT = ", make your shot in format: [A6] or [b1]"; + public static final String INPUTSHOTERROR = "Input should be like this: [A7] or [b2]. Try again!"; + public static final String CHECKED = "Cell is checked. Make another shot!"; + public static final String KILLALL = ", you destroyed all enemy ships. Congratulations!"; + public static final String NEXTMOVE2 = "Press ENTER to finish your move"; + public static final String COMPUTERMOVE = "Computer is thinking..."; +} diff --git a/src/test/java/course_project/sea_battle/GameTest.java b/src/test/java/course_project/sea_battle/GameControllerTest.java similarity index 71% rename from src/test/java/course_project/sea_battle/GameTest.java rename to src/test/java/course_project/sea_battle/GameControllerTest.java index 94f6ff80..e3bdc77a 100644 --- a/src/test/java/course_project/sea_battle/GameTest.java +++ b/src/test/java/course_project/sea_battle/GameControllerTest.java @@ -1,6 +1,7 @@ package course_project.sea_battle; import base.UnitBase; +import course_project.sea_battle.controller.GameController; import course_project.sea_battle.model.Player; import course_project.sea_battle.model.Point; import course_project.sea_battle.model.Ship; @@ -16,7 +17,7 @@ import static org.junit.jupiter.api.Assertions.*; -class GameTest extends UnitBase { +class GameControllerTest extends UnitBase { private static final String INPUTSHIPERROR = "Input should be like this: [A7 h] or [B2 h]. Try again!"; private static final String OUTOFBOARD = "Impossible to place ship here because it is out of board!"; @@ -30,11 +31,11 @@ void testNameSetter() { "Vera\n"; setInput(input); - Game game = new Game(); - game.setUpNames(); + GameController gameController = new GameController(); + gameController.setUpNames(); - Player player1 = game.getPlayer1(); - Player player2 = game.getPlayer2(); + Player player1 = gameController.getPlayer1(); + Player player2 = gameController.getPlayer2(); assertEquals("Tom", player1.getName()); assertEquals("Vera", player2.getName()); @@ -68,11 +69,11 @@ void testValidCoordsShipPlacing() { "\n"; setInput(input); - Game game = new Game(); - game.setUpShips(); + GameController gameController = new GameController(); + gameController.setUpShips(); - long numOfShips1 = game.getPlayer1().countShips(); - long numOfShips2 = game.getPlayer2().countShips(); + long numOfShips1 = gameController.getPlayer1().countShips(); + long numOfShips2 = gameController.getPlayer2().countShips(); assertEquals(10, numOfShips1); assertEquals(10, numOfShips2); @@ -110,11 +111,11 @@ void testOnlyValidCoordsShipPlacing() { "\n"; setInput(input); - Game game = new Game(); - game.setUpShips(); + GameController gameController = new GameController(); + gameController.setUpShips(); - long numOfShips1 = game.getPlayer1().countShips(); - long numOfShips2 = game.getPlayer2().countShips(); + long numOfShips1 = gameController.getPlayer1().countShips(); + long numOfShips2 = gameController.getPlayer2().countShips(); assertEquals(10, numOfShips1); assertEquals(10, numOfShips2); @@ -128,11 +129,11 @@ void testComputerShipPlacing() { "\n"; setInput(input); - Game game = new Game(); - game.setUpShips(); + GameController gameController = new GameController(); + gameController.setUpShips(); - long numOfShips1 = game.getPlayer1().countShips(); - long numOfShips2 = game.getPlayer2().countShips(); + long numOfShips1 = gameController.getPlayer1().countShips(); + long numOfShips2 = gameController.getPlayer2().countShips(); assertEquals(10, numOfShips1); assertEquals(10, numOfShips2); @@ -176,25 +177,25 @@ void testShooter() { coordinates.add(new Point(9, 9)); Ship ship2 = new Ship(coordinates2); - Game game = new Game(); - game.getPlayer1().getMyShips().add(ship); - game.getPlayer2().getMyShips().add(ship2); + GameController gameController = new GameController(); + gameController.getPlayer1().getMyShips().add(ship); + gameController.getPlayer2().getMyShips().add(ship2); - game.getPlayer1().getMyBoard().placeShip(ship); - game.getPlayer2().getMyBoard().placeShip(ship2); + gameController.getPlayer1().getMyBoard().placeShip(ship); + gameController.getPlayer2().getMyBoard().placeShip(ship2); - int numOfPlayer1AllShips = game.getPlayer1().getMyShips().size(); - int numOfPlayer2AllShips = game.getPlayer1().getMyShips().size(); + int numOfPlayer1AllShips = gameController.getPlayer1().getMyShips().size(); + int numOfPlayer2AllShips = gameController.getPlayer1().getMyShips().size(); assertEquals(1, numOfPlayer1AllShips); assertEquals(1, numOfPlayer2AllShips); - game.play(); + gameController.play(); - long numOfPlayer1AliveShips = game.getPlayer1().getMyShips().stream() + long numOfPlayer1AliveShips = gameController.getPlayer1().getMyShips().stream() .filter(Ship::isAlive) .count(); - long numOfPlayer2AliveShips = game.getPlayer2().getMyShips().stream() + long numOfPlayer2AliveShips = gameController.getPlayer2().getMyShips().stream() .filter(Ship::isAlive) .count(); @@ -204,31 +205,31 @@ void testShooter() { @Test void testDefineWinner() { - Game game = new Game(); - Player player1 = game.getPlayer1(); - Player player2 = game.getPlayer2(); + GameController gameController = new GameController(); + Player player1 = gameController.getPlayer1(); + Player player2 = gameController.getPlayer2(); player1.setName("Tom"); player2.setName("Vera"); Ship ship = new Ship(Arrays.asList(new Point(1, 1))); - List tomShips = game.getPlayer1().getMyShips(); + List tomShips = gameController.getPlayer1().getMyShips(); tomShips.add(ship); - game.defineWinner(); + gameController.defineWinner(); assertEquals(GAMEOVER + "Tom!", getOutput()); removeFromOutput(GAMEOVER + "Tom!"); - List veraShips = game.getPlayer2().getMyShips(); + List veraShips = gameController.getPlayer2().getMyShips(); veraShips.add(ship); tomShips.remove(0); - game.defineWinner(); + gameController.defineWinner(); assertEquals(GAMEOVER + "Vera!", getOutput()); removeFromOutput(GAMEOVER + "Vera!"); veraShips.remove(0); - game.defineWinner(); + gameController.defineWinner(); assertEquals(TIE, getOutput()); } From 4e09aa0186e9cca6957f5b84b0feb52acc515cb0 Mon Sep 17 00:00:00 2001 From: Tom Shandrikov Date: Thu, 23 Sep 2021 08:31:10 +0300 Subject: [PATCH 33/33] course_project. Hope, last commit. Few changes more. --- .../sea_battle/controller/GameController.java | 4 ++-- .../course_project/sea_battle/utils/Constants.java | 11 +++++++++++ .../course_project/sea_battle/view/BoardPrinter.java | 11 ++--------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/java/course_project/sea_battle/controller/GameController.java b/src/main/java/course_project/sea_battle/controller/GameController.java index 325d9511..b4d29fa5 100644 --- a/src/main/java/course_project/sea_battle/controller/GameController.java +++ b/src/main/java/course_project/sea_battle/controller/GameController.java @@ -10,9 +10,9 @@ import java.util.Scanner; +import static course_project.sea_battle.utils.Constants.*; + public class GameController extends Thread { - private static final String TIE = "Game over. It's a TIE!"; - private static final String GAMEOVER = "Game over. The winner is: "; private final Scanner scanner = new Scanner(System.in); private final InputShipReader inputShipReader = new InputShipReader(scanner); diff --git a/src/main/java/course_project/sea_battle/utils/Constants.java b/src/main/java/course_project/sea_battle/utils/Constants.java index a03a6390..b9a2ac4a 100644 --- a/src/main/java/course_project/sea_battle/utils/Constants.java +++ b/src/main/java/course_project/sea_battle/utils/Constants.java @@ -14,10 +14,21 @@ public class Constants { public static final String OUTOFBOARD = "Impossible to place ship here because it is out of board!"; public static final String SHIPSCROSS = "Impossible to place ship here because ship crosses with another one!"; + public static final String RED = "\u001B[31m"; + public static final String GREEN = "\u001B[32m"; + public static final String RESET = "\u001B[0m"; + public static final String CYAN = "\u001B[36m"; + public static final String MISS = GREEN + "0" + RESET; + public static final String HIT = RED + "X" + RESET; + public static final String WAVE = CYAN + "~" + RESET; + public static final String MAKESHOT = ", make your shot in format: [A6] or [b1]"; public static final String INPUTSHOTERROR = "Input should be like this: [A7] or [b2]. Try again!"; public static final String CHECKED = "Cell is checked. Make another shot!"; public static final String KILLALL = ", you destroyed all enemy ships. Congratulations!"; public static final String NEXTMOVE2 = "Press ENTER to finish your move"; public static final String COMPUTERMOVE = "Computer is thinking..."; + + public static final String TIE = "Game over. It's a TIE!"; + public static final String GAMEOVER = "Game over. The winner is: "; } diff --git a/src/main/java/course_project/sea_battle/view/BoardPrinter.java b/src/main/java/course_project/sea_battle/view/BoardPrinter.java index ab305f40..36620669 100644 --- a/src/main/java/course_project/sea_battle/view/BoardPrinter.java +++ b/src/main/java/course_project/sea_battle/view/BoardPrinter.java @@ -1,17 +1,10 @@ package course_project.sea_battle.view; - import course_project.sea_battle.model.Player; -public class BoardPrinter { - private static final String RED = "\u001B[31m"; - private static final String GREEN = "\u001B[32m"; - private static final String RESET = "\u001B[0m"; - private static final String CYAN = "\u001B[36m"; +import static course_project.sea_battle.utils.Constants.*; - private static final String MISS = GREEN + "0" + RESET; - private static final String HIT = RED + "X" + RESET; - private static final String WAVE = CYAN + "~" + RESET; +public class BoardPrinter { public static synchronized void showBoards(Player player) { int[][] myField = player.getMyBoard().getBoard();