-
Notifications
You must be signed in to change notification settings - Fork 1.9k
240617 #2116
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: main
Are you sure you want to change the base?
240617 #2116
Changes from all commits
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 |
|---|---|---|
| @@ -1,7 +1,9 @@ | ||
| package lotto; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| public static void main(String[] args) throws MyException { | ||
| // TODO: 프로그램 구현 | ||
| Money money = new Money(); | ||
| money.showMain(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,34 @@ | ||
| package lotto; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| public class Lotto { | ||
| private final List<Integer> numbers; | ||
|
|
||
| public Lotto(List<Integer> numbers) { | ||
| public Lotto(List<Integer> numbers) throws MyException { | ||
| validate(numbers); | ||
| checkRange(numbers); | ||
| this.numbers = numbers; | ||
| } | ||
|
|
||
| private void validate(List<Integer> numbers) { | ||
| // 6자리인지 검사 | ||
| private void validate(List<Integer> numbers) throws IllegalArgumentException { | ||
| if (numbers.size() != 6) { | ||
| throw new IllegalArgumentException(); | ||
| throw new IllegalArgumentException("[ERROR] 로또 숫자는 6자리여야 합니다."); | ||
| } | ||
| } | ||
|
|
||
| // TODO: 추가 기능 구현 | ||
|
|
||
| // 범위 확인 | ||
| private void checkRange(List<Integer> numbers) throws MyException { | ||
| for (Integer number : numbers) { | ||
| if (number < 1 || number > 45) { | ||
| throw new MyException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| package lotto; | ||
|
|
||
| import camp.nextstep.edu.missionutils.Randoms; | ||
| import camp.nextstep.edu.missionutils.Console; | ||
| import org.assertj.core.api.ThrowableAssert; | ||
|
|
||
| import java.util.*; | ||
|
|
||
| public class Money { | ||
| public void showMain() { | ||
| getMoney(); | ||
| } | ||
|
|
||
| // 구입금액 입력받기 | ||
| public ThrowableAssert.ThrowingCallable getMoney() { | ||
|
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. 예외를 반환하는데 예외의 타입이 assertj를 사용하시는데 |
||
| try { | ||
| System.out.println("구입금액을 입력해주세요."); | ||
| int money = Integer.parseInt(Console.readLine()); | ||
| getModulo(money); | ||
| showNum(money / 1000); | ||
| } catch (MyException e) { // 예외처리 반복 https://woojin.tistory.com/74 참고 | ||
| System.out.println("[ERROR] 금액이 1000으로 나누어 떨어지지 않습니다."); | ||
| getMoney(); | ||
| } catch (NumberFormatException e) { // 숫자가 아닐 경우도 예외처리 | ||
| System.out.println("[ERROR] 숫자를 입력해주세요."); | ||
| getMoney(); | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| // 1000으로 나누어 떨어지지 않으면 exception | ||
| public ThrowableAssert.ThrowingCallable getModulo(int money) throws MyException { | ||
|
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. 나누어 떨어지지 않으면 예외만 던지도록 하면 더 좋을 것 같아요 |
||
| if (money % 1000 != 0) { | ||
| throw new MyException(); | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| // 로또 번호 셀렉 | ||
| public ThrowableAssert.ThrowingCallable showNum(int money) throws MyException { | ||
| System.out.println(); | ||
|
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. 따로 출력되는 부분을 나누면 더 좋을 거 같아요~ |
||
| System.out.println(money + "개를 구매했습니다."); | ||
| List<Integer>[] lotto = new List[money * 6]; | ||
|
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. 배열은 가급적 사용하지 않는 걸 추천해요 그리고 Lotto 객체를 사용했다면 좋았지 않을까 싶어요 |
||
|
|
||
| for (int i = 0; i < money; i++) { | ||
| List<Integer> list = selectNum(); | ||
| lotto[i] = list; | ||
| System.out.println(lotto[i]); | ||
| } | ||
|
|
||
| WinNum win = new WinNum(); | ||
| win.showWin(lotto); | ||
| return null; | ||
| } | ||
|
|
||
| // 랜덤 숫자 고르고 Lotto로 넘김 | ||
| private List<Integer> selectNum() throws MyException { | ||
| // https://qh5944.tistory.com/152 참고 -, UnsupportedOperationException 해결 | ||
| List<Integer> numbers = Randoms.pickUniqueNumbersInRange(1, 45, 6); | ||
| List<Integer> result = new ArrayList<>(); | ||
|
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 result = new ArrayList<>(Randoms.pickUniqueNumbersInRange(1, 45, 6)); 이렇게 하면 더 좋을거 같아요 |
||
| result.addAll(numbers); | ||
| Collections.sort(result); | ||
| try { | ||
| new Lotto(result); // Lotto에서 6개, 범위, 중복까지 확인 | ||
| } catch (MyException | IllegalArgumentException e) { | ||
| selectNum(); | ||
| } | ||
| return result; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package lotto; | ||
| // https://staticclass.tistory.com/72 참고 | ||
| public class MyException extends java.lang.Exception { | ||
|
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. 커스텀 예외를 작성한 부분이 인상적이네요! 😃 |
||
| public MyException() { | ||
| } | ||
|
|
||
| public MyException(String errMoney) { | ||
| super(errMoney); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| package lotto; | ||
|
|
||
| import org.assertj.core.api.ThrowableAssert; | ||
|
|
||
| import java.util.*; | ||
|
|
||
| public class Result { | ||
| public void showResult(List<Integer>[] lotto, List<Integer> win, int bonus) { | ||
| HashMap<Integer, Integer> count = count(lotto, win, bonus); | ||
| HashMap<String, Integer> result = result(count); | ||
| double percent = rate(count, lotto.length / 6); | ||
| printResult(result, percent); | ||
| } | ||
|
|
||
| // 맞춘갯수끼리 map | ||
| private HashMap<Integer, Integer> count(List<Integer>[] lotto, List<Integer> win, int bonus) { | ||
| HashMap<Integer, Integer> map = new HashMap<>(); | ||
| for (int i = 0; i < lotto.length / 6; i++) { | ||
| int correct = count(lotto[i], win); | ||
| if (correct == 5 && countBonus(lotto[i], bonus)) { | ||
| correct = 7; // 보너스까지 맞았다면 7로 설정 | ||
| } | ||
| // mapping, https://gymdev.tistory.com/39 참고 | ||
| map.put(correct, map.getOrDefault(correct, 0) + 1); | ||
| } | ||
| return map; | ||
| } | ||
|
|
||
| // 복권 한개당 일치하는 숫자 확인 | ||
| public int count(List<Integer> lotto, List<Integer> win) { | ||
| int correct = 0; | ||
| for (int i = 0; i < lotto.size(); i++) { | ||
| if(countBonus(lotto, win.get(i))){ | ||
| correct++; | ||
| } | ||
| } | ||
| return correct; | ||
| } | ||
|
|
||
| // 5개+보너스숫자 확인 | ||
| private boolean countBonus(List<Integer> lotto, int bonus) { | ||
| for (Integer integer : lotto) { | ||
| if (integer == bonus) { | ||
|
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. contains();contains를 사용했다면 코드도 줄고 가독성도 더 높아질 것 같아요 |
||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| // 순서대로 결과 mapping, https://tosuccess.tistory.com/138 참고 | ||
| private HashMap<String, Integer> result(HashMap<Integer, Integer> count) { | ||
| LinkedHashMap<String, Integer> result = new LinkedHashMap<>(); | ||
| for (PRICE price : PRICE.values()) { | ||
| result.put(price.getRank(), 0); | ||
| if (count.containsKey(price.getNumber())) { | ||
| result.replace(price.getRank(), count.get(price.getNumber())); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| // 수익률 구하기 | ||
| private double rate(HashMap<Integer, Integer> result, int n) { | ||
|
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. 하드코딩은 좋지 않은 것 같아요 😭 |
||
| double avg = (double) (result.getOrDefault(3, 0) * 5 + result.getOrDefault(4, 0) * 50 | ||
| + result.getOrDefault(5, 0) * 1500 + result.getOrDefault(7, 0) * 30000 | ||
| + result.getOrDefault(6, 0) * 2000000) / n * 100; | ||
|
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. 소수점 둘째 자리에서 반올림이 됐는지 확인이 어렵네요 |
||
| return avg; | ||
| } | ||
|
|
||
| // 결과 출력 | ||
| private void printResult(HashMap<String, Integer> result, double percent) { | ||
| for (String key : result.keySet()) { | ||
| System.out.println(key + result.get(key) + "개"); | ||
| } | ||
| System.out.printf("총 수익률은 %3.1f%%입니다.", percent); | ||
| } | ||
| } | ||
|
|
||
| enum PRICE { | ||
|
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. 한 java 파일에 여러 클래스를 놔두기 보단 내부로 사용하거나 |
||
| FIFTH(3, "3개 일치 (5,000원) - "), | ||
| FOURTH(4, "4개 일치 (50,000원) - "), | ||
| THIRD(5, "5개 일치 (1,500,000원) - "), | ||
| SECOND(7, "5개 일치, 보너스 볼 일치 (30,000,000원) - "), | ||
| FIRST(6, "6개 일치 (2,000,000,000원) - "); | ||
|
|
||
| final private int number; | ||
| final private String rank; | ||
|
|
||
| public int getNumber() { | ||
| return number; | ||
| } | ||
|
|
||
| public String getRank() { | ||
| return rank; | ||
| } | ||
|
|
||
| private PRICE(int number, String text) { | ||
| this.number = number; | ||
| this.rank = text; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| package lotto; | ||
|
|
||
| import camp.nextstep.edu.missionutils.Console; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.InputMismatchException; | ||
| import java.util.List; | ||
|
|
||
| public class WinNum { | ||
| public void showWin(List<Integer>[] lotto) { | ||
| List<Integer> win = selectResult(); | ||
| int bonus = getBonus(); | ||
|
|
||
| Result result = new Result(); | ||
| result.showResult(lotto, win, bonus); | ||
| } | ||
|
|
||
| // 당첨 숫자 입력받기 | ||
| private List<Integer> selectResult() { | ||
| List<Integer> result = new ArrayList<>(); | ||
| try { | ||
| System.out.println("\n당첨 번호를 입력해 주세요."); | ||
| String[] num = Console.readLine().split(","); | ||
| result = toList(num); | ||
| new Lotto(result); | ||
| } catch (IllegalArgumentException | MyException e) { | ||
| System.out.println(e.getMessage()); | ||
| selectResult(); | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| // 문자열 정수형으로 변환하며, Lotto에서 확인 | ||
| private List<Integer> toList(String[] s) { | ||
| List<Integer> result = new ArrayList<>(s.length); | ||
| try { | ||
| for (String string : s) { | ||
| result.add(Integer.parseInt(string)); | ||
| } | ||
| Collections.sort(result); | ||
| } catch (NumberFormatException e) { | ||
| System.out.println("[ERROR] 숫자가 아닙니다."); | ||
| selectResult(); | ||
|
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. 순환 참조를 발생하고 toList 메소드를 실행하는 부분에 재귀를 해서 스택오버플로우 발생 위험이 있을 것 같아요 |
||
| } | ||
| return result; | ||
| } | ||
|
|
||
| // 보너스 번호 입력받기 | ||
| private int getBonus() { | ||
| try { | ||
| System.out.println("\n보너스 번호를 입력해 주세요."); | ||
| int num = Integer.parseInt(Console.readLine()); | ||
| validate(num); | ||
| return num; | ||
| } catch (InputMismatchException | IllegalArgumentException e) { | ||
| System.out.println("[ERROR] " + e.getMessage()); | ||
| getBonus(); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| private void validate(int num) { | ||
| if (num < 1 || num > 45) { | ||
| throw new IllegalArgumentException("보너스 번호는 1~45 사이의 숫자여야 합니다."); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package lotto; | ||
|
|
||
| import org.junit.jupiter.api.DisplayName; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
|
||
| public class MoneyTest { | ||
| @DisplayName("구입 금액 입력받기") | ||
| @Test | ||
| void nonNumericTest() throws MyException { | ||
|
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. 기능 구현한 하나의 메소드에서 많은 일을 처리하고 있어서 테스트하기 힘들었을 것 같아요 |
||
| Money money = new Money(); | ||
| assertThatThrownBy(money.getModulo(50)) | ||
| .isInstanceOf(MyException.class); | ||
| } | ||
|
|
||
| @DisplayName("랜덤숫자 보여주기") | ||
| @Test | ||
| void showRandomNumber() throws MyException { | ||
| Money money = new Money(); | ||
| assertThatThrownBy(money.showNum(8)) | ||
| .isInstanceOf(MyException.class); | ||
| } | ||
| } | ||
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.
showMain 메소드에서는 예외를 던지지 않는데
메인에서 예외를 던지도록 되어 있네요
만약 메인에서 예외를 throws 한다면 어떻게 되나요?