영화 예매 콘솔 프로그램 만들기
다른 도움 없이 혼자 로직을 구현하고 구조에 대한 이해를 할 수 있으면 그 다음 단계로 class를 사용해서 파일을 분리하고 본격적인 플러터 앱 만들기를 도전할 수 있다.
2월 말 부터 혼자서 끝까지 앱을 만들어보는 최종 프로젝트를 시작하기 위해서라도 열심히 하고 싶은데 예제풀이가 잘 따라주지 않아서 어렵다.
장바구니에 담은 아이템을 삭제하려고 할 때,
1. 프린트문이 인덱스값을 삭제하기 전에 와야 에러가 나지 않는다.
2. 이 코드의 문제점은 장바구니 안 인덱스를 지웠을 때 다른 인덱스값이 출력될 수 있다는 부분이다.
if (index >= 0 && index < cartList.length) {
int newCount = readIntInput('새로운 수량 입력 (0 입력 시 삭제)');
if (newCount <= 0) {
// ! (순서가 프린트문이 위쪽으로 와야한다. 인덱스 값이 먼저 삭제되었는데 열어보려고 하면 에러가 나기 때문.)
print('${cartList[index]['title']}항목이 삭제되었습니다.');
// 변수에 저장한게 없을 경우, 다른 아이템이 뒤에 있다면 지워진 자리로 온 엉뚱한 다른 타이틀이 출력됨
cartList.removeAt(index);
}
}
if (index >= 0 && index < cartList.length) {
int newCount = readIntInput('새로운 수량 입력 (0 입력 시 삭제)');
if (newCount <= 0) {
// 삭제하기 전 변수에 미리 저장해두어야 삭제 후에도 이름을 기억해서 출력한다.
String deletedTitle = cartList[index]['title'];
// 변수에 저장한게 없을 경우, 다른 아이템이 뒤에 있다면 지워진 자리로 온 엉뚱한 다른 타이틀이 출력됨
cartList.removeAt(index);
// 저장해둔 이름을 출력
print('$deletedTitle 항목이 삭제되었습니다.');
}
}
수량을 변경하는 코드를 맞게 작성했다고 생각했는데 2매를 선택한 것을 1매로 변경하고자 했으나 콘솔에서 변경된 수량이 적용되지 않는다.

뉴카운트 값이 1 이상일 경우를 만들어주지 않아서 발생한 문제
조건을 추가해 주었고, 정상적으로 장바구니의 수량이 변경되며 조건에 맞는 항목을 선택해야 변경이 되는 것도 확인하였다.
자꾸 어떤 변수를 넣어야 할지 헷갈리는 부분이 흐름을 이해하는데 방해가 되었다.
else {
// 수량이 1 이상이면 수량 변경
// 원본 movies에서 해당 아이디를 찾아서 남은 좌석을 체크하고, 잔여좌석 초과/변경가능 조건문
var leftSeats = movies.firstWhere(
(item) => item['id'] == cartList[index]['id'],
);
if (newCount > leftSeats['availableSeats']) {
print('남은 잔여 좌석 수: ${leftSeats['availableSeats']}매 이내로 다시 입력해주세요.');
} else {
// 1 이상일 때 카트리스트에 뉴카운트 값이 담겨서 출력된다.
cartList[index]['count'] = newCount;
print('${cartList[index]['title']}의 수량이 $newCount매로 변경되었습니다.');
}
}
장바구니 안의 영화목록이 2가지 이상일 때 해당 영화의 번호를 입력하니 잘못된 항목으로 취급되어서 변경이 되지 않는다.

장바구니 목록의 2번째 순서인걸 출력을 해야되는데
원본 리스트 안의 영화등록 순번대로 출력이 되어서 2번째 항목임에도 '3번: 영화'로 표시되어 있어서 사용자에게 혼동을 주게 되었다.
변경할 항목번호를 2로 입력하면 2번째 항목이 정상적으로 변경이 되는 부분을 확인

id값이 cartList에 추가된 순서대로 뜨는게 아니라 movies의 id값을 그대로 가지고와서 출력이 된다.
print('\n[예매 목록]');
// cartList를 순회하며 번호 / 제목 / 가격 / 수량 / 소계 출력
for (var i = 0; i < cartList.length; i++) {
var item = cartList[i];
var itemCount = item['price'] * item['count'];
print(
'${item['id']}번: ${item['title']} | 가격: ${item['price']}원 | 선택 좌석 수: ${item['count']}매 | 합계: $itemCount원',
);
}
현재 리스트의 인덱스값을 순차적으로 보여주게끔 수정했다.
print('\n[예매 목록]');
// cartList를 순회하며 번호 / 제목 / 가격 / 수량 / 소계 출력
for (var i = 0; i < cartList.length; i++) {
var item = cartList[i];
var itemCount = item['price'] * item['count'];
print(
// item 대신 i+1을 사용해 리스트안에 순차적인 번호를 부여한다.
'${i + 1}번: ${item['title']} | 가격: ${item['price']}원 | 선택 좌석 수: ${item['count']}매 | 합계: $itemCount원',
);
}

예매 목록 보기
목록에 있는 영화 중 3번 항목을 10장 예매를 하고 결제완료 후 다시 영화목록을 띄우니 전체 영화목록의 예매가능좌석 숫자가 줄어드는 문제가 발생했다.

반복문 내부의 로직에서 실수가 발생했다.
어떤 영화를 샀는지 구분하지 못하고 전체를 대상으로 빼기 연산을 수행한 것.
1. 원본리스트를 만들 때 하나의 맵 변수를 돌려쓰거나 했을 수 있다.
2. 이중 반복문 안에서 빼기를 해서 리스트 전체를 돌며 모든 요소의 좌석을 빼고 있을 수 있다.
for (var item in cartList) {
for (var movie in movies) {
movie['availableSeats'] -= item['count'];
}
}
원본리스트와 카트리스트에 담겨있는 영화가 일치하는지 먼저 찾아준 뒤,
일치하는 영화의 좌석에서 카트리스트의 카운트 값을 빼준 것을 적용시키면 된다.
for (var item in cartList) {
// 원본리스트 안에서 카트리스트 아이템의 id와 일치하는 원본 영화를 찾는다.
var subtractSeats = movies.firstWhere(
(movie) => movie['id'] == item['id'],
);
// 찾은 원본 영화의 좌석을 차감 한다. 다이나믹 타입이어서 인트로 확정 지어줘야 에러가 나지 않음..
subtractSeats['availableSeats'] =
(subtractSeats['availableSeats'] as int) - (item['count'] as int);
}