[JavaScript] 미니게임 프로젝트 | 숫자 야구⚾

승연·2022년 7월 19일
2

Game World

목록 보기
6/6
post-thumbnail

Game World


미니 프로젝트 대망의 마지막 게임으로 숫자 야구 게임을 만들었습니다.

🙋‍♀️ 게임 설명 좀 해주세요

감춰진 4자리 숫자를 9회 안에 맞추는 게임입니다.

🤔 어떤 기능이 있나요?

  • 숫자 맞추기
    • 사용자는 9회 안에 컴퓨터가 무작위로 정한 4자리 숫자를 맞춰야 한다.

🔎 사용 기술은 무엇인가요?

HTML, CSS, JavaScript를 이용하여 만들었습니다.

🙊 어디서 해볼 수 있나요?

https://sypear.github.io/game-world/game-bac.html



Game World - 숫자 야구⚾


1. 순서도 그리기




2. 숫자만 입력할 수 있도록 하기

formInputWrapper.addEventListener("keyup", function(e) {
  ...
  
  const regExp = /[^0-9]/g;

  if (regExp.test(e.target.value)) {
    e.target.value = "";
  }
  
  ...
}

정규식을 이용하여 keyup 이벤트 발생 시 입력값이 0~9가 아니면 값을 공백으로 변경하도록 했습니다.




3. 확인 버튼 클릭 시 입력값 체크

확인 버튼 클릭 시 4개의 input 값 중
빈값이 하나라도 있는지, 중복되는 값이 있는지를 체크하도록 했습니다.


3-1. 빈값 체크

// input value들을 변수에 저장
let numArr = [num1.value, num2.value, num3.value, num4.value];

// 빈값 체크
for (let i = 0; i < ANSWER_SIZE; i++) {
  if (!numArr[i])
    showAlert("숫자를 전부 입력해주세요.");
  	return;
	}
}

빈값 체크는 input value들을 배열에 넣은 후, 반복문을 돌리면서 배열의 값 중 Falsy 값이 있다면 빈 값이 있는 것으로 판단했습니다.

공백 값 입력 후 콘솔에 찍었을 때, 실제로는
빈 문자열('')로 출력되고 있어 조건문을 if (numArr[i] === "")으로 작성해도 문제없이 동작했지만, false로 반환 되는 다른 값이 들어올 경우도 생각하여 Falsy 값일 때 전부 조건문에 걸리도록 작성하였습니다. (Falsy 값의 종류 참고 페이지)


3-2. 중복 값 체크

// 중복 체크
let numSet = new Set(numArr);

if (numArr.length > numSet.size) 
  showAlert("중복된 숫자가 있어요!");
  return;
}

중복 값 체크는 중복을 허용하지 않는 Set 객체를 이용하여 구현했습니다.
input value들을 저장하고 있는 배열을 새로 만든 Set 객체에 대입하였고, 기존 배열과 Set 객체의 크기가 똑같은지 체크하였습니다.

만약 Set 객체의 크기가 기존 배열보다 작다면 중복 값이 있다는 뜻이므로 중복 값이 있는 것으로 판단했습니다.




4. 아웃/스트라이크/볼 판단하기

4-1. 아웃

function checkUserOut(userInputArr) {
    for (let i = 0; i < ANSWER_SIZE; i++) {
        if (answer.indexOf(userInputArr[i]) !== -1) {
            return false;
        };
    }

    return true;
}

indexOf() 메소드를 이용해서 정답 배열 안에 사용자가 입력한 값이 하나도 없다면 아웃으로 처리했습니다.


4-2. 스트라이크/볼

function checkHit(userInputArr) {
    let result = { ball: 0, strike: 0 };

    for (let i = 0; i < ANSWER_SIZE; i++) {
        if (answer.indexOf(userInputArr[i]) !== -1) {
            // 스트라이크인지 볼인지 체크
            if (answer.indexOf(userInputArr[i]) === i) {
                result.strike++;
            } else {
                result.ball++;
            }
        }
    }

    return result;
}

indexOf() 메소드를 이용하여 정답 배열 안에 사용자가 입력한 값이 있는 경우
정답의 인덱스와 사용자 입력값의 인덱스가 같다면 스트라이크로, 같지 않다면 볼로 처리했습니다.




5. 승리/패배 판단하기

5-1. 승리

4스트라이크 시, 승리로 판단했습니다.

5-2. 패배

4스트라이크를 하지 못한 상태이면서 회차가 9회일 때, 패배로 판단했습니다.




6. 사용자를 위한 기능 ✨

숫자 야구 로직 구현과는 무관하지만, 사용자를 위한 기능들을 넣어 보았습니다.


6-1. 숫자 야구 규칙 모달창

숫자 야구 규칙을 까먹었거나, 처음 해보는 사용자들을 위해 메뉴 좌측 인포 아이콘을 클릭하면 규칙을 확인할 수 있도록 했습니다.

친구가 숫자 야구 게임을 하다가 규칙을 헷갈려 하길래 인포 아이콘을 눌러보라고 말해줬습니다. (뿌듯)


가독성을 위해 단어 단위로 줄 바꿈을 하고 싶어서 CSS의 word-break: keep-all 속성을 이용했습니다.

  • word-break : CSS word-break 속성은 텍스트가 자신의 콘텐츠 박스 밖으로 오버플로 할 때 줄을 바꿀 지 지정합니다.
  • kepp-all 값 : 한중일(CJK) 텍스트에서는 줄을 바꿀 때 단어를 끊지 않습니다.

  • 출처 : [MDN] word-break

6-2. 모바일에서는 숫자 키패드가 나오도록

HTML의 inputmode = "numeric" 속성을 이용하여 숫자 키패드가 나오도록 하였습니다.

  • inputmode : 사용자가 요소나 요소의 콘텐츠를 편집할 때 입력할 수 있는 데이터 유형의 힌트를 제공하는 열거형 특성입니다.
  • text (기본값) : 사용자의 현재 로케일에 맞는 표준 키보드를 제공합니다.
  • numeric 값 : 숫자 형 키보드를 제공합니다. 소수점은 없으며, 음의 부호는 제공할 수도, 제공하지 않을 수도 있습니다.

  • 출처 : [MDN] inputmode

6-3. 값 입력 시 자동으로 다음 필드로 이동하도록

if (e.target.value.length === 1 && e.target.nextElementSibling) {
	e.target.nextElementSibling.focus();
}

keyup 이벤트 발생 시 input value가 입력된 상태이고 다음 필드가 존재하는 경우, 포커스를 자동으로 다음 필드로 옮기도록 구현했습니다.


6-4. 엔터키로 결과 확인 모달창 띄우기/닫기를 할 수 있도록

if (e.code === "Enter" && isShowAlertModal === false) {
	checkInput();
}

엔터키가 입력되었을 때 결과 확인을 진행하도록 했습니다.

그리고 엔터키로 결과 확인 모달창을 닫을 수 있게

// 엔터키 클릭으로 모달창 닫기
document.addEventListener("keydown", function(e) {
    if (alertModal.classList.contains("show")) {
        if (e.code === "Enter" && isShowAlertModal === true) {
            alertModal.classList.remove("show");
        }
    }
});

결과 확인 모달창이 열려있는 경우, 엔터키를 입력했을 때 모달창을 닫도록 하였습니다.

이때, 모달창 열기/닫기를 엔터키로 함께 사용하게 되면서
모달창을 닫기 위해 엔터키를 눌렀는데 바로 모달창이 열려버려서 의도와 다르게😥 모달창이 계속해서 뜨는 장애가 발생했습니다.

해당 장애 해결을 위해서 isShowAlertModal 라는 플래그 값을 만들어 모달창이 열렸을 때 true, 닫혔을 때 false를 저장하도록 했습니다.

플래그 값 추가 후 장애가 해결된 모습입니다.




마치는 글

드디어 JavaScript 미니게임 프로젝트가 끝났습니다.

간단한 사이트지만 기획부터 기능 구현까지 스스로 해보면서 HTML/CSS, JavaScript와 좀 더 친해질 수 있었습니다. 😊


🌈 느낀 점

사용자가 가장 좋아하는 기능은 내가 가장 공들인 기능이 아닐 수 있다.
잘 만든 기능은 열심히 만든 기능이 아니라, 사용자가 좋아하는 기능이다.

프로젝트를 진행하면서 가장 오랜 시간이 들었고, 가장 어려웠고, 또 가장 공들여서 만든 게임이 카드 짝 맞추기 게임이었습니다.
그래서 저에게는 제일 애착이 가는 게임인데요.
슬프게도 인기가 정말 없었습니다. (오히려 지루하다는 평이 많아서 마음이 아팠던..😥)

가장 인기가 많았던 게임은 상대적으로 금방 만들었던 다른 색깔 찾기였습니다.
다른 색깔 찾기 신기록을 세웠다는 카톡이 지금까지도 오고 있습니다. (이렇게 인기가 많을 줄이야)
'사용자의 니즈가 가장 중요하다'라는 말을 굉~장히 많이 들어왔는데요, '당연히 중요하지!' 라고 생각은 해왔었는데 사실 직접적으로 느껴보지는 못했었습니다.

그런데 이번 프로젝트를 진행하면서 주변 사람들에게 게임을 보여주고 피드백을 듣는 과정을 통해
수백 시간을 고민해서 수천 시간동안 만든 서비스라도 사용자가 원하지 않는 것이라면 모든 노력이 물거품이 될 수 있겠구나..라는 것을 느꼈습니다.


마지막으로

미니게임 프로젝트 아이디어를 얻는 데 많은 도움이 된 웹 프론트엔드 공부법 - 입문자편 <커리큘럼> 글을 써주신 teo님께 감사드립니다.

profile
✈️ https://sypear.tistory.com/

2개의 댓글

comment-user-thumbnail
2022년 10월 23일

와!!! 너무너무 감사합니다 +_+ 제가 생각했던 커리큘럼을 이렇게 기대이상으로 다 해주는 분이 있다니 놀랍네요!! 고맙습니다. 서비스 기획력부터 완성도랑 깨알 디테일, 설계나 사고하는 순서 블로그 정리력까지 너무 너무 멋져요!!

1개의 답글