✅ 장바구니 및 구매하기 기능 추가
- 장바구니 생성 및 관리 기능
- 사용자가 선택한 메뉴를 장바구니에 추가할 수 있는 기능을 제공한다.
- 장바구니는 메뉴명, 수량, 가격 정보를 저장하며, 항목을 동적으로 추가 및 조회할 수 있어야 한다.
- 사용자가 잘못된 선택을 했을 경우 예외를 처리한다. (ex : 유효하지 않은 메뉴 번호 입력)
- 장바구니 출력 및 금액 계산
- 사용자가 결제를 시도하기 전에, 장바구니에 담긴 모든 메뉴와 총 금액을 출력한다.
- 출력 예시
- 각 메뉴의 이름, 가격, 수량
- 총 금액 합계
- 장바구니 담기 기능
- 메뉴를 클릭하면 장바구니에 추가할 지 물어보고, 입력값에 따라 “추가”, “취소” 처리한다.
- 장바구니에 담은 목록을 출력한다.
- 주문 기능
- 장바구니에 담긴 모든 항목을 출력한다.
- 합산하여 총 금액을 계산하고, “주문하기”를 누르면 장바구니를 초기화합니다.
package ChallengeLv1;
public class CLv1Main {
public static void main(String[] args) {
CLv1Menu cLv1Menu = new CLv1Menu();
// CLv1Menu 에 있는 lv4Menus 라는 리스트에 getter 를 사용해 햄버거 정보를 추가
cLv1Menu.getCLv1Menus().add(new CLv1Menu("Burgers"));
cLv1Menu.getCLv1Menus().add(new CLv1Menu("Drinks"));
cLv1Menu.getCLv1Menus().add(new CLv1Menu("Desserts"));
// CLv1Menu 에 있는 burgersMenu 라는 리스트에 getter 를 사용해 햄버거 정보를 추가
cLv1Menu.getBurgersMenu().add(new CLv1MenuItem("ShackBurger", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거"));
cLv1Menu.getBurgersMenu().add(new CLv1MenuItem("SmokeShack", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거"));
cLv1Menu.getBurgersMenu().add(new CLv1MenuItem("Cheeseburger", 6.9, "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거"));
cLv1Menu.getBurgersMenu().add(new CLv1MenuItem("Hamburger", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거"));
// CLv1Menu 에 있는 drinksMenu 라는 리스트에 getter 를 사용해 음료 정보를 추가
cLv1Menu.getDrinksMenu().add(new CLv1MenuItem("Fountain Soda", 2.9, "코카콜라, 코카콜라 제로, 스프라이트, 환타 오렌지"));
cLv1Menu.getDrinksMenu().add(new CLv1MenuItem("Lemonade", 4.5, "매장에서 직접 만드는 상큼한 레몬에이드"));
cLv1Menu.getDrinksMenu().add(new CLv1MenuItem("Fresh Brewed Iced Tea", 3.7, "직접 유기농 홍차를 우려낸 아이스 티"));
cLv1Menu.getDrinksMenu().add(new CLv1MenuItem("Fifty/Fifty", 4.0, "레몬에이드와 유기농 홍차를 우려낸 아이스 티가 만나 탄생한 시그니처 음료"));
// CLv1Menu 에 있는 dessertsMenu 라는 리스트에 getter 를 사용해 디저트 정보를 추가
cLv1Menu.getDessertsMenu().add(new CLv1MenuItem("Shack Attack", 6.2, "진한 초콜릿 커스터드에 퍼지 소스와 세 가지 초콜릿 토핑이 블렌딩된 콘크리트"));
cLv1Menu.getDessertsMenu().add(new CLv1MenuItem("Classic Hand-Spun Shakes", 6.8, "쫀득하고 진한 커스터드가 들어간 클래식 쉐이크"));
cLv1Menu.getDessertsMenu().add(new CLv1MenuItem("Cup & Cones", 5.7, "신선하게 제조하는 쫀득하고 진한 아이스크림"));
CLv1Kiosk cLv1Kiosk = new CLv1Kiosk(cLv1Menu);
cLv1Kiosk.start(); // CLv1Kiosk 에 있는 start 함수 실행
}
}
package ChallengeLv1;
public class CLv1MenuItem {
// 1. 속성
private String name;
private double price;
private String foodDetails;
// 2. 생성자
public CLv1MenuItem(String name, double price, String foodDetails) {
this.name = name;
this.price = price;
this.foodDetails = foodDetails;
}
// 3. 기능(메서드)
// 주소값을 출력하는 것이 아닌 리스트안에 들어있는 값을 출력하기 위해 toString 메서드 작성
public String toString() {
return name + " | " + "W" + price + " | " + foodDetails;
}
// name 의 getter 메서드
public String getName() {
return name;
}
// price 의 getter 메서드
public double getPrice() {
return price;
}
}
package ChallengeLv1;
import java.util.InputMismatchException;
import java.util.Scanner;
public class CLv1Kiosk {
CLv1Menu cLv1Menu;
CLv1Cart cLv1Cart = new CLv1Cart();
Scanner scanner = new Scanner(System.in);
int num1 = 0; // 메인메뉴 선택을 위한 변수 생성
int num2 = 0; // 버거메뉴, 음료메뉴, 디저트 메뉴 선택을 위한 변수 생성
// 2. 생성자
public CLv1Kiosk(CLv1Menu cLv1Menu) {
this.cLv1Menu = cLv1Menu;
}
// 3. 기능(메서드)
// 메뉴 입력값을 받아 유효성 검사 후 반환하는 메서드
public int getInput(Scanner scanner, int min, int max) {
int input = -1;
while (true) {
System.out.print("원하시는 메뉴를 선택해주세요: ");
try {
input = scanner.nextInt();
if (input < min || input > max) {
throw new IllegalArgumentException();
}
break;
} catch (IllegalArgumentException | InputMismatchException e) {
System.out.println("올바른 숫자를 입력해주세요.");
scanner.nextLine();
}
}
return input;
}
public void start() { // 입력과 반복문 로직
while (true) { // 사용자가 종료를 누르기 전까지 계속 반복
System.out.println("\n");
cLv1Menu.mainMenu(); // 메인 메뉴를 출력하는 메서드
if (!cLv1Cart.getCarts().isEmpty()) { // 장바구니에 값이 들어있을 경우 order menu 를 보여준다.
System.out.println("\n");
cLv1Cart.orderMenu();
num1 = getInput(scanner, 0, 5); // 코드가 반복되는 부분을 getInput 메서드로 처리(메뉴 입력값을 받아 유효성 검사 후 반환하는 메서드)
}
if (cLv1Cart.getCarts().isEmpty()) { // 장바구니가 비어있을 경우 0,1,2,3 이외의 값 입력시 예외처리
System.out.println("\n");
num1 = getInput(scanner, 0, 3); // 코드가 반복되는 부분을 getInput 메서드로 처리(메뉴 입력값을 받아 유효성 검사 후 반환하는 메서드)
}
if (num1 == 0) break; // 프로그램 종료
while (true) { // 사용자가 종료하기 전까지 반복한다.
System.out.println("\n");
if (num1 == 1) {
cLv1Menu.burgersMenu();
} else if (num1 == 2) {
cLv1Menu.drinkMenu();
} else if (num1 == 3) {
cLv1Menu.dessertsMenu();
} else if (num1 == 4) { // 메인메뉴에서 4를 입력했을 때 orders 메서드(장바구니를 확인 후 주문하는 메서드)가 실행된다.
cLv1Cart.orders();
break;
} else if (num1 == 5) { // 메인메뉴에서 5를 입력했을 때 cancel 메서드(진행중인 주문을 취소하는 메서드)가 실행된다.
cLv1Cart.cancel();
break;
}
try { // 다른 값을 입력했을 시 예외처리
System.out.print("원하시는 메뉴를 선택해주세요: ");
num2 = scanner.nextInt();
if (num2 == 0) break; // 0을 입력하면 메인메뉴로 돌아가게 된다.
if (num1 == 1) {
System.out.println("선택한 메뉴: " + cLv1Menu.getBurgersMenu().get(num2 - 1));
cLv1Cart.getCarts().add(cLv1Menu.getBurgersMenu().get(num2 - 1)); // burgerMenu 리스트에 들어있는 선택한 메뉴를 cartsList 에 저장하기 위해 getter 를 사용한다.
} else if (num1 == 2) {
System.out.println("선택한 메뉴: " + cLv1Menu.getDrinksMenu().get(num2 - 1));
cLv1Cart.getCarts().add(cLv1Menu.getDrinksMenu().get(num2 - 1)); // burgerMenu 리스트에 들어있는 선택한 메뉴를 cartsList 에 저장하기 위해 getter 를 사용한다.
} else if (num1 == 3) {
System.out.println("선택한 메뉴: " + cLv1Menu.getDessertsMenu().get(num2 - 1));
cLv1Cart.getCarts().add(cLv1Menu.getDessertsMenu().get(num2 - 1)); // burgerMenu 리스트에 들어있는 선택한 메뉴를 cartsList 에 저장하기 위해 getter 를 사용한다.
}
cLv1Cart.cartsAdd(); // cartsAdd 메서드(장바구니에 메뉴를 추가하는 메서드)를 실행한다.
break; // 메인메뉴로 돌아가게 된다.
} catch (IndexOutOfBoundsException | InputMismatchException e) {
System.out.println("올바른 숫자를 입력해주세요");
scanner.nextLine(); // 버퍼에 남아있는 값을 제거하기 위해 사용
}
}
}
}
}
package ChallengeLv1;
import java.util.ArrayList;
import java.util.List;
public class CLv1Menu {// MenuItem 클래스를 관리하는 클래스
// 1. 속성
private final List<CLv1MenuItem> burgersMenu = new ArrayList<>(); // 버거 메뉴를 저장하는 리스트
private final List<CLv1MenuItem> drinksMenu = new ArrayList<>(); // 음료 메뉴를 저장하는 리스트
private final List<CLv1MenuItem> dessertsMenu = new ArrayList<>(); // 디저트 메뉴를 저장하는 리스트
private final List<CLv1Menu> cLv1Menus = new ArrayList<>(); // 메인 메뉴를 저장하는 리스트
private String name;
// 2. 생성자
public CLv1Menu() {
}
public CLv1Menu(String name) {
this.name = name;
}
// 3. 기능(메서드)
// 메인 메뉴를 보여주는 메서드
public void mainMenu() {
System.out.println("[ MAIN MENU ]");
for (int i = 0; i < cLv1Menus.size(); i++) {
System.out.print(i + 1 + ". ");
System.out.println(cLv1Menus.get(i));
}
System.out.println("0. 종료");
}
// 버거 메뉴를 보여주는 메서드
public void burgersMenu() {
System.out.println("[ BURGERS MENU ]");
for (int i = 0; i < burgersMenu.size(); i++) {
System.out.print(i + 1 + ". ");
System.out.println(burgersMenu.get(i));
}
System.out.println("0. 뒤로가기");
}
// 음료 메뉴를 보여주는 메서드
public void drinkMenu() {
System.out.println("[ DRINKS MENU ]");
for (int i = 0; i < drinksMenu.size(); i++) {
System.out.print(i + 1 + ". ");
System.out.println(drinksMenu.get(i));
}
System.out.println("0. 뒤로가기");
}
// 디저트 메뉴를 보여주는 메서드
public void dessertsMenu() {
System.out.println("[ DESSERTS MENU ]");
for (int i = 0; i < dessertsMenu.size(); i++) {
System.out.print(i + 1 + ". ");
System.out.println(dessertsMenu.get(i));
}
System.out.println("0. 뒤로가기");
}
// 주소값을 출력하는 것이 아닌 리스트안에 들어있는 값을 출력하기 위해 toString 메서드 작성
public String toString() {
return name;
}
// 버거 메뉴의 getter 메서드
public List<CLv1MenuItem> getBurgersMenu() {
return burgersMenu;
}
// 음료 메뉴의 getter 메서드
public List<CLv1MenuItem> getDrinksMenu() {
return drinksMenu;
}
// 디저트 메뉴의 getter 메서드
public List<CLv1MenuItem> getDessertsMenu() {
return dessertsMenu;
}
// 메인 메뉴의 getter 메서드
public List<CLv1Menu> getCLv1Menus() {
return cLv1Menus;
}
}
package ChallengeLv1;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Scanner;
public class CLv1Cart {
// 1. 속성
// 선택한 메뉴의 정보를 저장하는 리스트
private final List<CLv1MenuItem> cartsList = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
// 2. 생성자
// 3. 기능
// 장바구니에 메뉴를 추가하는 메서드
public void cartsAdd() {
System.out.println("\n");
System.out.println("\"" + cartsList.get(cartsList.size() - 1) + "\""); // cartsList 에 담겨있는 마지막 값을 보여준다.(선택한 메뉴가 cartsList 마지막에 저장되어 있다.)
System.out.println("위 메뉴를 장바구니에 추가하시겠습니까?");
System.out.println("1. 확인 2. 취소");
int cartNum = 0; // 장바구니에 추가 여부를 위한 변수 생성
while (true) {
try {
cartNum = scanner.nextInt();
if (cartNum != 1 && cartNum != 2) {
throw new IllegalArgumentException();
}
} catch (IllegalArgumentException | InputMismatchException e) {
System.out.println("올바른 숫자를 입력해주세요.");
scanner.nextLine(); // 버퍼에 남아있는 값을 제거하기 위해 사용
}
if (cartNum == 1) { // 1을 입력하면 장바구니에 추가된 메뉴 이름을 출력한다.
System.out.println(cartsList.get(cartsList.size() - 1).getName() + " 이 장바구니에 추가되었습니다.");
break; // 바른 값을 입력했을 시 while 문에서 빠져나온다.
} else if (cartNum == 2) { // 2를 입력하면 장바구니에 추가하지 않기 때문에 cartsList 에 있는 마지막 값을 삭제한다.
cartsList.remove(cartsList.size() - 1);
System.out.println("메뉴 선택이 취소되었습니다.");
break; // 바른 값을 입력했을 시 while 문에서 빠져나온다.
}
}
}
// ORDER MENU 를 출력하는 메서드
public void orderMenu() {
System.out.println("[ ORDER MENU ]\n" +
"4. Orders | 장바구니를 확인 후 주문합니다.\n" +
"5. Cancel | 진행중인 주문을 취소합니다.");
}
// 진행중인 주문을 취소하는 메서드
public void cancel() {
cartsList.clear(); // cartsList 에 담겨 있는 모든 값을 제거한다.
}
// 장바구니를 확인 후 주문하는 메서드
public void orders() {
int finalOrd = 0; // 최종으로 메뉴를 주문하기 위한 변수 생성
double sumResult = 0; // 주문할 가격의 합을 나타내기 위한 변수 생성
while (finalOrd != 1 && finalOrd != 2) { // 1또는 2를 입력하기 전까지 반복
System.out.println("\n" + "아래와 같이 주문 하시겠습니까?");
System.out.println("[ Orders ]\n" + cartsList + "\n"); // 장바구니에 담겨 있는 메뉴를 보여준다.
int size = cartsList.size(); // cartsList 의 사이즈 변수 생성
double sum = 0; // total 금액 변수 생성
for (int i = 0; i < size; i++) { // cartsList 에 있는 가격의 합을 for 문을 활용해 구한다.
sum += cartsList.get(i).getPrice();
}
sumResult = Math.round(sum * 10) / 10.0; // 가격의 합을 소숫점 첫째자리까지 나타내기 위해 Math.round 를 사용한다.
System.out.println("[ Total ]" + "\n" + "W " + sumResult + "\n");
System.out.println("1. 주문 2. 메뉴판");
try { // 1과 2 제외 다른 값이 입력됐을 경우 예외처리
finalOrd = scanner.nextInt(); // 최종으로 메뉴를 주문하기 위해 숫자를 입력 받는다.
if (finalOrd < 1 || finalOrd > 2) {
throw new IllegalArgumentException();
}
} catch (IllegalArgumentException | InputMismatchException e) {
System.out.println("올바른 값을 입력해주세요");
scanner.nextLine(); // 버퍼에 남아있는 값을 제거하기 위해 사용
}
}
if (finalOrd == 1) {
System.out.println("\n" + "주문이 완료되었습니다. 금액은 W " + sumResult + "입니다.");
cartsList.clear();
}
}
// cartsList 의 getter 메서드
public List<CLv1MenuItem> getCarts() {
return cartsList;
}
}
장바구니에 추가할 메뉴의 이름을 불러올 때 정상적으로 작동하지 않고
IndexOutOfBoundsException오류가 나는 상황
System.out.println("\"" + cartsList.get(cartsList.size()) + "\"");처럼 잘못 작성했을 때 오류가 발생한다.cartsList.size()는 리스트의 크기를 반환하는데 리스트의 인덱스는 0부터 시작하므로size()는 마지막 인덱스보다1더 큰 값을 반환한다. 예를 들어 리스트의 크기가3일 경우 마지막 인덱스는2인데size()는3를 반환하므로size(3)는 존재하지 않는 인덱스이기 때문에IndexOutOfBoundsException오류가 발생한다.
System.out.println("\"" + cartsList.get(cartsList.size() - 1) + "\"");로 적어줘야한다.
IndexOutOfBoundsException오류를 통해 리스트의 인덱스 범위를 잘못 이해하고 접근할 때 발생하는 문제를 경험하면서size()는 리스트의 크기일 뿐 마지막 인덱스를 의미하지 않는다는 점을 새로 배웠다.
또한 소수점 처리를 할 때Math.round(sum * 10) / 10.0을 사용하여 소수점을 특정 자리까지 반올림하는 방법을 알게 되었다.