Web Front-end 공부/Java script

Js 끝말잇기 게임 만들기

Hanachoi 2022. 5. 24. 16:30
  • 끝말잇기 게임의 대략적인 순서도 
    1. 몇 명이 참가할지 선택한다
    2. 참가자 순서를 정한다
    3. 첫 번째 사람이 제시어를 말한다
    4. 다음사람이 단어를 말한다
    5. 단어가 올바른가? 판단해본다 
      1. 올바르다면 : 다시 4번으로 올라가 다음사람이 단어를 말한다. 4-5-5.1 계속 반복
      2. 틀렸다면 : 틀렸다고 표시한다 -> 끝

 

 

  • html태그 만들기 : 자바스크립트와 html, css는 뗄 수없는 관계다. 자바스크립트로 화면을 움직이려면 먼저 hmtl 태그가 필요함.
<body>
    <div><span id = "order">1</span>번째 참가자</div>
    <div>제시어 : <span id="word" ></span></div>
    <input type="text">
    <button>입력</button>  
    
    <script>
      const number = parseInt(prompt('몇 명이 참가하나요? '));
      //const realNumber =Number(number); 이런 코드를 하나 더 짜서 const number 값을 바꿔줄 수 도 있고, 바로 parseInt나, number를 써서 숫자로 바꿔 줄수도 있다//
      alert(number);
      const yesOrNo = confirm('맞나요?')


    </script>
</body>
  • 처음에 과정 1을 실행하기 위해서, 사용자에게 몇 명이 참가할 것인지 물어봐야한다. 입력창(input)태그를 써도 되지만, 여기서는 prompt라는 창을 띄워서 물어볼 것. 하지만 여기서 사용자가 입력하는 숫자는 숫자가 아니라 문자열(string)으로 값이 들어오기 때문에 parseInt를 붙여서 값을 숫자로 받아오도록 붙여준다. 
  • 그 다음에 alert(number)을 띄워서 사용자가 입력한 숫자를 확인시켜주고.
  • confirm 함수를 통해서 값이 맞는지 확인하도록 만들어 준다. [확인]을 누르면 콘솔창에 true, [취소]를 누르면 false 값이 뜰 텐데, 이걸 이용해서 프로그래밍을 작성하면 된다. 

 

 

#HTML 태그 선택하기 

  • document.querySelector('선택자') 를 통해서 html태그를 선택할 수 있다. 
document.querySelector('input'); //input태그를 선택할 수 있음 //
  • 그리고 변수명을 const $input = document.querySelector('input')이런식으로 $표시를 붙여서 이름을 붙여준다. 태그를 선택해서 변수에 넣을대는 $를 붙여주는데, 그래야 이건 자바스크립트 값이 아니라 태그를 선택했다는 것을 쉽게 알 수 있다. $$를 두개붙이면 여러개의 태그를 동시에 선택했을 때 붙여준다. 
const $$buttons = document.querySelectorAll('button');
  • document.querySelectorAll은 해당 이름이 붙은 모든 태그를 불러올 수 있다. 그냥 기본 querySelector는 제일 첫 번째 태그만 불러옴.  

 

  • 배열은 안에 값이 있으면 값이 있는 만큼 앞에 (3)갯수를 알려준다. 하지만 document.querySelectorAll('button')부분을 보면 nodelist값을 불러오는데, 이건 얘가 객체이고, 배열처럼 생긴 유사배열이라고 부른다. 배열은 아닌데 배열처럼 보이는애들은 배열의 메서드나 속성을 쓸 수 없는 경우가 많아서 구분이 필요함 

 

  • 위의 html 태그에서 <span>태그에 미리 id값을  부여해놨다. id는 태그에 달 수 있는 고유한 값이라, 한번 사용한 id 값은 다른 태그에 재사용 할 수 없다. (자바스크립트 기준. html에서는 여러번 사용 가능)
  • id값을 부를때는 #을 붙여서 부를 수 있다. 
document.querySelector('#아이디');

 

 

  • 이번에는 버튼 여러개가 있는데, 그중에 버튼2,버튼 3을 선택하고 싶다면?
  • 버튼을 2개이상 선택하고 싶을때는 document.querySelectorAll('')로 들어가줘야 한다. 
  • 그리고 button2,3에 class 값을 줘서 btn을 호출해주면 됨 
  • class 값을 부를때는 [.클라스]로 불러준다. 
 <button>입력</button>  
    <button class = "btn"> 입력2</button>  
    <button class = "btn"> 입력3</button>
    
<script>
	document.querySelectorAll('.btn');
</script>
  • 만약에 버튼1과 3을 부르고 싶다면? 그냥 버튼2에 있는 class값을 때서 1에 붙여주던가, 아니면 새로운 class값을 주고 걔도 같이 불러주면 된다
<button class = 'target'>버튼1</button>
<button class = 'btn'>버튼2</button>
<button class = 'btn target'>버튼3</button>

<script>
 	document.querySelectorAll('.target')
</script>

 

  • 어떤 태그안에 들어있는 다른 태그를 선택할때
  • 선택자를 여러개 적으면 된다. 띄어쓰기로 구분함 
<body>
  <div><span id="order">1</span>번째 참가자</div>
  <div>제시어: <span id="word"></span></div>
  <input type="text">
  <button>입력</button>
  <script>
    const $span = document.querySelector('div span');
    console.log($span);
  </script>
</body>
  • 가장먼저 나오는 선택자가 기준태그고 다음에 나오는 선택자는 기준 태그 안에 들어있는 태그다. 
  • 선택자가 div span 일 때, div태그 안에 들어있는 span 태그를 찾는 것 
  • 하지만 이렇게 너무 꼬리를 물고 넘어가는것 같으면 그냥 id값을 줘서 찾는게 낫다. id는 고유한 값이기 때문에 
document.querySelector('선택자 내부선택자 내부선택자...');

document.querySelector("body #target button'); // body 태그안에 id가 target인 애 안에 button 태그를 찾아라//
  • 자식과 자손태그의 차이점은 ? 자식태그는 기준태그 바로 밑까지의 태그 
  • div의 자식태그 span
<div><span></span></div>

document.querySelector('div span')

document.querySelector( 'div>span')/ // >표시로 바로 자식태그만 찾을 수도 있음
  • div의 자손태그 p까지 호출 할 수 있음 
<div><span><p></p></span></div>

document.querySelector('div p')
//div 안에 있는 자손태그를 바로 부를 수 있다 //
  • 선택자는 css와 연관되어있음. css에서 선택자를 공부해서 익히고 자바스크립트에서 그대로 쓰면 됨

 

#이벤트 리스너 달기(콜백함수)

  • 우리가 만든  input박스안에 값을 입력하고, 버튼을 누르면 그게 바로 웹페이지 위에서 이벤트가 발생한 것이다. 
  • html이 페이지를 만들어주면 우리는 자바스크립트로 웹페이지와 상호작용이 가능해진다. 
  • input태그를 선택해 addEvenetListner를 달아준다. 글자가 input될때마다 뒤에 달린 function()이 실행된다.
document.querySelector('input').addEventListener('input',function(){
        console.log('글자입력')
      });

      document.querySelector('button').addEventListener('click',function(){
        console.log('버튼클릭')
      });
      
      //콘솔창을 확인해보면 글자를 입력할때 글자입력/ 버튼을 클릭할때 버튼클릭 이렇게 글자가 따로 뜸//

 

  • 함수를 바깥으로 분리해서 사용할 수도 있다.
<script>
const onClickButton = () =>{
	console.log('버튼클릭');
}

const $button = document.querySelector('button');
$button.addEventListener('click',onClickButton);
</script>
    • 리스너 함수는 콜백함수라고도 부른다. 
    • 어떤 동작이 실행되고 난 뒤에 연이어서 실행되는 애들이 콜백함수 
태그.addEventListener('이벤트이름', 리스너함수);
  • 함수를 변수에 넣어서 이름을 정해줬다면, 리스너함수 자리에 적어줄 때 ()를 넣지 않도록 조심하기
  • function(){} 안에는 우리가 적지 않아도 return undefined; 가 들이었는거라고 했었다. 만약에 우리가 함수를 쓸 때, [태그.addEventListner('이벤트이름', 리스너함수());] 라고 써버리면 저 함수 자리를 undefined로 채우는 것과 마찬가지다. 함수자리니까 함수의 이름만 넣는다
  • 여러번  재 사용될 함수면 따로 빼서 이름을 붙여주는게 더 좋고, 한번만 쓰고 말거라면 그냥 익명함수로 한번쓰고 말아도 된다. 
  • 어떤 값을 입력했는지까지 알아내고 싶다면?  event를 매개변수에 넣어주고 event.target.value를 넣어주면 어떤 글자를 입력하는지 까지 볼 수 있다. 
document.querySelector('input').addEventListener('input', (event) =>{
	console.log('글자입력' , event.target.value);
});

 

 

#첫 번째 사람인지 판단하기 

  • 참가자 순서는 딱히 코드로 짜지 않아도 아마 순서대로 게임을 돌릴것이다.
  • [첫번째 사람이 제시어를 말한다] 라는 부분에서 순서도를 수정할 필요가 생겼다. 
  • 순서를 정한다음, 첫번째 사람이 제시어를 말하기 전까지는 어떤 이벤트도 발생하지 않는다. 그럼 다음 절차로도 넘어가지 않음. 이때 순서도를 한번 끊어주는게 좋음.
  • 참가자 순서를 정한다 -> 대기 // 순서도 분리//
  • 입력버튼 클릭 -> 첫번째 사람이 제시어를 말한다. 로 수정
  • 그렇다면 첫번째 참가자인건 어떻게 판단할 수 있을까?
  • 우리는 첫번째 '제시어'를 말한 사람을 찾고 싶은 것이다.  그럼 첫번째 참가자가 제시어를 말하기 전까지는 제시어 : 칸이 비어있을 것이다. 그럼 제시어가 없으면 첫번째 참가자이구나! 라고 판단할 수 있음.
  • 첫번째 사람이 제시어를 말한다. -> 제시어가 비어있는가? 로 수정 
  • 계속 왔다갔다 하면서 코드와 순서도를 차례로 바꿔주면 된다. 
  • 참가자 순서를 정한다 -> 대기 : 분리했던 1번 순서도에서도 변화가 생겼다. 참가자 순서를 정한다 ->제시어를 저장할 변수를 만든다. 추가
   let word; //제시어
      
    
      const onClickButton = () => {
        if(!word){//제시어가 비어있다(word가 없다를 표현하기 위해서 !를 써서 false로 만듬)//

        }else{//제시어가 비어있지 않다. 

        }
  • 제시어가 비어있는 경우는 if문, 제시어가 들어가 있는 경우는 else 문으로 코드를 나눠서 작성하면된다. 

 

 const number = Number(prompt('몇 명이 참가하나요?'));
      const $button = document.querySelector('button');
      const $input = document.querySelector('input');
      
      let word; //제시어
      let newWord // 새로 입력한 제시어 
      
    
      const onClickButton = () => {
        if(!word){//제시어가 비어있는가?
          //비어있다
          word = newWord //입력한 단어가 제시어가 된다.

        }else{//제시어가 비어있지 않다. 

        }

      };
  • 사용자가 단어를 입력해야 제시어와 비교가 가능하다. word = newWord  코드를 넣어서 사용자가 입력한 단어를 새로운 제시어로 만들어 준다. 그럼 데이터를 받았으니까 화면도 여기에 맞게 변할 수 있도록 코드를 작성해줘야 한다.  항상 변수만 바꿔주지 말고 화면구현도 똑같이 바꿔줘야 된다고 생각하기
  • 또 하나 거슬리는건, 우리가 input박스에 단어를 입력했으면 입력했던 단어가 지워져야 다음 참가자가 입력하기 편해질 것이다.  $input.value = ''; input의 value 값을 빈값으로 만들어주기 
  • input 태그는 안에 들어있는 값이 value 이고, span이나 다른 태그들은 안에 들어있는 값이 textContent로 들어가진다. 
 const onClickButton = () => {
        if(!word){//제시어가 비어있는가?
          //비어있다
          word = newWord; // 제시어가 비어있으면 입력한 단어가 제시어가 된다. 
          $word.textContent = word; // 제시어 : 부분에 입력한 단어가 들어가도록 화면 구현//
          $input.value = ''; // 제시어를 입력했으면 다음 입력자가 입력하기 편하도록 써있는 단어를 지워주기//
        }else{
          //제시어가 비어있지 않다. 
          
        }
  • 다음으로 else 부분, 제시어가 비어있지 않는 경우를 코딩한다.
  • 첫번째 사람이 제시어를 입력했다면 [제시어 : ] 부분에 제시어가 입력되어 있을 것이다. 

#올바른 단어인지 판단하기

  • 위의 코드에서 else 부분을 작성한다. 제시어가 비어있지 않다면 여기서 다시, 제시어가 맞을때, 아닐때로 나눌 수 있을 것이다. if/else문을 하나 더 넣어준다. 
 const onClickButton = () => {
        if(!word){//제시어가 비어있는가?
          //비어있다
          word = newWord; // 제시어가 비어있으면 입력한 단어가 제시어가 된다. 
          $word.textContent = word; // 제시어 : 부분에 입력한 단어가 들어가도록 화면 구현//
          $input.value = ''; // 제시어를 입력했으면 다음 입력자가 입력하기 편하도록 써있는 단어를 지워주기//
        }else{
          //제시어가 비어있지 않다. 
          if(word[word.length-1] === newWord[0]){ //올바른 단어인가?//
            //제시어의 끝단어와 새로운 단어의 첫번째 단어가 같으면 성립//
            //성립됬으면 위에서 if문과 동일해진다.//
            word = newWord;
            $word.textContent = word;
            $input.value = '';

          }else{//올바르지 않은 단어인가?//

          }
          
        }

      };
  • 2번째 참가자가 말한 단어가 1번째 참가자의 끝 단어를 잘 연결했는지는 어떻게 알 수 있나? 우리는 문자열의 배열도 알아 볼 수 있는 방법이 있었지. 그래서 word(기존제시어) 의 마지막 문자열 word[word.length-1]의 값이 newWord(새롭게 들어오는 제시어) 의 첫번째 문자열 newWord[0]와 같아질때, 두 번째 참가자도 정확히 말했다는걸 알 수 있다. 그래서 if문의 조건식에 이런 조건식을 달아줬고, 여기서 true가 된다면 위에서 첫번째 제시어가 들어왔을 때랑 똑같이 데이터를 받고, 화면을 구현하는 동일한 코드를 사용하게 되는 것이다. 
  • 그리고 첫번째 사람에서 다음사람으로 순서가 넘어가게 되면 우리는 html 화면 에서 [1번째 참가자] 부분의 1을 다음 숫자로 넘겨줘야 한다. 이건 어떻게 구현할까?
  • 다음사람에게 순서를 넘긴다. 부분을 또다시 새새하게 분류해서 코드를 짜준다. 현재순서를 파악한다(지금 몇번째가 제시어를 말했지?) -> 현재순서에서 1을 더한 값이 number(promt('몇명이 참가'))보다 큰가? 
  • yes : 다음 순서를 1로 (만약 마지막 순서가 3이라면, 참가자 숫자가 3이었겠지, 이 때 number가 3보다 크다면 다음 번호가 아닌 첫번째 타자에게 다시 순서가 넘어가야 된다. )
  • No : 다음 순서를 현재순서 +1로
if(word[word.length-1] === newWord[0]){ //올바른 단어인가?//
            //제시어의 끝단어와 새로운 단어의 첫번째 단어가 같으면 성립//
            //성립됬으면 위에서 if문과 동일해진다.//
    word = newWord;
    $word.textContent = word;
    $input.value = '';

    const order = Number(order.textContent); // 현재순서
    if(order+1 > Number ){
      $order.textContent = 1; //textcontent는 자동으로 형변환해서 문자로 들어감. 
    }else{
      $order.textContent = order + 1;
    }
  • 이렇게 한 부분의 코드를 짜고 나면 전체적인 순서도도 참고를 해서 조율을 해 나가야된다. 
  • 이 //현재순서//에 대한 부분은 가장 맨처음 if(!word)부분에도 적용되야 하는 부분이다. 그 부분에도 순서에 대한 코드를 복사붙여넣기 해준다. 

 

  • 추가적으로 input창에 입력을 하고 나면 다음 사람이 입력하기 쉽도록 커서가 깜빡이면서 움직이도록 디테일을 살려줄 수 있다. 
  • 순서도에서도 다음사람에게 순서를 넘긴다 ->입력창을 비우고 커서를 둔다 를 추가해준다. 
  • 커서에 대한 명령은 focus();로 가능함. if문과 else문 의 뒤에 이 코드를 추가해준다. 
 $input.focus();

 

 

#순서도 최적화하기

  • 지금 만든 순서도를 보면 [입력된 단어가 제시어가 된다 -> 다른사람에게 순서를 넘긴다 ->입력창을 비우고 커서를 둔다.] 부분이 계속적으로 반복되게 되어있다.
  • 이렇게 반복되는 부분을 좀 더 간결하게 정리하는 테크닉이 있다. 
  • 우리가 여태까지 짰던 순서도는 알고리즘이라고 할 수 있다. 코딩테스트에서보는 알고리즘은 알고리즘을 잘 짜고 최단으로 절차를 효율적으로 단순화 시키는 것까지도 포함된다.
  • 제시어가 비어있는가? // 입력한 단어가 올바른가? 이 부분은 사실 하나로 합쳐질 수 있다. 제시어가 비어있는가? 또는 입력한 단어가 올바른가? 로 합쳐주자 
  • 또는 || 으로 합쳐주었다.
  • or은 하나만 true면 true, 하나만 false면 false // and는 둘다 true여야 true, 둘다 false 여야 false로 정해진다는거 기억해두자!
const onClickButton = () => {
        if(!word || word[word.length-1] === newWord[0]) // 밑에 있던 if부분을 없애고 둘이 합쳐줬다

 

  • 그리고 또하나, 값을 비워주고 커서를 만들어 주는 코드는 두 if문의 끝에 달려있고 겹치는 내용이기 때문에 if-else문 밖으로 아에 빼내 버릴수도 있다.
  • 그럼 길었던 코드를 이정도까지 짧게 줄여 줄 수 있다. 
     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; //textcontent는 자동으로 형변환해서 문자로 들어감. //
          }else{
            $order.textContent = order + 1;
         }
       
          }else{//올바르지 않은 단어인가?//
            alert('올바르지 않은 단어입니다')
          }

          $input.value ='';
          $input.focus(); // 위에서 중복되는 부분을 지워주고 아에 if-else문 밖으로 빼내버렸다.