-
Notifications
You must be signed in to change notification settings - Fork 1.1k
2단계 - 로또 #4196
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
base: yangseungin
Are you sure you want to change the base?
2단계 - 로또 #4196
Changes from all commits
f6f5695
9e40cdd
9b9d00b
7a23a2a
e0a0e49
eb3d89a
737fdf8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # 로또 구현 | ||
|
|
||
| ## 기능 요구사항 | ||
|
|
||
| ### 입력 | ||
|
|
||
| - [ ] 사용자로부터 로또 구입 금액을 입력받는다 | ||
| - [ ] 입력받은 금액이 올바른지 검증한다 | ||
| - [ ] 1000원 단위가 아니면 IllegalArgumentException을 발생시킨다 | ||
| - [ ] 음수 또는 0원이 입력되면 IllegalArgumentException을 발생시킨다 | ||
| - [ ] 당첨 번호를 입력받는다 | ||
| - [ ] 쉼표 로 구분된 6개의 숫자가 아니면 IllegalArgumentException을 발생시킨다. | ||
|
|
||
| ## 로또 번호 | ||
|
|
||
| - [x] 로또 번호는 1부터 45 사이의 숫자이다 | ||
| - [x] 로또 번호 범위를 벗어나면 IllegalArgumentException을 발생시킨다 | ||
|
|
||
| ## 로또 | ||
|
|
||
| - [x] 로또 번호는 총 6개이다 | ||
| - [x] 로또 번호는 중복되지 않아야 한다 | ||
| - [x] 로또 번호 중복 시 IllegalArgumentException을 발생시킨다 | ||
| - [x] 로또 번호를 오름차순으로 정렬한다 | ||
|
|
||
| ## 로또 티켓 | ||
|
|
||
| - [x] 구입 금액을 1000으로 나눈 갯수반큼 로또 티켓을 발행한다. | ||
| - [x] 1부터 45까지의 숫자 중 중복되지 않는 6개의 숫자를 무작위로 선택한다 | ||
|
|
||
|
|
||
| ## 랭킹 | ||
| - [x] 로또 번호와 당첨 번호를 비교하여 일치하는 개수에 따라 돈을 받는다 | ||
| - 3개 일치: 5,000원 | ||
| - 4개 일치: 50,000원 | ||
| - 5개 일치: 1,500,000원 | ||
| - 6개 일치: 2,000,000,000원 | ||
| - [x] 2개 이하는 낙첨이다 | ||
|
|
||
| ## 당첨 | ||
| - [ ] 각 등수별 당첨 개수를 집계한다 | ||
|
|
||
| ## 수익률 계산 | ||
|
|
||
| - [ ] 총 당첨 금액을 계산하여 수익률을 계산한다 | ||
| - [ ] 수익률 = 총 당첨 금액 / 구입 금액 | ||
| - [ ] 수익률을 소수점 둘째 자리까지 표시한다 | ||
|
|
||
| ## 출력 | ||
|
|
||
| - [ ] 구입한 로또 개수를 출력한다 | ||
| - [ ] 발행된 각 로또 번호를 출력한다 | ||
| - [ ] 당첨 통계를 출력한다 (각 등수별 당첨 개수) | ||
| - [ ] 총 수익률을 출력한다 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,71 @@ | ||||||||||||||||
| package lotto; | ||||||||||||||||
|
|
||||||||||||||||
| import java.util.ArrayList; | ||||||||||||||||
| import java.util.Collections; | ||||||||||||||||
| import java.util.Comparator; | ||||||||||||||||
| import java.util.HashSet; | ||||||||||||||||
| import java.util.List; | ||||||||||||||||
| import java.util.Set; | ||||||||||||||||
|
|
||||||||||||||||
| public class Lotto { | ||||||||||||||||
|
|
||||||||||||||||
| private static final int LOTTO_NUMBER_COUNT = 6; | ||||||||||||||||
|
|
||||||||||||||||
| private final List<LottoNumber> numbers; | ||||||||||||||||
|
|
||||||||||||||||
| public Lotto(List<Integer> numbers) { | ||||||||||||||||
| validateSize(numbers); | ||||||||||||||||
| validateDuplicate(numbers); | ||||||||||||||||
| this.numbers = createLottoNumbers(numbers); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| private void validateSize(List<Integer> numbers) { | ||||||||||||||||
| if (numbers.size() != LOTTO_NUMBER_COUNT) { | ||||||||||||||||
| throw new IllegalArgumentException("로또 번호는 총 6개여야 합니다."); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| private void validateDuplicate(List<Integer> numbers) { | ||||||||||||||||
| Set<Integer> uniqueNumbers = new HashSet<>(numbers); | ||||||||||||||||
|
Contributor
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. 중복을 허용하지 않는다면 인스턴스 변수를 List가 아니라 List으로 구현하는 것은 어떨까? |
||||||||||||||||
| if (uniqueNumbers.size() != LOTTO_NUMBER_COUNT) { | ||||||||||||||||
| throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| private List<LottoNumber> createLottoNumbers(List<Integer> numbers) { | ||||||||||||||||
| List<LottoNumber> lottoNumbers = new ArrayList<>(); | ||||||||||||||||
| for (Integer number : numbers) { | ||||||||||||||||
| lottoNumbers.add(new LottoNumber(number)); | ||||||||||||||||
| } | ||||||||||||||||
| Collections.sort(lottoNumbers, Comparator.comparingInt(LottoNumber::getValue)); | ||||||||||||||||
| return lottoNumbers; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| public List<Integer> getNumbers() { | ||||||||||||||||
| List<Integer> result = new ArrayList<>(); | ||||||||||||||||
| for (LottoNumber number : numbers) { | ||||||||||||||||
| result.add(number.getValue()); | ||||||||||||||||
| } | ||||||||||||||||
| return result; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| public int countMatchNumber(Lotto other) { | ||||||||||||||||
| int count = 0; | ||||||||||||||||
| for (LottoNumber number : numbers) { | ||||||||||||||||
| if (other.contains(number)) { | ||||||||||||||||
|
Contributor
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. 👍 |
||||||||||||||||
| count++; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| return count; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| private boolean contains(LottoNumber number) { | ||||||||||||||||
| for (LottoNumber lottoNumber : numbers) { | ||||||||||||||||
| if (lottoNumber.equals(number)) { | ||||||||||||||||
| return true; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| return false; | ||||||||||||||||
|
Comment on lines
+63
to
+68
Contributor
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.
Suggested change
콜렉션의 contains()를 활용해 구현하면 어떨까? |
||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| } | ||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||||||||||||||||||||||||||||||
| package lotto; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| import java.util.Objects; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| public class LottoNumber { | ||||||||||||||||||||||||||||||||||
|
Contributor
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. LottoNumber 값으로 추상화한 것 💯 |
||||||||||||||||||||||||||||||||||
| private static final int MIN_NUMBER = 1; | ||||||||||||||||||||||||||||||||||
| private static final int MAX_NUMBER = 45; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| private final int value; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| public LottoNumber(int value) { | ||||||||||||||||||||||||||||||||||
| validate(value); | ||||||||||||||||||||||||||||||||||
| this.value = value; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| public LottoNumber(String value) { | ||||||||||||||||||||||||||||||||||
| this(Integer.parseInt(value)); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+18
Contributor
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.
Suggested change
주 생성자를 마지막에 구현하는 것이 컨벤션 |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| private void validate(int value) { | ||||||||||||||||||||||||||||||||||
| if (value < MIN_NUMBER || value > MAX_NUMBER) { | ||||||||||||||||||||||||||||||||||
| throw new IllegalArgumentException("로또 번호는 1부터 45 사이의 숫자여야 한다"); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| public int getValue() { | ||||||||||||||||||||||||||||||||||
| return value; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||
| public boolean equals(Object o) { | ||||||||||||||||||||||||||||||||||
| if (o == null || getClass() != o.getClass()) return false; | ||||||||||||||||||||||||||||||||||
| LottoNumber that = (LottoNumber) o; | ||||||||||||||||||||||||||||||||||
| return value == that.value; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||
| public int hashCode() { | ||||||||||||||||||||||||||||||||||
| return Objects.hashCode(value); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||
| public String toString() { | ||||||||||||||||||||||||||||||||||
| return "LottoNumber{value= " + value + "}"; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| package lotto; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| public class LottoTickets { | ||
| private static final int LOTTO_PRICE = 1000; | ||
| private static final int MIN_LOTTO_NUMBER = 1; | ||
| private static final int MAX_LOTTO_NUMBER = 45; | ||
| private static final int LOTTO_NUMBER_COUNT = 6; | ||
|
|
||
| private final List<Lotto> lottos; | ||
|
|
||
| private LottoTickets(List<Lotto> lottos) { | ||
| this.lottos = lottos; | ||
| } | ||
|
|
||
| public static LottoTickets create(int purchaseAmount) { | ||
|
Contributor
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. purchaseAmount도 원시 값인데 포장해 보면 어떨까? |
||
| int count = purchaseAmount / LOTTO_PRICE; | ||
| List<Lotto> lottos = new ArrayList<>(); | ||
| for (int i = 0; i < count; i++) { | ||
| lottos.add(createRandomLotto()); | ||
| } | ||
| return new LottoTickets(lottos); | ||
| } | ||
|
|
||
| private static Lotto createRandomLotto() { | ||
| //TODO 많은 일을 하고 있음 | ||
|
Contributor
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. 공감함 |
||
| List<Integer> numbers = new ArrayList<>(); | ||
| for (int i = MIN_LOTTO_NUMBER; i <= MAX_LOTTO_NUMBER; i++) { | ||
| numbers.add(i); | ||
| } | ||
| Collections.shuffle(numbers); | ||
|
|
||
| List<Integer> selectedNumbers = new ArrayList<>(); | ||
| for (int i = 0; i < LOTTO_NUMBER_COUNT; i++) { | ||
| selectedNumbers.add(numbers.get(i)); | ||
| } | ||
|
|
||
| return new Lotto(selectedNumbers); | ||
| } | ||
|
|
||
| public int size() { | ||
| return lottos.size(); | ||
| } | ||
|
|
||
| public List<Lotto> getLottos() { | ||
| return new ArrayList<>(lottos); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package lotto; | ||
|
|
||
| public enum Rank { | ||
| FIRST(6, 2_000_000_000), | ||
| SECOND(5, 1_500_000), | ||
| THIRD(4, 50_000), | ||
| FOURTH(3, 5_000), | ||
| MISS(0, 0); | ||
|
|
||
| private final int matchCount; | ||
| private final int winningAmount; | ||
|
|
||
| Rank(int matchCount, int winningAmount) { | ||
| this.matchCount = matchCount; | ||
| this.winningAmount = winningAmount; | ||
| } | ||
|
|
||
| public static Rank valueOf(int matchCount) { | ||
| for (Rank rank : values()) { | ||
| if (rank.matchCount == matchCount) { | ||
| return rank; | ||
| } | ||
| } | ||
| return MISS; | ||
| } | ||
|
|
||
| public int getWinningAmount() { | ||
| return winningAmount; | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package lotto; | ||
|
|
||
| //- [ ] 로또 번호는 총 6개이다 | ||
| //- [ ] 로또 번호는 1부터 45 사이의 숫자이다 | ||
| // - [ ] 로또 번호 범위를 벗어나면 IllegalArgumentException을 발생시킨다 | ||
| //- [ ] 로또 번호는 중복되지 않아야 한다 | ||
| // - [ ] 로또 번호 중복 시 IllegalArgumentException을 발생시킨다 | ||
|
|
||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
|
||
| public class LottoNumberTest { | ||
| @Test | ||
| void 로또_번호_생성() { | ||
| LottoNumber lottoNumber = new LottoNumber(1); | ||
|
|
||
| assertThat(lottoNumber.getValue()).isEqualTo(1); | ||
| } | ||
|
|
||
| @Test | ||
| void 로또_번호의_범위를_벗어나면_예외발생1to45() { | ||
| assertThatThrownBy(() -> new LottoNumber(0)) | ||
| .isInstanceOf(IllegalArgumentException.class) | ||
| .hasMessage("로또 번호는 1부터 45 사이의 숫자여야 한다"); | ||
|
|
||
| assertThatThrownBy(() -> new LottoNumber(46)) | ||
| .isInstanceOf(IllegalArgumentException.class) | ||
| .hasMessage("로또 번호는 1부터 45 사이의 숫자여야 한다"); | ||
| } | ||
|
|
||
| @Test | ||
| void 같은_번호는_동등성을_가진다() { | ||
| LottoNumber number1 = new LottoNumber(1); | ||
| LottoNumber number2 = new LottoNumber(1); | ||
|
|
||
| assertThat(number1).isEqualTo(number2); | ||
| } | ||
|
|
||
| } |
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.
위와 같이 주 생성자를 추가하고 부 생성자가 주 생성자를 호출하도록 구현하면 어떨까?
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.
지속적으로 리뷰해주시는 내용인데 이부분이 바로 잘안되는듯하네요 신경써서 진행해보겠습니다