pc와의 가위바위보에서 승리해 점수를 얻는 게임
좋은 코드는 아니지만 시나리오에 따라서 정리해볼게요. ^^
가위는 1, 바위는 2, 보는 3으로 지정해 pc가 1,2,3중 하나를 랜덤으로 선택할 수 있도록 해줍니다.
pcPlayerSelection = Math.floor(Math.random() * 3 + 1);
Math.random() * 3 + 1 으로 0부터가 아니라 1부터 나오도록 해주고,전체에 Math.floor를 씌어 정수값만 나오도록 해줬습니다.
이후, 랜덤으로 정해진 pcPlayerSelection에 따라 이미지가 변경될 수 있도록 알맞은 이미지를 넣어줍니다.
function changePcPlayer() {
pcPlayerSelection = Math.floor(Math.random() * 3 + 1);
//가위
if (pcPlayerSelection == 1) {
pc_img.src = 'img/scissor.png';
}
//바위
else if (pcPlayerSelection == 2) {
pc_img.src = 'img/rock.png';
}
//보
else if (pcPlayerSelection == 3) {
pc_img.src = 'img/paper.png';
}
}
setInterval()을 사용해 위의 changePcPlayer()함수를 특정시간마다 호출해
pc 선택지를 계속해서 랜덤으로 바꿀 수 있도록 해줍니다.
let interval = 0;
let speed = 490; // 0.49초
//페이지에 자동으로 그려짐
window.onload = function () {
interval = setInterval(changePcPlayer, speed);
};
일단 가위, 바위, 보 3개의 버튼을 만들어줍니다. 게임스러움을 위해 귀여운 이모지도 옆에 같이 넣어봤어요.
<div class="player_button">
<input type="button" id="scissors" value="가위 ✌" />
<input type="button" id="rock" value="바위 ✊" />
<input type="button" id="paper" value="보 ✋" />
</div>
사용자 선택지를 만들고 확인하는 것은 너무 쉽죠? 사용자가 어떤 버튼을 눌렀는지만 확인해주면 됩니다. 이를 위해 3가지 버튼에 value값을 사용해 줍니다.
const player_button = document.querySelector('.player_button');
let playerSelection = 0;
// 플레이어 선택 계산하는 함수
player_button.addEventListener('click', function (e) {
if (e.target.value == '가위 ✌') {
playerSelection = 1;
player_img.src = 'img/scissor.png';
} else if (e.target.value == '바위 ✊') {
playerSelection = 2;
player_img.src = 'img/rock.png';
} else if (e.target.value == '보 ✋') {
playerSelection = 3;
player_img.src = 'img/paper.png';
}
rockPaperScissor(playerSelection);
});
addEventListener로 click 이벤트를 기다리고, click시에 e.target.value를 확인해 선택지를 playerSelection에 넣어줍니다.
이후 사용자의 선택값을 가위바위보 메인 함수로 보내줍니다.
사용자가 버튼을 선택하기 전까지, pc의 선택은 setInterval()을 통해 특정시간마다 추출되고 있습니다. 사용자 선택이 결정된 순간 setInterval()을 멈춰주면 그 순간의 pc 선택을 추출해올 수 있겠죠?
clearInterval(interval);
clearInterval()을 호출해 인터벌을 끝내주면, pcPlayerSelection에는 pc의 선택값이 들어가게 됩니다.
pc선택값과 사용자 선택값을 얻어낸 이후에 두 선택지를 비교해 승패를 결정하면 끝입니다!
1) 무승부
if(result === 0) {
return 0;
}
2) 승리
else if (result == 1 || result == -2) {
...
}
3) 패배
else if (result == 2 || result == -1) {
...
}
가위바위보에 승리에 다음 라운드로 이동 시에 pc 선택지 변환 속도가 조금씩 더 빨라지도록 만들었습니다.
말도 안 되게 빠른 변환은 막기 위해 maxSpeed를 사용해 줬습니다.
let speed = 490; // 0.5초
let maxSpeed = 90;
//이겼을시에
if (speed > maxSpeed) {
speed = speed - 30; //승리시에만 속도 올라감
}
//졌을시에는 그대로
이겼을 시에만 0.3초씩 감소하게 지정해 줬습니다.
한 라운드가 지날 때마다 승패와 같은 게임 정보를 모달창에 보여줄 수 있도록 만들었습니다.
모달창을 어떻게 만드는지 조차 몰랐던 나.. 반성하면서 열심히 검색했습니다🙄
<div class="modal" id="rps-modal">
<div class="modal-content"> </div>
</div>
모달창 기본 구조는 위와 같습니다. 뒷 화면 전체를 모달로 덮기 위한 modal과 실질적으로 정보를 담아낼 modal-content를 만들어줬습니다.
모달이 띄워지는 순간 뒷 배경은 흐려지고 클릭될 수 없어야 하며, 모달 컨텐츠는 중앙으로 배치되어야 합니다.
.modal {
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: rgba(0, 0, 0, 0.4);
display: none;
}
항상 고정된 위치에서 뒷배경을 덮어야 하기에 position: fixed;와 z-index: 1;을 줍니다. 뒷 배경 전체를 덮을 수 있게 width, height를 100%로 주고 스크롤을 막아줬습니다.
z-index의 default값은 0이고, 우리는 모달창에 1을 줬기에 배경보다 한층 위에 있다고 생각해 주면 됩니다.
display: none;
게임 진행 중에는 모달이 보이지 않아야 하기에 display: none;을 지정했습니다. 게임이 끝날 때 display: block;으로 보이도록 해주세요.
.modal-content {
margin: 15% auto;
}
margin: 15% auto;로 모달 콘텐츠를 화면 중앙으로 정렬합니다. 위아래에는 15% margin을 주고, auto로는 가로 중앙 정렬을 해주는 코드입니다.
가위바위보 게임 결과를 매개변수로 받아 모달창안에 바로 결과를 삽입하는 함수를 만들어 구현했습니다.
매 라운드마다 같은 모달창에 다른 내용을 그려내기 위해 innerHtml을 사용했습니다.
//게임결과를 모달에 그리는 함수
function paintResult(result, player, pc) {
modal_text.innerHTML = `
<h2 class="rps_result">Score : ${playerScore}점</h2>`;
modal.style.display = 'block';
}
모달창이 띄워지고 5초 뒤에 자동으로 닫힐 수 있는 기능을 구현하고 싶었습니다.
모달창을 닫는 건 display = 'none'으로 해주면 되는데 1초씩 감소하는 건 어떻게 인식할까??
생각해 보니 타이머랑 같은 원리더라구요 (당연함
setinterval을 사용해 1초씩 감소할 때마다 남은 시간을 정정해 주고 0초가 되면 모달창이 닫히도록 해줬습니다.
let time = 5; // 모달창 시간
const modal_time = document.querySelector('#time');
let modal_close = 0;
//모달창 자동 닫히게 하는 함수
function closeModal() {
modal_time.innerText = time;
modal_close = setInterval(function () {
modal_time.innerText = --time; //1초씩 마이너스
if (time === 0) {
// 0초가 되면 모달창 숨김
modal.style.display = 'none';
restartGame();//게임 재시작
}
}, 1000);
}
게임을 진행하다 보니 계속 타이머에서 오류가 생기더라고요..? 알고 보니 타이머를 계속 작동시키기만 하고 타이머를 끄지를 않았어요 ㅋㅋ
clearInterval(modal_close);
만든 타이머는 꼭 clearInterval() 해주세요.
//모달창 닫기 버튼이나, 모달창 바깥부분을 클릭하면 모달창이 닫힘
modal.addEventListener('click', (e) => {
const target = e.target;
if (target === modal || target === modal_closeBtn) {
modal.style.display = 'none';
restartGame();
}
});
모달창 관리하는 것 !!
처음 내 계획은 모달창을 컴포넌트로 만들고 css를 적용해 관리하는 것이었다. 막상 만들어보니 게임마다 적용할 크기가 제각각이어서 냅다 아이디와 클래스를 덕지덕지 붙이는 나를 볼 수 있었다.
결과는 엉망진창 코드 .. 😓