diff --git a/docs/README.md b/docs/README.md index e69de29bb2d..64a73ef0114 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,57 @@ +#Lotto 클래스 +기본 Lotto클래스에 추가된 기능은 다음과 같습니다. + +- public Lotto() : 기본 생성자. 다른 클래스에서 Lotto 클래스를 초기화하여 사용하기 위해 만들었습니다. +- public List getNumbers() : Lotto 클래스의 멤버변수 numbers를 반환하는 함수. +- public int rankLotto(List userNumbers, int bonus) : Lotto class에 저장된 로또 번호와 당첨번호 userNumbers, 보너스번호 bonus를 이용하여 복권의 등수를 계산합니다. +- public int checkLRank(int cnt, boolean bonusFlag) : rankLotto 함수에서 당첨번호와 겹치는 번호의 개수 cnt, 보너스번호의 당첨 유무 bonusFlag를 이용하여 복권의 등수를 계산합니다. + +#InputInfo 클래스 +사용자의 입력을 처리하는 클래스입니다. 로또구매금액, 당첨번호, 보너스 번호를 입력받고 예외를 처리합니다. + +-public InputInfo() : 기본 생성자. 당첨번호를 저장할 List userNumbers와 예외처리를 위해 만든 CheckError check를 초기화합니다. +-public setPrice() : 로또구매금액을 입력받고 처리하는 함수. 구매 금액을 입력받은 뒤 "문자 예외->음수 예외->1000원으로 나누어 떨어지지 않는 예외" 순서로 예외를 처리하고 입력한 형식이 맞다면 int price 멤버변수에 저장합니다. +-public setNumbers() : 당첨번호를 입력받고 처리하는 함수. 당첨번호를 입력받은 뒤 "입력 형식 예외->입력한 숫자 개수가 다른 예외->문자 예외->중복 예외" 순서로 예외를 처리하고 입력한 형식이 맞다면 List userNumbers 멤버 변수에 저장합니다. +-public setBonus() : 보너스번호를 입력받고 처리하는 함수. 보너스번호를 입력받은 뒤 "문자 예외->범위 예외->당첨번호와 중복된 숫자 예외" 순서로 예외를 처리하고 입력한 형식이 맞다면 int bonus 멤버변수에 저장합니다. +-public List changeNumbersType(String[] str) : 당첨번호를 입력받는 과정에서 String[] 타입으로 입력받은 당첨번호를 List 타입으로 변경하기 위한 함수. +-public int getPrice(), public List getUserNumbers(), public int getBonus() : 해당 멤버변수의 값을 반환합니다. + +#BuyLotto 클래스 +입력받은 로또구매금액을 바탕으로 로또를 구매하기 위한 클래스입니다. + +-public BuyLotto(int price) : 기본 생성자. InputInfo 클래스를 통해 입력받은 price를 매개변수로 받습니다. 또한, 객체를 생성하면서 int count 멤버변수와 Lotto[] lottos 멤버변수의 값을 setting합니다. +-public void setCount(int price) : 로또구매개수를 계산하여 int count 멤버변수에 저장합니다. +-public void setLottos() : 로또구매개수만큼의 로또를 만들고, Lotto[] lottos에 저장합니다. +-public void printBuyLottos() : 구매한 로또의 정보를 출력합니다. +-public int getCount(), public Lotto[] getLottos() : 해당 멤버변수의 값을 반환합니다. + +#CalculateBenefit 클래스 +입력받은 당첨번호와 보너스번호를 바탕으로 구매한 로또의 이익을 확인하기 위한 클래스입니다. + +-public CalculateBenefit(int price, int bonus, Lotto[] lottos, List userNumber) : 기본 생성자: InputInfo 클래스를 통해 입력받은 로또구매금액, 보너스번호, 구매한 로또 리스트, 당첨번호를 매개변수로 받습니다. 또한, 객체를 생성하면서 int[] lottoRank를 초기화하고, int benefit과 double benefitRate를 setting합니다. +-public void setBenefit(Lotto[] lottos) : 구매한 로또로 번 돈을 계산하는 함수. Lotto 클래스의 rankLotto를 이용하여 등수를 알아내고, 해당 등수의 상금을 모두 합하여 benefit에 저장하면서 총 이익을 계산합니다. 이 과정에서 1~5등까지의 로또 개수를 lottoRank에 저장합니다. +-public void setBenefitRate(Lotto[] lottos) : 구매한 로또로 번 돈을 바탕으로 총 수익률을 계산하는 함수. benefit을 price로 나누어 계산한 값을 benefitRate에 저장합니다. +-public int checkMoney(int rank) : 등수별 상금을 반환하는 함수. +-public int getBenefit(), public double getBenefitRate(), public int[] getLottoRank() : 해당 멤버변수의 값을 반환합니다. + +#CheckError 클래스 +사용자 입력 과정에서 발생하는 예외를 확인하기 위한 클래스 입니다. + +-public CheckError() : 기본생성자. +-public boolean chk_Str(String str) : str의 값이 정수에 매칭되지 않으면 오류 메세지를 출력하고 true를 반환, 매칭되면 false를 반환합니다. +-public boolean chk_Neg(int val) : val의 값이 0 또는 음수이면 오류 메세지를 출력하고 true를 반환, 0 또는 음수가 아니면 true를 반환합니다. +-public boolean chk_Mod(int price) : price의 값이 1000으로 나눠떨어지지 않으면 오류 메세지를 출력하고 true를 반환, 1000으로 나눠떨어지면 false를 반환합니다. +-public boolean chk_Count(String[] str) : str의 길이가 6이 아니면 오류 메세지를 출력하고 true를 반환, 6이면 false를 반환합니다. +-public boolean chk_Range(int val) : val의 범위가 1~45가 아니면 오류 메세지를 출력하고 true를 반환, 1~45이면 false를 반환합니다. +-public boolean chk_Duplication(String[] val) : val의 원소에 중복되는 값이 있으면 오류 메세지를 출력하고 true를 반환, 없으면 false를 반환합니다. +-public boolean chk_Input(String[] str) : str의 원소에 문자가 있으면 오류 메세지를 출력하고 true를 반환, 없으면 false를 반환합니다. +-public boolean chk_BonusDuplication(List numbers, int bonus) : 보너스번호가 당첨번호의 숫자와 겹치면 오류 메세지를 출력하고 true를 반환, 겹치지 않으면 나눠떨어지면 false를 반환합니다. + +#LottoError 클래스 +CheckError 클래스에서 처리하는 예외를 다루기 위한 ENUM 클래스입니다. + +#Game 클래스 +InputInfo, BuyLotto, CalculateBenefit 클래스를 이용하여 로또 게임을 처리하는 클래스 + +-public Game() : 기본 생성자. 위의 3가지 클래스를 순차적으로 setting하여 로또 게임을 처리합니다. +-public void printResult() : 로또 게임의 당첨 통계를 출력합니다. diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index d190922ba44..7a6dccaa0a5 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -3,5 +3,7 @@ public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + LottoGameController controller = new LottoGameController(); + controller.run(); } } diff --git a/src/main/java/lotto/BonusNumber.java b/src/main/java/lotto/BonusNumber.java new file mode 100644 index 00000000000..bc2521c929b --- /dev/null +++ b/src/main/java/lotto/BonusNumber.java @@ -0,0 +1,23 @@ +package lotto; + +import java.util.InputMismatchException; + +public class BonusNumber { + private LottoWinningNumbers winningNumbers; + private int bonus; + public BonusNumber(LottoWinningNumbers winningNumbers, String bonusInput) { + this.winningNumbers = winningNumbers; + validate(bonusInput); + bonus = Integer.parseInt(bonusInput); + } + public void validate(String bonusInput){ + ErrorChecker checker = new ErrorChecker(); + if(checker.checkString(bonusInput)) throw new IllegalArgumentException(LOTTOERROR.String_Error.getMessage()); + int bonus = Integer.parseInt(bonusInput); + if(checker.checkRange(bonus)) throw new IllegalArgumentException(LOTTOERROR.Range_Error.getMessage()); + if(checker.checkBonusDuplication(winningNumbers.getWinningNumbers(), bonus)) throw new IllegalArgumentException(LOTTOERROR.BonusDuplication_Error.getMessage()); + } + public int getBonus(){ + return bonus; + } +} diff --git a/src/main/java/lotto/ErrorChecker.java b/src/main/java/lotto/ErrorChecker.java new file mode 100644 index 00000000000..1093ba078bd --- /dev/null +++ b/src/main/java/lotto/ErrorChecker.java @@ -0,0 +1,64 @@ +package lotto; + +import java.util.HashSet; +import java.util.List; + +public class ErrorChecker { + public ErrorChecker(){ + } + public boolean checkString(String str){ + if(!str.matches("-?\\d+")){ + return true; + } + return false; + } + public boolean checkNegativeNumber(int val){ + if(val<=0){ + return true; + } + return false; + } + public boolean checkDivision(int price){ + if(price%1000!=0){ + return true; + } + return false; + } + public boolean checkAmount(String[] str){ + if(str.length!=6) { + return true; + } + return false; + } + public boolean checkRange(int val){ + if(val<1 || val>45) { + return true; + } + return false; + } + public boolean checkDuplication(List val){ + HashSet uniqueVal = new HashSet<>(); + for(int v : val) { + if (!uniqueVal.add(v)) { + return true; + } + } + return false; + } + public boolean checkInputFormat(String[] str){ + for(String s : str) { + if (!s.matches("-?\\d+")) { + return true; + } + } + return false; + } + public boolean checkBonusDuplication(List numbers, int bonus){ + for(int num : numbers){ + if(num == bonus) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/lotto/InputView.java b/src/main/java/lotto/InputView.java new file mode 100644 index 00000000000..8df1ba8605e --- /dev/null +++ b/src/main/java/lotto/InputView.java @@ -0,0 +1,20 @@ +package lotto; +import camp.nextstep.edu.missionutils.Console; +import java.util.*; + +public class InputView { + public InputView(){} + public String inputPrice(){ + String priceInput = Console.readLine(); + return priceInput; + } + public String[] inputWinningNumbers(){ + String inputWinningNumbers = Console.readLine(); + return inputWinningNumbers.split(","); + } + public String inputBonus(){ + String inputBonus = Console.readLine(); + return inputBonus; + } +} + diff --git a/src/main/java/lotto/LOTTOERROR.java b/src/main/java/lotto/LOTTOERROR.java new file mode 100644 index 00000000000..59add4ff642 --- /dev/null +++ b/src/main/java/lotto/LOTTOERROR.java @@ -0,0 +1,24 @@ +package lotto; + +public enum LOTTOERROR { + + String_Error("[ERROR] 입력한 값에 문자가 있습니다. 숫자를 입력해주세요."), + Negative_Error("[ERROR] 입력한 값이 0 또는 음수입니다. 로또 구매 금액은 양수여야 합니다."), + Division_Error( "[ERROR] 로또 구매 금액은 1000원으로 나누어 떨어져야 합니다."), + Amount_Error("[ERROR] 당첨 번호는 6개의 숫자를 입력해야 합니다."), + Range_Error("[ERROR] 당첨 번호는 1부터 45 사이의 숫자여야 합니다."), + Duplication_Error("[ERROR] 당첨 번호 6개 중 중복되는 값이 있습니다."), + InputFormat_Error("[ERROR] 당첨 번호가 쉼표로 구분되지 않았거나 문자를 입력했습니다."), + BonusDuplication_Error("[ERROR] 보너스 번호는 당첨 번호에 없는 숫자를 입력해야 합니다."); + + private final String message; + LOTTOERROR(String message) { + this.message = message; + } + + public String getMessage() { return message; } + public void printMessage(){ + System.out.println(message); + } + +} diff --git a/src/main/java/lotto/Lotto.java b/src/main/java/lotto/Lotto.java index 519793d1f73..085ffceecb1 100644 --- a/src/main/java/lotto/Lotto.java +++ b/src/main/java/lotto/Lotto.java @@ -1,10 +1,15 @@ package lotto; +import java.util.ArrayList; import java.util.List; public class Lotto { private final List numbers; + public Lotto(){ + numbers = new ArrayList<>(); + } + public Lotto(List numbers) { validate(numbers); this.numbers = numbers; @@ -15,6 +20,40 @@ private void validate(List numbers) { throw new IllegalArgumentException(); } } + public List getNumbers(){ + return numbers; + } + public int rankLotto(List userNumbers, int bonus){ + int rank; + int cnt=0; + boolean bonusFlag = false; + for(int userNum : userNumbers){ + for(int num : numbers){ + if(num == userNum) cnt++; + if(num == bonus) bonusFlag = true; + } + } + rank = checkRank(cnt, bonusFlag); + return rank; + } + public int checkRank(int cnt, boolean bonusFlag){ + if(cnt==6){ + return 1; + } + if(cnt==5&&bonusFlag){ + return 2; + } + if(cnt==5){ + return 3; + } + if(cnt==4){ + return 4; + } + if(cnt==3){ + return 5; + } + return 0; + } // TODO: 추가 기능 구현 } diff --git a/src/main/java/lotto/LottoBenefitRateCalculator.java b/src/main/java/lotto/LottoBenefitRateCalculator.java new file mode 100644 index 00000000000..eb9ad2fef37 --- /dev/null +++ b/src/main/java/lotto/LottoBenefitRateCalculator.java @@ -0,0 +1,47 @@ +package lotto; +import java.util.*; + +public class LottoBenefitRateCalculator { + private double benefitRate; + private int[] lottoRank; + private int[] lottoReward; + public LottoBenefitRateCalculator(){ + lottoRank = new int[]{0,0,0,0,0,0}; + lottoReward = new int[]{VALUESETTING.None_Reward.getValue(), VALUESETTING.Fifth_Reward.getValue(), VALUESETTING.Second_Reward.getValue(), VALUESETTING.Third_Reward.getValue() + , VALUESETTING.Fourth_Reward.getValue(), VALUESETTING.Fifth_Reward.getValue()}; + } + public int calculateBenefit(int amount, Lotto[] lottos, List winningNumbers, int bonus){ + int benefit = 0; + int rank; + for(Lotto lotto : lottos){ + rank = lotto.rankLotto(winningNumbers, bonus); + System.out.println(rank); + benefit+=lottoReward[rank]; + lottoRank[rank]++; + } + return benefit; + } + public void setBenefitRate(int price, Lotto[] lottos, List winningNumbers, int bonus){ + int benefit = calculateBenefit(price, lottos, winningNumbers, bonus); + benefitRate = ((double) benefit / (double) price) * 100; + } + public void printResult(){ + System.out.println("당첨 통계"); + System.out.println("---"); + for(int i = 4 ; i >= 0 ; i--){ + if(i==4) System.out.println("3개 일치 (5,000원) - " + lottoRank[i] + "개"); + if(i==3) System.out.println("4개 일치 (50,000원) - " + lottoRank[i] + "개"); + if(i==2) System.out.println("5개 일치 (1,500,000원) - " + lottoRank[i] + "개"); + if(i==1) System.out.println("5개 일치 (30,000,000원) - " + lottoRank[i] + "개"); + if(i==0) System.out.println("6개 일치 (2,000,000,000원) - " + lottoRank[i] + "개"); + } + String s_benefitRate = String.format("%.1f", benefitRate); + System.out.println("총 수익률은 " + s_benefitRate + "%입니다."); + } + public int[] getLottoRank(){ + return lottoRank; + } + public double getBenefitRate(){ + return benefitRate; + } +} diff --git a/src/main/java/lotto/LottoGameController.java b/src/main/java/lotto/LottoGameController.java new file mode 100644 index 00000000000..0f4fc81f615 --- /dev/null +++ b/src/main/java/lotto/LottoGameController.java @@ -0,0 +1,57 @@ +package lotto; + +public class LottoGameController { + private InputView inputView; + private OutputView outputView; + public LottoGameController() { + inputView = new InputView(); + outputView = new OutputView(); + } + public LottoSeller inputLottoSeller(){ + while(true) { + try { + outputView.printPriceInputMessage(); + String priceInput = inputView.inputPrice(); + LottoSeller lottoSeller = new LottoSeller(priceInput); + return lottoSeller; + } catch (IllegalArgumentException e) { + outputView.printErrorMessage(e); + } + } + } + public LottoWinningNumbers inputLottoWinningNumbers(){ + while(true) { + try { + outputView.printWinningNumbersInputMessage(); + String[] winningNumbersInput = inputView.inputWinningNumbers(); + LottoWinningNumbers lottoWinningNumbers = new LottoWinningNumbers(winningNumbersInput); + return lottoWinningNumbers; + } catch (IllegalArgumentException e) { + outputView.printErrorMessage(e); + } + } + } + public BonusNumber inputBonusNumber(LottoWinningNumbers winningNumbers){ + while(true) { + try { + outputView.printBonusNumberInputMessage(); + String bonusInput = inputView.inputBonus(); + BonusNumber bonusNumber = new BonusNumber(winningNumbers, bonusInput); + return bonusNumber; + } catch (IllegalArgumentException e) { + outputView.printErrorMessage(e); + } + } + } + public void run(){ + LottoSeller seller = inputLottoSeller(); + outputView.printBoughtLottos(seller); + LottoWinningNumbers winningNumbers = inputLottoWinningNumbers(); + BonusNumber bonus = inputBonusNumber(winningNumbers); + LottoBenefitRateCalculator benefit = new LottoBenefitRateCalculator(); + benefit.setBenefitRate(seller.getPrice(), seller.getLottos(), winningNumbers.getWinningNumbers(), bonus.getBonus()); + outputView.printResult(benefit); + } + +} + diff --git a/src/main/java/lotto/LottoSeller.java b/src/main/java/lotto/LottoSeller.java new file mode 100644 index 00000000000..ac352719d12 --- /dev/null +++ b/src/main/java/lotto/LottoSeller.java @@ -0,0 +1,46 @@ +package lotto; +import java.util.*; +import java.util.stream.Collectors; + +import camp.nextstep.edu.missionutils.Randoms; + +public class LottoSeller { + private int price; + private int amount; + private Lotto[] lottos; + public LottoSeller(){} + public LottoSeller(String priceInput){ + validate(priceInput); + price = Integer.parseInt(priceInput); + amount = price / 1000; + sellLottos(); + } + public void validate(String priceInput){ + ErrorChecker checker = new ErrorChecker(); + if(checker.checkString(priceInput)) throw new IllegalArgumentException(LOTTOERROR.String_Error.getMessage()); + int price = Integer.parseInt(priceInput); + if(checker.checkNegativeNumber(price)) throw new IllegalArgumentException(LOTTOERROR.Negative_Error.getMessage()); + if(checker.checkDivision(price)) throw new IllegalArgumentException(LOTTOERROR.Division_Error.getMessage()); + } + public void sellLottos(){ + lottos = new Lotto[amount]; + for(int i=0;i numbers = Randoms.pickUniqueNumbersInRange(1, 45, 6); + Lotto lotto = new Lotto(sortLotto(numbers)); + lottos[i] = lotto; + } + } + public List sortLotto(List lotto){ + List sortedLotto = lotto.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList()); + return sortedLotto; + } + public int getPrice(){ + return price; + } + public int getAmount(){ + return amount; + } + public Lotto[] getLottos(){ + return lottos; + } +} diff --git a/src/main/java/lotto/LottoWinningNumbers.java b/src/main/java/lotto/LottoWinningNumbers.java new file mode 100644 index 00000000000..1943fa94a6c --- /dev/null +++ b/src/main/java/lotto/LottoWinningNumbers.java @@ -0,0 +1,28 @@ +package lotto; + +import java.util.*; +import java.util.stream.Collectors; + +public class LottoWinningNumbers { + private List winningNumbers; + public LottoWinningNumbers(String[] winningNumbersInput) { + validate(winningNumbersInput); + winningNumbers = changeNumbersType(winningNumbersInput); + } + public void validate(String[] winningNumbersInput){ + ErrorChecker checker = new ErrorChecker(); + if(checker.checkInputFormat(winningNumbersInput)) throw new IllegalArgumentException(LOTTOERROR.InputFormat_Error.getMessage()); + if(checker.checkAmount(winningNumbersInput)) throw new IllegalArgumentException(LOTTOERROR.Amount_Error.getMessage()); + List winningNumbers = changeNumbersType(winningNumbersInput); + for(int number : winningNumbers) if(checker.checkRange(number)) throw new IllegalArgumentException(LOTTOERROR.Range_Error.getMessage()); + if(checker.checkDuplication(winningNumbers)) throw new IllegalArgumentException(LOTTOERROR.Duplication_Error.getMessage()); + } + public List changeNumbersType(String[] str){ + List temp = Arrays.asList(str); + List numbers = temp.stream().map(Integer::parseInt).collect(Collectors.toList()); + return numbers; + } + public List getWinningNumbers(){ + return winningNumbers; + } +} diff --git a/src/main/java/lotto/OutputView.java b/src/main/java/lotto/OutputView.java new file mode 100644 index 00000000000..0c37f85f11e --- /dev/null +++ b/src/main/java/lotto/OutputView.java @@ -0,0 +1,44 @@ +package lotto; + +import java.util.*; + +public class OutputView { + public OutputView(){} + public void printPriceInputMessage(){ + System.out.println("구매금액을 입력해주세요."); + } + public void printWinningNumbersInputMessage(){ + System.out.println("당첨 번호를 입력해주세요."); + } + public void printBonusNumberInputMessage(){ + System.out.println("보너스 번호를 입력해주세요."); + } + public void printBoughtLottos(LottoSeller lottoSeller){ + System.out.println(lottoSeller.getAmount()+"개를 구매했습니다."); + Lotto[] lottos = lottoSeller.getLottos(); + List numbers; + for(Lotto lotto : lottos){ + System.out.print("["); + numbers = lotto.getNumbers(); + for(int i=0;i