Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
cb02376
docs: 불필요한 empty 파일 삭제
damilog Feb 11, 2022
b97ac62
docs: 기능 README 작성
damilog Feb 11, 2022
d313574
feat: CarTest 구현
kim-svadoz Feb 11, 2022
4da1ef3
feat: Car 추상 클래스 구현
kim-svadoz Feb 11, 2022
4cedf61
feat: Controller 클래스 추가
kim-svadoz Feb 11, 2022
ccde597
Application 클래스 추가
kim-svadoz Feb 11, 2022
fce513d
feat: Car 추상 클래스의 구현체 구현
kim-svadoz Feb 11, 2022
0a9a9ec
feat: View 클래스 추가
kim-svadoz Feb 11, 2022
0e531c0
refactor: Car 추상 클래스에 constructor 생성하여 중복 제거
damilog Feb 14, 2022
788ca21
refactor: Car 추상 클래스를 사용해 Avante, K5, Sonata 구현체 구현
damilog Feb 14, 2022
cbcc6a0
feat: 여행 거리를 입력받을 수 있는 InputView 구현
kim-svadoz Feb 14, 2022
2425fc7
feat: main에서 Controller를 실행하도록 구현
kim-svadoz Feb 14, 2022
e2eddd1
feat: rent Application의 start() 추가
kim-svadoz Feb 14, 2022
482793e
feat: RentCompany 클래스 factory method (create()) 추가
damilog Feb 14, 2022
0573a5c
feat: Car Class에 이름을 반환하는 추상 메서드 추가
kim-svadoz Feb 14, 2022
e43744a
feat: 이름과 연료량을 Map으로 반환하는 기능 구현
kim-svadoz Feb 14, 2022
1deb60b
fix: View에서 이동거리 반환 타입을 문자열에서 정수로 변경
kim-svadoz Feb 14, 2022
d8a753e
feat: RentCompany가 만든 report를 출력하는 기능 구현
kim-svadoz Feb 14, 2022
6609962
feat: 사용자의 여행거리 입력을 받아 Report를 출력하는 기능 구현
kim-svadoz Feb 14, 2022
bc9021d
refactor: TRIP_MANAGER 문구 수정
damilog Feb 14, 2022
769fba3
refactor: 불필요한 String.format 제거
damilog Feb 14, 2022
04e2258
style: 불필요한 import 문 제거
damilog Feb 14, 2022
9d57098
feat: RentCompany Test 추가
damilog Feb 14, 2022
5285a06
docs: README 업데이트
damilog Feb 14, 2022
71f7796
docs: 블랙잭 기능 요구사항 작성
kim-svadoz Feb 14, 2022
38b9202
chore: rentcar 패키지 분리 및 기존 코드 이동
kim-svadoz Feb 14, 2022
8d56730
chore: 블랙잭 패키지 분리 및 스켈레톤 구성
kim-svadoz Feb 14, 2022
5fc6a94
feat: 게임에 참여할 사람의 이름을 입력받는 기능 구현
kim-svadoz Feb 14, 2022
b96f688
feat: Application class에서 main문 실행하도록 구현
kim-svadoz Feb 14, 2022
3ab57d3
feat: GameController 생성 및 start() 구현
kim-svadoz Feb 14, 2022
dd5f319
refactor: splitPlayerName 바로 Return하도록 리팩터링
damilog Feb 14, 2022
f062dac
feat: Card Class 구현
damilog Feb 14, 2022
c30d1e8
feat: Player Class 구현
damilog Feb 14, 2022
0062d44
feat: playerNames를 기준으로 Player 클래스 list를 생성하는 로직 구현
damilog Feb 14, 2022
00e32f9
styles: 빠진 import문 추가
kim-svadoz Feb 14, 2022
c06cbc2
feat: Random 클래스로 bound 이하의 랜덤값을 추출하는 유틸 클래스 구현
kim-svadoz Feb 14, 2022
0f4111b
feat: 카드 개별의 이름과 점수를 가지고 있는 enum Class 구현
kim-svadoz Feb 14, 2022
1fd696b
feat: 전체 카드의 상태를 들고 있는 클래스 구현
kim-svadoz Feb 14, 2022
df6f0bf
feat: 딜러 클래스 추가
kim-svadoz Feb 14, 2022
d97b2c6
feat: Card 클래스 getter() 추가, 생성자 인자로 symbol 추가
kim-svadoz Feb 14, 2022
68d9c1d
feat: Player 클래스 getter() 추가, addCard() 추가
kim-svadoz Feb 14, 2022
a2c4f92
feat: Controller에서 딜러를 생성하고 모두에게 2장씩 나눠주는 기능 구현
kim-svadoz Feb 14, 2022
810d8a4
feat: getter() 추가
kim-svadoz Feb 14, 2022
33e4137
fix: 맵에서 선택된 카드가 제거되지 않은 문제 해결
kim-svadoz Feb 14, 2022
349996d
feat: 초기 배분한 카드와 카드상태를 출력하는 메서드 구현
kim-svadoz Feb 14, 2022
492ab61
feat: 카드를 배분하고 난 뒤 메시지를 출력하는 컨트롤러 로직 구현
kim-svadoz Feb 14, 2022
900c114
docs: Update README.md
kim-svadoz Feb 14, 2022
dafc7cc
feat: card가 담겨있는 map getter 구현
damilog Feb 15, 2022
8d30a6d
feat: cardPack symbol test 추가
damilog Feb 15, 2022
4dafdc9
feat: 심볼별 카드 수량을 체크하는 CardPack test 코드 구현
damilog Feb 15, 2022
9774590
feat: 심볼별 카드 종류가 Enum CardType를 모두 포함하는지 확인하는 테스트 코드 구현
damilog Feb 15, 2022
0e5e941
style: CardPack removeCard 관련 TODO 주석 추가
damilog Feb 15, 2022
ef0c462
feat: 딜러를 플레이어 리스트에 추가하여 게임 진행하도록 변경
kim-svadoz Feb 15, 2022
9457616
feat: Player class에서 딜러인지 판별하는 상태 추가
kim-svadoz Feb 15, 2022
70e688c
feat: 컨트롤러에서 딜러와 일반플레이어를 같은 리스트에 담아 게임 진행
kim-svadoz Feb 15, 2022
212ff4f
feat: isDelear getter() 추가
kim-svadoz Feb 15, 2022
176ee2f
feat: 게임을 진행하는 Dealer 클래스 구현
kim-svadoz Feb 15, 2022
ff55ccd
feat: InputView에서 플레이어가 y 또는 n을 선택하는 기능 구현
kim-svadoz Feb 15, 2022
b521d58
feat: OutputView에서 카드를 더 받겠냐는 메시지를 던지는 기능 구현
kim-svadoz Feb 15, 2022
c15d518
feat: 한명에게 카드를 분배하는 기능 구현
kim-svadoz Feb 15, 2022
972447c
feat: Controller에서 Players만드는 메서드를 분리
kim-svadoz Feb 15, 2022
bca2a79
refactor: CardPack#removeCard() rename -> pickCard()
kim-svadoz Feb 15, 2022
030bf46
feat: Player class 카드를 받고 점수를 추가하는 메서드 분리
kim-svadoz Feb 15, 2022
90056e2
feat: 게임플레이어를 감싸는 일급컬렉션 생성
kim-svadoz Feb 15, 2022
d719731
fix: CardPack#pickCard 로직 변경
kim-svadoz Feb 15, 2022
cea8f93
feat: OutputView 딜러가 한장 더 받았다는 메시지 출력 기능 구현
kim-svadoz Feb 15, 2022
86799b7
feat: Dealer Class 내부 메서드 로직 변경
kim-svadoz Feb 15, 2022
8947cb3
feat: 일급컬렉션 생성으로 인한 Controller 로직 변경
kim-svadoz Feb 15, 2022
a3c0f07
fix: CardType의 Name을 수정
kim-svadoz Feb 15, 2022
6974cd1
refactor: Stream 내부 구현 변수명 변경
kim-svadoz Feb 15, 2022
81e21a8
feat: CardType에서 Ace를 위한 멤버변수 및 생성자 추가
kim-svadoz Feb 15, 2022
53fa7a1
feat: Card 에서 Ace를 위한 멤버변수 및 생성자 추가
kim-svadoz Feb 15, 2022
0c3361f
feat: Ace인 경우를 구분하여 카드팩을 생성
kim-svadoz Feb 15, 2022
be15ff6
fix: OutputView에서 제대로딘 카드이름을 출력하도록 수정
kim-svadoz Feb 15, 2022
30a0189
refactor: 필요없는 파라미터 제거
kim-svadoz Feb 15, 2022
f93fbd4
feat: Player#addScore Ace인 경우 최선의 포인트를 선택하는 기능 구현
kim-svadoz Feb 15, 2022
5858e73
styles: 메서드명 오탈자 수정으로 인한 변경
kim-svadoz Feb 15, 2022
520b607
feat: OutputView에서 게임결과를 출력하는 기능 구현
kim-svadoz Feb 15, 2022
c49b06e
feat: Controller에서 gamePlayers를 받아 결과를 출력하도록 구현
kim-svadoz Feb 15, 2022
44a0d82
refactor: 미사용 import문 제거
kim-svadoz Feb 15, 2022
4006f75
feat: OutputView에서 게임결과 출력기능 구현
kim-svadoz Feb 15, 2022
bab3a01
feat: Controller에서 게임결과 출력하도록 구현
kim-svadoz Feb 15, 2022
c67556e
docs: Update README
kim-svadoz Feb 15, 2022
22d41b5
feat: GamePlayers#makePlayers 단위테스트 로직 구현
kim-svadoz Feb 16, 2022
446ef1d
feat: Dealer#initializeGame 단위테스트 로직 구현
kim-svadoz Feb 16, 2022
e1fdc0f
refactor: 사용하지 않는 print문 제거
kim-svadoz Feb 16, 2022
f11d6aa
refactor: 외부에서 사용않는 메서드는 private
kim-svadoz Feb 16, 2022
fe5a66b
feat: 단위테스트를 위해 Player에 score를 인자로 받는 생성자 추가
kim-svadoz Feb 16, 2022
c9a7ef7
feat: Player#Ace 에이스를 받았을 때 최선의 값을 더하는 로직 테스트 구현
kim-svadoz Feb 16, 2022
87b93b3
feat: CardShuffler에서의 메서드 분리
kim-svadoz Feb 16, 2022
e4b0c93
feat: 카드팩에서 랜덤카드를 뽑을 때 재고가 있는 경우만 뽑아오는 기능 구현
kim-svadoz Feb 16, 2022
9972ae7
feat: CardPack#pickCard 로직 수정
kim-svadoz Feb 16, 2022
db75b6f
02/17 00:02
kim-svadoz Feb 16, 2022
8a2977d
styles: Controller에 final 키워드 부여
kim-svadoz Feb 16, 2022
3ea2ca9
fix: ace의 개수를 세는 로직 수정
kim-svadoz Feb 16, 2022
b9adb4f
refactor: 중복되는 코드 변경
kim-svadoz Feb 16, 2022
7cd211c
refactor: List<GamePlayer>를 담는 로직 변경
kim-svadoz Feb 16, 2022
614e604
refactor: 게임 초기 2장씩 나눠주는 기능 로직 변경
kim-svadoz Feb 16, 2022
6cdd78c
Merge pull request #1 from kim-svadoz/step1-temp
kim-svadoz Feb 16, 2022
f3dd988
docs: Update README
kim-svadoz Feb 16, 2022
35dcfb3
chore: card 관련된 클래스는 card 패키지로 분리
kim-svadoz Feb 17, 2022
2c53c7b
chore: 게임플레이어 관련 클래스는 gameplayer로 패키지 분리
kim-svadoz Feb 17, 2022
a7fe789
chore: 게임플레이어 리스트의 일급컬렉션을 gameplayer 패키지로 이동
kim-svadoz Feb 17, 2022
64e08ab
styles: 필요없는 코드 제거 및 오타 수정
kim-svadoz Feb 17, 2022
258454c
refactor: controller에서 최종 상태를 출력하는 메서드 분리
kim-svadoz Feb 17, 2022
2944f07
feat: 불변이어야 하는 모든 필드에 final 부여
kim-svadoz Feb 17, 2022
2f56aa6
refactor: 미사용 print문 제거
kim-svadoz Feb 17, 2022
4f72ffe
feat: OutputView에서 특정 플레이어의 카드상태를 반환하는 메서드 구현
kim-svadoz Feb 17, 2022
e05f946
chore: 플레이어가 가진 카드의 일급컬렉션은 게임플레이어와 같은 패키지로 이동
kim-svadoz Feb 17, 2022
c1900ce
fix: Dealear#playGame() 인자를 GamePlayers 객체를 받도록 변경
kim-svadoz Feb 17, 2022
5b875ca
fix: 게임플레이어와 딜러 간 메시지를 교환하는 방식으로 변경
kim-svadoz Feb 17, 2022
bf6984e
fix: CardPack의 인스턴스는 정적팩터리메서드로 생성
kim-svadoz Feb 17, 2022
a075f48
feat: Cards에서 카드의 총합 점수를 최선으로 계산하는 로직 변경
kim-svadoz Feb 17, 2022
8e11872
refactor: 미사용 print문 제거
kim-svadoz Feb 17, 2022
c3d9a00
refactor: Controller에서 print구문 메서드 분리
kim-svadoz Feb 17, 2022
48e9949
feat: OutputView에서 공통코드 메서드 분리
kim-svadoz Feb 17, 2022
f34a1c0
feat: OutputView에서 최종 승패 헤더 문구 출력 추가
kim-svadoz Feb 17, 2022
9f3dfde
feat: String name의 원시값을 포장하는 클래스 구현
kim-svadoz Feb 17, 2022
7ec5ea4
feat: List<Name>을 포장하는 일급컬렉션 클래스 구현
kim-svadoz Feb 17, 2022
7aba82d
fix: 게임플레이어의 이름 상태를 원시값이 아닌 Name 클래스로 변경
kim-svadoz Feb 17, 2022
0816dbb
feat: 이름을 사용하는 이외 로직에서도 포장된 이름 객체를 활용하도록 변경
kim-svadoz Feb 17, 2022
66144aa
fix: GamePlayers의 생성방법을 정적팩토리메서드로 변경
kim-svadoz Feb 17, 2022
19cb561
feat: CardPackTest 변경
kim-svadoz Feb 17, 2022
c1f0bfd
feat: DealerTest 내부 구현 로직 수정
kim-svadoz Feb 17, 2022
24226e4
feat: PlayerTest 내부 구현 로직 변경
kim-svadoz Feb 17, 2022
9caa918
refactor: GamePlayersTest 내부 구현 로직 변경
kim-svadoz Feb 17, 2022
d37b745
refactor: GamePlayer#getGameResult의 인자로 게임플레이어 객체를 받도록 변경
kim-svadoz Feb 17, 2022
98a8e02
feat: 승패를 결정할 때 점수가 21을 초과한다면 패배 처리 로직 구현
kim-svadoz Feb 17, 2022
f62c760
feat: Names에서 중복된 이름을 검사하는 로직 추가
kim-svadoz Feb 17, 2022
dc27fa9
feat: 이름의 중복 검사를 위한 equals() and hashcode() 추가
kim-svadoz Feb 17, 2022
e2e3b6d
feat: Controller에서 이름 입력시 중복된 이름이라면 다시 시도하도록 구현
kim-svadoz Feb 17, 2022
5f47bbe
refactor: 필요없는 구문 삭제
kim-svadoz Feb 17, 2022
d333559
refactor: BLACK_JACK 매직넘버를 21로 부여해 가독성 증대
kim-svadoz Feb 17, 2022
95d67a3
feat: CardPackTest#remove 단위테스트 작성
kim-svadoz Feb 17, 2022
e7881a8
feat: NameTest 단위테스트 작성
kim-svadoz Feb 17, 2022
1b2d2f9
feat: NamesTest 단위테스트 작성
kim-svadoz Feb 17, 2022
6c7cb0c
feat: GamePlayer의 구현체 단위테스트 작성
kim-svadoz Feb 17, 2022
dcd2709
chore: 테스트 패키지 분리
kim-svadoz Feb 17, 2022
e157204
refactor: 미사용 import문 제거
kim-svadoz Feb 17, 2022
9c5e2a4
feat: CardsTest#caculate() 단위테스트 작성
kim-svadoz Feb 17, 2022
e5e7553
docs: Update README
kim-svadoz Feb 17, 2022
52a8b1e
refactor: CardPack#create > createWithShuffling로 네이밍
damilog Feb 17, 2022
a307ae7
styles: 변수, 메서드명 구체화하여 네이밍, 코드 포맷팅
damilog Feb 17, 2022
6bf3b42
refactor: 불필요한 메서드 삭제 (Car 클래스)
damilog Feb 21, 2022
3725f8b
refactor: Car 클래스 getChargeQuantity 다시 생성
damilog Feb 21, 2022
620bcf0
refactor: getTripDistance() 상위 클래스로 이동(Car)
damilog Feb 21, 2022
757ab4f
refactor: K5, Avante, Sonata DISTANCE_PER_LITER 접근 방식 수정
damilog Feb 21, 2022
e6a009b
refactor: cardPack 정적 팩토리 메서드 네이밍 수정
damilog Feb 21, 2022
7dfdabf
refactor: getter 위치 하단으로 이동 (CardPack)
damilog Feb 21, 2022
22b8ed8
refactor: 첫번째 카드 index (0) 상수화
damilog Feb 21, 2022
b70757c
refactor: 생성자 메서드 체이닝 사용하여 리팩터링
damilog Feb 22, 2022
a1f9818
refactor: 메소드 호출되는 순으로 순서 변경
damilog Feb 22, 2022
7a74bb1
refactor: 메서드명 수정
damilog Feb 22, 2022
e75b900
refactor: 메서드명 수정
damilog Feb 22, 2022
81cdb2d
refactor: while 문 안의 증감 연산자 조건문에서 분리
damilog Feb 22, 2022
751f71d
refactor: while 문 안에 0 상수화 (MIN_ACE_COUNT)
damilog Feb 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 50 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,50 @@
# java-blackjack
# java-blackjack

## 기능

### Car
- [X] 이동거리로 주입해야할 연료량을 계산한다.
- [X] 차종을 리턴한다.
- [X] 연료량을 리턴한다.

### RentCompany
- [X] InputView를 생성한다.
- [X] InputView로 부터 받은 이동거리로 Car를 생성한다.
- [X] ReportView를 생성한다.
- [X] Car로부터 받은 연료량으로 ReportView를 생성한다.

### InputView
- [X] 이동거리 입력 받는다.

### ReportView
- [X] 차량별 주입해야할 연료량을 출력한다.


## 블랙잭 기능 요구사항

### 입력
- [x] 게임에 참여할 사람의 이름을 입력한다.
- [x] 쉼표 기준으로 분리한다

### 출력
- [ ]

### 카드
- [x] Ace는 1 또는 11로 계산한다.
- [x] King, Queen, Jack은 10으로 계산한다.
- [x] 나머지 카드는 카드숫자를 기본으로 계산한다.

### 게임
- [x] 게임시작 시 2장의 카드를 지급 받는다.
- [x] 21을 초과하지 않으면 카드를 계속 받을 수 있다.
- [x] 21을 초과하면 패배로 처리한다.
- [x] 21을 초과하지 않으면서 21에 가까운 사람이 이긴다.
#### 딜러
- [x] 처음에 받은 2장의 합계가 16이하면 1장을 추가로 지급받는다.

# TODO
- [x] 플레이어를 추상클래스 혹은 인터페이스로 구현하기
- [x] 딜러가 한장 더 받는다는 메시지를 맨 마지막에 위치
- [x] 딜러의 상대적 최종 승패 구현
- [x] 단위 테스트 보완하기
- [x] 최종승패 딜러 로직 버그 수정
11 changes: 11 additions & 0 deletions src/main/java/blackjack/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package blackjack;

import blackjack.controller.GameController;

public class Application {

public static void main(String[] args) {
GameController gameController = new GameController();
gameController.start();
}
}
51 changes: 51 additions & 0 deletions src/main/java/blackjack/controller/GameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package blackjack.controller;

import blackjack.domain.Dealer;
import blackjack.domain.card.CardPack;
import blackjack.domain.gameplayer.GamePlayers;
import blackjack.domain.gameplayer.Name;
import blackjack.domain.gameplayer.Names;
import blackjack.view.InputView;
import blackjack.view.OutputView;
import java.util.List;
import java.util.stream.Collectors;

public class GameController {

public void start() {
final CardPack cardPack = CardPack.create();
final Dealer dealer = new Dealer(cardPack);
final GamePlayers gamePlayers = GamePlayers.makePlayers(getConsoleNames());

dealer.initializeGame(gamePlayers);
printInitialStatus(gamePlayers);

dealer.playGame(gamePlayers);
printFinalStatus(gamePlayers);
}

private Names getConsoleNames() {
try {
return convertStringsToNames(InputView.getPlayerName());
} catch (IllegalArgumentException e) {
e.printStackTrace();
return getConsoleNames();
}
}

private Names convertStringsToNames(List<String> originNames) {
return new Names(originNames.stream()
.map(Name::new)
.collect(Collectors.toList()));
}

private void printInitialStatus(GamePlayers gamePlayers) {
OutputView.printInitialMessage(gamePlayers);
OutputView.printCardAllStatus(gamePlayers);
}

private void printFinalStatus(GamePlayers gamePlayers) {
OutputView.printCardResult(gamePlayers);
OutputView.printGameResult(gamePlayers);
}
}
52 changes: 52 additions & 0 deletions src/main/java/blackjack/domain/Dealer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package blackjack.domain;

import blackjack.domain.card.CardPack;
import blackjack.domain.gameplayer.GamePlayer;
import blackjack.domain.gameplayer.GamePlayers;
import blackjack.view.InputView;
import blackjack.view.OutputView;
import java.util.List;

public class Dealer {
Copy link

Choose a reason for hiding this comment

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

DealerDealerPlayer는 어떤 차이점이 있나요? 🤔
사실상 네이밍 만으로는 명확하게 구분할 수 없을 거예요. 👀
Dealer 클래스의 함수들을 살펴보니 사실상 BlackjackGame 객체 역할을 하는 것 같아요. 🧐


private final CardPack cardPack;

public Dealer(final CardPack cardPack) {
this.cardPack = cardPack;
}

public void initializeGame(final GamePlayers gamePlayers) {
List<GamePlayer> players = gamePlayers.getAllPlayers();
Copy link

@Rok93 Rok93 Feb 18, 2022

Choose a reason for hiding this comment

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

gamePlayers 객체에게 메시지를 보내보면 어떨까요? 🤔

아래 playGame 메서드의 경우에도 객체의 상태 값을 외부로 꺼내서 직접 로직을 수행하는 로직들이 보이네요. 👀
객체에게 메시지를 보내서 결과만 받아볼 수 있도록 구조를 변경해보면 좋을 것 같아요. 🤗

참고 자료


players.forEach(player -> {
player.receiveCard(cardPack.pick());
player.receiveCard(cardPack.pick());
});
}

public void playGame(GamePlayers gamePlayers) {
final List<GamePlayer> players = gamePlayers.getPlayers();
final GamePlayer dealer = gamePlayers.getDealer();

for (final GamePlayer player : players) {
playerGameProcess(player);
}
dealerGameProcess(dealer);
}

private void playerGameProcess(final GamePlayer player) {
while (player.isContinue() && InputView.getPlayerChoice(player)) {
Copy link

Choose a reason for hiding this comment

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

Dealer 클래스는 Model 객체인 것 같은데 해당 로직에 View 로직들이 존재하고 있어요. 🥲
MVC 패턴에 따라 View와 Model을 분리해주세요! 🙏

player.receiveCard(cardPack.pick());
OutputView.printCardStatus(player);
}

OutputView.printCardStatus(player);
}

private void dealerGameProcess(final GamePlayer dealer) {
while (dealer.isLowerThanBound()) {
OutputView.printDealerAcceptCard();
dealer.receiveCard(cardPack.pick());
}
}
}
20 changes: 20 additions & 0 deletions src/main/java/blackjack/domain/card/Card.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package blackjack.domain.card;

public class Card {

private final CardSymbol cardSymbol;
private final CardType cardType;

public Card(final CardSymbol cardSymbol, final CardType cardType) {
this.cardSymbol = cardSymbol;
this.cardType = cardType;
}

public CardSymbol getCardSymbol() {
return cardSymbol;
}

public CardType getCardType() {
return cardType;
}
}
37 changes: 37 additions & 0 deletions src/main/java/blackjack/domain/card/CardPack.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package blackjack.domain.card;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CardPack {

private static final int PICKED_CARD_INDEX = 0;
private static final List<Card> cards = new ArrayList<>();
private final List<Card> cardPack;

static {
for (final CardSymbol symbol : CardSymbol.values()) {
Arrays.stream(CardType.values())
.forEach(type -> cards.add(new Card(symbol, type)));
}
}

public CardPack(List<Card> cardPack) {
this.cardPack = cardPack;
}

public static CardPack create() {
Collections.shuffle(cards);
return new CardPack(new ArrayList<>(cards));
}

public Card pick() {
return cardPack.remove(PICKED_CARD_INDEX);
}

public List<Card> getCardPack() {
return Collections.unmodifiableList(cardPack);
}
}
18 changes: 18 additions & 0 deletions src/main/java/blackjack/domain/card/CardSymbol.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package blackjack.domain.card;

public enum CardSymbol {
SPADE("스페이드"),
DIAMOND("다이아몬드"),
CLOVER("클로버"),
HEART("하트");

private final String symbol;

CardSymbol(final String symbol) {
this.symbol = symbol;
}

public String getSymbol() {
return this.symbol;
}
}
47 changes: 47 additions & 0 deletions src/main/java/blackjack/domain/card/CardType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package blackjack.domain.card;

public enum CardType {
ACE("A", 11, 1),
Copy link

Choose a reason for hiding this comment

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

단 하나의 예외 상황 때문에 새로운 상태를 추가하는 게 맞을까요? 🤔
객체의 인스턴스 변수(= 상태 값)는 진짜로 필요하다고 생각하는 것만 가지는 것이 좋습니다. 😃
객체가 너무 많은 상태 값을 가진다는 것은 그 객체는 너무 많은 책임을 가지고 있을 확률이 높아요. 🥲
🧐
지금의 경우 ACE는 lowerAcePoint가 1로 초기화되겠지만, 다른 인스턴스들도 0(int형 default) 으로 초기화 될 거예요! 👀 예상치 못한 상태 값들을 가지고 있으므로 이 CardType을 사용할 때, 신경 써야 할 포인트가 늘어나서 예상치 못한 예외가 발생할 확률이 높아져요. 🥲 되도록 ACE의 예외 케이스 때문에 상태를 두기 보다는 다른 방식으로 해결하는 게 좋다고 생각해요.

객체지향 생활체조 원칙 7 - 2개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다 를 참고해보시면 좋을 것 같아요! 🤗

image

TWO("2", 2),
THREE("3", 3),
FOUR("4", 4),
FIVE("5", 5),
SIX("6", 6),
SEVEN("7", 7),
EIGHT("8", 8),
NINE("9", 9),
TEN("10", 10),
JACK("J", 10),
QUEEN("Q", 10),
KING("K", 10);

private final String name;
private final int point;
private final int lowerAcePoint;

CardType(String name, int point) {
this(name, point, 0);
}

CardType(String name, int point, int lowerAcePoint) {
this.name = name;
this.point = point;
this.lowerAcePoint = lowerAcePoint;
}

public String getName() {
return this.name;
}

public int getPoint() {
return this.point;
}

public int getLowerAcePoint() {
return this.lowerAcePoint;
}

public boolean isAce() {
return this == CardType.ACE;
}
}
64 changes: 64 additions & 0 deletions src/main/java/blackjack/domain/gameplayer/Cards.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package blackjack.domain.gameplayer;

import blackjack.domain.card.Card;
import blackjack.domain.card.CardType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Cards {

private static final int BLACK_JACK = 21;

private final List<Card> cards;

public Cards() {
this.cards = new ArrayList<>();
}

public void receiveCard(final Card card) {
cards.add(card);
}

public List<Card> toList() {
return Collections.unmodifiableList(cards);
}

public int calculateCards() {
final int sumOfCards = getSumOfCards();
final int aceCount = countAceCard();

if (sumOfCards > BLACK_JACK && aceCount > 0) {
return calculateBestSumWithAce(sumOfCards);
}
return sumOfCards;
}

private int getSumOfCards() {
return cards.stream()
.map(Card::getCardType)
.mapToInt(CardType::getPoint)
Comment on lines +39 to +40
Copy link

Choose a reason for hiding this comment

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

아래와 같이 Card 객체에 getPoint와 같은 메서드를 정의해서 사용하면 어떨까요? 😃

Suggested change
.map(Card::getCardType)
.mapToInt(CardType::getPoint)
.mapToInt(Card::getPoint)

.sum();
}

private int countAceCard() {
return (int) cards.stream()
.filter(card -> card.getCardType().isAce())
.count();
}

private int calculateBestSumWithAce(final int sum) {
final int MIN_ACE_COUNT = 0;
final int lowerAcePoint = CardType.ACE.getLowerAcePoint();
final int higherAcePoint = CardType.ACE.getPoint();

int aceCount = countAceCard();
int totalPoint = sum;

while (aceCount > MIN_ACE_COUNT && totalPoint > BLACK_JACK) {
totalPoint = totalPoint - higherAcePoint + lowerAcePoint;
aceCount--;
}
return totalPoint;
}
}
Loading