From da9c4d83bad2fc138f2803d3fc61dcce6af01095 Mon Sep 17 00:00:00 2001 From: thoi2 Date: Mon, 4 Nov 2024 22:53:01 +0900 Subject: [PATCH 1/3] =?UTF-8?q?lotto=206=EC=97=90=EC=84=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 +++ src/main/java/lotto/Application.java | 169 ++++++++++++++++++++++ src/main/java/lotto/Lotto.java | 21 ++- src/main/java/lotto/PrizeMoneyByRank.java | 44 ++++++ 4 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 src/main/java/lotto/PrizeMoneyByRank.java diff --git a/README.md b/README.md index 5fa2560b46..42aff68e82 100644 --- a/README.md +++ b/README.md @@ -1 +1,24 @@ # java-lotto-precourse + + +# 미션 - 로또 + +## 기능 구현 + +1. 1 ~ 45 까지 중복되지 않는 정수 6개 반환 기능 +2. Lotto 클래스 getter, toString 구현 +3. 당첨 번호 입력 기능 +4. 보너스 번호 입력 기능 +5. 등수 확인 기능 + * 일반 등수만 확인 기능(1, 3, 4, 5등) + * 보너스 번호 포함 확인 기능(3등 중에서 2등 뽑기) +6. 로또 구입 금액 입력 기능 +7. 총 구매 로또 개수 계산 기능 +8. 로또 발행 기능 +9. 등수별 당첨금액 및 번호 일치 개수 열거형 +10. 당첨 내역 출력 기능 +11. 수익률 출력 기능 +12. 예외 처리 + * IllegalArgumentException + * IllegalStateException +13. 메인 메서드 구현 diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba4..e462747226 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,176 @@ package lotto; +import camp.nextstep.edu.missionutils.Randoms; +import camp.nextstep.edu.missionutils.Console; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; public class Application { + private static final int PRICEPERLOTTO = 1000; + public static void main(String[] args) { // TODO: 프로그램 구현 + int payMoney = getPayMoney(); + int lottoPurchasesNum = calculateLottoPurchasesNum(payMoney); + List myLottoNum = myLottoNum(lottoPurchasesNum); + List luckyNum = getLuckyNum(); + int bonusNumber = getBonusNumber(luckyNum); + int[][] result = matchByLotto(luckyNum, myLottoNum, lottoPurchasesNum, bonusNumber); + displayResults(result,payMoney); + + } + + public static List lottoNumberGenerator() { + List lottoNumber = Randoms.pickUniqueNumbersInRange(1, 45, 6); + return lottoNumber; + } + + public static int getPayMoney() { + while (true) { + try { + System.out.println("구입금액을 입력해 주세요."); + String unCheckedPayMoney = Console.readLine(); + int payMoney = checkPayMoney(unCheckedPayMoney); + return payMoney; + } catch (NumberFormatException e) { + System.out.println("[ERROR] 구입 금액은 정수만 입력가능합니다."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + public static int checkPayMoney(String unCheckedPayMoney) { + int checkPayMoney = Integer.parseInt(unCheckedPayMoney); + if (checkPayMoney < PRICEPERLOTTO || checkPayMoney % PRICEPERLOTTO > 0) { + throw new IllegalArgumentException("[ERROR] 구매금액은 1000으로 나누어 떨어져야합니다."); + } + return checkPayMoney; + } + + public static int calculateLottoPurchasesNum(int payMoney) { + int lottoPurchasesNum = payMoney / PRICEPERLOTTO; + System.out.println(lottoPurchasesNum + "개를 구매했습니다."); + return lottoPurchasesNum; + } + + public static List myLottoNum(int lottoPurchasesNum) { + List myLottoNum = new ArrayList<>(); + for (int i = 1; i < lottoPurchasesNum + 1; i++) { + Lotto lotto = new Lotto(lottoNumberGenerator()); + myLottoNum.add(lotto); + System.out.println(lotto); + } + return myLottoNum; + } + + public static List getLuckyNum() { + while (true) { + try { + System.out.println("\n당첨 번호를 입력해 주세요."); + String unCheckedLuckyNumber = Console.readLine(); + List luckyNum = checkLuckyNum(unCheckedLuckyNumber); + new Lotto(luckyNum); + return luckyNum; + } catch (NumberFormatException e) { + System.out.println("[ERROR] 로또 번호는 정수만 입력가능합니다."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + public static List checkLuckyNum(String unCheckedLuckyNumber) { + StringTokenizer tokenizer = new StringTokenizer(unCheckedLuckyNumber, ","); + List checkLuckyNum = new ArrayList<>(); + while (tokenizer.hasMoreTokens()) { + int token = Integer.parseInt(tokenizer.nextToken()); + checkLuckyNum.add(token); + } + return checkLuckyNum; + } + + public static int getBonusNumber(List luckyNum) { + while (true) { + try { + System.out.println("\n보너스 번호를 입력해 주세요."); + String unCheckedBonusNumber = Console.readLine(); + int bonusNumber = checkBonusNumber(unCheckedBonusNumber,luckyNum); + return bonusNumber; + } catch (NumberFormatException e) { + System.out.println("[ERROR] 보너스 번호는 정수만 입력가능합니다."); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + public static int checkBonusNumber(String unCheckedBonusNumber,List luckyNum) { + int checkBonusNumber = Integer.parseInt(unCheckedBonusNumber); + if (checkBonusNumber < 0 || checkBonusNumber > 45) { + throw new IllegalArgumentException("[ERROR] 보너스 번호는 1부터 45 사이의 숫자여야 합니다."); + } + if (luckyNum.contains(checkBonusNumber)) { + throw new IllegalArgumentException("[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다."); + } + return checkBonusNumber; + } + + public static int getMatchPoint(List luckyNum, List lottoNum) { + int matchPoint = 0; + for (int i = 0; i < luckyNum.size(); i++) { + if (lottoNum.contains(luckyNum.get(i))) { + matchPoint += 1; + } + } + return matchPoint; + } + + public static int[][] matchByLotto(List luckyNum, List myLottoNum, int purchaseNum, int bonusNum) { + int[][] matchPoints = new int[purchaseNum][2]; + for (int i = 0; i < purchaseNum; i++) { + int matchPoint = getMatchPoint(luckyNum, myLottoNum.get(i).getNumbers()); + matchPoints[i][0] = matchPoint; + if (matchPoint == 5) { + matchPoints[i][1] = calculateSecondtoThird(myLottoNum.get(i).getNumbers(), bonusNum); + } + } + return matchPoints; + } + + public static int calculateSecondtoThird(List myLottoNum, int bonusNumber) { + for (int i = 0; i < myLottoNum.size(); i++) { + if (myLottoNum.contains(bonusNumber)) { + return 1; + } + } + return 0; + } + + public static void displayResults(int[][] matchPoints, int payMoney) { + int[] rankCount = new int[PrizeMoneyByRank.values().length]; + int myPorfit = 0; + for (int[] result : matchPoints) { + PrizeMoneyByRank rank = PrizeMoneyByRank.getRankByMatchCount(result[0], result[1]); + rankCount[rank.ordinal()]++; + } + + for (PrizeMoneyByRank rank : PrizeMoneyByRank.values()) { + if (rank != PrizeMoneyByRank.TRASH) { + System.out.printf("%d개 일치 (%d원) - %d개%n", rank.getMatchCount(), rank.getPrizeMoney(), rankCount[rank.ordinal()]); + myPorfit += rank.getPrizeMoney()*rankCount[rank.ordinal()]; + } + } + myProfitRate(payMoney,myPorfit); + + } + public static double myProfitRate(double payMoney, double myProfit){ + double profitRate = myProfit/payMoney*100; + System.out.println("총 수익률은 "+Math.round(profitRate*10/10)+"%입니다."); + return profitRate; } } + + + diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 88fc5cf12b..18845e3b79 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -1,5 +1,4 @@ package lotto; - import java.util.List; public class Lotto { @@ -11,10 +10,28 @@ public Lotto(List numbers) { } private void validate(List numbers) { - if (numbers.size() != 6) { + final int lottoSize = 6; + if (numbers.size() != lottoSize) { throw new IllegalArgumentException("[ERROR] 로또 번호는 6개여야 합니다."); } + for(int number : numbers) { + if (number < 0 || number > 45) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + } + } + public List getNumbers(){ + return numbers; } + @Override + public String toString(){ + return numbers.toString(); + } + + + + // TODO: 추가 기능 구현 + } diff --git a/src/main/java/lotto/PrizeMoneyByRank.java b/src/main/java/lotto/PrizeMoneyByRank.java new file mode 100644 index 0000000000..4e8dd51c0c --- /dev/null +++ b/src/main/java/lotto/PrizeMoneyByRank.java @@ -0,0 +1,44 @@ +package lotto; + +public enum PrizeMoneyByRank { + FIFTH(3,5000), + FOURTH(4,50000), + THIRD(5,1500000), + SECOND(5,30000000), + FIRST(6,2000000000), + TRASH(0,0); + + private final int matchCount; + private final int prizeMoney; + + + PrizeMoneyByRank(int matchCount, int prizeMoney){ + this.matchCount = matchCount; + this.prizeMoney = prizeMoney; + } + public int getMatchCount(){ + return matchCount; + } + + public int getPrizeMoney() { + return prizeMoney; + } + public static PrizeMoneyByRank getRankByMatchCount(int matchCount, int bonusMatch){ + if(matchCount == FIRST.getMatchCount()){ + return FIRST; + } + if(matchCount == SECOND.getMatchCount()&& bonusMatch == 1 ){ + return SECOND; + } + if(matchCount == THIRD.getMatchCount()&& bonusMatch == 0 ){ + return THIRD; + } + if(matchCount == FOURTH.getMatchCount()){ + return FOURTH; + } + if(matchCount == FIFTH.getMatchCount()){ + return FIFTH; + } + return TRASH; + } +} From f04eadf8fc6530ba700956a3262699c09f3b26c1 Mon Sep 17 00:00:00 2001 From: thoi2 Date: Mon, 4 Nov 2024 23:52:49 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Add=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20Refactor=20=EC=B6=9C=EB=A0=A5=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=B3=B4=EB=84=88=EC=8A=A4=EB=B3=BC=20=EC=9D=BC?= =?UTF-8?q?=EC=B9=98=20=EC=B6=94=EA=B0=80=EB=A5=BC=20=EC=9C=84=ED=95=B4=20?= =?UTF-8?q?=EC=A0=84=EB=A9=B4=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 41 ++++++++++++++++++---------- src/main/java/lotto/Lotto.java | 4 +++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index e462747226..2f69821eea 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -149,28 +149,39 @@ public static int calculateSecondtoThird(List myLottoNum, int bonusNumb } public static void displayResults(int[][] matchPoints, int payMoney) { - int[] rankCount = new int[PrizeMoneyByRank.values().length]; - int myPorfit = 0; + int[] rankCounts = new int[PrizeMoneyByRank.values().length]; + for (int[] result : matchPoints) { PrizeMoneyByRank rank = PrizeMoneyByRank.getRankByMatchCount(result[0], result[1]); - rankCount[rank.ordinal()]++; + rankCounts[rank.ordinal()]++; } + printStatistics(rankCounts); + double totalProfit = calculateTotalProfit(rankCounts); + displayProfitRate(payMoney, totalProfit); + } + + public static void printStatistics(int[] rankCounts) { + System.out.println("당첨 통계\n---"); + System.out.printf("3개 일치 (%d원) - %d개%n", PrizeMoneyByRank.FIFTH.getPrizeMoney(), rankCounts[PrizeMoneyByRank.FIFTH.ordinal()]); + System.out.printf("4개 일치 (%d원) - %d개%n", PrizeMoneyByRank.FOURTH.getPrizeMoney(), rankCounts[PrizeMoneyByRank.FOURTH.ordinal()]); + System.out.printf("5개 일치 (%d원) - %d개%n", PrizeMoneyByRank.THIRD.getPrizeMoney(), rankCounts[PrizeMoneyByRank.THIRD.ordinal()]); + System.out.printf("5개 일치, 보너스 볼 일치 (%d원) - %d개%n", PrizeMoneyByRank.SECOND.getPrizeMoney(), rankCounts[PrizeMoneyByRank.SECOND.ordinal()]); + System.out.printf("6개 일치 (%d원) - %d개%n", PrizeMoneyByRank.FIRST.getPrizeMoney(), rankCounts[PrizeMoneyByRank.FIRST.ordinal()]); + } + + public static double calculateTotalProfit(int[] rankCounts) { + double totalProfit = 0; for (PrizeMoneyByRank rank : PrizeMoneyByRank.values()) { if (rank != PrizeMoneyByRank.TRASH) { - System.out.printf("%d개 일치 (%d원) - %d개%n", rank.getMatchCount(), rank.getPrizeMoney(), rankCount[rank.ordinal()]); - myPorfit += rank.getPrizeMoney()*rankCount[rank.ordinal()]; + totalProfit += rank.getPrizeMoney() * rankCounts[rank.ordinal()]; } } - myProfitRate(payMoney,myPorfit); - - } - public static double myProfitRate(double payMoney, double myProfit){ - double profitRate = myProfit/payMoney*100; - System.out.println("총 수익률은 "+Math.round(profitRate*10/10)+"%입니다."); - return profitRate; + return totalProfit; } -} - - + public static void displayProfitRate(double payMoney, double totalProfit) { + double profitRate = totalProfit / payMoney * 100; + System.out.printf("총 수익률은 %.1f%%입니다.%n", profitRate); + } +} \ No newline at end of file diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 18845e3b79..21261ba9dc 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -18,6 +18,10 @@ private void validate(List numbers) { if (number < 0 || number > 45) { throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); } + if (numbers.indexOf(number) != numbers.lastIndexOf(number)){ + throw new IllegalArgumentException("[ERROR] 로또 번호에는 중복이 없어야 합니다."); + } + } } public List getNumbers(){ From 833c863970acda97cc7f5a143d5cb0c0594898d2 Mon Sep 17 00:00:00 2001 From: thoi2 Date: Mon, 4 Nov 2024 23:59:51 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix=20=EC=B6=9C=EB=A0=A5=ED=99=94=EB=A9=B4?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index 2f69821eea..86b90da1f1 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -162,12 +162,12 @@ public static void displayResults(int[][] matchPoints, int payMoney) { } public static void printStatistics(int[] rankCounts) { - System.out.println("당첨 통계\n---"); - System.out.printf("3개 일치 (%d원) - %d개%n", PrizeMoneyByRank.FIFTH.getPrizeMoney(), rankCounts[PrizeMoneyByRank.FIFTH.ordinal()]); - System.out.printf("4개 일치 (%d원) - %d개%n", PrizeMoneyByRank.FOURTH.getPrizeMoney(), rankCounts[PrizeMoneyByRank.FOURTH.ordinal()]); - System.out.printf("5개 일치 (%d원) - %d개%n", PrizeMoneyByRank.THIRD.getPrizeMoney(), rankCounts[PrizeMoneyByRank.THIRD.ordinal()]); - System.out.printf("5개 일치, 보너스 볼 일치 (%d원) - %d개%n", PrizeMoneyByRank.SECOND.getPrizeMoney(), rankCounts[PrizeMoneyByRank.SECOND.ordinal()]); - System.out.printf("6개 일치 (%d원) - %d개%n", PrizeMoneyByRank.FIRST.getPrizeMoney(), rankCounts[PrizeMoneyByRank.FIRST.ordinal()]); + System.out.println("\n당첨 통계\n---"); + System.out.printf("3개 일치 (5,000원) - %d개%n", rankCounts[PrizeMoneyByRank.FIFTH.ordinal()]); + System.out.printf("4개 일치 (50,000원) - %d개%n", rankCounts[PrizeMoneyByRank.FOURTH.ordinal()]); + System.out.printf("5개 일치 (1,500,000원) - %d개%n", rankCounts[PrizeMoneyByRank.THIRD.ordinal()]); + System.out.printf("5개 일치, 보너스 볼 일치 (30,000,000원) - %d개%n", rankCounts[PrizeMoneyByRank.SECOND.ordinal()]); + System.out.printf("6개 일치 (2,000,000,000원) - %d개%n", rankCounts[PrizeMoneyByRank.FIRST.ordinal()]); } public static double calculateTotalProfit(int[] rankCounts) {