From ab8a1c1a7cdfbb54ce3143015c614897e757d13a Mon Sep 17 00:00:00 2001 From: whoenykkk Date: Mon, 3 Nov 2025 23:29:50 +0900 Subject: [PATCH 1/6] =?UTF-8?q?docs:=20README.md=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 5fa2560b46..b40be1bccb 100644 --- a/README.md +++ b/README.md @@ -1 +1,26 @@ # java-lotto-precourse + +## 기능 요구사항 + +### 1. 입력 기능 +- 로또 구입 금액 입력받기 (1,000원 단위 검증) +- 당첨 번호 6개 입력받기 (쉼표 구분) +- 보너스 번호 입력받기 + +### 2.로또 발행 기능 +- 구입 금액에 따른 로또 개수 계산 +- 1~45 범위에서 중복 없는 6개 번호 생성 +- 로또 번호 오름차순 정렬 및 출력 + +### 3.당첨 처리 기능 +- 구매 로또와 당첨 번호 비교 +- 당첨 등수 판정 (1등~5등) +- 당첨 내역 집계 + +### 4.결과 출력 기능 +- 당첨 통계 출력 +- 수익률 계산 및 출력 + +### 5.예외 처리 기능 +- 입력값 검증 및 예외 처리 +- 에러 메시지 출력 \ No newline at end of file From 1b321c0a5e2ea749c5d0c6b1243fe4cb1c03dac6 Mon Sep 17 00:00:00 2001 From: whoenykkk Date: Mon, 3 Nov 2025 23:46:02 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 59 +++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba4..f1ef099aa7 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,62 @@ package lotto; +import camp.nextstep.edu.missionutils.Console; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + System.out.println("구입금액을 입력해 주세요."); + int purchaseAmount = parsePurchaseAmount(Console.readLine()); + + System.out.println("당첨 번호를 입력해 주세요."); + List winningNumbers = parseWinningNumbers(Console.readLine()); + + System.out.println("보너스 번호를 입력해 주세요."); + int bonusNumber = parseBonusNumber(Console.readLine(), winningNumbers); + } + + private static int parsePurchaseAmount(String input) { + int amount = Integer.parseInt(input); + if (amount % 1000 != 0) { + throw new IllegalArgumentException("[ERROR] 구입 금액은 1,000원 단위로 입력해야 합니다."); + } + return amount; + } + + private static List parseWinningNumbers(String input) { + String[] parts = input.split(","); + if (parts.length != 6) { + throw new IllegalArgumentException("[ERROR] 당첨 번호는 6개여야 합니다."); + } + + List numbers = Arrays.stream(parts) + .map(String::trim) + .map(Integer::parseInt) + .toList(); + + for (int number : numbers) { + if (number < 1 || number > 45) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + } + + if (new HashSet<>(numbers).size() != 6) { + throw new IllegalArgumentException("[ERROR] 당첨 번호는 중복될 수 없습니다."); + } + + return numbers; + } + + private static int parseBonusNumber(String input, List winningNumbers) { + int bonusNumber = Integer.parseInt(input); + if (bonusNumber < 1 || bonusNumber > 45) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + if (winningNumbers.contains(bonusNumber)) { + throw new IllegalArgumentException("[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다."); + } + return bonusNumber; } -} +} \ No newline at end of file From df5be248231d7673c2f580b2ef268e425bd7ed47 Mon Sep 17 00:00:00 2001 From: whoenykkk Date: Mon, 3 Nov 2025 23:46:59 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 24 ++++++++++++++++++++++++ src/main/java/lotto/Lotto.java | 12 ++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index f1ef099aa7..868e920342 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,15 +1,20 @@ package lotto; import camp.nextstep.edu.missionutils.Console; +import camp.nextstep.edu.missionutils.Randoms; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.ArrayList; public class Application { public static void main(String[] args) { System.out.println("구입금액을 입력해 주세요."); int purchaseAmount = parsePurchaseAmount(Console.readLine()); + List lottos = generateLottos(purchaseAmount); + printLottos(lottos); + System.out.println("당첨 번호를 입력해 주세요."); List winningNumbers = parseWinningNumbers(Console.readLine()); @@ -17,6 +22,25 @@ public static void main(String[] args) { int bonusNumber = parseBonusNumber(Console.readLine(), winningNumbers); } + private static List generateLottos(int purchaseAmount) { + int count = purchaseAmount / 1000; + System.out.println(count + "개를 구매했습니다."); + + List lottos = new ArrayList<>(); + for (int i = 0; i < count; i++) { + List numbers = Randoms.pickUniqueNumbersInRange(1, 45, 6); + lottos.add(new Lotto(numbers)); + } + return lottos; + } + + private static void printLottos(List lottos) { + for (Lotto lotto : lottos) { + System.out.println(lotto.toString()); + } + System.out.println(); + } + private static int parsePurchaseAmount(String input) { int amount = Integer.parseInt(input); if (amount % 1000 != 0) { diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 88fc5cf12b..e6944b4b2e 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -16,5 +16,13 @@ private void validate(List numbers) { } } - // TODO: 추가 기능 구현 -} + @Override + public String toString() { + List sortedNumbers = numbers.stream().sorted().toList(); + return sortedNumbers.toString(); + } + + public List getNumbers() { + return numbers; + } +} \ No newline at end of file From ff4a5209f6cbb296adfd38374b30034a3575a89b Mon Sep 17 00:00:00 2001 From: whoenykkk Date: Mon, 3 Nov 2025 23:50:05 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 19 +++++++++++ src/main/java/lotto/Lotto.java | 17 ++++++++++ src/main/java/lotto/Rank.java | 51 ++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 src/main/java/lotto/Rank.java diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index 868e920342..e1c1a2afff 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -6,6 +6,8 @@ import java.util.HashSet; import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; public class Application { public static void main(String[] args) { @@ -20,6 +22,23 @@ public static void main(String[] args) { System.out.println("보너스 번호를 입력해 주세요."); int bonusNumber = parseBonusNumber(Console.readLine(), winningNumbers); + + Map results = checkWinnings(lottos, winningNumbers, bonusNumber); + } + + private static Map checkWinnings(List lottos, List winningNumbers, int bonusNumber) { + Map results = new HashMap<>(); + + for (Rank rank : Rank.values()) { + results.put(rank, 0); + } + + for (Lotto lotto : lottos) { + Rank rank = lotto.checkRank(winningNumbers, bonusNumber); + results.put(rank, results.get(rank) + 1); + } + + return results; } private static List generateLottos(int purchaseAmount) { diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index e6944b4b2e..01bd6d0afd 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -1,6 +1,7 @@ package lotto; import java.util.List; +import java.util.Collections; public class Lotto { private final List numbers; @@ -25,4 +26,20 @@ public String toString() { public List getNumbers() { return numbers; } + + public Rank checkRank(List winningNumbers, int bonusNumber) { + int matchCount = countMatches(winningNumbers); + boolean bonusMatch = numbers.contains(bonusNumber); + return Rank.valueOf(matchCount, bonusMatch); + } + + private int countMatches(List winningNumbers) { + int count = 0; + for (int number : numbers) { + if (winningNumbers.contains(number)) { + count++; + } + } + return count; + } } \ No newline at end of file diff --git a/src/main/java/lotto/Rank.java b/src/main/java/lotto/Rank.java new file mode 100644 index 0000000000..287f6b2052 --- /dev/null +++ b/src/main/java/lotto/Rank.java @@ -0,0 +1,51 @@ +package lotto; + +public enum Rank { + FIRST(6, false, 2_000_000_000), + SECOND(5, true, 30_000_000), + THIRD(5, false, 1_500_000), + FOURTH(4, false, 50_000), + FIFTH(3, false, 5_000), + NONE(0, false, 0); + + private final int matchCount; + private final boolean bonusMatch; + private final int prize; + + Rank(int matchCount, boolean bonusMatch, int prize) { + this.matchCount = matchCount; + this.bonusMatch = bonusMatch; + this.prize = prize; + } + + public static Rank valueOf(int matchCount, boolean bonusMatch) { + if (matchCount == 6) { + return FIRST; + } + if (matchCount == 5 && bonusMatch) { + return SECOND; + } + if (matchCount == 5) { + return THIRD; + } + if (matchCount == 4) { + return FOURTH; + } + if (matchCount == 3) { + return FIFTH; + } + return NONE; + } + + public int getPrize() { + return prize; + } + + public int getMatchCount() { + return matchCount; + } + + public boolean isBonusMatch() { + return bonusMatch; + } +} \ No newline at end of file From 4c6fc6b7ea8737d2d2e5adf376a8644cf5c272db Mon Sep 17 00:00:00 2001 From: whoenykkk Date: Mon, 3 Nov 2025 23:51:42 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=EA=B2=B0=EA=B3=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index e1c1a2afff..5770fdce5c 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -24,6 +24,7 @@ public static void main(String[] args) { int bonusNumber = parseBonusNumber(Console.readLine(), winningNumbers); Map results = checkWinnings(lottos, winningNumbers, bonusNumber); + printResults(results, purchaseAmount); } private static Map checkWinnings(List lottos, List winningNumbers, int bonusNumber) { @@ -41,6 +42,27 @@ private static Map checkWinnings(List lottos, List results, int purchaseAmount) { + System.out.println("당첨 통계"); + System.out.println("---"); + System.out.println("3개 일치 (5,000원) - " + results.get(Rank.FIFTH) + "개"); + System.out.println("4개 일치 (50,000원) - " + results.get(Rank.FOURTH) + "개"); + System.out.println("5개 일치 (1,500,000원) - " + results.get(Rank.THIRD) + "개"); + System.out.println("5개 일치, 보너스 볼 일치 (30,000,000원) - " + results.get(Rank.SECOND) + "개"); + System.out.println("6개 일치 (2,000,000,000원) - " + results.get(Rank.FIRST) + "개"); + + double profitRate = calculateProfitRate(results, purchaseAmount); + System.out.println("총 수익률은 " + String.format("%.1f", profitRate) + "%입니다."); + } + + private static double calculateProfitRate(Map results, int purchaseAmount) { + int totalPrize = 0; + for (Rank rank : results.keySet()) { + totalPrize += rank.getPrize() * results.get(rank); + } + return (double) totalPrize / purchaseAmount * 100; + } + private static List generateLottos(int purchaseAmount) { int count = purchaseAmount / 1000; System.out.println(count + "개를 구매했습니다."); From 58640674eebcdc263bd2a4467baa7d93c26c32a8 Mon Sep 17 00:00:00 2001 From: whoenykkk Date: Mon, 3 Nov 2025 23:56:38 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/lotto/Application.java | 94 ++++++++++++++++++++-------- src/main/java/lotto/Lotto.java | 11 ++++ 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index 5770fdce5c..4f0135afd9 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -12,21 +12,51 @@ public class Application { public static void main(String[] args) { System.out.println("구입금액을 입력해 주세요."); - int purchaseAmount = parsePurchaseAmount(Console.readLine()); + int purchaseAmount = readPurchaseAmount(); List lottos = generateLottos(purchaseAmount); printLottos(lottos); System.out.println("당첨 번호를 입력해 주세요."); - List winningNumbers = parseWinningNumbers(Console.readLine()); + List winningNumbers = readWinningNumbers(); System.out.println("보너스 번호를 입력해 주세요."); - int bonusNumber = parseBonusNumber(Console.readLine(), winningNumbers); + int bonusNumber = readBonusNumber(winningNumbers); Map results = checkWinnings(lottos, winningNumbers, bonusNumber); printResults(results, purchaseAmount); } + private static int readPurchaseAmount() { + while (true) { + try { + return parsePurchaseAmount(Console.readLine()); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + private static List readWinningNumbers() { + while (true) { + try { + return parseWinningNumbers(Console.readLine()); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + + private static int readBonusNumber(List winningNumbers) { + while (true) { + try { + return parseBonusNumber(Console.readLine(), winningNumbers); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + } + private static Map checkWinnings(List lottos, List winningNumbers, int bonusNumber) { Map results = new HashMap<>(); @@ -83,11 +113,15 @@ private static void printLottos(List lottos) { } private static int parsePurchaseAmount(String input) { - int amount = Integer.parseInt(input); - if (amount % 1000 != 0) { - throw new IllegalArgumentException("[ERROR] 구입 금액은 1,000원 단위로 입력해야 합니다."); + try { + int amount = Integer.parseInt(input); + if (amount % 1000 != 0) { + throw new IllegalArgumentException("[ERROR] 구입 금액은 1,000원 단위로 입력해야 합니다."); + } + return amount; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("[ERROR] 구입 금액은 숫자여야 합니다."); } - return amount; } private static List parseWinningNumbers(String input) { @@ -96,32 +130,40 @@ private static List parseWinningNumbers(String input) { throw new IllegalArgumentException("[ERROR] 당첨 번호는 6개여야 합니다."); } - List numbers = Arrays.stream(parts) - .map(String::trim) - .map(Integer::parseInt) - .toList(); + try { + List numbers = Arrays.stream(parts) + .map(String::trim) + .map(Integer::parseInt) + .toList(); - for (int number : numbers) { - if (number < 1 || number > 45) { - throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + for (int number : numbers) { + if (number < 1 || number > 45) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } } - } - if (new HashSet<>(numbers).size() != 6) { - throw new IllegalArgumentException("[ERROR] 당첨 번호는 중복될 수 없습니다."); - } + if (new HashSet<>(numbers).size() != 6) { + throw new IllegalArgumentException("[ERROR] 당첨 번호는 중복될 수 없습니다."); + } - return numbers; + return numbers; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("[ERROR] 당첨 번호는 숫자여야 합니다."); + } } private static int parseBonusNumber(String input, List winningNumbers) { - int bonusNumber = Integer.parseInt(input); - if (bonusNumber < 1 || bonusNumber > 45) { - throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); - } - if (winningNumbers.contains(bonusNumber)) { - throw new IllegalArgumentException("[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다."); + try { + int bonusNumber = Integer.parseInt(input); + if (bonusNumber < 1 || bonusNumber > 45) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + if (winningNumbers.contains(bonusNumber)) { + throw new IllegalArgumentException("[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다."); + } + return bonusNumber; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("[ERROR] 보너스 번호는 숫자여야 합니다."); } - return bonusNumber; } } \ No newline at end of file diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 01bd6d0afd..7fe4d27e9f 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Collections; +import java.util.HashSet; public class Lotto { private final List numbers; @@ -15,6 +16,16 @@ private void validate(List numbers) { if (numbers.size() != 6) { throw new IllegalArgumentException("[ERROR] 로또 번호는 6개여야 합니다."); } + + for (int number : numbers) { + if (number < 1 || number > 45) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다."); + } + } + + if (new HashSet<>(numbers).size() != 6) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 중복될 수 없습니다."); + } } @Override