이 프로젝트는 우아한테크코스 프리코스 2주차 과제인 무작위 값을 구해 4 이상이면 전진하여 겨루는 초간단 자동차 경주 게임를 다루고 있습니다.
- 사용자가 몇 번 이동할 것인지 정하면 우승자를 구하는 초간단 자동차 경주 게임을 구현한다.
- 주어진 횟수 동안 n대의 자동차는
전진 또는 멈춤으로 동작한다.
- 자동차에 이름을 부여할 수 있다.
- 자동차 이름은
,로 구분하며 이름은5자 이하만 가능하다.
pobi,woni,jun- 사용자는 몇 번의 이동을 할 것인지 입력할 수 있다.
5- 전진 조건은 0에서 9 사이의 무작위 값을 구한 후 무작위 값이 4 이상인 경우다.
- 자동차 경주 게임을 완료한 후
누가 우승했는지 알려준다. 우승자는 한 명 이상일 수 있다. - 우승자가 여러 명일 경우
,를 이용하여 구분한다.
pobi : --
woni : ----
jun : ---최종 우승자 : pobi최종 우승자 : pobi, jun- 사용자가 잘못된 값을 입력할 경우 [ERROR] 메시지와 함께 Error 발생 후 애플리케이션 종료된다.
경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
pobiwonijun
[ERROR]경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
pobi,woni,jun
시도할 횟수는 몇 회인가요?
한
[ERROR]-
경주할 자동차 이름 자동차 이름은
,를 기준으로 구분하며5자 이하로 제한
pobi,woni,jun -
시도할 횟수 몇 번 이동할 것인지 입력
5
-
차수별 실행 결과
pobi : -- woni : ---- jun : ---
-
우승자 안내 문구 공동 우승 가능
최종 우승자 : pobi최종 우승자 : pobi, jun
경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
pobi,woni,jun
시도할 횟수는 몇 회인가요?
5
실행 결과
pobi : -
woni :
jun : -
pobi : --
woni : -
jun : --
pobi : ---
woni : --
jun : ---
pobi : ----
woni : ---
jun : ----
pobi : -----
woni : ----
jun : -----
최종 우승자 : pobi, juninitializeGame함수는 자동차 이름과 이동 횟수를 입력 받고 유효성 검증 후, 각 자동차의 점수판을 초기화합니다.
async function initializeGame() {
const playerNames = await getPlayerNames();
validatePlayerNames(playerNames);
const moveCountInput = await Console.readLineAsync(MESSAGES.INPUT_MOVE_COUNT);
validateMoveCount(moveCountInput);
const moveCount = Number(moveCountInput);
const playerScores = createScoreBoard(playerNames);
return { playerScores, moveCount };
}runGame함수는 입력받은 횟수만큼 게임을 진행합니다. 각 라운드가 끝날 때마다자동차의 전진 여부를 판단하고 점수를 업데이트하고 우승자를 판별합니다.
function runGame(playerScores, moveCount) {
playRounds(playerScores, moveCount);
Console.print(`${MESSAGES.WINNER_MESSAGE}${findWinners(playerScores)}`);
}무작위 값이 4 이상인 경우에만 전진하며, 전진 여부에 따라 플레이어 점수를 갱신합니다.
function playGame(player) {
if (Random.pickNumberInRange(0, 9) >= GAME_SETTINGS.MIN_SUCCESS_SCORE) {
player.score += 1;
}
}- 모든 라운드가 종료되면
최고 점수를 획득한 자동차를 기준으로 최종 우승자를 판별합니다. - 공동 우승을 허용합니다.
function findWinners(playerScores) {
const maxScore = Math.max(...playerScores.map((player) => player.score));
return playerScores
.filter((player) => player.score === maxScore)
.map((player) => player.name)
.join(GAME_SETTINGS.PLAYER_NAME_DELIMITER);
}- 단위 테스트(Unit Testing)를 통해 예외 상황과 함수 동작을 검증했습니다.
- 테스트는
Jest를 사용했으며, 다음과 같은 주요 함수를 테스트했습니다.
- 게임 초기화 테스트
-
유효한 자동차 이름과 이동 횟수 입력에 대해 초기화가 이루어지고 그렇지 않은 입력에 에러가 발생하는지 검증합니다. -
자동차 이름
- 5자 이하이며 쉼표로 구분
- 허용 가능한 특수문자는
-_!: - 중간 공백은 인정되나 닉네임 앞뒤 공백은 이름에서 제외
return userInput.split(DELIMITER).map((e) => e.trim());expect(validatePlayerNames(['minda', 'sim?', 'java'])).toThrow(
ERROR_MESSAGES.INVALID_PLAYER_NAME
);- 이동 횟수
- 양의 정수만 허용
expect(validateMoveCount('-1')).toThrow(ERROR_MESSAGES.INVALID_MOVE_COUNT);- 게임 진행 로직
- 주어진 이동 횟수만큼 라운드가 진행되며, 라운드 결과가
올바르게 출력되는지 검증합니다. - 테스트 시나리오
- 이동 횟수가 3회라면 3번의 라운드가 반복되어 각 라운드별로 전진 결과 출력
- 각 라운드 종료 시 모든 자동차의 점수판이 올바르게 기록되는지 확인
const inputs = ['minda,marge,lisa', '3'];
const randomValues = [5, 3, 4, 6, 2, 7, 9, 2, 8];
const expectedLogs = [
'minda : -',
'marge : ',
'lisa : -',
'\n',
'minda : --',
'marge : ',
'lisa : --',
'\n',
'minda : ---',
'marge : ',
'lisa : ---',
'\n',
`${MESSAGES.WINNER_MESSAGE}minda, lisa`,
];
expectedLogs.forEach((log) => {
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(log));
});- 전진 조건
- 무작위 숫자가
4 이상일 때만자동차가 전진하는지 테스트합니다. - 테스트 시나리오
- 4 이상일 때만 점수가 1 증가
- 3 이하일 때는 정수가 변하지 않음
jest
.spyOn(MissionUtils.Random, 'pickNumberInRange')
.mockReturnValue(GAME_SETTINGS.MIN_SUCCESS_SCORE);
playGame(car);
expect(car.score).toBe(1);- 우승자 판별 검증
-
게임 종료 후 최고 점수에 따라 우승자가 올바르게 판별되는지, 공동 우승자가 출력되는지 검증합니다.
-
시나리오
- 단일 우승자
minda가 최고 점수를 획득한 경우 최종 우승자는minda
const playerScores = [ { name: 'minda', score: 3 }, { name: 'marge', score: 1 }, { name: 'lisa', score: 0 }, ]; const winner = findWinners(playerScores); expect(winner).toBe('minda');
- 공동 우승자
marge와lisa가 최고 점수를 획득한 경우, 두 이름이 쉼표로 구분되어 출력
const playerScores = [ { name: 'minda', score: 1 }, { name: 'marge', score: 3 }, { name: 'lisa', score: 3 }, ]; const winners = findWinners(playerScores); expect(winners).toBe('marge, lisa');
- 단일 우승자
다음 명령어로 실행할 수 있습니다.
npm run test