-
Notifications
You must be signed in to change notification settings - Fork 388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2단계 - 블랙잭(베팅)] 오찌(오지훈) 미션 제출합니다. #301
Changes from 21 commits
d260ec1
2ebdb05
e5b9592
320970f
0c7d20c
c6ba660
281c0bf
30b9b66
f94176f
d44185a
110a51c
4eeb85a
f13022f
30996e3
86765b3
95d3c2b
4e0f6e2
490fb54
3538e24
b1cab92
29af8b8
d76d395
d816dc8
e131a0b
87e82c3
6c8c717
36855da
80aead9
28eb0a6
919372c
19f07b4
f32bf69
f990136
758cf9f
7433560
3890608
d116b8f
01fbd6d
0c47442
1785af3
d89f026
322ee9e
500a55a
44ca077
ed50441
45fbc6f
453ae04
0cd60cf
79a8465
4f6e5a7
c8d8697
158061e
f773465
2477149
f40aa15
21a914d
9119d44
a0dd0eb
3641a00
9be5ffa
eb9631d
d933b6b
e9f038d
3eddd19
0a96c63
62f21df
d1ee8a2
b750865
f828c08
537e3c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package blackjack; | ||
|
||
public class BlackjackApplication { | ||
|
||
public static void main(String[] args) { | ||
BlackjackGame blackjackGame = new BlackjackGame(); | ||
blackjackGame.play(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package blackjack.domain; | ||
|
||
public class Betting { | ||
|
||
private final int betMoney; | ||
|
||
public Betting(int betMoney) { | ||
validate(betMoney); | ||
this.betMoney = betMoney; | ||
} | ||
|
||
private void validate(int betMoney) { | ||
if (betMoney <= 0) { | ||
throw new IllegalArgumentException("[ERROR] 베팅 금액은 0원 이하일 수 없습니다."); | ||
} | ||
} | ||
|
||
public int getValue() { | ||
return betMoney; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,47 +2,42 @@ | |
|
||
import blackjack.domain.participant.Dealer; | ||
import blackjack.domain.participant.Player; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.EnumMap; | ||
import java.util.LinkedHashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class GameResult { | ||
|
||
private final Map<Outcome, Integer> dealerResult; | ||
private final Map<String, Outcome> playersResult; | ||
private final Map<String, Integer> earnings; | ||
|
||
private GameResult(Map<Outcome, Integer> dealerResult, Map<String, Outcome> playersResult) { | ||
this.dealerResult = Collections.unmodifiableMap(new EnumMap<>(dealerResult)); | ||
this.playersResult = Collections.unmodifiableMap(new LinkedHashMap<>(playersResult)); | ||
public GameResult(Map<String, Integer> earnings) { | ||
this.earnings = Collections.unmodifiableMap(new LinkedHashMap<>(earnings)); | ||
} | ||
|
||
public static GameResult of(Dealer dealer, List<Player> players) { | ||
Map<Outcome, Integer> dealerResult = new EnumMap<>(Outcome.class); | ||
Map<String, Outcome> playersResult = new LinkedHashMap<>(); | ||
Map<String, Integer> playersEarnings = new LinkedHashMap<>(); | ||
|
||
initDealerResult(dealerResult); | ||
for (Player player : players) { | ||
Outcome playerOutcome = Outcome.judge(player, dealer); | ||
playersResult.put(player.getName(), playerOutcome); | ||
dealerResult.merge(playerOutcome.getOpposite(), 1, Integer::sum); | ||
int playerEarnings = calculateEarnings(player, playerOutcome); | ||
int dealerEarnings = getDealerEarnings(playerEarnings); | ||
playersEarnings.merge(dealer.getName(), dealerEarnings, Integer::sum); | ||
playersEarnings.put(player.getName(), playerEarnings); | ||
} | ||
|
||
return new GameResult(dealerResult, playersResult); | ||
return new GameResult(playersEarnings); | ||
} | ||
|
||
private static void initDealerResult(Map<Outcome, Integer> dealerResult) { | ||
Arrays.stream(Outcome.values()) | ||
.forEach(value -> dealerResult.put(value, 0)); | ||
private static int getDealerEarnings(int playerEarnings) { | ||
return playerEarnings * (-1); | ||
} | ||
|
||
public Map<Outcome, Integer> getDealerResult() { | ||
return dealerResult; | ||
private static int calculateEarnings(Player player, Outcome outcome) { | ||
return (int) (player.getBetting().getValue() * outcome.getEarningsRate()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분 관련해서 코멘트 남겼는데요, 점점 더 도메인 로직들이 많아지네요. 한 번 확인부탁드립니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 확인했습니다 😄 확실히 제가 봐도 로직이 이상하게 복잡해지네요. 최대한 로직을 줄이면서도 동작이 같도록 리팩토링 해볼게요 :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 생각해보니 이걸 static 메서드로 뺄 필요가 없었네요! :) |
||
} | ||
|
||
public Map<String, Outcome> getPlayersResult() { | ||
return playersResult; | ||
public Map<String, Integer> getEarnings() { | ||
return earnings; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,50 +4,50 @@ | |
import blackjack.domain.participant.Player; | ||
|
||
public enum Outcome { | ||
WIN("승"), | ||
DRAW("무"), | ||
LOSE("패"); | ||
WIN("승", 1), | ||
DRAW("무", 0), | ||
LOSE("패", -1), | ||
WIN_BLACKJACK("승", 1.5); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 승리를 했을 때는 2배의 금액을 돌려받고 블랙잭일 경우 1.5배를 돌려받습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 처음에 좀 헷갈리긴 했는데 금액으로 생각한다면 본인이 원래 베팅한 금액 + 수익 으로 해서 이겼을 때 2배를 받는거가 생각해보면 맞기는 한데, 여기서 수익으로 계산하는 부분은 원래 베팅한 금액을 배제한 금액이 되는 것 같더라고요!(그래서 LOSE면 베팅 금액을 잃으니까 수익이 -가 되는 상황이 되는거죠) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아하 제가 룰을 오해하고 있었네요 🥲 |
||
|
||
private final String name; | ||
private final double earningsRate; | ||
|
||
Outcome(String name) { | ||
Outcome(String name, double earningsRate) { | ||
this.name = name; | ||
this.earningsRate = earningsRate; | ||
} | ||
|
||
public static Outcome judge(Player player, Dealer dealer) { | ||
if (player.isBust() || !player.isBlackJack() && dealer.isBlackJack()) { | ||
if (player.isBlackjack() && !dealer.isBlackjack()) { | ||
return WIN_BLACKJACK; | ||
} | ||
if (player.isBust() || !player.isBlackjack() && dealer.isBlackjack()) { | ||
return Outcome.LOSE; | ||
} | ||
if (dealer.isBust() || player.isBlackJack() && !dealer.isBlackJack()) { | ||
if (dealer.isBust() || player.isBlackjack() && !dealer.isBlackjack()) { | ||
return Outcome.WIN; | ||
} | ||
if (player.isBlackJack() && dealer.isBlackJack()) { | ||
if (player.isBlackjack() && dealer.isBlackjack()) { | ||
return Outcome.DRAW; | ||
} | ||
return judgeByScore(player.getScore(), dealer.getScore()); | ||
} | ||
|
||
private static Outcome judgeByScore(int score, int target) { | ||
if (score > target) { | ||
private static Outcome judgeByScore(Score score, Score target) { | ||
if (score.compareTo(target) > 0) { | ||
return Outcome.WIN; | ||
} | ||
if (score == target) { | ||
if (score.equals(target)) { | ||
return Outcome.DRAW; | ||
} | ||
return Outcome.LOSE; | ||
} | ||
|
||
public Outcome getOpposite() { | ||
if (this == WIN) { | ||
return LOSE; | ||
} | ||
if (this == LOSE) { | ||
return WIN; | ||
} | ||
return DRAW; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public double getEarningsRate() { | ||
return earningsRate; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
package blackjack.domain; | ||
|
||
public class Score { | ||
public class Score implements Comparable<Score> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
getter가 등장하면 로직을 객체 안으로 넣을 수 있는지 확인해보면 좋습니다. 그리고나서 추천드리는 건 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사실 작성할 때는 상태 패턴을 알고 작성한건 아니고 어떻게 하면 클래스를 뺄 수 있을까 생각하긴 한거였는데...ㅎ |
||
|
||
private final int value; | ||
|
||
|
@@ -12,6 +12,15 @@ public int getValue() { | |
return value; | ||
} | ||
|
||
public boolean isLessThan(int value) { | ||
return this.value < value; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제가 Comparable을 구현하긴 했는데요, 자체적으로 isLessThan을 쓸 일이 있어서 만들었습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 혹시 방법이 통일된다는게 정확히 어떤 말씀을 말하시는건가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 지금과 같은 구조를 의도하는 코멘트였습니다. 제대로 표현을 못했네요 🥲 사실 이 방법이나 |
||
|
||
@Override | ||
public int compareTo(Score target) { | ||
return Integer.compare(value, target.value); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,14 @@ | ||
package blackjack.domain.card; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class Card { | ||
|
||
private static final List<Card> pool = createCardPool(); | ||
|
||
private final Pattern pattern; | ||
private final Denomination denomination; | ||
|
||
|
@@ -10,6 +17,30 @@ public Card(Pattern pattern, Denomination denomination) { | |
this.denomination = denomination; | ||
} | ||
|
||
public static Card of(Pattern pattern, Denomination denomination) { | ||
return pool.stream() | ||
.filter(card -> card.pattern == pattern && card.denomination == denomination) | ||
.findAny() | ||
.orElseThrow(() -> new IllegalArgumentException("[ERROR] 올바르지 않은 카드입니다.")); | ||
} | ||
|
||
private static List<Card> createCardPool() { | ||
return Arrays.stream(Pattern.values()) | ||
.map(Card::createCardsBy) | ||
.flatMap(Collection::stream) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private static List<Card> createCardsBy(Pattern pattern) { | ||
return Arrays.stream(Denomination.values()) | ||
.map(denomination -> new Card(pattern, denomination)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public static List<Card> getPool() { | ||
return pool; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 고민을 조금 했던 부분인데요, pool을 static으로 유지해서 deck에서 가져다 쓰는 것과 getPool 이라는 static 메서드를 열어두는 것 중 어느 것이 더 나은 방법일까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lazy한 초기화를 하는 등 특별히 getter가 하는게 없다면 따로 둘 필요는 없어보이긴 하네요. |
||
|
||
public Pattern getPattern() { | ||
return pattern; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코멘트에 남겼던 부분의 연장선인데요, Names 객체가 생성 시 중복 검증이라는 로직 하나를 한 뒤 다시 getter로 꺼내줘서 List으로 처리하고 있어요. 중복 검증 하나 만으로도 불필요한 래핑이 아니라고 볼 수 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1단계 코멘트에도 남겼지만 도메인에 대한 로직이 도메인에 있는건 크게 어색하지 않은 거 같아요.
여기서 로직은
이름이 중복되면 안된다
보다는플레이어들의 이름이 중복되면 안된다
가 적당하지 않을까요?해당 도메인 로직을 처리하기 위해서는
Players
객체가 필요하지 않을까요?아마도 검증 이후에 getter를 사용해서 데이터를 꺼내쓰면 의미가 없지 않나에 대해서 고민하고 계신 거 같아요.
이 부분은 콜백 함수를 통해서 해결할 수 있습니다. 여유가 되신다면 한 번쯤 구현해보시고 지금 코드와 변경된 코드의 장단점을 비교해보는 것도 좋을 거 같네요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
자바에도 콜백이 있는줄은 처음 알았네요! 지금은 적용할 여유가 없을 것 같고 따로 공부를 해보도록 하겠습니다 :)