Skip to content
This repository was archived by the owner on Oct 25, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
# Java Core June 2021

## *Nikolaev Artem*
## *Belyaevskov Alexander*

| 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](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/AlexanderBelyaevskov/src/main/java/homework_1) | The app that reads input arguments and prints them, until "error" argument |
| HW2 | [Traffic light](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_2/TrafficLight/TrafficLight.java) | App reads current time in seconds from the console and prints the traffic light |
| HW2 | [Pyramid printer](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_2/PyramidPrinter/PyramidPrinter.java) | App reads positive integer numbers from the console and prints pyramid of "x" characters |
| HW2 | [Random chars table](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_2/RandomCharsTable/RandomCharsTable.java) | App reads from the console width and length of the chart, strategy keyword (even or odd). Prints to the console the chart of random chars from A to Z, and in separate line all the chars (from the chart) that match strategy |
| HW3 | [Immutable class example](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_3/ImmutableTask.java) | Example of an immutable class |
| HW4 | [Custom file reader](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_4/custom_file_reader/CustomFileReader.java) | Examples of 3 methods implementations for file reading |
| HW4 | [Singleton](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/AlexanderBelyaevskov/src/main/java/homework_4/singleton) | Examples of an singleton class |
| HW4 | [Custom Annotation](https://github.com/NikolaevArtem/Java_Core_June_2021/tree/feature/AlexanderBelyaevskov/src/main/java/homework_4/custom_annotation) | Example of an annotation that changes field name in ToString() method |
| HW5 | [Power of number](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_5/power_of_number/PowerOfNumber.java) | Power of number implementation with recursion method |
| HW5 | [Custom regex matcher](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_5/custom_regex_matcher/CustomRegexMatcher.java) | Input email argument check with regex |
| HW6 | [Map problems generator](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_6/map_problems_generator/MapProblemsCollisionGenerator.java) | Implement a class with overdid equals() and hashCode() methods, which generates 100% collision when used as key in HashMap collection.|
| HW7 | [Funtional interface](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/homework_7/Main.java) | Custom functional interface implementation.|
| Course project | [Sea battle](https://github.com/NikolaevArtem/Java_Core_June_2021/blob/feature/AlexanderBelyaevskov/src/main/java/course_project/Main.java) | Sea battle console game.|

[CodingBat done page](https://codingbat.com/done?user=abelyaevskov@gmail.com&tag=6930560875)

[Link to markdown giude](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ repositories {
}

dependencies {
implementation 'org.junit.jupiter:junit-jupiter:5.7.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
Expand Down
168 changes: 168 additions & 0 deletions src/main/java/course_project/Game.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package course_project;

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class Game {

private final Scanner reader;
private final SeaBattleMap[] battleMaps = new SeaBattleMap[2];
private final String mapsSpacing = " ";

private SeaBattleMap activeBattleMap;
private String activePlayer;

private GameStatus status;
private String currentInput;

Game() {
reader = new Scanner(new InputStreamReader(System.in));
}

void run() {
System.out.println("Welcome to SEA BATTLE console game!");
System.out.println("Follow instructions to play the game or type \"exit\" anytyme to terminate program");
try {
start();
runBattle();
} finally {
reader.close();
}
}

private void start() {
status = GameStatus.SettingShips;
setBattleMaps();
setShips();
}

private void runBattle() {
status = GameStatus.Battle;

activeBattleMap = battleMaps[1];
activePlayer = battleMaps[0].getPlayerName();

mainLoop:
while (true) {
for (int i = 0, j = 1; i < 2; i++, j--) {
while (true) {
printBattleMaps();
if (readShootCommand())
if (!activeBattleMap.shoot(new Point(currentInput))) {
break;
}
if (activeBattleMap.getShips().size() == 0) {
System.out.printf("%s wins! Congrats!", activePlayer);
System.out.println();
break mainLoop;
}
}
activeBattleMap = battleMaps[i];
activePlayer = battleMaps[j].getPlayerName();
}
}
}

private void setBattleMaps() {
for (int i = 0; i < 2; i++) {
battleMaps[i] = new SeaBattleMap(10, "Player " + (i + 1));
}
}

private boolean readShootCommand() {
System.out.printf("%s make a shoot (e.g. A1 or E9): ", activePlayer);
currentInput = reader.nextLine();
if (currentInput.equals("exit")) {
throw new RuntimeException("Terminated by user");
}
String shootValidationPattern = "[A-J]([1-9]{1}|10)$";
if (!currentInput.matches(shootValidationPattern)) {
printErrorMessage("Wrong shoot command!");
return false;
}
return true;
}

private void printBattleMap(SeaBattleMap battleMap) {
System.out.println(
battleMap.getView(status).stream().collect(Collectors.joining(System.lineSeparator()))
);
}

private void printBattleMaps() {
ArrayList<String> view1 = battleMaps[0].getView(status);
ArrayList<String> view2 = battleMaps[1].getView(status);

System.out.println(
Stream.iterate(0, i -> i + 1)
.limit(view1.size())
.map(i -> view1.get(i).concat(mapsSpacing).concat(view2.get(i)))
.collect(Collectors.joining(System.lineSeparator()))
);
}

private void setShips() {
for (SeaBattleMap battleMap : battleMaps) {
activeBattleMap = battleMap;
while (true) {
if (setNSizeShip(4))
break;
}
while (true) {
if (setNSizeShip(3))
break;
}
while (true) {
if (setNSizeShip(2))
break;
}
while (true) {
if (setNSizeShip(1))
break;
}
}
}

private boolean setNSizeShip(int size) {
int shipsCount = 5 - size - activeBattleMap.getNSizedShipsCount(size);
for (int i = 0; i < shipsCount; i++) {
printBattleMap(activeBattleMap);
System.out.printf("%s, enter position and location type (R = right, D = down) " +
"to set %s-size ship (e.g. A1 R or A1 D): ", activeBattleMap.getPlayerName(), size);
String input = reader.nextLine();
if (input.equals("exit")) {
throw new RuntimeException("Terminated by user");
}
String setShipsValidationPattern = "[A-J]([1-9]{1}|10)\\s([RD])$";
if (!input.matches(setShipsValidationPattern)) {
printErrorMessage("Wrong ship position command!");
return false;
}

String[] inputParts = input.split("\\s");

ShipLocationType shipLocationType = ShipLocationType.TO_RIGHT;
if (inputParts[1].equals("D")) {
shipLocationType = ShipLocationType.TO_DOWN;
}
try {
activeBattleMap.addShip(new Point(inputParts[0]), size, shipLocationType);
} catch (IllegalArgumentException e) {
printErrorMessage(e.getMessage());
return false;
}

}
return true;
}

private void printErrorMessage(String message) {
final String ANSI_RED = "\u001B[31m";
final String ANSI_BLACK = "\u001B[0m";
System.out.println(ANSI_RED + message + ANSI_BLACK);
}

}
7 changes: 7 additions & 0 deletions src/main/java/course_project/GameStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package course_project;

enum GameStatus {

SettingShips,
Battle
}
9 changes: 9 additions & 0 deletions src/main/java/course_project/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package course_project;

public class Main {

public static void main(String[] args) {
new Game().run();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good! The game works fine, even though it's not really comfortable to play. I didn't find any bugs, and you show good knowledge and skills using Java Core and Java libraries, Java 8 features as well.

To make better: refactor interface (automatic ship placement, field representation to more comfortable. You chose the easiest approach where fields representation is the same for both players, it could be improved.)
Also, here and there I can see typos and Code Conventions violations in minor things. Not critical, but disturbing.

}

}
9 changes: 9 additions & 0 deletions src/main/java/course_project/MapPointType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package course_project;

enum MapPointType {

Ship,
FiredShip,
Emty,
Fired
}
83 changes: 83 additions & 0 deletions src/main/java/course_project/Point.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package course_project;

import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

class Point {

private final int x;
private final int y;
private MapPointType type;

Point(String consoleInput) {

int y = IntStream.iterate(65, i -> i+1)
.limit(10)
.mapToObj(i -> String.valueOf((char) i))
.collect(Collectors.toList())
.indexOf(consoleInput.substring(0,1));
this.x = Integer.parseInt(consoleInput.substring(1))-1;
this.y = y;
}

Point(int x, int y, MapPointType type) {
this.x = x;
this.y = y;
this.type = type;
}

int getX() {
return x;
}

int getY() {
return y;
}

void setType(MapPointType type) {
this.type = type;
}

MapPointType getType() {
return type;
}

String getView(GameStatus status) {
if (status == GameStatus.Battle) {
return getBattleView();
}
else {
return getSettingShipsView();
}
}

private String getSettingShipsView() {
if (getType() == MapPointType.Ship) {
return "\u25B2" + " ";
}
return " ";
}

private String getBattleView() {
switch (getType()
) {
case FiredShip: return "\u2713" + " ";
case Fired: return "\u00D7" + " ";
default: return " ";
}
}


@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return x == point.x && y == point.y;
}

@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
Loading