diff --git a/README.md b/README.md index 5fa2560b46..51e9a7cd34 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ # java-lotto-precourse + + • 로또 번호 생성: 1~45 사이의 중복되지 않은 숫자 6개 생성 + • 로또 구매: 구입 금액 입력 및 로또 발행 + • 당첨 번호 입력: 당첨 번호 및 보너스 번호 입력 + • 당첨 결과 계산: 당첨 내역 및 수익률 출력 + • 예외 처리: 잘못된 입력 값 처리 및 에러 메시지 출력 + • Java Enum 활용: 당첨 등수와 금액을 관리하는 데 사용합니다. + • Random 및 Console API: camp.nextstep.edu.missionutils.Randoms와 camp.nextstep.edu.missionutils.Console을 사용합니다. diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba4..16406880d2 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,7 +1,30 @@ package lotto; +import java.util.List; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + try { + // 1. 사용자로부터 구입 금액 입력받기 + int purchaseAmount = InputView.getPurchaseAmount(); + + // 2. 로또 번호 생성 + List purchasedLottos = LottoGenerator.generateLottos(purchaseAmount); + + // 3. 생성된 로또 번호 출력 + OutputView.printLottos(purchasedLottos); + + // 4. 당첨 번호 입력받기 + List winningNumbers = InputView.getWinningNumbers(); + int bonusNumber = InputView.getBonusNumber(); + + // 5. 당첨 결과 계산: 구매 금액(purchaseAmount)을 추가로 전달합니다. + LottoResult result = LottoChecker.check(purchasedLottos, winningNumbers, bonusNumber, purchaseAmount); + + // 6. 당첨 내역 및 수익률 출력 + OutputView.printResult(result); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } } -} +} \ No newline at end of file diff --git a/src/main/java/lotto/InputView.java b/src/main/java/lotto/InputView.java new file mode 100644 index 0000000000..d0f7b7a63d --- /dev/null +++ b/src/main/java/lotto/InputView.java @@ -0,0 +1,38 @@ +package lotto; + +import camp.nextstep.edu.missionutils.Console; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class InputView { + public static int getPurchaseAmount() { + System.out.println("구입금액을 입력해 주세요."); + int amount = Integer.parseInt(Console.readLine()); + if (amount % 1000 != 0) { + throw new IllegalArgumentException("[ERROR] 구입 금액은 1,000원 단위여야 합니다."); + } + return amount; + } + + public static List getWinningNumbers() { + System.out.println("당첨 번호를 입력해 주세요."); + String input = Console.readLine(); + List numbers = Arrays.stream(input.split(",")) + .map(Integer::parseInt) + .collect(Collectors.toList()); + if (numbers.size() != 6 || numbers.stream().anyMatch(num -> num < 1 || num > 45)) { + throw new IllegalArgumentException("[ERROR] 당첨 번호는 1부터 45 사이의 숫자 6개여야 합니다."); + } + return numbers; + } + + public static int getBonusNumber() { + System.out.println("보너스 번호를 입력해 주세요."); + int bonusNumber = Integer.parseInt(Console.readLine()); + if (bonusNumber < 1 || bonusNumber > 45) { + throw new IllegalArgumentException("[ERROR] 보너스 번호는 1부터 45 사이의 숫자여야 합니다."); + } + return bonusNumber; + } +} diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 88fc5cf12b..b6da3422bf 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -1,5 +1,6 @@ package lotto; +import java.util.Collections; import java.util.List; public class Lotto { @@ -7,14 +8,17 @@ public class Lotto { public Lotto(List numbers) { validate(numbers); + Collections.sort(numbers); this.numbers = numbers; } private void validate(List numbers) { - if (numbers.size() != 6) { - throw new IllegalArgumentException("[ERROR] 로또 번호는 6개여야 합니다."); + if (numbers.size() != 6 || numbers.stream().distinct().count() != 6) { + throw new IllegalArgumentException("[ERROR] 로또 번호는 중복되지 않는 6개의 숫자여야 합니다."); } } - // TODO: 추가 기능 구현 + public List getNumbers() { + return numbers; + } } diff --git a/src/main/java/lotto/LottoChecker.java b/src/main/java/lotto/LottoChecker.java new file mode 100644 index 0000000000..3b1e0e3080 --- /dev/null +++ b/src/main/java/lotto/LottoChecker.java @@ -0,0 +1,18 @@ +package lotto; + +import java.util.List; + +public class LottoChecker { + // 구매 금액을 인자로 받도록 수정합니다. + public static LottoResult check(List purchasedLottos, List winningNumbers, int bonusNumber, int purchaseAmount) { + // LottoResult 객체 생성: 구매 금액을 전달합니다. + LottoResult result = new LottoResult(purchaseAmount); + + // 각 로또 번호를 비교하여 당첨 등수를 추가합니다. + for (Lotto lotto : purchasedLottos) { + LottoRank rank = LottoRank.calculate(lotto, winningNumbers, bonusNumber); + result.addRank(rank); + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/lotto/LottoGenerator.java b/src/main/java/lotto/LottoGenerator.java new file mode 100644 index 0000000000..57f3fac40e --- /dev/null +++ b/src/main/java/lotto/LottoGenerator.java @@ -0,0 +1,16 @@ +package lotto; + +import camp.nextstep.edu.missionutils.Randoms; +import java.util.ArrayList; +import java.util.List; + +public class LottoGenerator { + public static List generateLottos(int amount) { + int numberOfLottos = amount / 1000; + List lottos = new ArrayList<>(); + for (int i = 0; i < numberOfLottos; i++) { + lottos.add(new Lotto(Randoms.pickUniqueNumbersInRange(1, 45, 6))); + } + return lottos; + } +} \ No newline at end of file diff --git a/src/main/java/lotto/LottoRank.java b/src/main/java/lotto/LottoRank.java new file mode 100644 index 0000000000..f2ec49ea6e --- /dev/null +++ b/src/main/java/lotto/LottoRank.java @@ -0,0 +1,59 @@ +package lotto; + +import java.util.List; + +public enum LottoRank { + FIRST(6, 2_000_000_000, "6개 일치 (2,000,000,000원)"), + SECOND(5, 30_000_000, "5개 일치, 보너스 볼 일치 (30,000,000원)"), + THIRD(5, 1_500_000, "5개 일치 (1,500,000원)"), + FOURTH(4, 50_000, "4개 일치 (50,000원)"), + FIFTH(3, 5_000, "3개 일치 (5,000원)"), + NONE(0, 0, "꽝"); + + private final int matchCount; + private final int prize; + private final String description; + + // Enum 생성자 + LottoRank(int matchCount, int prize, String description) { + this.matchCount = matchCount; + this.prize = prize; + this.description = description; + } + + public int getPrize() { + return prize; + } + + public String getDescription() { + return description; + } + + // 로또 등수를 계산하는 메서드 + public static LottoRank calculate(Lotto lotto, List winningNumbers, int bonusNumber) { + // 일치하는 번호 개수 계산 + int matchCount = (int) lotto.getNumbers().stream() + .filter(winningNumbers::contains) + .count(); + // 보너스 번호가 포함되어 있는지 확인 + boolean bonusMatch = lotto.getNumbers().contains(bonusNumber); + + // 등수 판별 + 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; + } +} \ No newline at end of file diff --git a/src/main/java/lotto/LottoResult.java b/src/main/java/lotto/LottoResult.java new file mode 100644 index 0000000000..be9bee26c5 --- /dev/null +++ b/src/main/java/lotto/LottoResult.java @@ -0,0 +1,34 @@ +package lotto; + +import java.util.HashMap; +import java.util.Map; + +public class LottoResult { + private final Map rankCounts = new HashMap<>(); + private int totalPrize = 0; + private int purchaseAmount; + + // 생성자: 로또 구매 금액을 전달받습니다. + public LottoResult(int purchaseAmount) { + this.purchaseAmount = purchaseAmount; + } + + // 당첨 등수를 추가하고 총 상금을 계산하는 메서드 + public void addRank(LottoRank rank) { + rankCounts.put(rank, rankCounts.getOrDefault(rank, 0) + 1); + totalPrize += rank.getPrize(); + } + + // 당첨 등수와 개수를 반환하는 메서드 + public Map getRankCounts() { + return rankCounts; + } + + // 수익률을 계산하는 메서드 + public double getYield() { + if (purchaseAmount == 0) { + return 0.0; // 구매 금액이 0이면 수익률은 0% + } + return (double) totalPrize / purchaseAmount * 100; + } +} \ No newline at end of file diff --git a/src/main/java/lotto/OutputView.java b/src/main/java/lotto/OutputView.java new file mode 100644 index 0000000000..10ec999db8 --- /dev/null +++ b/src/main/java/lotto/OutputView.java @@ -0,0 +1,27 @@ +package lotto; + +import java.util.List; +import java.util.Map; + +public class OutputView { + + // 구매한 로또 번호를 출력하는 메서드 + public static void printLottos(List lottos) { + System.out.println(lottos.size() + "개를 구매했습니다."); + for (Lotto lotto : lottos) { + System.out.println(lotto.getNumbers()); + } + } + + // 당첨 결과를 출력하는 메서드 + public static void printResult(LottoResult result) { + System.out.println("당첨 통계"); + System.out.println("---"); + for (Map.Entry entry : result.getRankCounts().entrySet()) { + LottoRank rank = entry.getKey(); + int count = entry.getValue(); + System.out.println(rank.getDescription() + " - " + count + "개"); + } + System.out.printf("총 수익률은 %.1f%%입니다.%n", result.getYield()); + } +} \ No newline at end of file