Vanilla JS로 숫자 야구 게임 만들기! - 2

Solmii·2020년 5월 5일
0

Project

목록 보기
3/14
post-thumbnail
post-custom-banner

4주차에 구현한 기능은...!

  1. 남은 기회 표시 => 정답이나 오답 시 멘트 변경
  2. 여태껏 입력했던 숫자와 힌트가 사라지지 않고 정답 입력창 아래에 계속 추가
  3. 홈런, 게임 오버 후 도전 버튼 더이상 동작 안하게!
  4. 정답자가 입력한 숫자에 중복이 있으면 "중복되지 않는 숫자를 입력해주세요." 출력

구현 못한😭 기능은

  1. 스트라이크와 볼이 하나도 없을때 (0S 0B)일때 OUT!! 이라고 표시
  2. 3OUT이 넘어가면, 기회가 남아있어도 바로 게임 오버

slice 메서드

splice 메서드는 특정 배열의 요소를 잘라내거나 추가하는데, 잘라낼때 원본 배열에서는 해당 요소가 삭제된다. (ctrl + x) 느낌!!

반면에 slice 는 어떤 배열에서 복사한 요소를 새로운 배열 객체로 반환하고, 원본 배열은 바뀌지 않는다. (ctrl + c) 느낌!

const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2)); // ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4)); // ["camel", "duck"]
  1. ( ) 안에 숫자 하나만 입력할 경우, 그 위치 이후로 모든 요소를 선택!
  2. 2개 이상의 숫자를 입력할 경우, array.slice( start, end ) 로 동작하여,
    start에 해당하는 요소부터 end 바로 전의 요소까지를 선택하여 새로운 배열을 만

sort 메서드

배열의 요소를 적절한 위치에 정렬한 후 그 배열을 반환한다.
(기본 정렬 순서는 유니코드 코드 포인트를 따른다 = ㄱㄴㄷ, ABC, 123 순)

const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months); // ["Dec", "Feb", "Jan", "March"]

const number = [1, 30, 4, 21, 100000];
number.sort();
console.log(number); // [1, 100000, 21, 30, 4]

map 메서드

const guess = gameInput.value;
const guessList = guess.split("").map(Number);

gameInput 에 정답자가 1234 를 입력 ⇒
"1", "2", "3", "4" 4개의 문자열 X
["1", "2", "3", "4"] 문자 배열 X

"1234" 하나의 문자열로 데이터가 들어온다!

guess.split("") 으로 각 음절마다 분리된 4개의 문자 배열로 만들어 준다.

그리고 이 문자 배열을 .map(Number); 메서드를 이용해 숫자 배열로 변경!


Node.textContent property

innerHTML

logList.innerHTML += `<li>${count}번째 도전 <span class="point">${guess}</span> : ${strike}S ${ball}B</li>`;

Element 속성(property) innerHTML 은 요소(element) 내에 포함 된 HTML 또는 XML 마크업을 가져오거나 설정한다.
text/html으로 파싱(Parsing)되며, 큰 차이는 없으나 아래 2개의 프로퍼티에 비해 파싱이 느리다.

예제 처럼 <li>, <span> 등의 태그를 가져올 수 있고, JavaScript 내의 요소도 당연히 출력할 수 있다!

단! innerHTML 은 파싱이 느리고, XSS(Cross-Site Scripting) 공격(해커가 웹페이지에 악성 스크립트를 삽입) 에 취약한 사례로 언급된다.

이런 보안 문제에 대해 모르고 innerHTML 를 사용했으나, 벨로그 정리하면서 다시 한번 찾아보니 이런 문제가 있었다....😭
시간이 나면 다른 방법으로 코딩해서 수정할 예정!

textContent

paintAnswer.textContent = `${answer}`;

text/plain 으로 파싱한 결과이다.
다른 프로퍼티들에 비해 파싱이 빠르고, 보안도 좋다.

해당 text의 가공되지 않은 모습을 받아오기 때문에 이후에 자유롭게 가공할 수 있다.

innerText

gameHint.innerText = "Game Over!!";

text/plain 으로 파싱한 결과이다.
textContent 와의 차이점은,

  1. 원시 텍스트가 최종적으로 화면에 렌더링 된 모습(내용 숨김이나 줄바꿈 같이 의도적인 스타일링)으로 출력
  2. 다른 브라우저보다 IE 환경에서 성능이 더 좋다.

⇒ 특별히 스타일 적용이 없는 문자열이거나 IE 환경 중심이 아니라면 textContent 를 쓰는게 좋다.


중복 체크할때 사용한 Set

  • ES2015 (ES6) 부터 등장한 새로운 data object
const findDuplicate = Array.from(new Set(guessList));
  if (findDuplicate.length < 4) {
    alert("중복되지 않는 숫자를 입력해주세요.");
  }

⇒ 중복되는 숫자를 제거하는 방법에는 Set, Filter, Reduce 등이 있다.
이 중에서, Set을 이용하여 중복 숫자를 체크해보았다.

Set() : 유니크한 값만 저장할 수 있도록 하기 때문에, 배열에서 넣게 되면 중복되는 값이 사라진다.

Array.from() : 유사 배열 객체(array-like object)나반복 가능한 객체(iterable object)를 복사해 새로운 Array 객체를 만든다.

  1. findDuplicate 이라는 상수를 지정해주고, Array.from() 으로 guessList 배열(정답자가 입력한 정답 string을 음절단위로 쪼개고 number로 바꾼 배열)을 복사해준다.

  2. 이 때, new Set 키워드를 이용해서 guessList 배열 안에서 중복되는 값이 있을 경우 삭제하고, 유니크한 값만 남긴채 복사한다.

  3. findDuplicatelength 를 비교한다.

    3-1. length ≥ 4 라면 중복되는 값이 없고 유니크한 값이 4개라는 뜻이니 다음 함수로 넘긴다.

    3-2. length < 4 라면 중복되는 값이 제거되고 남은 유니크한 값이 4개 미만이라는 뜻이니 "중복되지 않는 숫자를 입력해주세요." 라는 경고창을 출력한다.


window.open()

<button onclick="showPopup();">게임 방법</button>

HTML 에서 button 을 만들고, onclick 이벤트를 이용해서 클릭시, showPopup() 함수가 실행되는 버튼을 만들다.

function showPopup() {
  window.open( 
    "rule_popup.html", // url
    "game_rule_popup", // name
    "width=500, height=700, left=100, top=100" // specs
  );
}

그리고 JavaScript 에서 showPopup() 함수 정의!

그리고 페이지를 새창에서 열 수 있게 해주는 JS에 내장된 window 객체의 open() 함수를 사용했다.

window.open(url, name, specs, replace); 으로 사용하며,

url : 새창에서 열리는 페이지의 주소. 값을 비워두면 빈창(about:blank)이 보인다.

name : 페이지의 이름 혹은 속성을 정할수도 있다. 속성의 종류는

_blank : 새 창에 열린다. (기본값)
_parent : 부모 프레임에 열린다.
_self : 현재 페이지를 대체
_top : 로드된 프레임셋을 대체
name(임의의 이름) : 새 창이 열리고 창의 이름을 지정.
동일한 이름에 다시 open() 을 하면 기존의 열린창의 내용이 바뀌고, 다른 이름을 사용하면 또다른 새창이 열립니다.

specs : 창의 크기, 스크롤여부, 리사이즈 가능등의 속성을 지정

channelmode=yes|no|1|0 : 전체화면으로 창이 열린다. (IE만 동작)
directories=yes|no|1|0 : 디렉토리 버튼의 표시여부인데, 사용되지 않는다.
fullscreen=yes|no|1|0 : 전체 화면 모드 (IE만 동작)
height=pixels : 창의 높이를 지정 (height=500)
width=pixels : 창의 너비를 지정 (width=700)
left=pixels : 창의 화면 왼쪽에서의 위치를 지정, 음수 사용불가
top=pixels : 창의 화면 위쪽에서의 위치를 지정, 음수 사용불가
location=yes|no|1|0 : 주소 표시줄 사용여부를 지정 (Opera만 동작)
menubar=yes|no|1|0 : 메뉴바 사용여부를 지정
resizable=yes|no|1|0 : 창의 리사이즈 가능 여부를 지정 (IE만 동작)
scrollbars=yes|no|1|0 : 스크롤바 사용 여부를 지정 (IE, Firefox, Opera 동작)
status=yes|no|1|0 : 상태바를 보여줄지 지정
titlebar=yes|no|1|0 : 타이틀바를 보여줄지 지정
호출 응용 프로그램이 HTML 응용 프로그램이거나 신뢰할 수있는 대화 상자가 아니면 무시된다.
toolbar=yes|no|1|0 : 툴바를 보여줄지 지정 (IE, Firefox 동작)

replace : 히스토리 목록에 새 항목을 만들지 현재 항목을 대체할지 지정

(true : 현재 히스토리를 대체, false : 히스토리에 새 항목을 만듬)

profile
하루는 치열하게 인생은 여유롭게
post-custom-banner

0개의 댓글