주사위 던지기 게임

Ji Hyeok Im·2023년 3월 2일
0

Javascript

목록 보기
7/17

다음과 같이 위쪽 버튼을 클릭하면 1 ~ 6 의 값을 가지는 주사위를 던져 그 값을 확인할 수 있고

아래쪽 버튼을 클릭하면 주사위 눈의 합이 51 이상이 될때까지 반복해서 주사위를 던져

점수를 생성한 결과가 표시되는 웹 페이지를 만드려고 한다.

주사위 던지기 로직

버튼을 클릭하면 랜덤으로 생성되는 1 ~ 6 사이의 정수값을 반환받아 결과창에 표시한다.

첫번째 버튼을 클릭할 때 실행되는 함수(1)을 생성하고 그 안에서 Math.random() 함수를 실행해

그 실행 결과로부터 정수값을 반환받아 결과창에 출력한다.

재차 버튼 클릭시 함수가 새로 실행되어 실행시마다 다른 결과를 받아볼 수 있도록 한다.

그 아래에는 클릭하면 51점 이상의 점수를 생성하는 함수(2)를 실행할 두번째 버튼을 추가한다.

이 버튼 클릭시 실행되는 함수(2)는 Math.random() 함수로부터 반환받은

1 ~ 6사이의 정수값들을 그 합이 51이 넘을 때까지 반복문을 통해 더한다.

주사위를 굴린 횟수를 i 라고 놓을 때 결과창에 주사위를 i 번 굴려 획득한 값들의 합계를 표시한다.

코드 구현하기

주사위를 굴린 값이 저장될 변수는 함수(1)과 함수(2)에서 모두 쓰인다.

따라서 가장 먼저 이 값을 담을 변수 diceNum을 전역 변수로 선언하고 아직 값을 알 수 없으므로 null로 초기화한다.

그 후 랜덤으로 1 ~ 6 사이의 정수값을 생성해 변수 diceNum에 반환하는 기능을 수행할 전역함수 getDiceNum()을 생성한다.

이 getDiceNum() 함수는 생성 위치에 유의해야 하는데 함수(1)과 함수(2)에서 동작 횟수가 다르기 때문이다.

함수(1)에서는 클릭시 한번 실행되는 것으로 끝이지만

함수(2)에서는 반복해서 주사위를 던질 때마다 랜덤한 값을 생성해야 하므로 여러번 실행되어야 한다.

때문에 전역함수로 생성해서 다른 함수의 내부에서 필요할때마다 실행문으로 호출하는 것이 깔끔하다.

함수(1) : 주사위 던지기

첫번째 버튼을 클릭했을 때 실행될 함수 diceRoll()을 생성한다.

함수 내부에는 결과값을 출력할 div 요소의 속성을 가져올 변수 diceResult를 선언해둔다.

그 후 전역함수 getDiceNum() 함수의 실행문을 작성해 변수 diceNum에 값이 저장되게 한다.

이후 결과 값을 출력받을 변수 diceResult의 innerHTML 속성에 diceNum의 값을 출력한다.

추가로 결과문을 "diceNum이 나왔습니다" 와 같이 작성하려고 할 때,

1,3,6 일때는 "이 나왔습니다" 가 자연스럽고 2,4,5 일때는 "가 나왔습니다" 가 자연스럽다.

문장을 "이(가)" 로 수정해도 무방하지만 문자열 "이" 또는 "가" 를 대입할 변수 postStr을 새로 선언해서

if - else문을 통해 알맞은 문자열 값이 대입되도록 한다.

함수(2) : 51점 이상의 점수 생성하기

다음으로 두번째 버튼을 클릭했을 때 실행될 함수 sumDiceRoll()을 생성한다.

먼저 주사위 눈들을 더한 값을 저장할 변수 sumDiceNum을 선언해두고

함수 실행 전에는 아직 더해 받은 값이 없으니 0으로 초기화해둔다.

주사위를 굴린 횟수인 변수 i 또한 함수 실행 전에는 0회 이므로 0으로 선언 및 초기화한다.

그리고 역시 결과값을 출력받을 div요소의 속성값을 가져올 변수 sumDiceResult를 선언해둔다.

그 후 반복문을 작성한다. 주사위 눈의 값에 따라 굴리는 횟수는 얼마든지 달라질 수 있으므로

횟수 기반 반복에 사용하는 for 문보다 조건을 만족하는 동안은 횟수에 관계없이 반복되는 while 문을 이용하는 것이 편리하다.

while 문의 조건식은 주사위 눈의 합계인 sumDiceNum이 51보다 작을 때로 설정해서

sumDiceNum이 51보다 크거나 같아지는 회차의 실행이 끝나면 while문을 빠져나오게 한다.

while 문의 실행문에는 반복회차마다 주사위 값을 새롭게 생성하도록 getDiceNum() 함수의 실행문을 적고

sumDiceNum += diceNum; 으로 생성된 주사위 값을 계속 더한다.

이것이 반복될 때마다 주사위를 굴린 횟수인 변수 i를 1씩 증가시킨다.

while문의 실행이 종료되면 변수 sumDiceNum에 51보다 크거나 같은 값이 대입되어 있을 것이므로

변수 sumDiceResult의 innerHTML 속성에 횟수 i 와 합계 sumDiceNum을 출력한다.

1차 수정

결과문 출력시 각 주사위 눈의 값을 열거하도록 하고 싶다.

while문의 반복때마다 생성되는 diceNum의 값을 열거하려면 반복회차마다 값들의 마지막에 추가되도록 해야 한다.

( ... , n-1회차 diceNum, n회차 diceNum)

이를 위해 먼저 빈 배열인 diceArr를 선언하고 while문 안에서 .push 메서드를 이용해

각 회차 diceNum의 값을 배열 diceArr에 추가한다.

이제 for - of 문을 사용해서 배열의 값을 모두 알 수 있다.

조건문 안에서 배열의 값을 담을 변수인 eachDiceNum을 선언하고

새로 div#eachDiceResult 요소와 그 속성값을 가져올 변수 eachDiceResult를 추가해서

변수의 innerHTML 속성에 += (eachDiceNum + ", ") 시킨다.

eachDiceNum의 타입이 number 이더라도 뒤에 ", " 를 같이 더하면 타입 변환 없이도 문자열의 더하기 형식으로 추가될 것이다.

여기서 마치면 대입연산자로 += 을 줬기 때문에 버튼을 재차 클릭했을 때 기존에 열거된 값들 뒤로

새로 주사위를 굴린 값들이 더해지게 되는 문제가 발생한다.

이를 방지하기 위해 for - of 문 위로 변수 eachDiceResult의 innerHTML 에 빈 문자열을 먼저 대입하도록 해서

실행 순서상 기존 값들이 지워지고 새 값들이 표시되도록 한다.

2차 수정

정상적으로 실행되지만 for - of의 실행문 마지막에 더한 ", " 때문에 마지막 숫자 뒤에도 ", " 가 붙는 것이 거슬린다.

for - of 문을 폐기하고 대신 for 문을 사용해 문제를 해결한다.

마지막 숫자 뒤에 ", " 가 붙지 않게 하려면 마지막 직전 회차까지는 ", " 를 더하고,

마지막 회차에선 ", " 를 빼고 배열의 값만 더하도록 하면 된다.

그러기 위해선 마지막 직전 회차와 마지막 회차의 배열 인덱스를 알아야 한다.

주사위를 굴린 횟수인 i 만큼 배열 요소의 개수가 있을 것이므로

마지막 배열은 diceArr[ ( i - 1 ) ] 이 될 것이고 이 배열의 인덱스는 ( i - 1) 이다.

for 문의 조건식 안에서 배열의 마지막 직전 회차까지의 인덱스 값을 담을 변수인 변수 j를 선언하고

변수 j는 0부터 ( i - 1 ) 보다 작은 값을 가지는 동안 1씩 증가하는 조건을 준다.

for 문의 실행문으로 마지막 직전 회차의 배열인 diceArr[ j ] 까지의 값을 추가하도록 하고

for 문을 빠져 나와서 마지막 회차의 배열인 diceArr [ ( i - 1 ) ] 의 값을 따로 추가한다.

3차 수정

Array 메서드 join() 을 사용하면 코드 한줄로도 같은 효과 구현이 가능하다.

실행 화면


profile
Programming study

0개의 댓글