코딩하는라민

렛츠기릿 자바스크립트 #5 끝말잇기 게임 만들기 본문

Core/JavaScript

렛츠기릿 자바스크립트 #5 끝말잇기 게임 만들기

코딩하는라민 2022. 10. 27. 14:40
728x90
반응형

렛츠기릿 자바스크립트 #5 끝말잇기 게임 만들기

책 + 저자 강의 + 추가로 모르는 내용들 필기 추가하면서 공부

 

 


 

 

 

책 저자 강의(제로초)

 


 

1. 순서도 그리기

간단하게 정리해본 끝말잇기 순서도

§. 순서도 그리기가 왜 중요할까?

- 프로그래머는 코딩을 하는 것도 중요하지만 절차를 세우고 오류를 수정하는 것.

- 순서도를 통해 코드를 수정하고, 코드를 토대로 순서도를 보완해가자.

 

 

§. 프로그램의 절차를 만들 때의 원칙 

  ① 절차의 개수는 고정

  ② 절차는 항상 같은 내용 → 구체적인 내용보다는 포괄적인 내용 ex) 4명, A, B,...(x) → 다음 사람(o)

  ③ (최대한) 모든 가능성 고려

  ④ 예시는 절차를 검증하는 데 사용 구체적인 예시

 

- 분기점 : 판단을 요구하는 절차에서 Yes/No로 화살표 순서도가 갈라지는 부분

- 거슬러 올라간다 → 반복

 

 

 

2. 몇 사람이 참가할 건지 선택하는 페이지 만들기

■ 브라우저에 대화상자를 띄우는 함수
 prompt    /    alert    /    confirm

→ 실제로는 잘 사용하지 않는다.

 

① prompt 함수 : 사용자로부터 값을 전달받는다.

- 기본 형태 : prompt('메시지 message', '기본값 default');

 

const number = prompt('게임 참가 인원을 입력하세요.');

→ prompt 로 입력한 값들은 모두 '문자열'이다.

따라서 숫자를 입력받아야 하는 경우 아래와 같이 숫자로 바꿔주는 작업을 진행해야 한다.

Number, parseInt 의 차이

더보기

① 문자열을 숫자형으로 변환할 때,

- Number : 문자열 → 숫자형

let number = Number('1234');
console.log(number, typeof number);
// 1234, 'number'

- parseInt : 문자열 → 정수형

let parseint = parseInt('1234');
console.log(parseint, typeof parseint);
// 1234, 'number'

 

② 문자가 섞인 경우,

- Number : 숫자+문자 → NaN값 반환

let number = Number('1234코딩');
console.log(number, typeof number);
// NaN

- parseInt : 숫자+문자 → 숫자로 시작해서 숫자가 끝날 때까지만 형변환

let parseint = parseInt('1234코딩');
console.log(parseint, typeof parseint);
// 1234

- parseInt : 문자+숫자 → NaN 값 반환

let parseint = parseInt('코딩1234');
console.log(parseint, typeof parseint);
// NaN
const number = Number(prompt('게임 참가 인원을 입력하세요.'));

-  취소 또는 입력값이 없으면 null 값을 반환

 

 

alert 함수 : 메시지로 사용자에게 알릴 때 사용. 경고창.

alert('사용자에게 표시할 메시지입니다.');

 

confirm 함수 : 사용자에게 (확인)의사를 물어볼 때 사용. 예/아니오 값을 누르면 각 true, false 값이 콘솔 창에 기록된다.

const yesOrNo = confirm('이게 맞나요?');

 

 

 

3. 첫 번째 사람이 말할 단어 입력

태그 선택해서 콘솔에 띄우기

- 입력창으로 단어를 입력받아야 한다.(input 태그)

- input 태그는 HTML 이므로 JS 에 가져와야 함. → 이를 '선택'이라고 한다.

■ JS 에서 HTML 태그 가져오기
document.querySelector('선택자')

 

- 선택자로 input 을 넣어 실행해보면 HTML 에서 작성한 코드가 콘솔에 표시가 된다. 

- 즉, 선택자를 태그 이름으로 해두면 해당 태그가 선택됨

- 태그가 여러 개인 경우에는 제일 위의 태그만 선택된다.

document.querySelector('input');

 

 

 여러 개 태그 선택해서 콘솔에 띄우기

- document.querySelectorAll 함수 : 선택하고자 하는 태그가 여러개이고, 여러 개를 모두 선택할 경우 사용

- NodeList 는 유사배열이라고 한다. 배열인 척 하는 객체. 실제 배열이 아니라 객체이다(배열도 객체). 

document.querySelectorAll('button');

 

 

 

특정한 태그 하나 선택하기

document.querySelector('#word');
- id 속성
① # 사용
② 태그에 달 수 있는 고유 값
③ 재사용 불가능 (자바스크립트 기준, HTML은 여러번 사용 가능)

 

 

특정한 태그 여러 개 선택하기

- Class 속성
① . 사용
② id 속성과는 달리 여러 번 사용할 수 있다.
document.querySelectorAll('.btn');

- document.querySelector를 이용하면 하나만 선택되므로 주의

 

 

 

4. 태그에 이벤트 달기

- 이벤트 : 사용자가 태그와 상호작용 할 때 나타나는 것 ex) 입력 버튼을 누르는 것

- 이벤트 타겟 : 이벤트가 일어날 객체

- 이벤트 리스너 : 자바스크립트가 HTML에서 발생하는 이벤트를 감지할 수 있게 해주는 것

- 콜백함수 또는 리스너 함수 : 특정 작업이 실행되고 난 뒤에 추가로 실행되는 함수

 

addEventListener 함수 : 이벤트가 발생하면 함수를 실행

.addEventListener('이벤트 이름', 리스너함수 또는 콜백함수);

→ 자주 사용하는 이벤트

더보기

포커스 : focus, blur

폼 : reset, submit

뷰 : scroll, resize

키보드 : keydown, keyup

마우스 : mouseenter, mouseover, click, dbclick, mouseleave

드래그 앤 드롭 : dragstart, drag, dragleave, drop

 

① 이벤트 리스터 달기

const onClickButton = () => {
	console.log('버튼 클릭');
{

const $button = document.querySelector('button');
$button.addEventListener('click', onClickButton);

→ '클릭' 하면 onClickButton 함수가 실행된다.

이때 주의해야 할 점, 함수 이름에는 ()를 붙이지 않는다. 그 이유는 ()를 붙이면 클릭 이벤트와는 상관 없이 함수가 바로 실행되기 때문이다. 왜냐하면 함수는 undefined 값을 나타내는데 함수에 ()를 붙여서 쓰면 그 값은 undefined 가 되기 때문에 사용하면 안 됨.

→ 화살표 함수와 function 함수는 다르다. (여기서는 같음) 9장에서 다룰 예정.

 

 

② 사용자가 어떤 글자를 입력했는지 볼 수 있게 만들기

const onInput = (event) => {
	console.log('글자 입력', event.target.value);
{

const $input = document.querySelector('input');
$input.addEventListener('input', onInput);

 onInput 함수(input에)는 특별하게 '매개변수'가 존재한다.

→ event.target.value : input 에 입력한 값을 알아낼 수 있음. 입력 값들을 순서대로 얻을 수 있다. 이런 방식으로 마지막 입력 값을 얻을 수 있는 것. event 의 값은 매개변수이므로 다르게 설정 가능. 예를 들면 e 와 같이 사용 가능.

 

* .target 과 .target.value 의 차이점?

더보기

.target : 객체의 target 만 가져온다. target의 value 는 input. 즉, input 이라는 태그 자체를 가져온다.

console.log(event.target);
// <input type="text" value="햄버거">

 

.target.value : input의 value 를 가져온다.

console.log(event.target.value);
// 햄버거

 

 

 

 

5. 첫 번째 사람인지 판단하기 & 순서도 수정

◎ 첫번 째 수정 순서도

 

순서도 수정 1

 하지만, 이 순서도에서도 오류가 있는데, 제시어를 말한 사람이 첫 타자인지 아닌지를 판단할 필요가 있다. 그 다음으로 다음 사람이 단어를 말했을 때 단어가 올바른 단어인지 판단하면 된다.

  게임에는 [대기]와 [이벤트]가 존재한다.

 

순서도는 언제 끊어주는 것이 좋은가?
- input, click 이벤트는 사용자가 이벤트를 발생시키지 않으면 다음 단계로 넘어가지 않는 특성이 있다.
- 이런 경우에는 순서도를 끊어서 표현해주는 것이 좋다.

 

 

 

◎ 두번 째 수정 순서도 : 절차적 순서도로 변경

순서도 수정 2

 

 

 

 첫번째 참가자인지 어떻게 알까?

→ 첫번째 참가자일 때는 제시어가 없다.

제시어가 없다 = 첫 번째 참가자이다

 

 제시어는 변수로

- 제시어는 계속 바뀌기 때문에 변수로 만들기에 좋다.

- 처음 시작 시 단어를 저장할 변수는 빈 값으로 둔다. 왜냐하면 아직 제시어를 말하지 않은 상태이기 때문이다.

 

 

첫 번째 참가자이면 #word 안의 텍스트에 입력값 넣기

- #word : 빈값으로 둔 태그. 여기에 제시어를 저장할 것. 따라서 word 를 변수로 두고 코드를 짠다.

 

 버튼을 클릭하면 실행될 함수 정의 : onClickButton() 

  const number = Number(prompt('게임 참가 인원을 입력하세요.'));
  const $button = document.querySelector('button');
  const $input = document.querySelector('input');
  
  let word; //제시어
  const onClickButton = () => {
      if (!word) { //제시어가 비어있는가?
          // 비어 있다.
      } else {
          // 비어 있지 않다.
      }
  };
  
  const onInput = (event) => {
      console.log('글자 입력', event.target.value);
  };
  
  $button.addEventListener('click', onClickButton);
  $input.addEventListener('input', onInput);

 

 

 세번 째 수정 순서도 : 첫 번째 참가자인 경우 제시어는 비어있을 것

순서도 수정 3

 

제시어가 비어 있는가?

 

- 선언할 때 아무 값도 넣지 않으면 undefined 값.

- 즉, word는 if문에서 false 값이 된다.

- 따라서 !word 는 true 값이 나올 것.

- !word이 참이라면 제시어가 비어있는 것. 거짓이라면 제시어가 비어있지 않은 것.

let word; //제시어
  const onClickButton = () => {
      if (!word) { //제시어가 비어있는가?
          // 비어 있다.
      } else {
          // 비어 있지 않다.
      }
  };

 

 

네번 째 수정 순서도

순서도 수정 4

 

 

Yes : 제시어가 비어있는 경우
→ 입력한 단어가 제시어가 됨
  const number = Number(prompt('게임 참가 인원을 입력하세요.'));
  const $button = document.querySelector('button');
  const $input = document.querySelector('input');
  const $word = document.querySelector('#word');
  
  let word; //제시어
  let newWord; // 새로 입력한 단어
  const onClickButton = () => {
      if (!word) { //제시어가 비어있는가?
          word = newWord; //입력한 단어가 제시어가 된다.
          $word.textContent = word; //span 의 텍스트를 넣어주는 것
          $input.value = ''; // 입력창 초기화
      } else {
          // 비어 있지 않다.
      }
  };
  const onInput = (event) => {
      newWord = event.target.value; // 입력하는 단어를 새로 입력한 단어(newWord)로
  };
  
  $button.addEventListener('click', onClickButton);
  $input.addEventListener('input', onInput);

- 데이터를 바탕으로 화면도 바꿔줘야 적용이 된다.

 

 

  let word; //제시어
  let newWord; // 새로 입력한 단어

- word 와 newWord 를 변수로 저장

 

 

word = newWord;

- 제시어 = 새로 입력한 단어

- 즉, 새로 입력한 단어가 제시어가 된다.

 

 

$word.textContent = word;

- word 태그의 텍스트 값을 word 라고 정의

- span 에 값(텍스트)을 넣어주기 위해서 써준 것.

- .textContent : 태그 내부의 값을 얻거나 수정할 때 사용. 빈값인 경우 '  ' 의 결과를 얻을 수 있음.

- .textContent = 값 : 태그 내부의 문자열을 해당 값으로 설정

 

$input.value = '';

- 다음 사람도 단어를 입력해야 하므로 입력창을 초기화한다.

- input 과 같은 입력값은 value 를 바꿔줘야 한다.

→ span 이나 다른 태그들은 textContent 를 바꿔줘야 한다. 대부분의 태그들은 textContent 이다.

사용자의 입력창 = value
대부분의 태그들(span, ...) = textContent

 

 

 

No : 제시어가 비어있지 않은 경우
→ 단어가 올바른가, 올바르지 않은가?

const number = Number(prompt('게임 참가 인원을 입력하세요.'));
const $button = document.querySelector('button');
const $input = document.querySelector('input');
const $word = document.querySelector('#word');
let word; //제시어
let newWord; //현재 단어, 새로 입력한 단어

const onClickButton = () => {
    if (!word) { //제시어가 비어있는가?
      // 비어있다.
      word = newWord; //입력한 단어가 제시어가 된다.
      $word.textContent = word;
      $input.value = '';
    } else {
      // 비어 있지 않다.
      if(word[word.length - 1] === newWord[0]){ //올바른가
        word = newWord; //입력한 단어가 제시어가 된다.
        $word.textContent = word; //span 의 텍스트를 넣어주는 것
        $input.value = ''; // 입력창 초기화
      } else{ //올바르지 않은가
        
      }
    }
};
const onInput = (event) => {
    newWord = event.target.value; //입력하는 단어를 현재 단어로
};

$button.addEventListener('click', onClickButton);
$input.addEventListener('input', onInput);

- 제시어가 비어있지 않으면, 단어가 올바른가 ? 올바르지 않은가 ? 를 판단.

 

 

word[word.length - 1] === newWord[0]

- 문자열의 마지막 자리수 구하기

문자열 [ 문자열 . length - 1 ]

 

Yes : 제시어가 올바르다
→ 입력한 단어가 그 다음 제시어가 된다.

- 제시어가 올바르다 : 이전 제시어의 마지막 글자와, 현재 입력한 단어의 첫 글자가 같다 → 다음 절차로 넘어간다.

 

 

 

 

 다섯번 째 수정 순서도 : 제시어가 올바르면 다음 사람에게 순서를 넘긴다

순서도 수정 5

 

 

const number = Number(prompt('게임 참가 인원을 입력하세요.'));
const $button = document.querySelector('button');
const $input = document.querySelector('input');
const $word = document.querySelector('#word');
const $order = document.querySelector('#order');
let word; //제시어
let newWord; //현재 단어, 새로 입력한 단어

const onClickButton = () => {
    if (!word) { //제시어가 비어있는가?
      // 비어있다.
      word = newWord; //입력한 단어가 제시어가 된다.
      $word.textContent = word; //span 의 텍스트를 넣어주는 것
      $input.value = ''; // 입력창 초기화

      const order = Number($order.textContent);
      if(order+1>number){
        $order.textContent=1;
      } else{
        $order.textContent=order+1;
      }
    } else {
      // 비어 있지 않다.
      if(word[word.length - 1] === newWord[0]){ // 올바른가?
        // 올바르다
        word = newWord;
        $word.textContent = word; 
        $input.value = ''; 
        
		// 다음 턴으로 넘긴다
        const order = Number($order.textContent);
        if(order+1>number){
          $order.textContent=1;
        } else{
          $order.textContent=order+1;
        }
        
      } else{ //올바르지 않다
        
      }
    }
};
const onInput = (event) => {
    newWord = event.target.value; //입력하는 단어를 현재 단어로
};

$button.addEventListener('click', onClickButton);
$input.addEventListener('input', onInput);

- 다음 사람한테 넘기려면 내가 몇 번째인지 알아야 한다.

- 다음 사람의 순번이 number(총 인원) 보다 커지면 다시 첫번째 순서로 돌아와야 한다.

- 만약 다음 사람의 순번이 number 보다 크지 않다면 현재 순서에서 다음 순서로 넘어가므로 현재순서 + 1이 된다.

 

 

const order = Number($order.textContent);

- order 태그의 값을 숫자로 변환해주고 order 에 저장한다.

 

if(order+1>number){

- 현재 순서에 1을 더한 값이 게임 참가 총 인원의 수보다 크다면, 

 

$order.textContent=1;

- order 태그의 값을 1로 변경한다.

 

} else{
     $order.textContent=order+1;
}

- 그게 아니라면 ( 현재 순서에 1을 더한 값이 게임 참가 총 인원의 수보다 작다면) 현재 순서에 1을 더한다. 즉, 다음 사람한테 턴을 넘긴다.

 

 

 

 

 여섯번 째 수정 순서도 : 다음 사람에게 순서를 넘기면서 입력창을 비우고 커서는 활성화

순서도 수정 6

 

const number = Number(prompt('게임 참가 인원을 입력하세요.'));
const $button = document.querySelector('button');
const $input = document.querySelector('input');
const $word = document.querySelector('#word');
const $order = document.querySelector('#order');
let word; //제시어
let newWord; //현재 단어, 새로 입력한 단어

const onClickButton = () => {
    if (!word) { //제시어가 비어있는가?
      // 비어있다.
      word = newWord; //입력한 단어가 제시어가 된다.
      $word.textContent = word; //span 의 텍스트를 넣어주는 것
      $input.value = ''; // 입력창 초기화

      const order = Number($order.textContent);
      if(order+1>number){
        $order.textContent=1;
      } else{
        $order.textContent=order+1;
      }
    } else {
      // 비어 있지 않다.
      if(word[word.length - 1] === newWord[0]){ // 올바른가?
        // 올바르다
        word = newWord;
        $word.textContent = word; 
        $input.value = ''; 
        
		// 다음 턴으로 넘긴다
        const order = Number($order.textContent);
        if(order+1>number){
          $order.textContent=1;
        } else{
          $order.textContent=order+1;
        }
        $input.value='';  // 입력창 비우고 초기화
        $input.focus();   // 입력창에 커서 활성화
      } else{ //올바르지 않다
        $input.value='';
        $input.focus();
      }
    }
};
const onInput = (event) => {
    newWord = event.target.value; //입력하는 단어를 현재 단어로
};

$button.addEventListener('click', onClickButton);
$input.addEventListener('input', onInput);

- 단어 입력을 마쳤으면 입력창에 입력되어 있는 글자를 초기화시켜 비워준다.

- 입력을 마치면 입력창에 커서가 활성화되어있지 않으므로 커서를 다시 활성화시켜준다.

→ 올바른 단어를 입력했을 때, 올바르지 않은 단어를 입력했을 때 동일한 효과를 준다.

 

 

$input.value='';
$input.focus();

 

 

- 입력태그만 태그의 입력 값으로 value 를 쓴다.

- input 은 입력태그이기 때문에 내부의 값을 선택할 때 value 를 사용한다.

- 그 외는 textContent 사용

■ 대표적 입력태그 ■ 
input    /    select    /    textarea

 

 

 

No : 제시어가 올바르지 않다
→ 경고창 띄우기

 

alert('올바르지 않은 단어입니다!');

 

 

 

 

 일곱번 째 수정 순서도 : 순서도 중복 줄이기(입력창을 비우고 커서 활성화 부분 중복)

순서도 수정 7

 

 

 여덟번 째 수정 순서도 : 순서도 중복 줄이기(제시어가 비어있거나 단어가 올바른가?)

순서도 수정 8

- 제시어가 비어있는가? 와 입력한 단어가 올바른가? 의 Yes 와 No 라는 판단의 절차가 동일하므로 절차가 중복되고 있는 것.

- 따라서 or 으로 묶어주어 순서도를 간편하게 만들어준다.

 

 

◎ 중복을 줄인 순서도를 바탕으로 코드 간편화 시키기

const number = Number(prompt('게임 참가 인원을 입력하세요.'));
const $button = document.querySelector('button');
const $input = document.querySelector('input');
const $word = document.querySelector('#word');
const $order = document.querySelector('#order');
let word; //제시어
let newWord; //현재 단어, 새로 입력한 단어

const onClickButton = () => {
    if (!word || word[word.length - 1] === newWord[0]) { //제시어가 비어있는가?
      // 비어있다.
      word = newWord; //입력한 단어가 제시어가 된다.
      $word.textContent = word;
      const order = Number($order.textContent);
      if(order+1>number){
        $order.textContent=1;
      } else{
        $order.textContent=order+1;
      }
    } else {
      // 비어 있지 않다.
      alert('올바르지 않은 단어입니다!');
    }
    $input.value='';
    $input.focus();
};

const onInput = (event) => {
    newWord = event.target.value; //입력하는 단어를 현재 단어로
};

$button.addEventListener('click', onClickButton);
$input.addEventListener('input', onInput);

→ 간편해진 코드

 

!word || word[word.length - 1] === newWord[0]

- [절차1] ! word  → 절차1을 절차2 보다 먼저 판단하므로 우선순위가 높다. 따라서 왼편에 놓여야 함.

- [절차2] word[word.length - 1] === newWord[0]

 

 

 

 

 


 

 

728x90
반응형