diff --git a/README.md b/README.md index 5d686e9f..cb6ee53b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,26 @@ # Java Core June 2021 -## *Nikolaev Artem* +## *Tom Shandrikov* | Number | Solution | Short description | --- | --- | --- | -| HW1 | [Console printer](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/master/src/main/java/homework_1) | The app that reads input arguments and prints them, until "error" argument | +| 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.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) | 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. | +| 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) + +[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..820ef2b2 100644 --- a/build.gradle +++ b/build.gradle @@ -10,8 +10,16 @@ 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' + + testCompile("org.junit.jupiter:junit-jupiter-params:5.7.0") } test { 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 00000000..3c829327 Binary files /dev/null and b/src/main/java/course_project/sea_battle/GamePlayUpd.png differ 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..56a1518a --- /dev/null +++ b/src/main/java/course_project/sea_battle/Main.java @@ -0,0 +1,9 @@ +package course_project.sea_battle; + +import course_project.sea_battle.controller.GameController; + +public class Main { + public static void main(String[] args) { + 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 new file mode 100644 index 00000000..b4c65744 --- /dev/null +++ b/src/main/java/course_project/sea_battle/boards/Board.java @@ -0,0 +1,24 @@ +package course_project.sea_battle.boards; + +public 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/boards/MyBoard.java b/src/main/java/course_project/sea_battle/boards/MyBoard.java new file mode 100644 index 00000000..836e0ae1 --- /dev/null +++ b/src/main/java/course_project/sea_battle/boards/MyBoard.java @@ -0,0 +1,17 @@ +package course_project.sea_battle.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/controller/GameController.java b/src/main/java/course_project/sea_battle/controller/GameController.java new file mode 100644 index 00000000..b4d29fa5 --- /dev/null +++ b/src/main/java/course_project/sea_battle/controller/GameController.java @@ -0,0 +1,78 @@ +package course_project.sea_battle.controller; + +import course_project.sea_battle.boards.MyBoard; +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.GameModeAndNameSetter; +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.utils.Constants.*; + +public class GameController extends Thread { + + private final Scanner scanner = new Scanner(System.in); + private final InputShipReader inputShipReader = new InputShipReader(scanner); + + private Player player1; + private Player player2; + + public GameController() { + this.player1 = new Player(new MyBoard(), new MyBoard()); + this.player2 = new Player(new MyBoard(), new MyBoard()); + } + + @Override + public void run() { + setUpNames(); + setUpShips(); + play(); + defineWinner(); + } + + public void setUpNames() { + new GameModeAndNameSetter(inputShipReader).setNames(player1, player2); + } + + public void setUpShips() { + new ShipPlacer(inputShipReader).placeShip(player1, player2); + new ShipPlacer(inputShipReader).placeShip(player2, player1); + } + + public void play() { + while (bothPlayersHaveShips(player1, player2)) { + new InputShooterReader(scanner).checkAndValidatePlayerShot(player1, player2); + new InputShooterReader(scanner).checkAndValidatePlayerShot(player2, player1); + } + } + + 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(); + } + + 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() + "!"); + } + } + + public Player getPlayer1() { + return player1; + } + + public Player getPlayer2() { + return player2; + } + +} 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..fe489abb --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/Player.java @@ -0,0 +1,53 @@ +package course_project.sea_battle.model; + +import course_project.sea_battle.boards.MyBoard; + +import java.util.ArrayList; +import java.util.List; + +public class Player { + private String name; + private MyBoard myBoard; + private MyBoard myShots; + private boolean isComputer; + private final List myShips = new ArrayList<>(); + + public Player(MyBoard myBoard, MyBoard enemyBoard) { + this.myBoard = myBoard; + this.myShots = enemyBoard; + myBoard.setBasicGrids(); + myShots.setBasicGrids(); + } + + public long countShips() { + return getMyShips().stream().filter(Ship::isAlive).count(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getMyShips() { + return myShips; + } + + public MyBoard getMyBoard() { + return myBoard; + } + + 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/model/Point.java b/src/main/java/course_project/sea_battle/model/Point.java new file mode 100644 index 00000000..ab58e2da --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/Point.java @@ -0,0 +1,29 @@ +package course_project.sea_battle.model; + +import lombok.Data; + +@Data +public class Point { + private final int x; + private final int y; + + @Override + public String toString() { + return "[" + x + + "," + 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..36704528 --- /dev/null +++ b/src/main/java/course_project/sea_battle/model/Ship.java @@ -0,0 +1,30 @@ +package course_project.sea_battle.model; + +import java.util.List; + +public class Ship { + private final List coordinates; + private int lives; + + public Ship(List coordinates) { + this.coordinates = coordinates; + this.lives = coordinates.size(); + } + + public int getLives() { + return lives; + } + + public void setLives(int lives) { + this.lives = lives; + } + + public boolean isAlive() { + return lives > 0; + } + + public List getCoordinates() { + return 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/rules b/src/main/java/course_project/sea_battle/rules new file mode 100644 index 00000000..47a9b54e --- /dev/null +++ b/src/main/java/course_project/sea_battle/rules @@ -0,0 +1,18 @@ +GENERAL +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 +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]. + +RULES +Shot format: [A7] or [b1]. +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..1bee0499 --- /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.InputReader; +import lombok.SneakyThrows; + +import static course_project.sea_battle.utils.Constants.*; + +public class GameModeAndNameSetter { + private final InputReader inputReader; + + private int gameMode; + + public GameModeAndNameSetter(InputReader inputReader) { + this.inputReader = inputReader; + } + + @SneakyThrows + public void setNames(Player player1, Player player2) { + + defineGameMode(); + + System.out.println(PL1); + String player1Name = inputReader.readLine(); + player1.setName(player1Name); + System.out.println("Hello, " + player1Name + "!"); + + if (gameMode == 1) { + System.out.println(PL2); + String player2Name = inputReader.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 = inputReader.readLine(); + if (gameModeInput.matches("[1]|[2]")) { + gameMode = Integer.parseInt(gameModeInput); + break; + } + } + } + +} 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..37d630e5 --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/ShipPlacer.java @@ -0,0 +1,78 @@ +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.service.inputs.InputShipReader; +import lombok.SneakyThrows; + +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 int shipPlacementMode; + + public ShipPlacer(InputShipReader inputShipReader) { + this.inputShipReader = inputShipReader; + } + + @SneakyThrows + public void placeShip(Player player1, Player player2) { + + defineShipPlacementMode(player1); + + 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 (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, shipPlacementMode); + List coordinates = inputShipReader.getValidCoordinates(); + + Ship ship = new Ship(coordinates); + board.placeShip(ship); + player1.getMyShips().add(ship); + + if (shipPlacementMode == 1) { + System.out.println(PLACED); + showBoards(player1); + } + } + } + + if (shipPlacementMode == 2 && !player1.isComputer()) { + System.out.println(DONE); + showBoards(player1); + Thread.sleep(200); + } + if (!player1.isComputer() && !player2.isComputer()) { + inputShipReader.printBigSpace(); + } + } + + 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/InputReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputReader.java new file mode 100644 index 00000000..1493a9b4 --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/inputs/InputReader.java @@ -0,0 +1,28 @@ +package course_project.sea_battle.service.inputs; + +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; + + public String readLine() { + return scanner.nextLine(); + } + + 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 new file mode 100644 index 00000000..c3df2c4e --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShipReader.java @@ -0,0 +1,146 @@ +package course_project.sea_battle.service.inputs; + +import course_project.sea_battle.boards.MyBoard; +import course_project.sea_battle.model.Point; + +import java.util.*; + +import static course_project.sea_battle.utils.Constants.*; + +public class InputShipReader extends InputReader { + private int x; + private int y; + private Random random = new Random(); + + private String position; + private List coordinates; + + public InputShipReader(Scanner scanner) { + this.scanner = scanner; + } + + public void getAndValidateInput(int shipSize, MyBoard board, int gameMode) { + while (true) { + if (gameMode == 1) { + String input = readLine(); + if (!isValidInput(input)) continue; + } else if (gameMode == 2) { + getAutomaticCoordinates(); + } + + Point topLeftPoint = new Point(x, y); + if (!isShipWithinBoard(shipSize, gameMode)) continue; + coordinates = findCoordinates(shipSize, topLeftPoint); + if (shipsDoNotCross(board, shipSize, gameMode)) break; + } + } + + public void getAutomaticCoordinates() { + 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(" "); + 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(INPUTSHIPERROR); + return false; + } + } + + 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) { + if (gameMode == 1) 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, int gameMode) { + 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) { + if (gameMode == 1) System.out.println(SHIPSCROSS); + return false; + } + return true; + } + + 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/inputs/InputShooterReader.java b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java new file mode 100644 index 00000000..9ec52f6c --- /dev/null +++ b/src/main/java/course_project/sea_battle/service/inputs/InputShooterReader.java @@ -0,0 +1,209 @@ +package course_project.sea_battle.service.inputs; + +import course_project.sea_battle.boards.Board; +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.*; +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 { + private int x; + private int y; + private Shot shot; + private Ship currentShip; + private Random random = new Random(); + + public InputShooterReader(Scanner scanner) { + this.scanner = scanner; + } + + @SneakyThrows + public void checkAndValidatePlayerShot(Player player1, Player player2) { + if (!player1.isComputer()) { + if (!player2.isComputer()) { + showBoards(player1); + } + System.out.println(player1.getName() + MAKESHOT); + } + + while (true) { + + if (!player1.isComputer()) { + String input = readLine(); + if (!isValidInput(input)) continue; + } else { + defineShot(); + } + if (isShooted(player1, player2)) continue; + + 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); + + if (!isGameContinue(player1, player2, shot)) break; + } + } + + 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; + x = Integer.parseInt(input.substring(1)) - 1; + return true; + } else { + System.out.println(INPUTSHOTERROR); + return false; + } + } + + public boolean isShooted(Player me, Player enemy) { + if (enemy.getMyBoard().getBoard()[x][y] == 3 || enemy.getMyBoard().getBoard()[x][y] == 2) { + if (!me.isComputer()) { + System.out.println(CHECKED); + } + return true; + } + return false; + } + + public void getShotResult(Player enemy) { + if (enemy.getMyBoard().getBoard()[x][y] == 1) { + findOutHitOrKilled(enemy); + } else { + shot = Shot.MISS; + } + } + + 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) { + shot = Shot.KILLED; + currentShip = ship; + } else { + shot = Shot.HIT; + } + } + } + } + + public static void putOnBoard(Board board, Point shotPoint, Shot shot) { + int[][] tempBoard = board.getBoard(); + if (shot == Shot.MISS) { + tempBoard[shotPoint.getX()][shotPoint.getY()] = 2; + } else { + tempBoard[shotPoint.getX()][shotPoint.getY()] = 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(); + + 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[][] enemyMainBoard = enemy.getMyBoard().getBoard(); + + Set filteredPointsAround = coordinatesAroundTheShip.stream() + .distinct() + .filter(e -> (enemyMainBoard[e.getX()][e.getY()] == 0)) + .collect(Collectors.toSet()); + + for (Point point : filteredPointsAround) { + putOnBoard(me.getMyShots(), point, Shot.MISS); + putOnBoard(enemy.getMyBoard(), point, Shot.MISS); + } + } + + @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(500); + if (!me.isComputer()) { + showBoards(me); + } else { + showBoards(enemy); + } + if (enemy.countShips() == 0) { + System.out.println(me.getName() + KILLALL); + printBigSpaceInShooter(!me.isComputer() && !enemy.isComputer()); + return false; + } else { + if (!me.isComputer()) { + System.out.println(me.getName() + MAKESHOT); + } + } + } else if (shot == Shot.HIT) { + System.err.println("HIT!"); + 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(500); + if (!me.isComputer()) { + showBoards(me); + } else { + showBoards(enemy); + } + printBigSpaceInShooter(!me.isComputer() && !enemy.isComputer()); + return false; + } + return true; + } + +} 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..b9a2ac4a --- /dev/null +++ b/src/main/java/course_project/sea_battle/utils/Constants.java @@ -0,0 +1,34 @@ +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 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 new file mode 100644 index 00000000..36620669 --- /dev/null +++ b/src/main/java/course_project/sea_battle/view/BoardPrinter.java @@ -0,0 +1,71 @@ +package course_project.sea_battle.view; + +import course_project.sea_battle.model.Player; + +import static course_project.sea_battle.utils.Constants.*; + +public class BoardPrinter { + + public static synchronized 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", "W"); + break; + case 2: + System.out.printf(" %s", MISS); + break; + case 3: + System.out.printf(" %s", HIT); + break; + default: + } + } 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 2: + System.out.printf(" %s", MISS); + break; + case 3: + System.out.printf(" %s", HIT); + break; + default: + } + } + } + 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) + " "); + } + } +} diff --git a/src/main/java/homework_1/Main.java b/src/main/java/homework_1/Main.java index 07c029a2..e2df3188 100644 --- a/src/main/java/homework_1/Main.java +++ b/src/main/java/homework_1/Main.java @@ -2,8 +2,17 @@ public class Main { - public static void main(String[] args) { - System.out.println("Hello homework!"); - } + private static final String RED = "\u001B[31m"; + private static final String BLACK = "\u001B[0m"; + public static void main(String[] args) { + + 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/homework_2/pyramid_printer/Main.java b/src/main/java/homework_2/pyramid_printer/Main.java new file mode 100644 index 00000000..71e33035 --- /dev/null +++ b/src/main/java/homework_2/pyramid_printer/Main.java @@ -0,0 +1,8 @@ +package homework_2.pyramid_printer; + +public class Main { + + public static void main(String[] args) { + 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 new file mode 100644 index 00000000..70ee7dbe --- /dev/null +++ b/src/main/java/homework_2/pyramid_printer/PyramidPrinter.java @@ -0,0 +1,45 @@ +package homework_2.pyramid_printer; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class PyramidPrinter { + + 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:"); + + try { + int countX = bufferedReaderReadConsole(); + validateInput(countX); + printConsole(countX); + } catch (IOException | IllegalArgumentException e) { + System.out.println(ERROR); + } + } + + private void printConsole(int countX) { + StringBuilder result = new StringBuilder(""); + for (int i = 1; i <= countX; i++) { + for (int j = 0; j < i; j++) { + result.append("x"); + } + result.append("\n"); + } + System.out.println(result); + } + + private int bufferedReaderReadConsole() throws IOException, NumberFormatException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + return Integer.parseInt(reader.readLine()); + } + } + + private void validateInput(int i) { + if (i < 0) { + throw new IllegalArgumentException(); + } + } +} 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..be586c4b --- /dev/null +++ b/src/main/java/homework_2/random_chars_table/Main.java @@ -0,0 +1,8 @@ +package homework_2.random_chars_table; + +public class Main { + + public static void main(String[] args) { + 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 new file mode 100644 index 00000000..0db0598c --- /dev/null +++ b/src/main/java/homework_2/random_chars_table/RandomCharsTable.java @@ -0,0 +1,85 @@ +package homework_2.random_chars_table; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Random; + +public class RandomCharsTable { + + private 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; + + public void run() { + + System.out.println("[Input example: 2 3 odd]"); + System.out.println("Please, input 2 positive numbers and a strategy (even/odd)"); + + try { + String inputFull = bufferedReaderReadConsole(); + parseInput(inputFull); + validateInputData(length, width, strategy); + String strategyRes = createCharTable(); + System.out.println(strategyRes); + } catch (IOException | IllegalArgumentException e) { + System.out.println(ERROR); + } + } + + private String bufferedReaderReadConsole() throws IOException, NumberFormatException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + return reader.readLine(); + } + } + + private void parseInput(String s) { + + String[] array = s.split(" "); + + if (array.length != 3) { + 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) { + if (x < 1 || y < 1 || (!str.equals("odd") && !str.equals("even"))) { + throw new IllegalArgumentException(); + } + } + + 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++) { + Random r = new Random(); + int x = (r.nextInt(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/Main.java b/src/main/java/homework_2/traffic_light/Main.java new file mode 100644 index 00000000..3ff7f428 --- /dev/null +++ b/src/main/java/homework_2/traffic_light/Main.java @@ -0,0 +1,8 @@ +package homework_2.traffic_light; + +public class Main { + + public static void main(String[] args) { + 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 new file mode 100644 index 00000000..0c09df39 --- /dev/null +++ b/src/main/java/homework_2/traffic_light/TrafficLight.java @@ -0,0 +1,50 @@ +package homework_2.traffic_light; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class TrafficLight { + + 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:"); + try { + int seconds = bufferedReaderReadConsole(); + validateInput(seconds); + System.out.println(showLight(seconds)); + } catch (NumberFormatException | IOException ex) { + System.out.println(ERROR); + } catch (IllegalArgumentException ex) { + System.out.println(ex.getMessage()); + } + } + + private int bufferedReaderReadConsole() throws IOException, NumberFormatException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + return Integer.parseInt(reader.readLine()); + } + } + + private void validateInput(int i) throws IllegalArgumentException{ + if (i < 0) { + throw new IllegalArgumentException(ERROR); + } else if (i > 86399) { + throw new IllegalArgumentException("The day is over"); + } + } + + private String showLight(int i) { + + int secondsMod = i % 60; + return secondsMod < 35 ? GREEN + : secondsMod < 40 ? YELLOW + : secondsMod < 55 ? RED + : YELLOW; + } +} 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 + + '}'; + } + +} + 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..30e1782f --- /dev/null +++ b/src/main/java/homework_4/customAnnotation/ClassCoffeeAnnotation.java @@ -0,0 +1,32 @@ +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..2ef376ce --- /dev/null +++ b/src/main/java/homework_4/customAnnotation/Coffee.java @@ -0,0 +1,35 @@ +package homework_4.customAnnotation; + +@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(); + } + + @AskForCoffeeAnnotation("Give me please this one!") + public void askForCoffee() throws NoSuchMethodException { + 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..f801fd40 --- /dev/null +++ b/src/main/java/homework_4/customAnnotation/Main.java @@ -0,0 +1,31 @@ +package homework_4.customAnnotation; + +import java.lang.reflect.Method; + +public class Main { + public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { + + Coffee myCoffee = new Coffee(); + + System.out.println("Size: " + myCoffee.size); + System.out.println("With milk: " + myCoffee.hasMilk); + System.out.println("Price: " + myCoffee.price + "₽"); + + 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 new file mode 100644 index 00000000..49b20eb5 --- /dev/null +++ b/src/main/java/homework_4/customFileReader/CustomFileReader.java @@ -0,0 +1,72 @@ +package homework_4.customFileReader; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Scanner; + +public class CustomFileReader { + + private final String filename; + + private final StringBuilder result = new StringBuilder(); + + public CustomFileReader(String filename) { + this.filename = filename; + } + + // using FileReader + public void run1() throws IOException { + + try (FileReader reader = new FileReader(filename)) { + int ch; + while ((ch = reader.read()) != -1) { + char x = (char) ch; + if (x == '.' || x == ',') { + continue; + } + result.append(x); + } + } + System.out.println(result); + } + + + // using BufferedReader + public void run2() throws IOException { + + try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { + String line; + while ((line = reader.readLine()) != null) { + line = line.replaceAll("[,.]", ""); + result.append(line + "\n"); + } + } + System.out.println(result); + } + + // using Scanner + public void run3() throws IOException { + + try (Scanner scanner = new Scanner(Paths.get(filename))) { + String line; + while (scanner.hasNextLine()) { + line = scanner.nextLine().replaceAll("[,.]", ""); + result.append(line + "\n"); + } + } + System.out.println(result); + } + + // using Files.readAllBytes + public void run4() throws IOException { + + 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 new file mode 100644 index 00000000..dd4b4a7d --- /dev/null +++ b/src/main/java/homework_4/customFileReader/Main.java @@ -0,0 +1,16 @@ +package homework_4.customFileReader; + +import java.io.IOException; + +public class Main { + + private static String filename = "src/main/resources/custom_file_reader/file.txt"; + + public static void main(String[] args) throws IOException { + new CustomFileReader(filename).run1(); + new CustomFileReader(filename).run2(); + new CustomFileReader(filename).run3(); + new CustomFileReader(filename).run4(); + } + +} 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..da06f6ba --- /dev/null +++ b/src/main/java/homework_4/singleton/Singleton.java @@ -0,0 +1,37 @@ +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; + } + +} 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/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/main/java/homework_7/kittenToCatFunction/Cat.java b/src/main/java/homework_7/kittenToCatFunction/Cat.java new file mode 100644 index 00000000..01d79ad1 --- /dev/null +++ b/src/main/java/homework_7/kittenToCatFunction/Cat.java @@ -0,0 +1,37 @@ +package homework_7.kittenToCatFunction; + +public abstract class Cat { + private int age; + private String name; + private Kitten kitten; + + 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() { + 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/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 new file mode 100644 index 00000000..b6b37052 --- /dev/null +++ b/src/main/java/homework_7/kittenToCatFunction/Kitten.java @@ -0,0 +1,27 @@ +package homework_7.kittenToCatFunction; + +public abstract 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/kittenToCatFunction/KittenToCatFunction.java b/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java new file mode 100644 index 00000000..1d29e024 --- /dev/null +++ b/src/main/java/homework_7/kittenToCatFunction/KittenToCatFunction.java @@ -0,0 +1,6 @@ +package homework_7.kittenToCatFunction; + +@FunctionalInterface +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 new file mode 100644 index 00000000..466a5338 --- /dev/null +++ b/src/main/java/homework_7/kittenToCatFunction/Main.java @@ -0,0 +1,24 @@ +package homework_7.kittenToCatFunction; + +public class Main { + + public static void main(String[] args) { + + Kitten kitten = new EgyptKitten(1, "Push"); + + 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); + } +} 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/course_project/sea_battle/GameControllerTest.java b/src/test/java/course_project/sea_battle/GameControllerTest.java new file mode 100644 index 00000000..e3bdc77a --- /dev/null +++ b/src/test/java/course_project/sea_battle/GameControllerTest.java @@ -0,0 +1,236 @@ +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; +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 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!"; + 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 = "1\n" + + "Tom\n" + + "Vera\n"; + setInput(input); + + GameController gameController = new GameController(); + gameController.setUpNames(); + + Player player1 = gameController.getPlayer1(); + Player player2 = gameController.getPlayer2(); + + assertEquals("Tom", player1.getName()); + assertEquals("Vera", player2.getName()); + } + + @Test + void testValidCoordsShipPlacing() { + String input = "1\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" + + "1\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); + + GameController gameController = new GameController(); + gameController.setUpShips(); + + long numOfShips1 = gameController.getPlayer1().countShips(); + long numOfShips2 = gameController.getPlayer2().countShips(); + + assertEquals(10, numOfShips1); + assertEquals(10, numOfShips2); + } + + @Test + void testOnlyValidCoordsShipPlacing() { + String input = "1\n" + + "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" + + "1\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); + + GameController gameController = new GameController(); + gameController.setUpShips(); + + long numOfShips1 = gameController.getPlayer1().countShips(); + long numOfShips2 = gameController.getPlayer2().countShips(); + + assertEquals(10, numOfShips1); + assertEquals(10, numOfShips2); + } + + @Test + void testComputerShipPlacing() { + String input = "2\n" + + "\n" + + "2\n" + + "\n"; + setInput(input); + + GameController gameController = new GameController(); + gameController.setUpShips(); + + long numOfShips1 = gameController.getPlayer1().countShips(); + long numOfShips2 = gameController.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, 1)); + assertFalse(inputShipReader.isShipWithinBoard(4, 1)); + 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); + + GameController gameController = new GameController(); + gameController.getPlayer1().getMyShips().add(ship); + gameController.getPlayer2().getMyShips().add(ship2); + + gameController.getPlayer1().getMyBoard().placeShip(ship); + gameController.getPlayer2().getMyBoard().placeShip(ship2); + + int numOfPlayer1AllShips = gameController.getPlayer1().getMyShips().size(); + int numOfPlayer2AllShips = gameController.getPlayer1().getMyShips().size(); + + assertEquals(1, numOfPlayer1AllShips); + assertEquals(1, numOfPlayer2AllShips); + + gameController.play(); + + long numOfPlayer1AliveShips = gameController.getPlayer1().getMyShips().stream() + .filter(Ship::isAlive) + .count(); + long numOfPlayer2AliveShips = gameController.getPlayer2().getMyShips().stream() + .filter(Ship::isAlive) + .count(); + + assertEquals(1, numOfPlayer1AliveShips); + assertEquals(0, numOfPlayer2AliveShips); + } + + @Test + void testDefineWinner() { + 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 = gameController.getPlayer1().getMyShips(); + tomShips.add(ship); + + gameController.defineWinner(); + + assertEquals(GAMEOVER + "Tom!", getOutput()); + removeFromOutput(GAMEOVER + "Tom!"); + + List veraShips = gameController.getPlayer2().getMyShips(); + veraShips.add(ship); + tomShips.remove(0); + + gameController.defineWinner(); + assertEquals(GAMEOVER + "Vera!", getOutput()); + removeFromOutput(GAMEOVER + "Vera!"); + + veraShips.remove(0); + gameController.defineWinner(); + assertEquals(TIE, getOutput()); + } + +} \ No newline at end of file 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..296edb6c --- /dev/null +++ b/src/test/java/course_project/sea_battle/ModelTest.java @@ -0,0 +1,71 @@ +package course_project.sea_battle; + +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 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(); + MyBoard myShots = new MyBoard(); + + 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..18dea7e1 --- /dev/null +++ b/src/test/java/course_project/sea_battle/ViewTest.java @@ -0,0 +1,143 @@ +package course_project.sea_battle; + +import base.UnitBase; +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.model.Shot; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +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; + +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; + + MyBoard myBoard; + MyBoard myShots; + Player player1; + + @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 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 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); + + 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", "")); + + } + + @Test + 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); + + 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 MyBoard(); + player1 = new Player(myBoard, myShots); + } + +} diff --git a/src/test/java/homework_2/PyramidPrinterTest.java b/src/test/java/homework_2/PyramidPrinterTest.java new file mode 100644 index 00000000..129f8e7f --- /dev/null +++ b/src/test/java/homework_2/PyramidPrinterTest.java @@ -0,0 +1,45 @@ +package homework_2; + +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 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"); + runPrintRemoveFromOutput(); + + assertEquals("x", getOutputLines()[0]); + assertEquals("xx", getOutputLines()[1]); + assertEquals("xxx", getOutputLines()[2]); + } + + @Test + void given0_whenRun_thenEmpty() { + setInput("0"); + runPrintRemoveFromOutput(); + assertEquals("", getOutput()); + } + + @ParameterizedTest + @ValueSource(strings = {"2 3", "abc", "-1"}) + void givenERROR_whenRun_thenERROR(String input) { + setInput(input); + 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..692eec62 --- /dev/null +++ b/src/test/java/homework_2/RandomCharsTableTest.java @@ -0,0 +1,62 @@ +package homework_2; + +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 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"); + 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("^[ACEGIKMOQSUWY, -]*"); + + 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("^[BDFHJLNPRTVXZ, -]*"); + + assertTrue(tableLine1); + assertTrue(strategy); + assertTrue(tableLine3); + } + + @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()); + } + + 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 new file mode 100644 index 00000000..3438ea62 --- /dev/null +++ b/src/test/java/homework_2/TrafficLightTest.java @@ -0,0 +1,57 @@ +package homework_2; + +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 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"); + runPrintRemoveFromOutput(); + assertTrue(getOutput().contains("GREEN")); + } + + @Test + void given95_whenRun_thenYellow() { + setInput("95"); + runPrintRemoveFromOutput(); + assertTrue(getOutput().contains("YELLOW")); + } + + @Test + void given100_whenRun_thenRed() { + setInput("160"); + runPrintRemoveFromOutput(); + assertTrue(getOutput().contains("RED")); + } + + @Test + void givenBigNumber_whenRun_thenDayIsOver() { + setInput("86400"); + runPrintRemoveFromOutput(); + assertEquals("The day is over", getOutput()); + } + + @ParameterizedTest + @ValueSource(strings = {"1 2", "-1", "abc"}) + void givenERROR_whenRun_thenERROR(String input) { + setInput(input); + runPrintRemoveFromOutput(); + assertEquals(ERROR, getOutput()); + } + + private void runPrintRemoveFromOutput() { + new TrafficLight().run(); + printOut(); + removeFromOutput("Please, input a number of seconds:"); + } +} 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..595e4e87 --- /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, NoSuchMethodException { + 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.size.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.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 new file mode 100644 index 00000000..8b4fc5eb --- /dev/null +++ b/src/test/java/homework_4/customFileReader/CustomFileReaderTest.java @@ -0,0 +1,60 @@ +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.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CustomFileReaderTest extends UnitBase { + + private final String[] expected = new String[] + {"Я вас любил: любовь еще быть может", + "В душе моей угасла не совсем;", + "Но пусть она вас больше не тревожит;", + "Я не хочу печалить вас ничем"}; + + private String filename = "src/main/resources/custom_file_reader/file.txt"; + + @Test + void givenTextFile_whenRun1_thenEquals() throws IOException { + new CustomFileReader(filename).run1(); + assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); + } + + @Test + void givenTextFile_whenRun2_thenEquals() throws IOException { + new CustomFileReader(filename).run2(); + assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); + } + + @Test + void givenTextFile_whenRun3_thenEquals() throws IOException { + new CustomFileReader(filename).run3(); + assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); + } + + @Test + void givenTextFile_whenRun4_thenEquals() throws IOException { + new CustomFileReader(filename).run4(); + assertEquals(Arrays.toString(expected), Arrays.toString(getOutputLines())); + } + + @Test + void givenNotExistingFile_whenRun_thenException() { + + filename = "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(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 new file mode 100644 index 00000000..b76a873a --- /dev/null +++ b/src/test/java/homework_4/singleton/SingletonTest.java @@ -0,0 +1,16 @@ +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 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 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..f114dda3 --- /dev/null +++ b/src/test/java/homework_6/mapProblemsGenerator/MapProblemsGeneratorTest.java @@ -0,0 +1,35 @@ +package homework_6.mapProblemsGenerator; + +import base.UnitBase; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class MapProblemsGeneratorTest extends UnitBase { + + @Test + void testCatClass() { + MapProblemsCollisionGenerator generator1 = new MapProblemsCollisionGenerator(3); + MapProblemsCollisionGenerator generator2 = new MapProblemsCollisionGenerator(4); + assertEquals(generator1.hashCode(), generator2.hashCode()); + assertNotEquals(generator1, generator2); + } + + @Test + void testDatClass() { + 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