From c0a642afc7fbef3a646b5fba66a7ee437a310c21 Mon Sep 17 00:00:00 2001 From: deok-beom Date: Tue, 21 Nov 2023 16:12:11 +0900 Subject: [PATCH 01/13] =?UTF-8?q?Refactor:=20=EB=9E=8C=EB=8B=A4=20?= =?UTF-8?q?=EC=8B=A4=EC=8A=B5=201=20-=20=EC=9D=B5=EB=AA=85=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=A5=BC=20=EB=9E=8C=EB=8B=A4=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/nextstep/fp/CarTest.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/test/java/nextstep/fp/CarTest.java b/src/test/java/nextstep/fp/CarTest.java index 1ab1106f..ecab481a 100644 --- a/src/test/java/nextstep/fp/CarTest.java +++ b/src/test/java/nextstep/fp/CarTest.java @@ -8,24 +8,14 @@ public class CarTest { @Test public void 이동() { Car car = new Car("pobi", 0); - Car actual = car.move(new MoveStrategy() { - @Override - public boolean isMovable() { - return true; - } - }); + Car actual = car.move(() -> true); assertThat(actual).isEqualTo(new Car("pobi", 1)); } @Test public void 정지() { Car car = new Car("pobi", 0); - Car actual = car.move(new MoveStrategy() { - @Override - public boolean isMovable() { - return false; - } - }); + Car actual = car.move(() -> false); assertThat(actual).isEqualTo(new Car("pobi", 0)); } } From e033d75dca93057f5ec840ce8f4a10515330f245 Mon Sep 17 00:00:00 2001 From: deok-beom Date: Tue, 21 Nov 2023 16:12:28 +0900 Subject: [PATCH 02/13] =?UTF-8?q?Refactor:=20=EB=9E=8C=EB=8B=A4=20?= =?UTF-8?q?=EC=8B=A4=EC=8A=B5=202=20-=20=EB=9E=8C=EB=8B=A4=EB=A5=BC=20?= =?UTF-8?q?=ED=99=9C=EC=9A=A9=ED=95=B4=20=EC=A4=91=EB=B3=B5=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/fp/Condition.java | 5 +++++ src/main/java/nextstep/fp/Lambda.java | 22 ++-------------------- src/test/java/nextstep/fp/LambdaTest.java | 6 +++--- 3 files changed, 10 insertions(+), 23 deletions(-) create mode 100644 src/main/java/nextstep/fp/Condition.java diff --git a/src/main/java/nextstep/fp/Condition.java b/src/main/java/nextstep/fp/Condition.java new file mode 100644 index 00000000..92f4f149 --- /dev/null +++ b/src/main/java/nextstep/fp/Condition.java @@ -0,0 +1,5 @@ +package nextstep.fp; + +public interface Condition { + boolean isMatch(int number); +} diff --git a/src/main/java/nextstep/fp/Lambda.java b/src/main/java/nextstep/fp/Lambda.java index bd68fe1c..c40cde08 100644 --- a/src/main/java/nextstep/fp/Lambda.java +++ b/src/main/java/nextstep/fp/Lambda.java @@ -26,28 +26,10 @@ public void run() { }).start(); } - public static int sumAll(List numbers) { + public static int sumByCondition(List numbers, Condition condition) { int total = 0; for (int number : numbers) { - total += number; - } - return total; - } - - public static int sumAllEven(List numbers) { - int total = 0; - for (int number : numbers) { - if (number % 2 == 0) { - total += number; - } - } - return total; - } - - public static int sumAllOverThree(List numbers) { - int total = 0; - for (int number : numbers) { - if (number > 3) { + if (condition.isMatch(number)) { total += number; } } diff --git a/src/test/java/nextstep/fp/LambdaTest.java b/src/test/java/nextstep/fp/LambdaTest.java index f240ac65..0d4a80be 100644 --- a/src/test/java/nextstep/fp/LambdaTest.java +++ b/src/test/java/nextstep/fp/LambdaTest.java @@ -33,19 +33,19 @@ public void runThread() throws Exception { @Test public void sumAll() throws Exception { - int sum = Lambda.sumAll(numbers); + int sum = Lambda.sumByCondition(numbers, num -> true); assertThat(sum).isEqualTo(21); } @Test public void sumAllEven() throws Exception { - int sum = Lambda.sumAllEven(numbers); + int sum = Lambda.sumByCondition(numbers, num -> num % 2 == 0); assertThat(sum).isEqualTo(12); } @Test public void sumAllOverThree() throws Exception { - int sum = Lambda.sumAllOverThree(numbers); + int sum = Lambda.sumByCondition(numbers, num -> num > 3); assertThat(sum).isEqualTo(15); } } From c9f5b286a7dc9e4f01c2d9f29a78bc4bf3e10efc Mon Sep 17 00:00:00 2001 From: deok-beom Date: Tue, 21 Nov 2023 17:28:01 +0900 Subject: [PATCH 03/13] =?UTF-8?q?Refactor:=20map,=20reduce,=20filter=20?= =?UTF-8?q?=EC=8B=A4=EC=8A=B5=201,=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/fp/StreamStudy.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/nextstep/fp/StreamStudy.java b/src/main/java/nextstep/fp/StreamStudy.java index b446983a..d786d72e 100644 --- a/src/main/java/nextstep/fp/StreamStudy.java +++ b/src/main/java/nextstep/fp/StreamStudy.java @@ -5,6 +5,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -15,11 +16,7 @@ public static long countWords() throws IOException { .get("src/main/resources/fp/war-and-peace.txt")), StandardCharsets.UTF_8); List words = Arrays.asList(contents.split("[\\P{L}]+")); - long count = 0; - for (String w : words) { - if (w.length() > 12) count++; - } - return count; + return words.stream().filter(w -> w.length() > 12).count(); } public static void printLongestWordTop100() throws IOException { @@ -28,6 +25,11 @@ public static void printLongestWordTop100() throws IOException { List words = Arrays.asList(contents.split("[\\P{L}]+")); // TODO 이 부분에 구현한다. + words.stream() + .filter(w -> w.length() > 12) + .sorted(Comparator.comparingInt(String::length).reversed()) + .distinct() + .forEach(w -> System.out.println(w.toLowerCase())); } public static List doubleNumbers(List numbers) { @@ -35,10 +37,10 @@ public static List doubleNumbers(List numbers) { } public static long sumAll(List numbers) { - return numbers.stream().reduce(0, (x, y) -> x + y); + return numbers.stream().reduce(0, Integer::sum); } public static long sumOverThreeAndDouble(List numbers) { - return 0; + return (long) numbers.stream().filter(num -> num > 3).reduce(0, (total, num) -> total + num * 2); } } \ No newline at end of file From b84c1563f9cff409510d3a6cd26f457383e39f73 Mon Sep 17 00:00:00 2001 From: deok-beom Date: Tue, 21 Nov 2023 17:28:28 +0900 Subject: [PATCH 04/13] =?UTF-8?q?Refactor:=20Optional=EC=9D=84=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=B4=20=EC=A1=B0=EA=B1=B4=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/optional/User.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/nextstep/optional/User.java b/src/main/java/nextstep/optional/User.java index 9614c2f4..bc2aee7e 100644 --- a/src/main/java/nextstep/optional/User.java +++ b/src/main/java/nextstep/optional/User.java @@ -1,5 +1,7 @@ package nextstep.optional; +import java.util.Optional; + public class User { private String name; private Integer age; @@ -33,7 +35,10 @@ public static boolean ageIsInRange1(User user) { } public static boolean ageIsInRange2(User user) { - return false; + return Optional.ofNullable(user) + .map(User::getAge) + .filter(age -> age >= 30 && age <= 45) + .isPresent(); } @Override From 8ae41c6660eab5eb0bcdcf7658105f770f51d7c6 Mon Sep 17 00:00:00 2001 From: deok-beom Date: Tue, 21 Nov 2023 17:28:35 +0900 Subject: [PATCH 05/13] =?UTF-8?q?Refactor:=20Optional=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/optional/Users.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/nextstep/optional/Users.java b/src/main/java/nextstep/optional/Users.java index 6293040d..2e0ae832 100644 --- a/src/main/java/nextstep/optional/Users.java +++ b/src/main/java/nextstep/optional/Users.java @@ -2,6 +2,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; public class Users { static final User DEFAULT_USER = new User("codesquad", 100); @@ -13,11 +14,10 @@ public class Users { new User("honux", 45)); User getUser(String name) { - for (User user : users) { - if (user.matchName(name)) { - return user; - } - } - return DEFAULT_USER; + Optional result = users.stream() + .filter(user -> user.matchName(name)) + .findFirst(); + + return result.orElse(DEFAULT_USER); } } From 584284fe57e1d2b4ea6d187834a59a6e6b774438 Mon Sep 17 00:00:00 2001 From: deok-beom Date: Tue, 21 Nov 2023 17:28:44 +0900 Subject: [PATCH 06/13] =?UTF-8?q?Refactor:=20Optional=EC=97=90=EC=84=9C=20?= =?UTF-8?q?exception=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/optional/Expression.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/nextstep/optional/Expression.java b/src/main/java/nextstep/optional/Expression.java index 1c98cd6a..db14c95c 100644 --- a/src/main/java/nextstep/optional/Expression.java +++ b/src/main/java/nextstep/optional/Expression.java @@ -1,5 +1,8 @@ package nextstep.optional; +import java.util.Arrays; +import java.util.Optional; + enum Expression { PLUS("+"), MINUS("-"), TIMES("*"), DIVIDE("/"); @@ -14,12 +17,12 @@ private static boolean matchExpression(Expression e, String expression) { } static Expression of(String expression) { - for (Expression v : values()) { - if (matchExpression(v, expression)) { - return v; - } - } + Optional result = Arrays.stream(values()) + .filter(value -> matchExpression(value, expression)) + .findFirst(); - throw new IllegalArgumentException(String.format("%s는 사칙연산에 해당하지 않는 표현식입니다.", expression)); + return result.orElseThrow(() -> new IllegalArgumentException( + String.format("%s는 사칙연산에 해당하지 않는 표현식입니다.", expression)) + ); } } From cd033300b62c86c2952c7473a96aa569781c7a4b Mon Sep 17 00:00:00 2001 From: deok-beom Date: Wed, 22 Nov 2023 14:30:37 +0900 Subject: [PATCH 07/13] =?UTF-8?q?Test:=20=EC=B4=88=EA=B8=B0=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/fp/Car.java | 35 ----- src/main/java/nextstep/fp/Condition.java | 5 - src/main/java/nextstep/fp/Lambda.java | 38 ----- src/main/java/nextstep/fp/MoveStrategy.java | 5 - src/main/java/nextstep/fp/StreamStudy.java | 46 ------ src/main/java/nextstep/optional/Computer.java | 39 ------ .../java/nextstep/optional/ComputerStore.java | 26 ---- .../java/nextstep/optional/Expression.java | 28 ---- src/main/java/nextstep/optional/User.java | 74 ---------- src/main/java/nextstep/optional/Users.java | 23 --- src/test/java/blackjack/DealerTest.java | 47 +++++++ src/test/java/blackjack/PlayerTest.java | 131 ++++++++++++++++++ src/test/java/nextstep/fp/CarTest.java | 21 --- src/test/java/nextstep/fp/LambdaTest.java | 51 ------- .../java/nextstep/fp/StreamStudyTest.java | 48 ------- .../nextstep/optional/ComputerStoreTest.java | 59 -------- .../nextstep/optional/ExpressionTest.java | 22 --- src/test/java/nextstep/optional/UserTest.java | 27 ---- .../java/nextstep/optional/UsersTest.java | 21 --- 19 files changed, 178 insertions(+), 568 deletions(-) delete mode 100644 src/main/java/nextstep/fp/Car.java delete mode 100644 src/main/java/nextstep/fp/Condition.java delete mode 100644 src/main/java/nextstep/fp/Lambda.java delete mode 100644 src/main/java/nextstep/fp/MoveStrategy.java delete mode 100644 src/main/java/nextstep/fp/StreamStudy.java delete mode 100644 src/main/java/nextstep/optional/Computer.java delete mode 100644 src/main/java/nextstep/optional/ComputerStore.java delete mode 100644 src/main/java/nextstep/optional/Expression.java delete mode 100644 src/main/java/nextstep/optional/User.java delete mode 100644 src/main/java/nextstep/optional/Users.java create mode 100644 src/test/java/blackjack/DealerTest.java create mode 100644 src/test/java/blackjack/PlayerTest.java delete mode 100644 src/test/java/nextstep/fp/CarTest.java delete mode 100644 src/test/java/nextstep/fp/LambdaTest.java delete mode 100644 src/test/java/nextstep/fp/StreamStudyTest.java delete mode 100644 src/test/java/nextstep/optional/ComputerStoreTest.java delete mode 100644 src/test/java/nextstep/optional/ExpressionTest.java delete mode 100644 src/test/java/nextstep/optional/UserTest.java delete mode 100644 src/test/java/nextstep/optional/UsersTest.java diff --git a/src/main/java/nextstep/fp/Car.java b/src/main/java/nextstep/fp/Car.java deleted file mode 100644 index 2146c112..00000000 --- a/src/main/java/nextstep/fp/Car.java +++ /dev/null @@ -1,35 +0,0 @@ -package nextstep.fp; - -import java.util.Objects; - -public class Car { - private final String name; - private final int position; - - public Car(String name, int position) { - this.name = name; - this.position = position; - } - - public Car move(MoveStrategy moveStrategy) { - if (moveStrategy.isMovable()) { - return new Car(name, position + 1); - } - return this; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Car car = (Car) o; - return position == car.position && - Objects.equals(name, car.name); - } - - @Override - public int hashCode() { - - return Objects.hash(name, position); - } -} diff --git a/src/main/java/nextstep/fp/Condition.java b/src/main/java/nextstep/fp/Condition.java deleted file mode 100644 index 92f4f149..00000000 --- a/src/main/java/nextstep/fp/Condition.java +++ /dev/null @@ -1,5 +0,0 @@ -package nextstep.fp; - -public interface Condition { - boolean isMatch(int number); -} diff --git a/src/main/java/nextstep/fp/Lambda.java b/src/main/java/nextstep/fp/Lambda.java deleted file mode 100644 index c40cde08..00000000 --- a/src/main/java/nextstep/fp/Lambda.java +++ /dev/null @@ -1,38 +0,0 @@ -package nextstep.fp; - -import java.util.List; - -public class Lambda { - public static void printAllOld(List numbers) { - System.out.println("printAllOld"); - - for (int number : numbers) { - System.out.println(number); - } - } - - public static void printAllLambda(List numbers) { - System.out.println("printAllLambda"); - - numbers.forEach(System.out::println); - } - - public static void runThread() { - new Thread(new Runnable() { - @Override - public void run() { - System.out.println("Hello from thread"); - } - }).start(); - } - - public static int sumByCondition(List numbers, Condition condition) { - int total = 0; - for (int number : numbers) { - if (condition.isMatch(number)) { - total += number; - } - } - return total; - } -} diff --git a/src/main/java/nextstep/fp/MoveStrategy.java b/src/main/java/nextstep/fp/MoveStrategy.java deleted file mode 100644 index 1bd8c23c..00000000 --- a/src/main/java/nextstep/fp/MoveStrategy.java +++ /dev/null @@ -1,5 +0,0 @@ -package nextstep.fp; - -public interface MoveStrategy { - boolean isMovable(); -} diff --git a/src/main/java/nextstep/fp/StreamStudy.java b/src/main/java/nextstep/fp/StreamStudy.java deleted file mode 100644 index d786d72e..00000000 --- a/src/main/java/nextstep/fp/StreamStudy.java +++ /dev/null @@ -1,46 +0,0 @@ -package nextstep.fp; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -public class StreamStudy { - - public static long countWords() throws IOException { - String contents = new String(Files.readAllBytes(Paths - .get("src/main/resources/fp/war-and-peace.txt")), StandardCharsets.UTF_8); - List words = Arrays.asList(contents.split("[\\P{L}]+")); - - return words.stream().filter(w -> w.length() > 12).count(); - } - - public static void printLongestWordTop100() throws IOException { - String contents = new String(Files.readAllBytes(Paths - .get("src/main/resources/fp/war-and-peace.txt")), StandardCharsets.UTF_8); - List words = Arrays.asList(contents.split("[\\P{L}]+")); - - // TODO 이 부분에 구현한다. - words.stream() - .filter(w -> w.length() > 12) - .sorted(Comparator.comparingInt(String::length).reversed()) - .distinct() - .forEach(w -> System.out.println(w.toLowerCase())); - } - - public static List doubleNumbers(List numbers) { - return numbers.stream().map(x -> 2 * x).collect(Collectors.toList()); - } - - public static long sumAll(List numbers) { - return numbers.stream().reduce(0, Integer::sum); - } - - public static long sumOverThreeAndDouble(List numbers) { - return (long) numbers.stream().filter(num -> num > 3).reduce(0, (total, num) -> total + num * 2); - } -} \ No newline at end of file diff --git a/src/main/java/nextstep/optional/Computer.java b/src/main/java/nextstep/optional/Computer.java deleted file mode 100644 index cc0af4d7..00000000 --- a/src/main/java/nextstep/optional/Computer.java +++ /dev/null @@ -1,39 +0,0 @@ -package nextstep.optional; - -public class Computer { - private Soundcard soundcard; - - public Computer(Soundcard soundcard) { - this.soundcard = soundcard; - } - - public Soundcard getSoundcard() { - return soundcard; - } - - public static class Soundcard { - private USB usb; - - public Soundcard(USB usb) { - super(); - this.usb = usb; - } - - public USB getUsb() { - return usb; - } - } - - public static class USB { - private String version; - - public USB(String version) { - super(); - this.version = version; - } - - public String getVersion() { - return this.version; - } - } -} diff --git a/src/main/java/nextstep/optional/ComputerStore.java b/src/main/java/nextstep/optional/ComputerStore.java deleted file mode 100644 index 2695c967..00000000 --- a/src/main/java/nextstep/optional/ComputerStore.java +++ /dev/null @@ -1,26 +0,0 @@ -package nextstep.optional; - -import nextstep.optional.Computer.Soundcard; -import nextstep.optional.Computer.USB; - -public class ComputerStore { - public static final String UNKNOWN_VERSION = "UNKNOWN"; - - public static String getVersion(Computer computer) { - String version = UNKNOWN_VERSION; - if (computer != null) { - Soundcard soundcard = computer.getSoundcard(); - if (soundcard != null) { - USB usb = soundcard.getUsb(); - if (usb != null) { - version = usb.getVersion(); - } - } - } - return version; - } - - public static String getVersionOptional(Computer computer) { - return null; - } -} diff --git a/src/main/java/nextstep/optional/Expression.java b/src/main/java/nextstep/optional/Expression.java deleted file mode 100644 index db14c95c..00000000 --- a/src/main/java/nextstep/optional/Expression.java +++ /dev/null @@ -1,28 +0,0 @@ -package nextstep.optional; - -import java.util.Arrays; -import java.util.Optional; - -enum Expression { - PLUS("+"), MINUS("-"), TIMES("*"), DIVIDE("/"); - - private String expression; - - Expression(String expression) { - this.expression = expression; - } - - private static boolean matchExpression(Expression e, String expression) { - return expression.equals(e.expression); - } - - static Expression of(String expression) { - Optional result = Arrays.stream(values()) - .filter(value -> matchExpression(value, expression)) - .findFirst(); - - return result.orElseThrow(() -> new IllegalArgumentException( - String.format("%s는 사칙연산에 해당하지 않는 표현식입니다.", expression)) - ); - } -} diff --git a/src/main/java/nextstep/optional/User.java b/src/main/java/nextstep/optional/User.java deleted file mode 100644 index bc2aee7e..00000000 --- a/src/main/java/nextstep/optional/User.java +++ /dev/null @@ -1,74 +0,0 @@ -package nextstep.optional; - -import java.util.Optional; - -public class User { - private String name; - private Integer age; - - public User(String name, Integer age) { - this.name = name; - this.age = age; - } - - public String getName() { - return name; - } - - public Integer getAge() { - return age; - } - - public boolean matchName(String name) { - return this.name.equals(name); - } - - public static boolean ageIsInRange1(User user) { - boolean isInRange = false; - - if (user != null && user.getAge() != null - && (user.getAge() >= 30 - && user.getAge() <= 45)) { - isInRange = true; - } - return isInRange; - } - - public static boolean ageIsInRange2(User user) { - return Optional.ofNullable(user) - .map(User::getAge) - .filter(age -> age >= 30 && age <= 45) - .isPresent(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((age == null) ? 0 : age.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - User other = (User) obj; - if (age == null) { - if (other.age != null) - return false; - } else if (!age.equals(other.age)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } -} diff --git a/src/main/java/nextstep/optional/Users.java b/src/main/java/nextstep/optional/Users.java deleted file mode 100644 index 2e0ae832..00000000 --- a/src/main/java/nextstep/optional/Users.java +++ /dev/null @@ -1,23 +0,0 @@ -package nextstep.optional; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -public class Users { - static final User DEFAULT_USER = new User("codesquad", 100); - - List users = Arrays.asList( - new User("crong", 35), - new User("pobi", 30), - new User("jk", 40), - new User("honux", 45)); - - User getUser(String name) { - Optional result = users.stream() - .filter(user -> user.matchName(name)) - .findFirst(); - - return result.orElse(DEFAULT_USER); - } -} diff --git a/src/test/java/blackjack/DealerTest.java b/src/test/java/blackjack/DealerTest.java new file mode 100644 index 00000000..b315a556 --- /dev/null +++ b/src/test/java/blackjack/DealerTest.java @@ -0,0 +1,47 @@ +package blackjack; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DealerTest { + + @Test + void 생성() { + // given + Dealer dealer = new Dealer(); + + // when + String name = dealer.getName(); + + // then + assertThat(name).isEqualTo("딜러"); + } + + @Test + void 플레이_16이하() { + // given + Dealer dealer = new Dealer(); + dealer.addHand(Card.HEART_KING); + + // when + boolean isPlay = dealer.isPlay(); + + // then + assertThat(isPlay).isTrue(); + } + + @Test + void 플레이_17이상() { + // given + Dealer dealer = new Dealer(); + dealer.addHand(Card.HEART_KING); + dealer.addHand(Card.HEART_7); + + // when + boolean isPlay = dealer.isPlay(); + + // then + assertThat(isPlay).isFalse(); + } +} diff --git a/src/test/java/blackjack/PlayerTest.java b/src/test/java/blackjack/PlayerTest.java new file mode 100644 index 00000000..faf9f5f4 --- /dev/null +++ b/src/test/java/blackjack/PlayerTest.java @@ -0,0 +1,131 @@ +package blackjack; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PlayerTest { + + @Test + void 배팅() { + // given + Player player = new Player("tester"); + int batAmount = 10000; + + // when + player.bat(batAmount); + + // then + assertThat(player.getBatAmount()).isEqualTo(batAmount); + } + + @Test + void 딜링() { + // given + Player player = new Player("tester"); + + // when + player.addHand(Card.CLOVER_ACE); + + // then + assertThat(player.getHands().size()).isOne(); + assertThat(player.getHands()).contains(Card.CLOVER_ACE); + } + + @Test + void 히트() { + // given + Player player = new Player("tester"); + player.addHand(Card.CLOVER_KING); + player.addHand(Card.HEART_KING); + + // when + player.hit(Card.SPADE_KING); + + // then + assertThat(player.getHands().size()).isEqualTo(3); + assertThat(player.getHands()).contains(Card.CLOVER_KING, Card.HEART_KING, Card.SPADE_KING); + } + + @ParameterizedTest + @CsvSource(value = {"CLOVER_KING,HEART_KING,DIAMOND_2:22", "CLOVER_KING,HEART_KING:20"}, delimiter = ':') + void 정산(String input, int expect) { + // given + Player player = new Player("tester"); + addHandFromInput(input, player); + + // when + int result = player.calculate(); + + // then + assertThat(result).isEqualTo(expect); + } + + @ParameterizedTest + @ValueSource(strings = {"CLOVER_KING,HEART_KING,DIAMOND_ACE", "CLOVER_KING,DIAMOND_ACE"}) + void 정산_에이스(String input) { + // given + Player player = new Player("tester"); + addHandFromInput(input, player); + + // when + int result = player.calculate(); + + // then + assertThat(result).isEqualTo(21); + } + + @ParameterizedTest + @CsvSource(value = {"CLOVER_KING,HEART_KING,DIAMOND_2:true", "CLOVER_KING,HEART_KING:false"}, delimiter = ':') + void 버스트_여부(String input, boolean expect) { + // given + Player player = new Player("tester"); + addHandFromInput(input, player); + + // when + boolean isBust = player.isBust(); + + // then + assertThat(isBust).isEqualTo(expect); + } + + @Test + void 블랙잭() { + // given + Player player = new Player("tester"); + player.addHand(Card.CLOVER_KING); + player.addHand(Card.HEART_7); + player.addHand(Card.DIAMOND_4); + + // when + int result = player.calculate(); + + // then + assertThat(result).isEqualTo(21); + assertThat(player.isBlackJack()).isTrue(); + } + + @ParameterizedTest + @ValueSource(strings = {"CLOVER_KING,HEART_7,DIAMOND_5", "CLOVER_KING,HEART_7"}) + void 블랙잭_아님(String input) { + // given + Player player = new Player("tester"); + addHandFromInput(input, player); + + // when + boolean isBlackJack = player.isBlackJack(); + + // then + assertThat(isBlackJack).isFalse(); + } + + private static void addHandFromInput(String input, Player player) { + String[] cards = input.split(","); + for (String card : cards) { + player.addHand(Card.valueOf(card)); + } + } +} diff --git a/src/test/java/nextstep/fp/CarTest.java b/src/test/java/nextstep/fp/CarTest.java deleted file mode 100644 index ecab481a..00000000 --- a/src/test/java/nextstep/fp/CarTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package nextstep.fp; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class CarTest { - @Test - public void 이동() { - Car car = new Car("pobi", 0); - Car actual = car.move(() -> true); - assertThat(actual).isEqualTo(new Car("pobi", 1)); - } - - @Test - public void 정지() { - Car car = new Car("pobi", 0); - Car actual = car.move(() -> false); - assertThat(actual).isEqualTo(new Car("pobi", 0)); - } -} diff --git a/src/test/java/nextstep/fp/LambdaTest.java b/src/test/java/nextstep/fp/LambdaTest.java deleted file mode 100644 index 0d4a80be..00000000 --- a/src/test/java/nextstep/fp/LambdaTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package nextstep.fp; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -public class LambdaTest { - private List numbers; - - @BeforeEach - public void setup() { - numbers = Arrays.asList(1, 2, 3, 4, 5, 6); - } - - @Test - public void printAllOld() throws Exception { - Lambda.printAllOld(numbers); - } - - @Test - public void printAllLambda() throws Exception { - Lambda.printAllLambda(numbers); - } - - @Test - public void runThread() throws Exception { - Lambda.runThread(); - } - - @Test - public void sumAll() throws Exception { - int sum = Lambda.sumByCondition(numbers, num -> true); - assertThat(sum).isEqualTo(21); - } - - @Test - public void sumAllEven() throws Exception { - int sum = Lambda.sumByCondition(numbers, num -> num % 2 == 0); - assertThat(sum).isEqualTo(12); - } - - @Test - public void sumAllOverThree() throws Exception { - int sum = Lambda.sumByCondition(numbers, num -> num > 3); - assertThat(sum).isEqualTo(15); - } -} diff --git a/src/test/java/nextstep/fp/StreamStudyTest.java b/src/test/java/nextstep/fp/StreamStudyTest.java deleted file mode 100644 index 2962521a..00000000 --- a/src/test/java/nextstep/fp/StreamStudyTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package nextstep.fp; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -public class StreamStudyTest { - private List numbers; - - @BeforeEach - public void setup() { - numbers = Arrays.asList(1, 2, 3, 4, 5, 6); - } - - @Test - public void countWords() throws Exception { - long result = StreamStudy.countWords(); - System.out.println("result : " + result); - } - - @Test - public void printLongestWordTop100() throws Exception { - StreamStudy.printLongestWordTop100(); - } - - @Test - public void map() throws Exception { - List doubleNumbers = StreamStudy.doubleNumbers(numbers); - doubleNumbers.forEach(System.out::println); - } - - @Test - public void sumAll() throws Exception { - long sum = StreamStudy.sumAll(numbers); - assertThat(sum).isEqualTo(21); - } - - @Test - public void sumOverThreeAndDouble() throws Exception { - numbers = Arrays.asList(3, 1, 6, 2, 4, 8); - long sum = StreamStudy.sumOverThreeAndDouble(numbers); - assertThat(sum).isEqualTo(36); - } -} diff --git a/src/test/java/nextstep/optional/ComputerStoreTest.java b/src/test/java/nextstep/optional/ComputerStoreTest.java deleted file mode 100644 index b576253a..00000000 --- a/src/test/java/nextstep/optional/ComputerStoreTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package nextstep.optional; - -import nextstep.optional.Computer.Soundcard; -import nextstep.optional.Computer.USB; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ComputerStoreTest { - @Test - public void getVersion() { - String version = "pobi's usb"; - Soundcard soundcard = new Soundcard(new USB(version)); - Computer computer = new Computer(soundcard); - assertThat(ComputerStore.getVersion(computer)).isEqualTo(version); - } - - @Test - public void getVersionWhenComputerIsNull() throws Exception { - assertThat(ComputerStore.getVersion(null)).isEqualTo(ComputerStore.UNKNOWN_VERSION); - } - - @Test - public void getVersionWhenSoundcardIsNull() throws Exception { - Computer computer = new Computer(null); - assertThat(ComputerStore.getVersion(computer)).isEqualTo(ComputerStore.UNKNOWN_VERSION); - } - - @Test - public void getVersionWhenUSBIsNull() throws Exception { - Computer computer = new Computer(new Soundcard(null)); - assertThat(ComputerStore.getVersion(computer)).isEqualTo(ComputerStore.UNKNOWN_VERSION); - } - - @Test - public void getVersionOptional() { - String version = "pobi's usb"; - Soundcard soundcard = new Soundcard(new USB(version)); - Computer computer = new Computer(soundcard); - assertThat(ComputerStore.getVersionOptional(computer)).isEqualTo(version); - } - - @Test - public void getVersionOptionalWhenComputerIsNull() throws Exception { - assertThat(ComputerStore.getVersionOptional(null)).isEqualTo(ComputerStore.UNKNOWN_VERSION); - } - - @Test - public void getVersionOptionalWhenSoundcardIsNull() throws Exception { - Computer computer = new Computer(null); - assertThat(ComputerStore.getVersionOptional(computer)).isEqualTo(ComputerStore.UNKNOWN_VERSION); - } - - @Test - public void getVersionOptionalWhenUSBIsNull() throws Exception { - Computer computer = new Computer(new Soundcard(null)); - assertThat(ComputerStore.getVersionOptional(computer)).isEqualTo(ComputerStore.UNKNOWN_VERSION); - } -} diff --git a/src/test/java/nextstep/optional/ExpressionTest.java b/src/test/java/nextstep/optional/ExpressionTest.java deleted file mode 100644 index 32356261..00000000 --- a/src/test/java/nextstep/optional/ExpressionTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package nextstep.optional; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - - -public class ExpressionTest { - @Test - public void of() { - assertThat(Expression.PLUS == Expression.of("+")).isTrue(); - } - - @Test - public void notValidExpression() { - assertThatIllegalArgumentException() - .isThrownBy(() -> { - Expression.of("&"); - }); - } -} diff --git a/src/test/java/nextstep/optional/UserTest.java b/src/test/java/nextstep/optional/UserTest.java deleted file mode 100644 index bfc6af49..00000000 --- a/src/test/java/nextstep/optional/UserTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package nextstep.optional; - -import org.junit.jupiter.api.Test; - -import static nextstep.optional.User.ageIsInRange1; -import static nextstep.optional.User.ageIsInRange2; -import static org.assertj.core.api.Assertions.assertThat; - -public class UserTest { - @Test - public void whenFiltersWithoutOptional_thenCorrect() { - assertThat(ageIsInRange1(new User("crong", 35))).isTrue(); - assertThat(ageIsInRange1(new User("crong", 48))).isFalse(); - assertThat(ageIsInRange1(new User("crong", null))).isFalse(); - assertThat(ageIsInRange1(new User("crong", 29))).isFalse(); - assertThat(ageIsInRange1(null)).isFalse(); - } - - @Test - public void whenFiltersWithOptional_thenCorrect() { - assertThat(ageIsInRange2(new User("crong", 35))).isTrue(); - assertThat(ageIsInRange2(new User("crong", 48))).isFalse(); - assertThat(ageIsInRange2(new User("crong", null))).isFalse(); - assertThat(ageIsInRange2(new User("crong", 29))).isFalse(); - assertThat(ageIsInRange2(null)).isFalse(); - } -} diff --git a/src/test/java/nextstep/optional/UsersTest.java b/src/test/java/nextstep/optional/UsersTest.java deleted file mode 100644 index ec0f7329..00000000 --- a/src/test/java/nextstep/optional/UsersTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package nextstep.optional; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class UsersTest { - - @Test - public void getUser() { - Users users = new Users(); - assertThat(users.getUser("crong")).isEqualTo(new User("crong", 35)); - } - - - @Test - public void getDefaultUser() { - Users users = new Users(); - assertThat(users.getUser("codesquard")).isEqualTo(Users.DEFAULT_USER); - } -} From bfdf2b4ce447998843a4d4fde21181f82621dede Mon Sep 17 00:00:00 2001 From: deok-beom Date: Wed, 22 Nov 2023 14:30:49 +0900 Subject: [PATCH 08/13] =?UTF-8?q?Feat:=20=EC=97=B4=EA=B1=B0=ED=98=95=20Car?= =?UTF-8?q?d=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/blackjack/Card.java | 66 +++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/java/blackjack/Card.java diff --git a/src/main/java/blackjack/Card.java b/src/main/java/blackjack/Card.java new file mode 100644 index 00000000..efec268c --- /dev/null +++ b/src/main/java/blackjack/Card.java @@ -0,0 +1,66 @@ +package blackjack; + +public enum Card { + CLOVER_ACE(10), + CLOVER_1(1), + CLOVER_2(2), + CLOVER_3(3), + CLOVER_4(4), + CLOVER_5(5), + CLOVER_6(6), + CLOVER_7(7), + CLOVER_8(8), + CLOVER_9(9), + CLOVER_JACK(10), + CLOVER_QUEEN(10), + CLOVER_KING(10), + DIAMOND_ACE(10), + DIAMOND_1(1), + DIAMOND_2(2), + DIAMOND_3(3), + DIAMOND_4(4), + DIAMOND_5(5), + DIAMOND_6(6), + DIAMOND_7(7), + DIAMOND_8(8), + DIAMOND_9(9), + DIAMOND_JACK(10), + DIAMOND_QUEEN(10), + DIAMOND_KING(10), + HEART_ACE(10), + HEART_1(1), + HEART_2(2), + HEART_3(3), + HEART_4(4), + HEART_5(5), + HEART_6(6), + HEART_7(7), + HEART_8(8), + HEART_9(9), + HEART_JACK(10), + HEART_QUEEN(10), + HEART_KING(10), + SPADE_ACE(10), + SPADE_1(1), + SPADE_2(2), + SPADE_3(3), + SPADE_4(4), + SPADE_5(5), + SPADE_6(6), + SPADE_7(7), + SPADE_8(8), + SPADE_9(9), + SPADE_JACK(10), + SPADE_QUEEN(10), + SPADE_KING(10); + + private final int number; + + Card (int number) { + this.number = number; + } + + public int getNumber() { + return this.number; + } +} \ No newline at end of file From 85abbe62479da5b4a46b655ab03359b1fee849ee Mon Sep 17 00:00:00 2001 From: deok-beom Date: Wed, 22 Nov 2023 14:59:49 +0900 Subject: [PATCH 09/13] =?UTF-8?q?Feat:=20Deck,=20Player,=20Dealer=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/blackjack/Card.java | 8 +-- src/main/java/blackjack/Dealer.java | 13 +++++ src/main/java/blackjack/Deck.java | 37 ++++++++++++ src/main/java/blackjack/Player.java | 76 +++++++++++++++++++++++++ src/test/java/blackjack/PlayerTest.java | 33 +++++------ 5 files changed, 145 insertions(+), 22 deletions(-) create mode 100644 src/main/java/blackjack/Dealer.java create mode 100644 src/main/java/blackjack/Deck.java create mode 100644 src/main/java/blackjack/Player.java diff --git a/src/main/java/blackjack/Card.java b/src/main/java/blackjack/Card.java index efec268c..07190852 100644 --- a/src/main/java/blackjack/Card.java +++ b/src/main/java/blackjack/Card.java @@ -1,7 +1,7 @@ package blackjack; public enum Card { - CLOVER_ACE(10), + CLOVER_ACE(11), CLOVER_1(1), CLOVER_2(2), CLOVER_3(3), @@ -14,7 +14,7 @@ public enum Card { CLOVER_JACK(10), CLOVER_QUEEN(10), CLOVER_KING(10), - DIAMOND_ACE(10), + DIAMOND_ACE(11), DIAMOND_1(1), DIAMOND_2(2), DIAMOND_3(3), @@ -27,7 +27,7 @@ public enum Card { DIAMOND_JACK(10), DIAMOND_QUEEN(10), DIAMOND_KING(10), - HEART_ACE(10), + HEART_ACE(11), HEART_1(1), HEART_2(2), HEART_3(3), @@ -40,7 +40,7 @@ public enum Card { HEART_JACK(10), HEART_QUEEN(10), HEART_KING(10), - SPADE_ACE(10), + SPADE_ACE(11), SPADE_1(1), SPADE_2(2), SPADE_3(3), diff --git a/src/main/java/blackjack/Dealer.java b/src/main/java/blackjack/Dealer.java new file mode 100644 index 00000000..8994ca11 --- /dev/null +++ b/src/main/java/blackjack/Dealer.java @@ -0,0 +1,13 @@ +package blackjack; + +public class Dealer extends Player { + + public Dealer() { + super("딜러"); + } + + public boolean isPlay() { + int result = calculateHands(); + return result <= 16; + } +} diff --git a/src/main/java/blackjack/Deck.java b/src/main/java/blackjack/Deck.java new file mode 100644 index 00000000..b51db9bb --- /dev/null +++ b/src/main/java/blackjack/Deck.java @@ -0,0 +1,37 @@ +package blackjack; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +public class Deck { + private final List cards; + + public Deck() { + this.cards = getShuffledDeck(); + } + + private List getShuffledDeck() { + Random random = new Random(); + List noShuffled = Arrays.asList(Card.values()); + List shuffled = new ArrayList<>(); + for (int i = noShuffled.size(); i > 0; i--) { + int pick = random.nextInt(noShuffled.size()); + shuffled.add(noShuffled.get(pick)); + noShuffled.remove(pick); + } + + return shuffled; + } + + public Card draw() { + if (cards.isEmpty()) { + throw new IllegalArgumentException("덱에 남은 카드가 없습니다."); + } + + Card top = cards.get(cards.size() - 1); + cards.remove(cards.size() - 1); + return top; + } +} diff --git a/src/main/java/blackjack/Player.java b/src/main/java/blackjack/Player.java new file mode 100644 index 00000000..4153da55 --- /dev/null +++ b/src/main/java/blackjack/Player.java @@ -0,0 +1,76 @@ +package blackjack; + +import java.util.ArrayList; +import java.util.List; + +public class Player { + private final String name; + private final List hands; + private int chip; + + public Player(String name) { + this.name = name; + this.chip = 100000; + this.hands = new ArrayList<>(); + } + + public String getName() { + return this.name; + } + + public List getHands() { + return this.hands; + } + + + public int getChip() { + return chip; + } + + public void bat(int batAmount) { + if (chip - batAmount < 0) { + throw new IllegalArgumentException("배팅 금액이 너무 큽니다."); + } + + chip -= batAmount; + } + + public void addHand(Card card) { + hands.add(card); + } + + public int calculateHands() { + int sum = 0; + for (Card hand : hands) { + sum = addNumber(hand, sum); + } + + return sum; + } + + private int addNumber(Card hand, int sum) { + int number = hand.getNumber(); + if (isAce(hand) && sum + number > 21) { + return sum + 1; + } + + return sum + number; + } + + private boolean isAce(Card card) { + return card == Card.CLOVER_ACE + || card == Card.HEART_ACE + || card == Card.DIAMOND_ACE + || card == Card.SPADE_ACE; + } + + public boolean isBust() { + int result = calculateHands(); + return result > 21; + } + + public boolean isBlackJack() { + int result = calculateHands(); + return result == 21; + } +} diff --git a/src/test/java/blackjack/PlayerTest.java b/src/test/java/blackjack/PlayerTest.java index faf9f5f4..7911a5c5 100644 --- a/src/test/java/blackjack/PlayerTest.java +++ b/src/test/java/blackjack/PlayerTest.java @@ -10,44 +10,41 @@ public class PlayerTest { @Test - void 배팅() { + void 생성() { // given - Player player = new Player("tester"); - int batAmount = 10000; + Player player = new Player("pobi"); // when - player.bat(batAmount); + String name = player.getName(); // then - assertThat(player.getBatAmount()).isEqualTo(batAmount); + assertThat(name).isEqualTo("pobi"); } @Test - void 딜링() { + void 배팅() { // given Player player = new Player("tester"); + int batAmount = 10000; // when - player.addHand(Card.CLOVER_ACE); + player.bat(batAmount); // then - assertThat(player.getHands().size()).isOne(); - assertThat(player.getHands()).contains(Card.CLOVER_ACE); + assertThat(player.getChip()).isEqualTo(90000); } @Test - void 히트() { + void 손_패_추가() { // given Player player = new Player("tester"); - player.addHand(Card.CLOVER_KING); - player.addHand(Card.HEART_KING); // when - player.hit(Card.SPADE_KING); + player.addHand(Card.CLOVER_ACE); // then - assertThat(player.getHands().size()).isEqualTo(3); - assertThat(player.getHands()).contains(Card.CLOVER_KING, Card.HEART_KING, Card.SPADE_KING); + assertThat(player.getHands().size()).isOne(); + assertThat(player.getHands()).contains(Card.CLOVER_ACE); } @ParameterizedTest @@ -58,7 +55,7 @@ public class PlayerTest { addHandFromInput(input, player); // when - int result = player.calculate(); + int result = player.calculateHands(); // then assertThat(result).isEqualTo(expect); @@ -72,7 +69,7 @@ public class PlayerTest { addHandFromInput(input, player); // when - int result = player.calculate(); + int result = player.calculateHands(); // then assertThat(result).isEqualTo(21); @@ -101,7 +98,7 @@ public class PlayerTest { player.addHand(Card.DIAMOND_4); // when - int result = player.calculate(); + int result = player.calculateHands(); // then assertThat(result).isEqualTo(21); From 894b2a93c484b5ab4fbbf26884799422be97673d Mon Sep 17 00:00:00 2001 From: deok-beom Date: Wed, 22 Nov 2023 17:11:00 +0900 Subject: [PATCH 10/13] =?UTF-8?q?Feat:=20Game=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 13 ++ src/main/java/blackjack/Card.java | 112 +++++++------ src/main/java/blackjack/Dealer.java | 5 + src/main/java/blackjack/Deck.java | 2 +- src/main/java/blackjack/Game.java | 211 ++++++++++++++++++++++++ src/main/java/blackjack/Player.java | 25 ++- src/main/java/util/Terminal.java | 23 +++ src/test/java/blackjack/PlayerTest.java | 5 +- 8 files changed, 326 insertions(+), 70 deletions(-) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/blackjack/Game.java create mode 100644 src/main/java/util/Terminal.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000..750c9865 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,13 @@ +import blackjack.Game; + +public class Application { + public static void main(String[] args) { + Game game = new Game(); + game.addPlayer(); + game.proceedBattingStep(); + game.deal(); + game.proceedPlayerPlay(); + game.proceedDealerPlay(); + game.calculateResult(); + } +} diff --git a/src/main/java/blackjack/Card.java b/src/main/java/blackjack/Card.java index 07190852..d4af1a1a 100644 --- a/src/main/java/blackjack/Card.java +++ b/src/main/java/blackjack/Card.java @@ -1,66 +1,72 @@ package blackjack; public enum Card { - CLOVER_ACE(11), - CLOVER_1(1), - CLOVER_2(2), - CLOVER_3(3), - CLOVER_4(4), - CLOVER_5(5), - CLOVER_6(6), - CLOVER_7(7), - CLOVER_8(8), - CLOVER_9(9), - CLOVER_JACK(10), - CLOVER_QUEEN(10), - CLOVER_KING(10), - DIAMOND_ACE(11), - DIAMOND_1(1), - DIAMOND_2(2), - DIAMOND_3(3), - DIAMOND_4(4), - DIAMOND_5(5), - DIAMOND_6(6), - DIAMOND_7(7), - DIAMOND_8(8), - DIAMOND_9(9), - DIAMOND_JACK(10), - DIAMOND_QUEEN(10), - DIAMOND_KING(10), - HEART_ACE(11), - HEART_1(1), - HEART_2(2), - HEART_3(3), - HEART_4(4), - HEART_5(5), - HEART_6(6), - HEART_7(7), - HEART_8(8), - HEART_9(9), - HEART_JACK(10), - HEART_QUEEN(10), - HEART_KING(10), - SPADE_ACE(11), - SPADE_1(1), - SPADE_2(2), - SPADE_3(3), - SPADE_4(4), - SPADE_5(5), - SPADE_6(6), - SPADE_7(7), - SPADE_8(8), - SPADE_9(9), - SPADE_JACK(10), - SPADE_QUEEN(10), - SPADE_KING(10); + CLOVER_ACE(11, "A클로버"), + CLOVER_1(1, "1클로버"), + CLOVER_2(2, "2클로버"), + CLOVER_3(3, "3클로버"), + CLOVER_4(4, "4클로버"), + CLOVER_5(5, "5클로버"), + CLOVER_6(6, "6클로버"), + CLOVER_7(7, "7클로버"), + CLOVER_8(8, "8클로버"), + CLOVER_9(9, "9클로버"), + CLOVER_JACK(10, "J클로버"), + CLOVER_QUEEN(10, "Q클로버"), + CLOVER_KING(10, "K클로버"), + DIAMOND_ACE(11, "A다이아몬드"), + DIAMOND_1(1, "1다이아몬드"), + DIAMOND_2(2, "2다이아몬드"), + DIAMOND_3(3, "3다이아몬드"), + DIAMOND_4(4, "4다이아몬드"), + DIAMOND_5(5, "5다이아몬드"), + DIAMOND_6(6, "6다이아몬드"), + DIAMOND_7(7, "7다이아몬드"), + DIAMOND_8(8, "8다이아몬드"), + DIAMOND_9(9, "9다이아몬드"), + DIAMOND_JACK(10, "J다이아몬드"), + DIAMOND_QUEEN(10, "Q다이아몬드"), + DIAMOND_KING(10, "K다이아몬드"), + HEART_ACE(11, "A하트"), + HEART_1(1, "1하트"), + HEART_2(2, "2하트"), + HEART_3(3, "3하트"), + HEART_4(4, "4하트"), + HEART_5(5, "5하트"), + HEART_6(6, "6하트"), + HEART_7(7, "7하트"), + HEART_8(8, "8하트"), + HEART_9(9, "9하트"), + HEART_JACK(10, "J하트"), + HEART_QUEEN(10, "Q하트"), + HEART_KING(10, "K하트"), + SPADE_ACE(11, "A스페이드"), + SPADE_1(1, "1스페이드"), + SPADE_2(2, "2스페이드"), + SPADE_3(3, "3스페이드"), + SPADE_4(4, "4스페이드"), + SPADE_5(5, "5스페이드"), + SPADE_6(6, "6스페이드"), + SPADE_7(7, "7스페이드"), + SPADE_8(8, "8스페이드"), + SPADE_9(9, "9스페이드"), + SPADE_JACK(10, "J스페이드"), + SPADE_QUEEN(10, "Q스페이드"), + SPADE_KING(10, "K스페이드"); private final int number; + private final String name; - Card (int number) { + Card(int number, String name) { this.number = number; + this.name = name; } public int getNumber() { return this.number; } + + public String getName() { + return this.name; + } } \ No newline at end of file diff --git a/src/main/java/blackjack/Dealer.java b/src/main/java/blackjack/Dealer.java index 8994ca11..4df2eb5e 100644 --- a/src/main/java/blackjack/Dealer.java +++ b/src/main/java/blackjack/Dealer.java @@ -4,10 +4,15 @@ public class Dealer extends Player { public Dealer() { super("딜러"); + this.chip = 0; } public boolean isPlay() { int result = calculateHands(); return result <= 16; } + + public void subtractChip(double chip) { + this.chip -= chip; + } } diff --git a/src/main/java/blackjack/Deck.java b/src/main/java/blackjack/Deck.java index b51db9bb..0592173e 100644 --- a/src/main/java/blackjack/Deck.java +++ b/src/main/java/blackjack/Deck.java @@ -14,7 +14,7 @@ public Deck() { private List getShuffledDeck() { Random random = new Random(); - List noShuffled = Arrays.asList(Card.values()); + List noShuffled = new ArrayList<>(Arrays.asList(Card.values())); List shuffled = new ArrayList<>(); for (int i = noShuffled.size(); i > 0; i--) { int pick = random.nextInt(noShuffled.size()); diff --git a/src/main/java/blackjack/Game.java b/src/main/java/blackjack/Game.java new file mode 100644 index 00000000..09caa213 --- /dev/null +++ b/src/main/java/blackjack/Game.java @@ -0,0 +1,211 @@ +package blackjack; + +import util.Terminal; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class Game { + + private final Map playerAndBattingMap; + private final Dealer dealer; + private final Deck deck; + + public Game() { + playerAndBattingMap = new HashMap<>(); + dealer = new Dealer(); + this.deck = new Deck(); + } + + public void addPlayer() { + while (true) { + String in; + try { + in = Terminal.in("게임에 참여할 사람의 이름을 입력하세요. (쉼표 기준으로 분리)"); + Terminal.outln(); + } catch (IOException e) { + Terminal.out("입력이 바르지 않습니다."); + continue; + } + + String[] names = in.split(","); + for (String name : names) { + Player player = new Player(name); + playerAndBattingMap.put(player, 0); + } + return; + } + } + + public void proceedBattingStep() { + playerAndBattingMap.forEach((player, batAmount) -> proceedBattingStep(player)); + } + + private void proceedBattingStep(Player player) { + while (true) { + int batAmount; + + try { + String in = Terminal.in(String.format("%s의 배팅 금액은?", player.getName())); + Terminal.outln(); + batAmount = Integer.parseInt(in); + } catch (IOException e) { + Terminal.out("입력이 바르지 않습니다."); + continue; + } + catch (IllegalArgumentException e) { + Terminal.out(e.getMessage()); + continue; + } + + playerAndBattingMap.replace(player, batAmount); + return; + } + } + + public void deal() { + drawAndAddHand(dealer); + playerAndBattingMap.forEach((player, batAmount) -> drawAndAddHand(player)); + + StringBuilder sb = new StringBuilder(); + sb.append("딜러에게 1장, "); + boolean isFirst = true; + for (Player player : playerAndBattingMap.keySet()) { + if (!isFirst) { + sb.append(", "); + } + + sb.append(player.getName()); + isFirst = false; + } + + sb.append("에게 2장의 카드를 나누었습니다."); + + Terminal.out(sb.toString()); + showHand(dealer); + Terminal.outln(); + } + + private void drawAndAddHand(Player player) { + player.addHand(deck.draw()); + + if (player instanceof Dealer) { + return; + } + + player.addHand(deck.draw()); + } + + public void proceedPlayerPlay() { + playerAndBattingMap.forEach((player, batAmount) -> askStayOrHit(player)); + } + + private void askStayOrHit(Player player) { + showHand(player); + + while (!player.isBust()) { + String input; + + try { + input = Terminal.in(String.format("%s는 한 장의 카드를 더 받겠습니까? (예는 y, 아니오는 n)", player.getName())); + Terminal.outln(); + } catch (IOException e) { + Terminal.out("입력이 바르지 않습니다."); + continue; + } + + if (input.trim().equalsIgnoreCase("y")) { + player.addHand(deck.draw()); + showHand(player); + continue; + } + + if (input.trim().equalsIgnoreCase("n")) { + return; + } + + Terminal.out("y 또는 n 중에서 입력해주세요."); + } + } + + public void proceedDealerPlay() { + while (dealer.isPlay()) { + dealer.addHand(deck.draw()); + Terminal.out("딜러는 손패의 합이 16이하라 한장의 카드를 더 받았습니다."); + Terminal.outln(); + } + } + + public void calculateResult() { + showHand(dealer); + playerAndBattingMap.forEach((player, batAmount) -> showHand(player)); + + Terminal.out("## 최종 수익"); + for (Map.Entry entry : playerAndBattingMap.entrySet()) { + Player player = entry.getKey(); + int batAmount = entry.getValue(); + double profit = calculateProfit(player, batAmount); + + player.addChip(profit); + dealer.addChip(-profit); + } + + printFinalProfit(dealer); + playerAndBattingMap.forEach((player, batAmount) -> printFinalProfit(player)); + } + + public void showHand(Player player) { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("%s 카드 : ", player.getName())); + + List hands = player.getHands(); + for (int i = 0; i < hands.size(); i++) { + if ( i != 0 ) { + sb.append(", "); + } + + sb.append(hands.get(i).getName()); + } + + sb.append(String.format(" - 결과: %d", player.calculateHands())); + Terminal.out(sb.toString()); + } + + private double calculateProfit(Player player, int batAmount) { + if (player.isBust()) { + return -batAmount; + } + + if (player.isBlackJack()) { + if (dealer.isBlackJack()) { + return 0; + } + + return batAmount * 1.5; + } + + if (dealer.isBust()) { + return batAmount; + } + + int playerNumber = player.calculateHands(); + int dealerNumber = dealer.calculateHands(); + if (playerNumber > dealerNumber) { + return batAmount; + } + + if (playerNumber < dealerNumber) { + return -batAmount; + } + + return 0; + } + + private void printFinalProfit(Player player) { + String message = String.format("%s: %.0f", player.getName(), player.getChip()); + Terminal.out(message); + } +} diff --git a/src/main/java/blackjack/Player.java b/src/main/java/blackjack/Player.java index 4153da55..b656322c 100644 --- a/src/main/java/blackjack/Player.java +++ b/src/main/java/blackjack/Player.java @@ -4,13 +4,12 @@ import java.util.List; public class Player { - private final String name; - private final List hands; - private int chip; + protected final String name; + protected final List hands; + protected double chip; public Player(String name) { this.name = name; - this.chip = 100000; this.hands = new ArrayList<>(); } @@ -23,18 +22,10 @@ public List getHands() { } - public int getChip() { + public double getChip() { return chip; } - public void bat(int batAmount) { - if (chip - batAmount < 0) { - throw new IllegalArgumentException("배팅 금액이 너무 큽니다."); - } - - chip -= batAmount; - } - public void addHand(Card card) { hands.add(card); } @@ -70,7 +61,15 @@ public boolean isBust() { } public boolean isBlackJack() { + if (hands.size() != 2) { + return false; + } + int result = calculateHands(); return result == 21; } + + public void addChip(double chip) { + this.chip += chip; + } } diff --git a/src/main/java/util/Terminal.java b/src/main/java/util/Terminal.java new file mode 100644 index 00000000..23a1ab58 --- /dev/null +++ b/src/main/java/util/Terminal.java @@ -0,0 +1,23 @@ +package util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class Terminal { + + private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + public static String in(String message) throws IOException { + out(message); + return br.readLine(); + } + + public static void out(String message) { + System.out.println(message); + } + + public static void outln() { + System.out.println(); + } +} diff --git a/src/test/java/blackjack/PlayerTest.java b/src/test/java/blackjack/PlayerTest.java index 7911a5c5..2c08f6df 100644 --- a/src/test/java/blackjack/PlayerTest.java +++ b/src/test/java/blackjack/PlayerTest.java @@ -94,8 +94,7 @@ public class PlayerTest { // given Player player = new Player("tester"); player.addHand(Card.CLOVER_KING); - player.addHand(Card.HEART_7); - player.addHand(Card.DIAMOND_4); + player.addHand(Card.DIAMOND_ACE); // when int result = player.calculateHands(); @@ -106,7 +105,7 @@ public class PlayerTest { } @ParameterizedTest - @ValueSource(strings = {"CLOVER_KING,HEART_7,DIAMOND_5", "CLOVER_KING,HEART_7"}) + @ValueSource(strings = {"CLOVER_KING,HEART_7,DIAMOND_5", "CLOVER_KING,HEART_7", "CLOVER_KING,HEART_KING,CLOVER_ACE"}) void 블랙잭_아님(String input) { // given Player player = new Player("tester"); From 688d06438a40f9fdb897d119d3ae18974b009b01 Mon Sep 17 00:00:00 2001 From: deok-beom Date: Wed, 22 Nov 2023 17:12:04 +0900 Subject: [PATCH 11/13] =?UTF-8?q?Refactor:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EB=B0=8F=20method=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/blackjack/Dealer.java | 4 ---- src/main/java/blackjack/Game.java | 1 - src/test/java/blackjack/PlayerTest.java | 13 ------------- 3 files changed, 18 deletions(-) diff --git a/src/main/java/blackjack/Dealer.java b/src/main/java/blackjack/Dealer.java index 4df2eb5e..d8eade1c 100644 --- a/src/main/java/blackjack/Dealer.java +++ b/src/main/java/blackjack/Dealer.java @@ -11,8 +11,4 @@ public boolean isPlay() { int result = calculateHands(); return result <= 16; } - - public void subtractChip(double chip) { - this.chip -= chip; - } } diff --git a/src/main/java/blackjack/Game.java b/src/main/java/blackjack/Game.java index 09caa213..08a35d82 100644 --- a/src/main/java/blackjack/Game.java +++ b/src/main/java/blackjack/Game.java @@ -6,7 +6,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; public class Game { diff --git a/src/test/java/blackjack/PlayerTest.java b/src/test/java/blackjack/PlayerTest.java index 2c08f6df..bd4f276c 100644 --- a/src/test/java/blackjack/PlayerTest.java +++ b/src/test/java/blackjack/PlayerTest.java @@ -21,19 +21,6 @@ public class PlayerTest { assertThat(name).isEqualTo("pobi"); } - @Test - void 배팅() { - // given - Player player = new Player("tester"); - int batAmount = 10000; - - // when - player.bat(batAmount); - - // then - assertThat(player.getChip()).isEqualTo(90000); - } - @Test void 손_패_추가() { // given From 6834b8f94e6fbccba9b68675926d8cf34174be84 Mon Sep 17 00:00:00 2001 From: deok-beom Date: Thu, 23 Nov 2023 16:19:48 +0900 Subject: [PATCH 12/13] =?UTF-8?q?Refactor:=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=201.=20=EC=97=B4=EA=B1=B0=ED=98=95=20Card=EB=A5=BC=20?= =?UTF-8?q?=EC=97=B4=EA=B1=B0=ED=98=95=20Rank,=20=EC=97=B4=EA=B1=B0?= =?UTF-8?q?=ED=98=95=20Suit,=20=ED=81=B4=EB=9E=98=EC=8A=A4=20Card=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=202.=20Game=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=EB=A5=BC=20GameHandler=EB=A1=9C=20=EB=B3=80=EA=B2=BD=203.=20Ga?= =?UTF-8?q?me=20=ED=81=B4=EB=9E=98=EC=8A=A4=EC=97=90=EC=84=9C=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=EC=97=90=20=EC=9E=85=EB=A0=A5/=ED=91=9C=EC=8B=9C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20Game=20Input?= =?UTF-8?q?/Output=20View=EB=A1=9C=20=EB=B6=84=EB=A6=AC=204.=20=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4=20Game=20=ED=81=B4=EB=9E=98=EC=8A=A4=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EA=B0=81=20=ED=94=8C=EB=A0=88=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EC=9D=98=20=EB=B0=B0=ED=8C=85=20=EA=B8=88=EC=95=A1=EC=9D=84=20?= =?UTF-8?q?Map=EC=9C=BC=EB=A1=9C=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8D=98=20?= =?UTF-8?q?=EA=B2=83=EC=9D=84=20=ED=94=8C=EB=A0=88=EC=9D=B4=EC=96=B4=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=8A=A4=EC=8A=A4=EB=A1=9C=EA=B0=80=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD,=20=EC=9D=B4=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=9D=B5=20=EA=B3=84=EC=82=B0=EB=8F=84=20=ED=94=8C?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=20=EA=B0=9D=EC=B2=B4=EA=B0=80=20?= =?UTF-8?q?=EC=8A=A4=EC=8A=A4=EB=A1=9C=EA=B0=80=20=EC=88=98=ED=96=89?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 16 +- src/main/java/blackjack/Card.java | 72 ------- src/main/java/blackjack/Dealer.java | 4 + src/main/java/blackjack/Deck.java | 37 ---- src/main/java/blackjack/Game.java | 210 --------------------- src/main/java/blackjack/GameHandler.java | 155 +++++++++++++++ src/main/java/blackjack/Player.java | 33 ++-- src/main/java/blackjack/card/Card.java | 47 +++++ src/main/java/blackjack/card/Deck.java | 48 +++++ src/main/java/blackjack/card/Rank.java | 32 ++++ src/main/java/blackjack/card/Suit.java | 18 ++ src/main/java/view/GameInputView.java | 62 ++++++ src/main/java/view/GameOutputView.java | 68 +++++++ src/main/java/{util => view}/Terminal.java | 8 +- src/test/java/blackjack/DealerTest.java | 9 +- src/test/java/blackjack/PlayerTest.java | 27 +-- 16 files changed, 490 insertions(+), 356 deletions(-) delete mode 100644 src/main/java/blackjack/Card.java delete mode 100644 src/main/java/blackjack/Deck.java delete mode 100644 src/main/java/blackjack/Game.java create mode 100644 src/main/java/blackjack/GameHandler.java create mode 100644 src/main/java/blackjack/card/Card.java create mode 100644 src/main/java/blackjack/card/Deck.java create mode 100644 src/main/java/blackjack/card/Rank.java create mode 100644 src/main/java/blackjack/card/Suit.java create mode 100644 src/main/java/view/GameInputView.java create mode 100644 src/main/java/view/GameOutputView.java rename src/main/java/{util => view}/Terminal.java (77%) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 750c9865..79597bd0 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,13 +1,13 @@ -import blackjack.Game; +import blackjack.GameHandler; public class Application { public static void main(String[] args) { - Game game = new Game(); - game.addPlayer(); - game.proceedBattingStep(); - game.deal(); - game.proceedPlayerPlay(); - game.proceedDealerPlay(); - game.calculateResult(); + GameHandler gameHandler = new GameHandler(); + gameHandler.handleAddPlayer(); + gameHandler.handleBatting(); + gameHandler.handleDeal(); + gameHandler.handlePlayerPlay(); + gameHandler.proceedDealerPlay(); + gameHandler.handleCalculateStep(); } } diff --git a/src/main/java/blackjack/Card.java b/src/main/java/blackjack/Card.java deleted file mode 100644 index d4af1a1a..00000000 --- a/src/main/java/blackjack/Card.java +++ /dev/null @@ -1,72 +0,0 @@ -package blackjack; - -public enum Card { - CLOVER_ACE(11, "A클로버"), - CLOVER_1(1, "1클로버"), - CLOVER_2(2, "2클로버"), - CLOVER_3(3, "3클로버"), - CLOVER_4(4, "4클로버"), - CLOVER_5(5, "5클로버"), - CLOVER_6(6, "6클로버"), - CLOVER_7(7, "7클로버"), - CLOVER_8(8, "8클로버"), - CLOVER_9(9, "9클로버"), - CLOVER_JACK(10, "J클로버"), - CLOVER_QUEEN(10, "Q클로버"), - CLOVER_KING(10, "K클로버"), - DIAMOND_ACE(11, "A다이아몬드"), - DIAMOND_1(1, "1다이아몬드"), - DIAMOND_2(2, "2다이아몬드"), - DIAMOND_3(3, "3다이아몬드"), - DIAMOND_4(4, "4다이아몬드"), - DIAMOND_5(5, "5다이아몬드"), - DIAMOND_6(6, "6다이아몬드"), - DIAMOND_7(7, "7다이아몬드"), - DIAMOND_8(8, "8다이아몬드"), - DIAMOND_9(9, "9다이아몬드"), - DIAMOND_JACK(10, "J다이아몬드"), - DIAMOND_QUEEN(10, "Q다이아몬드"), - DIAMOND_KING(10, "K다이아몬드"), - HEART_ACE(11, "A하트"), - HEART_1(1, "1하트"), - HEART_2(2, "2하트"), - HEART_3(3, "3하트"), - HEART_4(4, "4하트"), - HEART_5(5, "5하트"), - HEART_6(6, "6하트"), - HEART_7(7, "7하트"), - HEART_8(8, "8하트"), - HEART_9(9, "9하트"), - HEART_JACK(10, "J하트"), - HEART_QUEEN(10, "Q하트"), - HEART_KING(10, "K하트"), - SPADE_ACE(11, "A스페이드"), - SPADE_1(1, "1스페이드"), - SPADE_2(2, "2스페이드"), - SPADE_3(3, "3스페이드"), - SPADE_4(4, "4스페이드"), - SPADE_5(5, "5스페이드"), - SPADE_6(6, "6스페이드"), - SPADE_7(7, "7스페이드"), - SPADE_8(8, "8스페이드"), - SPADE_9(9, "9스페이드"), - SPADE_JACK(10, "J스페이드"), - SPADE_QUEEN(10, "Q스페이드"), - SPADE_KING(10, "K스페이드"); - - private final int number; - private final String name; - - Card(int number, String name) { - this.number = number; - this.name = name; - } - - public int getNumber() { - return this.number; - } - - public String getName() { - return this.name; - } -} \ No newline at end of file diff --git a/src/main/java/blackjack/Dealer.java b/src/main/java/blackjack/Dealer.java index d8eade1c..f6f60076 100644 --- a/src/main/java/blackjack/Dealer.java +++ b/src/main/java/blackjack/Dealer.java @@ -11,4 +11,8 @@ public boolean isPlay() { int result = calculateHands(); return result <= 16; } + + public void addChip(double chip) { + this.chip -= chip; + } } diff --git a/src/main/java/blackjack/Deck.java b/src/main/java/blackjack/Deck.java deleted file mode 100644 index 0592173e..00000000 --- a/src/main/java/blackjack/Deck.java +++ /dev/null @@ -1,37 +0,0 @@ -package blackjack; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - -public class Deck { - private final List cards; - - public Deck() { - this.cards = getShuffledDeck(); - } - - private List getShuffledDeck() { - Random random = new Random(); - List noShuffled = new ArrayList<>(Arrays.asList(Card.values())); - List shuffled = new ArrayList<>(); - for (int i = noShuffled.size(); i > 0; i--) { - int pick = random.nextInt(noShuffled.size()); - shuffled.add(noShuffled.get(pick)); - noShuffled.remove(pick); - } - - return shuffled; - } - - public Card draw() { - if (cards.isEmpty()) { - throw new IllegalArgumentException("덱에 남은 카드가 없습니다."); - } - - Card top = cards.get(cards.size() - 1); - cards.remove(cards.size() - 1); - return top; - } -} diff --git a/src/main/java/blackjack/Game.java b/src/main/java/blackjack/Game.java deleted file mode 100644 index 08a35d82..00000000 --- a/src/main/java/blackjack/Game.java +++ /dev/null @@ -1,210 +0,0 @@ -package blackjack; - -import util.Terminal; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class Game { - - private final Map playerAndBattingMap; - private final Dealer dealer; - private final Deck deck; - - public Game() { - playerAndBattingMap = new HashMap<>(); - dealer = new Dealer(); - this.deck = new Deck(); - } - - public void addPlayer() { - while (true) { - String in; - try { - in = Terminal.in("게임에 참여할 사람의 이름을 입력하세요. (쉼표 기준으로 분리)"); - Terminal.outln(); - } catch (IOException e) { - Terminal.out("입력이 바르지 않습니다."); - continue; - } - - String[] names = in.split(","); - for (String name : names) { - Player player = new Player(name); - playerAndBattingMap.put(player, 0); - } - return; - } - } - - public void proceedBattingStep() { - playerAndBattingMap.forEach((player, batAmount) -> proceedBattingStep(player)); - } - - private void proceedBattingStep(Player player) { - while (true) { - int batAmount; - - try { - String in = Terminal.in(String.format("%s의 배팅 금액은?", player.getName())); - Terminal.outln(); - batAmount = Integer.parseInt(in); - } catch (IOException e) { - Terminal.out("입력이 바르지 않습니다."); - continue; - } - catch (IllegalArgumentException e) { - Terminal.out(e.getMessage()); - continue; - } - - playerAndBattingMap.replace(player, batAmount); - return; - } - } - - public void deal() { - drawAndAddHand(dealer); - playerAndBattingMap.forEach((player, batAmount) -> drawAndAddHand(player)); - - StringBuilder sb = new StringBuilder(); - sb.append("딜러에게 1장, "); - boolean isFirst = true; - for (Player player : playerAndBattingMap.keySet()) { - if (!isFirst) { - sb.append(", "); - } - - sb.append(player.getName()); - isFirst = false; - } - - sb.append("에게 2장의 카드를 나누었습니다."); - - Terminal.out(sb.toString()); - showHand(dealer); - Terminal.outln(); - } - - private void drawAndAddHand(Player player) { - player.addHand(deck.draw()); - - if (player instanceof Dealer) { - return; - } - - player.addHand(deck.draw()); - } - - public void proceedPlayerPlay() { - playerAndBattingMap.forEach((player, batAmount) -> askStayOrHit(player)); - } - - private void askStayOrHit(Player player) { - showHand(player); - - while (!player.isBust()) { - String input; - - try { - input = Terminal.in(String.format("%s는 한 장의 카드를 더 받겠습니까? (예는 y, 아니오는 n)", player.getName())); - Terminal.outln(); - } catch (IOException e) { - Terminal.out("입력이 바르지 않습니다."); - continue; - } - - if (input.trim().equalsIgnoreCase("y")) { - player.addHand(deck.draw()); - showHand(player); - continue; - } - - if (input.trim().equalsIgnoreCase("n")) { - return; - } - - Terminal.out("y 또는 n 중에서 입력해주세요."); - } - } - - public void proceedDealerPlay() { - while (dealer.isPlay()) { - dealer.addHand(deck.draw()); - Terminal.out("딜러는 손패의 합이 16이하라 한장의 카드를 더 받았습니다."); - Terminal.outln(); - } - } - - public void calculateResult() { - showHand(dealer); - playerAndBattingMap.forEach((player, batAmount) -> showHand(player)); - - Terminal.out("## 최종 수익"); - for (Map.Entry entry : playerAndBattingMap.entrySet()) { - Player player = entry.getKey(); - int batAmount = entry.getValue(); - double profit = calculateProfit(player, batAmount); - - player.addChip(profit); - dealer.addChip(-profit); - } - - printFinalProfit(dealer); - playerAndBattingMap.forEach((player, batAmount) -> printFinalProfit(player)); - } - - public void showHand(Player player) { - StringBuilder sb = new StringBuilder(); - sb.append(String.format("%s 카드 : ", player.getName())); - - List hands = player.getHands(); - for (int i = 0; i < hands.size(); i++) { - if ( i != 0 ) { - sb.append(", "); - } - - sb.append(hands.get(i).getName()); - } - - sb.append(String.format(" - 결과: %d", player.calculateHands())); - Terminal.out(sb.toString()); - } - - private double calculateProfit(Player player, int batAmount) { - if (player.isBust()) { - return -batAmount; - } - - if (player.isBlackJack()) { - if (dealer.isBlackJack()) { - return 0; - } - - return batAmount * 1.5; - } - - if (dealer.isBust()) { - return batAmount; - } - - int playerNumber = player.calculateHands(); - int dealerNumber = dealer.calculateHands(); - if (playerNumber > dealerNumber) { - return batAmount; - } - - if (playerNumber < dealerNumber) { - return -batAmount; - } - - return 0; - } - - private void printFinalProfit(Player player) { - String message = String.format("%s: %.0f", player.getName(), player.getChip()); - Terminal.out(message); - } -} diff --git a/src/main/java/blackjack/GameHandler.java b/src/main/java/blackjack/GameHandler.java new file mode 100644 index 00000000..29e1c577 --- /dev/null +++ b/src/main/java/blackjack/GameHandler.java @@ -0,0 +1,155 @@ +package blackjack; + +import blackjack.card.Deck; +import view.GameInputView; +import view.GameOutputView; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class GameHandler { + + private final List players; + private final Dealer dealer; + private final Deck deck; + + public GameHandler() { + players = new ArrayList<>(); + dealer = new Dealer(); + this.deck = new Deck(); + } + + public void handleAddPlayer() { + while (true) { + Optional in = GameInputView.askPlayerName(); + if (!in.isPresent()) { + continue; + } + + String[] names = in.get().split(","); + for (String name : names) { + Player player = new Player(name); + players.add(player); + } + return; + } + } + + public void handleBatting() { + for (Player player : players) { + bat(player); + } + } + + private void bat(Player player) { + while (true) { + Optional in = GameInputView.askBatAmount(player.getName()); + if (!in.isPresent()) { + continue; + } + + Integer batAmount = in.get(); + player.setBatAmount(batAmount); + return; + } + } + + public void handleDeal() { + draw(dealer); + for (Player player : players) { + draw(player); + } + + GameOutputView.announceDealResult(players); + } + + private void draw(Player player) { + int repeat = 2; + + if (player instanceof Dealer) { + repeat = 1; + } + + for (int i = 0; i < repeat; i++) { + player.addHand(deck.draw()); + } + } + + public void handlePlayerPlay() { + for (Player player : players) { + play(player); + } + } + + private void play(Player player) { + GameOutputView.showHand(player); + while (player.isNotBust()) { + Optional in = GameInputView.askHit(player.getName()); + + if (!in.isPresent()) { + continue; + } + + Boolean isHit = in.get(); + if (!isHit) { + return; + } + + player.addHand(deck.draw()); + GameOutputView.showHand(player); + } + } + + public void proceedDealerPlay() { + int count = 0; + while (dealer.isPlay()) { + dealer.addHand(deck.draw()); + count++; + } + GameOutputView.announceDealerPlay(count); + } + + public void handleCalculateStep() { + GameOutputView.showHand(dealer); + for (Player player : players) { + GameOutputView.showHand(player); + calculate(player); + dealer.addChip(player.getChip()); + } + + GameOutputView.announceFinalProfit(dealer, players); + } + + private void calculate(Player player) { + if (player.isBust()) { + player.loss(); + return; + } + + if (player.isBlackJack()) { + if (dealer.isBlackJack()) { + return; + } + + player.gainWithBlackJack(); + return; + } + + if (dealer.isBust()) { + player.gain(); + return; + } + + int playerNumber = player.calculateHands(); + int dealerNumber = dealer.calculateHands(); + if (playerNumber > dealerNumber) { + player.gain(); + return; + } + + if (playerNumber < dealerNumber) { + player.loss(); + } + } +} diff --git a/src/main/java/blackjack/Player.java b/src/main/java/blackjack/Player.java index b656322c..b290be5e 100644 --- a/src/main/java/blackjack/Player.java +++ b/src/main/java/blackjack/Player.java @@ -1,5 +1,7 @@ package blackjack; +import blackjack.card.Card; + import java.util.ArrayList; import java.util.List; @@ -7,6 +9,7 @@ public class Player { protected final String name; protected final List hands; protected double chip; + private int batAmount; public Player(String name) { this.name = name; @@ -21,11 +24,14 @@ public List getHands() { return this.hands; } - public double getChip() { return chip; } + public void setBatAmount(int batAmount) { + this.batAmount = batAmount; + } + public void addHand(Card card) { hands.add(card); } @@ -41,25 +47,22 @@ public int calculateHands() { private int addNumber(Card hand, int sum) { int number = hand.getNumber(); - if (isAce(hand) && sum + number > 21) { + if (hand.isAce() && sum + number > 21) { return sum + 1; } return sum + number; } - private boolean isAce(Card card) { - return card == Card.CLOVER_ACE - || card == Card.HEART_ACE - || card == Card.DIAMOND_ACE - || card == Card.SPADE_ACE; - } - public boolean isBust() { int result = calculateHands(); return result > 21; } + public boolean isNotBust() { + return !isBust(); + } + public boolean isBlackJack() { if (hands.size() != 2) { return false; @@ -69,7 +72,15 @@ public boolean isBlackJack() { return result == 21; } - public void addChip(double chip) { - this.chip += chip; + public void gain() { + this.chip += batAmount; + } + + public void gainWithBlackJack() { + this.chip += batAmount * 1.5; + } + + public void loss() { + this.chip -= batAmount; } } diff --git a/src/main/java/blackjack/card/Card.java b/src/main/java/blackjack/card/Card.java new file mode 100644 index 00000000..74cf3327 --- /dev/null +++ b/src/main/java/blackjack/card/Card.java @@ -0,0 +1,47 @@ +package blackjack.card; + +public class Card { + private final Rank rank; + private final Suit suit; + + public Card(Rank rank, Suit suit) { + this.rank = rank; + this.suit = suit; + } + + public String getCardName() { + return this.rank.getMark() + this.suit.getName(); + } + + public boolean isAce() { + return this.rank == Rank.ACE; + } + + public int getNumber() { + return this.rank.getNumber(); + } + + @Override + public int hashCode() { + int result = 17; + result = 37 * result * rank.hashCode(); + result = 37 * result * suit.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (obj.getClass() != this.getClass()) { + return false; + } + + Card compare = (Card) obj; + + return this.suit == compare.suit + && this.rank == compare.rank; + } +} diff --git a/src/main/java/blackjack/card/Deck.java b/src/main/java/blackjack/card/Deck.java new file mode 100644 index 00000000..f143dba5 --- /dev/null +++ b/src/main/java/blackjack/card/Deck.java @@ -0,0 +1,48 @@ +package blackjack.card; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +public class Deck { + private final List cards; + + public Deck() { + this.cards = getShuffledDeck(); + } + + private List getShuffledDeck() { + List cards = new ArrayList<>(); + for (Suit suit : Suit.values()) { + for (Rank rank : Rank.values()) { + Card card = new Card(rank, suit); + cards.add(card); + } + } + + return shuffleDeck(cards); + } + + private List shuffleDeck(List cards) { + Random random = new Random(); + List shuffledDeck = new LinkedList<>(); + for (int i = cards.size(); i > 0; i--) { + int pick = random.nextInt(cards.size()); + shuffledDeck.add(cards.get(pick)); + cards.remove(pick); + } + + return shuffledDeck; + } + + public Card draw() { + if (cards.isEmpty()) { + throw new IllegalArgumentException("덱에 남은 카드가 없습니다."); + } + + Card top = cards.get(0); + cards.remove(0); + return top; + } +} diff --git a/src/main/java/blackjack/card/Rank.java b/src/main/java/blackjack/card/Rank.java new file mode 100644 index 00000000..05aa4574 --- /dev/null +++ b/src/main/java/blackjack/card/Rank.java @@ -0,0 +1,32 @@ +package blackjack.card; + +public enum Rank { + ACE(11, "A"), + TWO(2, "2"), + THREE(3, "3"), + FOUR(4, "4"), + FIVE(5, "5"), + SIX(6, "6"), + SEVEN(7, "7"), + EIGHT(8, "8"), + NINE(9, "9"), + JACK(10, "J"), + QUEEN(10, "Q"), + KING(10, "K"); + + private final int number; + private final String mark; + + Rank(int number, String mark) { + this.number = number; + this.mark = mark; + } + + public int getNumber() { + return this.number; + } + + public String getMark() { + return this.mark; + } +} diff --git a/src/main/java/blackjack/card/Suit.java b/src/main/java/blackjack/card/Suit.java new file mode 100644 index 00000000..53a91855 --- /dev/null +++ b/src/main/java/blackjack/card/Suit.java @@ -0,0 +1,18 @@ +package blackjack.card; + +public enum Suit { + CLUB("클로버"), + DIAMOND("다이아몬드"), + HEART("하트"), + SPADE("스페이드"); + + private final String name; + + Suit (String name) { + this.name = name; + } + + public String getName() { + return this.name; + } +} diff --git a/src/main/java/view/GameInputView.java b/src/main/java/view/GameInputView.java new file mode 100644 index 00000000..d70f575b --- /dev/null +++ b/src/main/java/view/GameInputView.java @@ -0,0 +1,62 @@ +package view; + +import java.io.IOException; +import java.util.Optional; + +public class GameInputView { + + private final static String ASK_PLAYER_MESSAGE = "게임에 참여할 사람의 이름을 입력하세요. (쉼표 기준으로 분리)"; + private final static String INVALID_INPUT_MESSAGE = "입력이 바르지 않습니다"; + private final static String ASK_BAT_AMOUNT_FORMAT = "%s의 배팅 금액은?"; + private final static String AKS_HIT_FORMAT = "%s는 한 장의 카드를 더 받겠습니까? (예는 y, 아니오는 n)"; + private final static String YES = "y"; + private final static String NO = "n"; + + + public static Optional askPlayerName(){ + String names; + try { + names = Terminal.in(ASK_PLAYER_MESSAGE); + } catch (IOException e) { + names = null; + Terminal.outln(INVALID_INPUT_MESSAGE); + } + + return Optional.ofNullable(names); + } + + public static Optional askBatAmount(String name) { + Integer batAmount; + + try { + Terminal.emptyln(); + String in = Terminal.in(String.format(ASK_BAT_AMOUNT_FORMAT, name)); + batAmount = Integer.parseInt(in); + } catch (IOException | NumberFormatException e) { + batAmount = null; + Terminal.outln(INVALID_INPUT_MESSAGE); + } + + return Optional.ofNullable(batAmount); + } + + public static Optional askHit(String name) { + Boolean isHit = null; + + try { + String in = Terminal.in(String.format(AKS_HIT_FORMAT, name)); + + if (in.equalsIgnoreCase(YES)) { + isHit = true; + } + + if (in.equalsIgnoreCase(NO)) { + isHit = false; + } + } catch (IOException e) { + Terminal.outln(INVALID_INPUT_MESSAGE); + } + + return Optional.ofNullable(isHit); + } +} diff --git a/src/main/java/view/GameOutputView.java b/src/main/java/view/GameOutputView.java new file mode 100644 index 00000000..6b4df146 --- /dev/null +++ b/src/main/java/view/GameOutputView.java @@ -0,0 +1,68 @@ +package view; + +import blackjack.Dealer; +import blackjack.Player; +import blackjack.card.Card; + +import java.util.List; + +public class GameOutputView { + + private final static String DEAL_CARD_ANTECEDENT = "딜러에게 1장, "; + private final static String DEAL_CARD_SUBSEQUENT = "에게 2장의 카드를 나누었습니다."; + private final static String COMMA = ", "; + private final static String SHOW_CARD_ANTECEDENT_FORMAT = "%s 카드 : "; + private final static String SHOW_CARD_SUBSEQUENT_FORMAT = " - 결과: %d"; + private final static String ANNOUNCEMENT_DEALER_PLAY_FORMAT + = "딜러는 손패의 합이 17이상이 될 때까지 %d장의 카드를 더 받았습니다."; + private final static String ANNOUNCEMENT_RESULT = "## 최종 수익"; + private final static String NAME_AND_BAT_AMOUNT_PAIR_FORMAT = "%s: %.0f"; + + public static void announceDealResult(List players) { + Terminal.emptyln(); + StringBuilder sb = new StringBuilder(); + sb.append(DEAL_CARD_ANTECEDENT); + for (int i = 0; i < players.size(); i++) { + if (i != 0) { + sb.append(COMMA); + } + + sb.append(players.get(i).getName()); + } + + sb.append(DEAL_CARD_SUBSEQUENT); + Terminal.outln(sb.toString()); + } + + public static void showHand(Player player) { + StringBuilder sb = new StringBuilder(); + sb.append(String.format(SHOW_CARD_ANTECEDENT_FORMAT, player.getName())); + + List hands = player.getHands(); + for (int i = 0; i < hands.size(); i++) { + if (i != 0) { + sb.append(COMMA); + } + + sb.append(hands.get(i).getCardName()); + } + + sb.append(String.format(SHOW_CARD_SUBSEQUENT_FORMAT, player.calculateHands())); + Terminal.outln(sb.toString()); + } + + public static void announceDealerPlay(int count) { + Terminal.emptyln(); + Terminal.outln(String.format(ANNOUNCEMENT_DEALER_PLAY_FORMAT, count)); + Terminal.emptyln(); + } + + public static void announceFinalProfit(Dealer dealer, List players) { + Terminal.emptyln(); + Terminal.outln(ANNOUNCEMENT_RESULT); + Terminal.outln(String.format(NAME_AND_BAT_AMOUNT_PAIR_FORMAT, dealer.getName(), dealer.getChip())); + for (Player player : players) { + Terminal.outln(String.format(NAME_AND_BAT_AMOUNT_PAIR_FORMAT, player.getName(), player.getChip())); + } + } +} diff --git a/src/main/java/util/Terminal.java b/src/main/java/view/Terminal.java similarity index 77% rename from src/main/java/util/Terminal.java rename to src/main/java/view/Terminal.java index 23a1ab58..6daa189e 100644 --- a/src/main/java/util/Terminal.java +++ b/src/main/java/view/Terminal.java @@ -1,4 +1,4 @@ -package util; +package view; import java.io.BufferedReader; import java.io.IOException; @@ -9,15 +9,15 @@ public class Terminal { private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); public static String in(String message) throws IOException { - out(message); + outln(message); return br.readLine(); } - public static void out(String message) { + public static void outln(String message) { System.out.println(message); } - public static void outln() { + public static void emptyln() { System.out.println(); } } diff --git a/src/test/java/blackjack/DealerTest.java b/src/test/java/blackjack/DealerTest.java index b315a556..c7220259 100644 --- a/src/test/java/blackjack/DealerTest.java +++ b/src/test/java/blackjack/DealerTest.java @@ -1,5 +1,8 @@ package blackjack; +import blackjack.card.Card; +import blackjack.card.Rank; +import blackjack.card.Suit; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -22,7 +25,7 @@ public class DealerTest { void 플레이_16이하() { // given Dealer dealer = new Dealer(); - dealer.addHand(Card.HEART_KING); + dealer.addHand(new Card(Rank.KING, Suit.HEART)); // when boolean isPlay = dealer.isPlay(); @@ -35,8 +38,8 @@ public class DealerTest { void 플레이_17이상() { // given Dealer dealer = new Dealer(); - dealer.addHand(Card.HEART_KING); - dealer.addHand(Card.HEART_7); + dealer.addHand(new Card(Rank.KING, Suit.HEART)); + dealer.addHand(new Card(Rank.SEVEN, Suit.HEART)); // when boolean isPlay = dealer.isPlay(); diff --git a/src/test/java/blackjack/PlayerTest.java b/src/test/java/blackjack/PlayerTest.java index bd4f276c..7a7d9bbd 100644 --- a/src/test/java/blackjack/PlayerTest.java +++ b/src/test/java/blackjack/PlayerTest.java @@ -1,5 +1,8 @@ package blackjack; +import blackjack.card.Card; +import blackjack.card.Rank; +import blackjack.card.Suit; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -27,15 +30,15 @@ public class PlayerTest { Player player = new Player("tester"); // when - player.addHand(Card.CLOVER_ACE); + player.addHand(new Card(Rank.ACE, Suit.CLUB)); // then assertThat(player.getHands().size()).isOne(); - assertThat(player.getHands()).contains(Card.CLOVER_ACE); + assertThat(player.getHands()).contains(new Card(Rank.ACE, Suit.CLUB)); } @ParameterizedTest - @CsvSource(value = {"CLOVER_KING,HEART_KING,DIAMOND_2:22", "CLOVER_KING,HEART_KING:20"}, delimiter = ':') + @CsvSource(value = {"CLUB_KING,HEART_KING,DIAMOND_TWO:22", "CLUB_KING,HEART_KING:20"}, delimiter = ':') void 정산(String input, int expect) { // given Player player = new Player("tester"); @@ -49,7 +52,7 @@ public class PlayerTest { } @ParameterizedTest - @ValueSource(strings = {"CLOVER_KING,HEART_KING,DIAMOND_ACE", "CLOVER_KING,DIAMOND_ACE"}) + @ValueSource(strings = {"CLUB_KING,HEART_KING,DIAMOND_ACE", "CLUB_KING,DIAMOND_ACE"}) void 정산_에이스(String input) { // given Player player = new Player("tester"); @@ -63,7 +66,7 @@ public class PlayerTest { } @ParameterizedTest - @CsvSource(value = {"CLOVER_KING,HEART_KING,DIAMOND_2:true", "CLOVER_KING,HEART_KING:false"}, delimiter = ':') + @CsvSource(value = {"CLUB_KING,HEART_KING,DIAMOND_TWO:true", "CLUB_KING,HEART_KING:false"}, delimiter = ':') void 버스트_여부(String input, boolean expect) { // given Player player = new Player("tester"); @@ -80,8 +83,8 @@ public class PlayerTest { void 블랙잭() { // given Player player = new Player("tester"); - player.addHand(Card.CLOVER_KING); - player.addHand(Card.DIAMOND_ACE); + player.addHand(new Card(Rank.KING, Suit.CLUB)); + player.addHand(new Card(Rank.ACE, Suit.DIAMOND)); // when int result = player.calculateHands(); @@ -92,7 +95,7 @@ public class PlayerTest { } @ParameterizedTest - @ValueSource(strings = {"CLOVER_KING,HEART_7,DIAMOND_5", "CLOVER_KING,HEART_7", "CLOVER_KING,HEART_KING,CLOVER_ACE"}) + @ValueSource(strings = {"CLUB_KING,HEART_SEVEN,DIAMOND_FIVE", "CLUB_KING,HEART_SEVEN", "CLUB_KING,HEART_KING,CLUB_ACE"}) void 블랙잭_아님(String input) { // given Player player = new Player("tester"); @@ -106,9 +109,11 @@ public class PlayerTest { } private static void addHandFromInput(String input, Player player) { - String[] cards = input.split(","); - for (String card : cards) { - player.addHand(Card.valueOf(card)); + String[] cardNames = input.split(","); + for (String cardName : cardNames) { + String[] suitAndRank = cardName.split("_"); + Card card = new Card(Rank.valueOf(suitAndRank[1]), Suit.valueOf(suitAndRank[0])); + player.addHand(card); } } } From 7d9bfd18c6223a1d430b0db2467aecdde2b3b466 Mon Sep 17 00:00:00 2001 From: deok-beom Date: Fri, 24 Nov 2023 14:30:22 +0900 Subject: [PATCH 13/13] =?UTF-8?q?Refactor:=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=201.=20=EC=9B=90=EC=8B=9C=EA=B0=92=20=ED=8F=AC?= =?UTF-8?q?=EC=9E=A5=202.=20=ED=95=B8=EB=93=9C=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=EB=A5=BC=20=EB=A7=8C=EB=93=A4=EC=96=B4=20=EC=86=90=ED=8C=A8?= =?UTF-8?q?=EB=A5=BC=20=EA=B3=84=EC=82=B0=ED=95=98=EB=8A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=EC=9D=84=20=EC=9D=B4=EA=B4=80=ED=95=A8=203.=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EC=9D=98=20=EA=B8=B8=EC=9D=B4?= =?UTF-8?q?=EB=8A=94=20=EC=B5=9C=EB=8C=80=ED=95=9C=2070=EB=9D=BC=EC=9D=B8?= =?UTF-8?q?=EC=97=90=20=EA=B0=80=EA=B9=9D=EA=B2=8C,=20=EB=A7=A4=EC=84=9C?= =?UTF-8?q?=EB=93=9C=EC=9D=98=20=EA=B8=B8=EC=9D=B4=EB=8A=94=20=EC=B5=9C?= =?UTF-8?q?=EB=8C=80=ED=95=9C=2015=EB=9D=BC=EC=9D=B8=EC=97=90=20=EA=B0=80?= =?UTF-8?q?=EA=B9=9D=EA=B2=8C,=20=EC=9D=B8=EB=8D=B4=ED=8A=B8=EB=8A=94=201?= =?UTF-8?q?=EB=A1=9C=20=EA=B3=A0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 15 +- src/main/java/blackjack/GameHandler.java | 155 ------------------ src/main/java/blackjack/Player.java | 86 ---------- src/main/java/blackjack/card/Deck.java | 26 +-- src/main/java/blackjack/card/Hand.java | 58 +++++++ src/main/java/blackjack/card/OrderedDeck.java | 42 +++++ src/main/java/blackjack/game/BattingStep.java | 38 +++++ .../java/blackjack/game/CalculateStep.java | 76 +++++++++ src/main/java/blackjack/game/DealingStep.java | 42 +++++ src/main/java/blackjack/game/GameStarter.java | 37 +++++ src/main/java/blackjack/game/PlayStep.java | 62 +++++++ .../game/PlayerRegistrationStep.java | 46 ++++++ .../java/blackjack/{ => player}/Dealer.java | 4 +- src/main/java/blackjack/player/Gambler.java | 25 +++ src/main/java/blackjack/player/Player.java | 31 ++++ src/main/java/view/GameOutputView.java | 31 ++-- src/test/java/blackjack/DealerTest.java | 7 +- .../{PlayerTest.java => GamblerTest.java} | 53 +++--- 18 files changed, 519 insertions(+), 315 deletions(-) delete mode 100644 src/main/java/blackjack/GameHandler.java delete mode 100644 src/main/java/blackjack/Player.java create mode 100644 src/main/java/blackjack/card/Hand.java create mode 100644 src/main/java/blackjack/card/OrderedDeck.java create mode 100644 src/main/java/blackjack/game/BattingStep.java create mode 100644 src/main/java/blackjack/game/CalculateStep.java create mode 100644 src/main/java/blackjack/game/DealingStep.java create mode 100644 src/main/java/blackjack/game/GameStarter.java create mode 100644 src/main/java/blackjack/game/PlayStep.java create mode 100644 src/main/java/blackjack/game/PlayerRegistrationStep.java rename src/main/java/blackjack/{ => player}/Dealer.java (77%) create mode 100644 src/main/java/blackjack/player/Gambler.java create mode 100644 src/main/java/blackjack/player/Player.java rename src/test/java/blackjack/{PlayerTest.java => GamblerTest.java} (59%) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 79597bd0..6b49ecae 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,13 +1,12 @@ -import blackjack.GameHandler; +import blackjack.game.GameStarter; public class Application { public static void main(String[] args) { - GameHandler gameHandler = new GameHandler(); - gameHandler.handleAddPlayer(); - gameHandler.handleBatting(); - gameHandler.handleDeal(); - gameHandler.handlePlayerPlay(); - gameHandler.proceedDealerPlay(); - gameHandler.handleCalculateStep(); + GameStarter gameStarter = new GameStarter(); + gameStarter.start() + .proceedBattingStep() + .proceedDealingStep() + .proceedPlayStep() + .proceedCalculate(); } } diff --git a/src/main/java/blackjack/GameHandler.java b/src/main/java/blackjack/GameHandler.java deleted file mode 100644 index 29e1c577..00000000 --- a/src/main/java/blackjack/GameHandler.java +++ /dev/null @@ -1,155 +0,0 @@ -package blackjack; - -import blackjack.card.Deck; -import view.GameInputView; -import view.GameOutputView; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -public class GameHandler { - - private final List players; - private final Dealer dealer; - private final Deck deck; - - public GameHandler() { - players = new ArrayList<>(); - dealer = new Dealer(); - this.deck = new Deck(); - } - - public void handleAddPlayer() { - while (true) { - Optional in = GameInputView.askPlayerName(); - if (!in.isPresent()) { - continue; - } - - String[] names = in.get().split(","); - for (String name : names) { - Player player = new Player(name); - players.add(player); - } - return; - } - } - - public void handleBatting() { - for (Player player : players) { - bat(player); - } - } - - private void bat(Player player) { - while (true) { - Optional in = GameInputView.askBatAmount(player.getName()); - if (!in.isPresent()) { - continue; - } - - Integer batAmount = in.get(); - player.setBatAmount(batAmount); - return; - } - } - - public void handleDeal() { - draw(dealer); - for (Player player : players) { - draw(player); - } - - GameOutputView.announceDealResult(players); - } - - private void draw(Player player) { - int repeat = 2; - - if (player instanceof Dealer) { - repeat = 1; - } - - for (int i = 0; i < repeat; i++) { - player.addHand(deck.draw()); - } - } - - public void handlePlayerPlay() { - for (Player player : players) { - play(player); - } - } - - private void play(Player player) { - GameOutputView.showHand(player); - while (player.isNotBust()) { - Optional in = GameInputView.askHit(player.getName()); - - if (!in.isPresent()) { - continue; - } - - Boolean isHit = in.get(); - if (!isHit) { - return; - } - - player.addHand(deck.draw()); - GameOutputView.showHand(player); - } - } - - public void proceedDealerPlay() { - int count = 0; - while (dealer.isPlay()) { - dealer.addHand(deck.draw()); - count++; - } - GameOutputView.announceDealerPlay(count); - } - - public void handleCalculateStep() { - GameOutputView.showHand(dealer); - for (Player player : players) { - GameOutputView.showHand(player); - calculate(player); - dealer.addChip(player.getChip()); - } - - GameOutputView.announceFinalProfit(dealer, players); - } - - private void calculate(Player player) { - if (player.isBust()) { - player.loss(); - return; - } - - if (player.isBlackJack()) { - if (dealer.isBlackJack()) { - return; - } - - player.gainWithBlackJack(); - return; - } - - if (dealer.isBust()) { - player.gain(); - return; - } - - int playerNumber = player.calculateHands(); - int dealerNumber = dealer.calculateHands(); - if (playerNumber > dealerNumber) { - player.gain(); - return; - } - - if (playerNumber < dealerNumber) { - player.loss(); - } - } -} diff --git a/src/main/java/blackjack/Player.java b/src/main/java/blackjack/Player.java deleted file mode 100644 index b290be5e..00000000 --- a/src/main/java/blackjack/Player.java +++ /dev/null @@ -1,86 +0,0 @@ -package blackjack; - -import blackjack.card.Card; - -import java.util.ArrayList; -import java.util.List; - -public class Player { - protected final String name; - protected final List hands; - protected double chip; - private int batAmount; - - public Player(String name) { - this.name = name; - this.hands = new ArrayList<>(); - } - - public String getName() { - return this.name; - } - - public List getHands() { - return this.hands; - } - - public double getChip() { - return chip; - } - - public void setBatAmount(int batAmount) { - this.batAmount = batAmount; - } - - public void addHand(Card card) { - hands.add(card); - } - - public int calculateHands() { - int sum = 0; - for (Card hand : hands) { - sum = addNumber(hand, sum); - } - - return sum; - } - - private int addNumber(Card hand, int sum) { - int number = hand.getNumber(); - if (hand.isAce() && sum + number > 21) { - return sum + 1; - } - - return sum + number; - } - - public boolean isBust() { - int result = calculateHands(); - return result > 21; - } - - public boolean isNotBust() { - return !isBust(); - } - - public boolean isBlackJack() { - if (hands.size() != 2) { - return false; - } - - int result = calculateHands(); - return result == 21; - } - - public void gain() { - this.chip += batAmount; - } - - public void gainWithBlackJack() { - this.chip += batAmount * 1.5; - } - - public void loss() { - this.chip -= batAmount; - } -} diff --git a/src/main/java/blackjack/card/Deck.java b/src/main/java/blackjack/card/Deck.java index f143dba5..6c6d0725 100644 --- a/src/main/java/blackjack/card/Deck.java +++ b/src/main/java/blackjack/card/Deck.java @@ -1,36 +1,22 @@ package blackjack.card; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; +import java.util.*; public class Deck { private final List cards; public Deck() { - this.cards = getShuffledDeck(); + OrderedDeck orderedDeck = OrderedDeck.getInstance(); + this.cards = shuffle(orderedDeck.getDeck()); } - private List getShuffledDeck() { - List cards = new ArrayList<>(); - for (Suit suit : Suit.values()) { - for (Rank rank : Rank.values()) { - Card card = new Card(rank, suit); - cards.add(card); - } - } - - return shuffleDeck(cards); - } - - private List shuffleDeck(List cards) { + private List shuffle(List cards) { Random random = new Random(); List shuffledDeck = new LinkedList<>(); for (int i = cards.size(); i > 0; i--) { int pick = random.nextInt(cards.size()); - shuffledDeck.add(cards.get(pick)); - cards.remove(pick); + Card picked = cards.remove(pick); + shuffledDeck.add(picked); } return shuffledDeck; diff --git a/src/main/java/blackjack/card/Hand.java b/src/main/java/blackjack/card/Hand.java new file mode 100644 index 00000000..115f5966 --- /dev/null +++ b/src/main/java/blackjack/card/Hand.java @@ -0,0 +1,58 @@ +package blackjack.card; + +import java.util.ArrayList; +import java.util.List; + +public class Hand { + private final List cards; + + private static final int BLACK_JACK_NUMBER = 21; + + public Hand() { + cards = new ArrayList<>(); + } + + public void addCard(Card card) { + cards.add(card); + } + + public int calculateHand() { + int sum = 0; + for (Card card : cards) { + sum = addNumber(card, sum); + } + + return sum; + } + + private int addNumber(Card card, int sum) { + int number = card.getNumber(); + if (card.isAce() && sum + number > BLACK_JACK_NUMBER) { + return sum + 1; + } + + return sum + number; + } + + public boolean isBust() { + int result = calculateHand(); + return result > BLACK_JACK_NUMBER; + } + + public boolean isBlackJack() { + if (cards.size() != 2) { + return false; + } + + int result = calculateHand(); + return result == BLACK_JACK_NUMBER; + } + + public int size() { + return this.cards.size(); + } + + public Card get(int i) { + return this.cards.get(i); + } +} diff --git a/src/main/java/blackjack/card/OrderedDeck.java b/src/main/java/blackjack/card/OrderedDeck.java new file mode 100644 index 00000000..44ee289a --- /dev/null +++ b/src/main/java/blackjack/card/OrderedDeck.java @@ -0,0 +1,42 @@ +package blackjack.card; + +import java.util.*; + +/** + * 섞기 전의 덱을 캐싱 + */ +public class OrderedDeck { + private static OrderedDeck instance; + private final List cards; + + private OrderedDeck() { + cards = new ArrayList<>(); + for (Suit suit : Suit.values()) { + Set suitCardSet = makeSuitCards(suit); + cards.addAll(suitCardSet); + } + } + + private Set makeSuitCards(Suit suit) { + Set suitCardSet = new LinkedHashSet<>(); + + for (Rank rank : Rank.values()) { + Card card = new Card(rank, suit); + suitCardSet.add(card); + } + + return suitCardSet; + } + + public static OrderedDeck getInstance() { + if (instance == null) { + instance = new OrderedDeck(); + } + + return instance; + } + + public List getDeck() { + return new ArrayList<>(this.cards); + } +} diff --git a/src/main/java/blackjack/game/BattingStep.java b/src/main/java/blackjack/game/BattingStep.java new file mode 100644 index 00000000..5c6c87b6 --- /dev/null +++ b/src/main/java/blackjack/game/BattingStep.java @@ -0,0 +1,38 @@ +package blackjack.game; + +import blackjack.player.Gambler; +import view.GameInputView; + +import java.util.Optional; + +public class BattingStep { + + private final GameStarter gameStarter; + + protected BattingStep(GameStarter gameStarter) { + this.gameStarter = gameStarter; + } + + public DealingStep proceedDealingStep() { + DealingStep dealingStep = new DealingStep(this.gameStarter); + dealingStep.deal(); + return dealingStep; + } + + protected void bat() { + for (Gambler gambler : gameStarter.getGamblers()) { + bat(gambler); + } + } + + private void bat(Gambler gambler) { + Optional in = GameInputView.askBatAmount(gambler.getName()); + if (!in.isPresent()) { + bat(gambler); + return; + } + + Integer batAmount = in.get(); + gambler.setBatAmount(batAmount); + } +} diff --git a/src/main/java/blackjack/game/CalculateStep.java b/src/main/java/blackjack/game/CalculateStep.java new file mode 100644 index 00000000..995f1444 --- /dev/null +++ b/src/main/java/blackjack/game/CalculateStep.java @@ -0,0 +1,76 @@ +package blackjack.game; + +import blackjack.player.Dealer; +import blackjack.player.Gambler; +import view.GameOutputView; + +public class CalculateStep { + private final GameStarter gameStarter; + + public CalculateStep(GameStarter gameStarter) { + this.gameStarter = gameStarter; + } + + public void calculate() { + Dealer dealer = gameStarter.getDealer(); + + for (Gambler gambler : gameStarter.getGamblers()) { + doCalculateChain(gambler); + dealer.addChip(-gambler.getChip()); + } + + GameOutputView.announceFinalProfit(dealer, gameStarter.getGamblers()); + } + + private void doCalculateChain(Gambler gambler) { + calculateGamblerIsBust(gambler); + } + + private void calculateGamblerIsBust(Gambler gambler) { + if (gambler.getHand().isBust()) { + gambler.loss(); + return; + } + + calculateGamblerIsBlackJack(gambler); + } + + private void calculateGamblerIsBlackJack(Gambler gambler) { + if (gambler.getHand().isBlackJack()) { + calculateDealerIsBlackJack(gambler); + return; + } + + calculateDealerIsBust(gambler); + } + + private void calculateDealerIsBlackJack(Gambler gambler) { + if (gameStarter.getDealer().getHand().isBlackJack()) { + return; + } + + gambler.gainWithBlackJack(); + } + + private void calculateDealerIsBust(Gambler gambler) { + if (gameStarter.getDealer().getHand().isBlackJack()) { + gambler.gain(); + return; + } + + compareDealerAndGamblerNumber(gambler); + } + + private void compareDealerAndGamblerNumber(Gambler gambler) { + int playerNumber = gambler.getHand().calculateHand(); + int dealerNumber = gameStarter.getDealer().getHand().calculateHand(); + if (playerNumber > dealerNumber) { + gambler.gain(); + return; + } + + if (playerNumber < dealerNumber) { + gambler.loss(); + } + } +} diff --git a/src/main/java/blackjack/game/DealingStep.java b/src/main/java/blackjack/game/DealingStep.java new file mode 100644 index 00000000..53a41fc7 --- /dev/null +++ b/src/main/java/blackjack/game/DealingStep.java @@ -0,0 +1,42 @@ +package blackjack.game; + +import blackjack.player.Dealer; +import blackjack.player.Gambler; +import blackjack.player.Player; +import view.GameOutputView; + +public class DealingStep { + + private final GameStarter gameStarter; + + protected DealingStep(GameStarter gameStarter) { + this.gameStarter = gameStarter; + } + + public PlayStep proceedPlayStep() { + PlayStep playStep = new PlayStep(this.gameStarter); + playStep.playGambler(); + return playStep; + } + + protected void deal() { + draw(gameStarter.getDealer()); + for (Gambler gambler : gameStarter.getGamblers()) { + draw(gambler); + } + + GameOutputView.announceDealResult(gameStarter.getGamblers()); + } + + private void draw(Player player) { + int repeat = 2; + + if (player instanceof Dealer) { + repeat = 1; + } + + for (int i = 0; i < repeat; i++) { + player.addCardToHand(gameStarter.getDeck().draw()); + } + } +} diff --git a/src/main/java/blackjack/game/GameStarter.java b/src/main/java/blackjack/game/GameStarter.java new file mode 100644 index 00000000..b8562055 --- /dev/null +++ b/src/main/java/blackjack/game/GameStarter.java @@ -0,0 +1,37 @@ +package blackjack.game; + +import blackjack.card.Deck; +import blackjack.player.Dealer; +import blackjack.player.Gambler; + +import java.util.List; + +public class GameStarter { + + private List gamblers; + private final Dealer dealer; + private final Deck deck; + + public GameStarter() { + dealer = new Dealer(); + this.deck = new Deck(); + } + + public PlayerRegistrationStep start() { + PlayerRegistrationStep playerRegistrationStep = new PlayerRegistrationStep(this); + gamblers = playerRegistrationStep.addGambler(); + return playerRegistrationStep; + } + + public List getGamblers() { + return gamblers; + } + + public Dealer getDealer() { + return dealer; + } + + public Deck getDeck() { + return deck; + } +} diff --git a/src/main/java/blackjack/game/PlayStep.java b/src/main/java/blackjack/game/PlayStep.java new file mode 100644 index 00000000..9bf9f7b9 --- /dev/null +++ b/src/main/java/blackjack/game/PlayStep.java @@ -0,0 +1,62 @@ +package blackjack.game; + +import blackjack.player.Dealer; +import blackjack.player.Gambler; +import view.GameInputView; +import view.GameOutputView; + +import java.util.Optional; + +public class PlayStep { + + private final GameStarter gameStarter; + + protected PlayStep(GameStarter gameStarter) { + this.gameStarter = gameStarter; + } + + public void proceedCalculate() { + CalculateStep calculateStep = new CalculateStep(this.gameStarter); + calculateStep.calculate(); + } + + protected void playGambler() { + for (Gambler gambler : gameStarter.getGamblers()) { + GameOutputView.showHand(gambler); + playGambler(gambler); + playDealer(0); + } + } + + private void playGambler(Gambler gambler) { + if (gambler.getHand().isBust()) { + return; + } + + Optional in = GameInputView.askHit(gambler.getName()); + if (!in.isPresent()) { + playGambler(gambler); + return; + } + + Boolean isHit = in.get(); + if (!isHit) { + return; + } + + gambler.addCardToHand(gameStarter.getDeck().draw()); + GameOutputView.showHand(gambler); + playGambler(gambler); + } + + private void playDealer(int count) { + Dealer dealer = gameStarter.getDealer(); + if (dealer.isPlay()) { + dealer.addCardToHand(gameStarter.getDeck().draw()); + playDealer(++count); + return; + } + + GameOutputView.announceDealerPlay(count); + } +} diff --git a/src/main/java/blackjack/game/PlayerRegistrationStep.java b/src/main/java/blackjack/game/PlayerRegistrationStep.java new file mode 100644 index 00000000..ffbc9a8e --- /dev/null +++ b/src/main/java/blackjack/game/PlayerRegistrationStep.java @@ -0,0 +1,46 @@ +package blackjack.game; + +import blackjack.player.Gambler; +import view.GameInputView; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class PlayerRegistrationStep { + + private final GameStarter gameStarter; + + public PlayerRegistrationStep(GameStarter gameStarter) { + this.gameStarter = gameStarter; + } + + public BattingStep proceedBattingStep() { + BattingStep battingStep = new BattingStep(this.gameStarter); + battingStep.bat(); + return battingStep; + } + + protected List addGambler() { + Optional in = GameInputView.askPlayerName(); + if (!in.isPresent()) { + return addGambler(); + } + + String[] names = in.get().split(","); + List gamblers = new ArrayList<>(); + for (String name : names) { + validateNameAndAddGambler(name); + } + + return gamblers; + } + + private void validateNameAndAddGambler(String name) { + if (name.isEmpty()) { + return; + } + + gameStarter.getGamblers().add(new Gambler(name)); + } +} diff --git a/src/main/java/blackjack/Dealer.java b/src/main/java/blackjack/player/Dealer.java similarity index 77% rename from src/main/java/blackjack/Dealer.java rename to src/main/java/blackjack/player/Dealer.java index f6f60076..1dcc4ac4 100644 --- a/src/main/java/blackjack/Dealer.java +++ b/src/main/java/blackjack/player/Dealer.java @@ -1,4 +1,4 @@ -package blackjack; +package blackjack.player; public class Dealer extends Player { @@ -8,7 +8,7 @@ public Dealer() { } public boolean isPlay() { - int result = calculateHands(); + int result = this.hands.calculateHand(); return result <= 16; } diff --git a/src/main/java/blackjack/player/Gambler.java b/src/main/java/blackjack/player/Gambler.java new file mode 100644 index 00000000..5decdcc7 --- /dev/null +++ b/src/main/java/blackjack/player/Gambler.java @@ -0,0 +1,25 @@ +package blackjack.player; + +public class Gambler extends Player { + private int batAmount; + + public Gambler(String name) { + super(name); + } + + public void setBatAmount(int batAmount) { + this.batAmount = batAmount; + } + + public void gain() { + this.chip += batAmount; + } + + public void gainWithBlackJack() { + this.chip += batAmount * 1.5; + } + + public void loss() { + this.chip -= batAmount; + } +} diff --git a/src/main/java/blackjack/player/Player.java b/src/main/java/blackjack/player/Player.java new file mode 100644 index 00000000..94597395 --- /dev/null +++ b/src/main/java/blackjack/player/Player.java @@ -0,0 +1,31 @@ +package blackjack.player; + +import blackjack.card.Card; +import blackjack.card.Hand; + +public abstract class Player { + protected final String name; + protected final Hand hands; + protected double chip; + + public Player(String name) { + this.name = name; + this.hands = new Hand(); + } + + public String getName() { + return this.name; + } + + public Hand getHand() { + return this.hands; + } + + public double getChip() { + return chip; + } + + public void addCardToHand(Card card) { + hands.addCard(card); + } +} diff --git a/src/main/java/view/GameOutputView.java b/src/main/java/view/GameOutputView.java index 6b4df146..21d0f772 100644 --- a/src/main/java/view/GameOutputView.java +++ b/src/main/java/view/GameOutputView.java @@ -1,8 +1,9 @@ package view; -import blackjack.Dealer; -import blackjack.Player; -import blackjack.card.Card; +import blackjack.card.Hand; +import blackjack.player.Dealer; +import blackjack.player.Gambler; +import blackjack.player.Player; import java.util.List; @@ -18,36 +19,36 @@ public class GameOutputView { private final static String ANNOUNCEMENT_RESULT = "## 최종 수익"; private final static String NAME_AND_BAT_AMOUNT_PAIR_FORMAT = "%s: %.0f"; - public static void announceDealResult(List players) { + public static void announceDealResult(List gamblers) { Terminal.emptyln(); StringBuilder sb = new StringBuilder(); sb.append(DEAL_CARD_ANTECEDENT); - for (int i = 0; i < players.size(); i++) { + for (int i = 0; i < gamblers.size(); i++) { if (i != 0) { sb.append(COMMA); } - sb.append(players.get(i).getName()); + sb.append(gamblers.get(i).getName()); } sb.append(DEAL_CARD_SUBSEQUENT); Terminal.outln(sb.toString()); } - public static void showHand(Player player) { + public static void showHand(Player gambler) { StringBuilder sb = new StringBuilder(); - sb.append(String.format(SHOW_CARD_ANTECEDENT_FORMAT, player.getName())); + sb.append(String.format(SHOW_CARD_ANTECEDENT_FORMAT, gambler.getName())); - List hands = player.getHands(); - for (int i = 0; i < hands.size(); i++) { + Hand hand = gambler.getHand(); + for (int i = 0; i < hand.size(); i++) { if (i != 0) { sb.append(COMMA); } - sb.append(hands.get(i).getCardName()); + sb.append(hand.get(i).getCardName()); } - sb.append(String.format(SHOW_CARD_SUBSEQUENT_FORMAT, player.calculateHands())); + sb.append(String.format(SHOW_CARD_SUBSEQUENT_FORMAT, hand.calculateHand())); Terminal.outln(sb.toString()); } @@ -57,12 +58,12 @@ public static void announceDealerPlay(int count) { Terminal.emptyln(); } - public static void announceFinalProfit(Dealer dealer, List players) { + public static void announceFinalProfit(Dealer dealer, List gamblers) { Terminal.emptyln(); Terminal.outln(ANNOUNCEMENT_RESULT); Terminal.outln(String.format(NAME_AND_BAT_AMOUNT_PAIR_FORMAT, dealer.getName(), dealer.getChip())); - for (Player player : players) { - Terminal.outln(String.format(NAME_AND_BAT_AMOUNT_PAIR_FORMAT, player.getName(), player.getChip())); + for (Gambler gambler : gamblers) { + Terminal.outln(String.format(NAME_AND_BAT_AMOUNT_PAIR_FORMAT, gambler.getName(), gambler.getChip())); } } } diff --git a/src/test/java/blackjack/DealerTest.java b/src/test/java/blackjack/DealerTest.java index c7220259..7c7f6522 100644 --- a/src/test/java/blackjack/DealerTest.java +++ b/src/test/java/blackjack/DealerTest.java @@ -3,6 +3,7 @@ import blackjack.card.Card; import blackjack.card.Rank; import blackjack.card.Suit; +import blackjack.player.Dealer; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -25,7 +26,7 @@ public class DealerTest { void 플레이_16이하() { // given Dealer dealer = new Dealer(); - dealer.addHand(new Card(Rank.KING, Suit.HEART)); + dealer.addCardToHand(new Card(Rank.KING, Suit.HEART)); // when boolean isPlay = dealer.isPlay(); @@ -38,8 +39,8 @@ public class DealerTest { void 플레이_17이상() { // given Dealer dealer = new Dealer(); - dealer.addHand(new Card(Rank.KING, Suit.HEART)); - dealer.addHand(new Card(Rank.SEVEN, Suit.HEART)); + dealer.addCardToHand(new Card(Rank.KING, Suit.HEART)); + dealer.addCardToHand(new Card(Rank.SEVEN, Suit.HEART)); // when boolean isPlay = dealer.isPlay(); diff --git a/src/test/java/blackjack/PlayerTest.java b/src/test/java/blackjack/GamblerTest.java similarity index 59% rename from src/test/java/blackjack/PlayerTest.java rename to src/test/java/blackjack/GamblerTest.java index 7a7d9bbd..33b12783 100644 --- a/src/test/java/blackjack/PlayerTest.java +++ b/src/test/java/blackjack/GamblerTest.java @@ -3,6 +3,7 @@ import blackjack.card.Card; import blackjack.card.Rank; import blackjack.card.Suit; +import blackjack.player.Gambler; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -10,15 +11,15 @@ import static org.assertj.core.api.Assertions.assertThat; -public class PlayerTest { +public class GamblerTest { @Test void 생성() { // given - Player player = new Player("pobi"); + Gambler gambler = new Gambler("pobi"); // when - String name = player.getName(); + String name = gambler.getName(); // then assertThat(name).isEqualTo("pobi"); @@ -27,25 +28,25 @@ public class PlayerTest { @Test void 손_패_추가() { // given - Player player = new Player("tester"); + Gambler gambler = new Gambler("tester"); // when - player.addHand(new Card(Rank.ACE, Suit.CLUB)); + gambler.addCardToHand(new Card(Rank.ACE, Suit.CLUB)); // then - assertThat(player.getHands().size()).isOne(); - assertThat(player.getHands()).contains(new Card(Rank.ACE, Suit.CLUB)); + assertThat(gambler.getHand().size()).isOne(); + assertThat(gambler.getHand().get(0)).isEqualTo(new Card(Rank.ACE, Suit.CLUB)); } @ParameterizedTest @CsvSource(value = {"CLUB_KING,HEART_KING,DIAMOND_TWO:22", "CLUB_KING,HEART_KING:20"}, delimiter = ':') void 정산(String input, int expect) { // given - Player player = new Player("tester"); - addHandFromInput(input, player); + Gambler gambler = new Gambler("tester"); + addHandFromInput(input, gambler); // when - int result = player.calculateHands(); + int result = gambler.getHand().calculateHand(); // then assertThat(result).isEqualTo(expect); @@ -55,11 +56,11 @@ public class PlayerTest { @ValueSource(strings = {"CLUB_KING,HEART_KING,DIAMOND_ACE", "CLUB_KING,DIAMOND_ACE"}) void 정산_에이스(String input) { // given - Player player = new Player("tester"); - addHandFromInput(input, player); + Gambler gambler = new Gambler("tester"); + addHandFromInput(input, gambler); // when - int result = player.calculateHands(); + int result = gambler.getHand().calculateHand(); // then assertThat(result).isEqualTo(21); @@ -69,11 +70,11 @@ public class PlayerTest { @CsvSource(value = {"CLUB_KING,HEART_KING,DIAMOND_TWO:true", "CLUB_KING,HEART_KING:false"}, delimiter = ':') void 버스트_여부(String input, boolean expect) { // given - Player player = new Player("tester"); - addHandFromInput(input, player); + Gambler gambler = new Gambler("tester"); + addHandFromInput(input, gambler); // when - boolean isBust = player.isBust(); + boolean isBust = gambler.getHand().isBust(); // then assertThat(isBust).isEqualTo(expect); @@ -82,38 +83,38 @@ public class PlayerTest { @Test void 블랙잭() { // given - Player player = new Player("tester"); - player.addHand(new Card(Rank.KING, Suit.CLUB)); - player.addHand(new Card(Rank.ACE, Suit.DIAMOND)); + Gambler gambler = new Gambler("tester"); + gambler.addCardToHand(new Card(Rank.KING, Suit.CLUB)); + gambler.addCardToHand(new Card(Rank.ACE, Suit.DIAMOND)); // when - int result = player.calculateHands(); + int result = gambler.getHand().calculateHand(); // then assertThat(result).isEqualTo(21); - assertThat(player.isBlackJack()).isTrue(); + assertThat(gambler.getHand().isBlackJack()).isTrue(); } @ParameterizedTest @ValueSource(strings = {"CLUB_KING,HEART_SEVEN,DIAMOND_FIVE", "CLUB_KING,HEART_SEVEN", "CLUB_KING,HEART_KING,CLUB_ACE"}) void 블랙잭_아님(String input) { // given - Player player = new Player("tester"); - addHandFromInput(input, player); + Gambler gambler = new Gambler("tester"); + addHandFromInput(input, gambler); // when - boolean isBlackJack = player.isBlackJack(); + boolean isBlackJack = gambler.getHand().isBlackJack(); // then assertThat(isBlackJack).isFalse(); } - private static void addHandFromInput(String input, Player player) { + private static void addHandFromInput(String input, Gambler gambler) { String[] cardNames = input.split(","); for (String cardName : cardNames) { String[] suitAndRank = cardName.split("_"); Card card = new Card(Rank.valueOf(suitAndRank[1]), Suit.valueOf(suitAndRank[0])); - player.addHand(card); + gambler.addCardToHand(card); } } }