Small Grey Outline Pointer [레츠기릿JS] 끝말잇기 만들기
본문 바로가기
Dev./JavaScript

[레츠기릿JS] 끝말잇기 만들기

by sso. 2023. 4. 4.

 

세 가지의 대화상자 

const number = parseInt(prompt('몇 명이 참가하나요?'),10);
alert(number);
const yesOrNo = confirm('맞나요?');

prompt : 사용자로부터 값을 입력 받는다

alert : 사용자에게 경고 메세지를 표시

confirm : 사용자의 확인을 요구 (확인 / 취소)

 


 

선택자 querySelector / querySelectorAll

<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>

선택자 사이에 공백(띄어쓰기)을 주어 구분한다

 

 

 

 

document.querySelector('선택자 내부선택자 내부선택자...');

document.querySelector('body #target button...');
//body태그 안에 있는 id값이 target인 태그안에 들어있는 button태그를 찾는다

document.querySelector('div p'); 
//div 태그의 후손 태그인 p태그까지 찾아라 :: 띄어쓰기 사용

document.querySelector('div>span');
//후손태그는 필요없고 자식태그만 찾고 싶을 때 :: 띄어쓰기 대신 >

 

 


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

 

리스너함수(콜백함수)

태그.addEventListener('이벤트 이름', 리스너 함수);

콜백함수 : 어떤 동작이 실행되고 난 후, 이어서 실행되는 함수 

 

 

//function에 이름이 없어서 익명함수라고도 한다
document.querySelector('button').addEventListener('click',function(){
    console.log('버튼 클릭 확인');
});

//함수에 onClick 이라고 이름을 붙여주고 사용하는 경우
const onClick = function(){
    console.log('버튼 클릭 확인');
}
document.querySelector('button').addEventListener('click', onClick);

 

addEventListener('click', onClick)

이 때 함수자리에 함수() 이렇게 사용하면 안되고 함수를 그대로 넣어줘야 한다 
함수 호출하는 것이 아니라, 함수 자체를 넣어야 하기 때문!

 

addEventListener() 함수의 인수에 뭐가 들어갈지 잘 생각해야한다 

첫번째 인수에는 문자열 'click'

두번째 인수에는 onClick (함수)가 들어간다

 

//addEventListener() 의 인수에 함수 이름이 아니라 함수호출을 넣는다면...?

const onClick = function(){
    console.log('버튼 클릭 확인');
    //return undefined; 가 생략되어 있는 것
}
document.querySelector('button').addEventListener('click', onClick());

=> onClick() 자리에 onClick() 함수의 리턴값을 대입해보면 된다 
=> addEventListener('click', undefined) 가 된다

따라서 함수자리에는 함수() 가 아니라 함수이름만 넣어줘야 한다

 

 

document.querySelector('input').addEventListener('input',function(){
    console.log('글자 입력 확인');
});

//화살표 함수로 바꿔보기 function() 을 () => 로 변경

//사용자가 입력한 값 가져오기 event.target.value
document.querySelector('input').addEventListener('input', (event) => {
	console.log('글자 입력 확인', event.target.value);
});

 

 


 

프로그래밍 방식으로 절차적 사고를 하는 연습을 하려면 순서도를 그리면서(수정을 거치면서)절차를 계속 쪼개봐야 한다

절차를 만들었다면 이것을 어떻게 코드로 구현할 것인가를 고민해야 한다 

 

첫번째 참가자인지 확인하는 방법은 무엇인지 생각해본다

첫번째 참가자라면 제시어가 주어지지 않았을 것이고, 제시어 부분이 비어있을 것

 

 다시 순서도를 수정하고 추가할 부분이 있으면 추가한다

 

let word; //제시어를 저장할 변수 

const onClickButton = () => {
    //제시어가 비어 있는지 아닌지 확인하는 분기 
    if(!word){
        //제시어가 비어 있는가? YES 에 해당하는 순서도
    }else{
        //제시어가 비어 있는가? NO 에 해당하는 순서도 
    }
};

 

선언할 때 아무런 값을 넣지 않았으니 word undefined가 된다

undefined if 문 안에 들어가면 false로 취급되고, !word true로 취급 된다

‘단어가 비어 있는가?’를 !word로 표현

 

 

‘입력된 단어가 제시어가 된다’ 를 코딩하려면 참가자가 입력한 단어를 저장해야 한다

따라서 변수가 필요 => 이 변수는 newWord로 선언

입력한 단어를 input 이벤트 안에서 newWord 변수에 저장

 

데이터를 바꿔주고 나면 화면도 바꿔줘야 눈으로 확인할 수 있다 => 이 과정이 짝으로 이루어져야 함

 

let word; //제시어를 저장할 변수 
let newWord; //새로 입력한 단어

const onClickButton = () => {
    //제시어가 비어 있는지 아닌지 확인하는 분기 
    if(!word){
        //제시어가 비어 있는 경우의 코드
        word = newWord; //입력한 단어가 제시어가 된다 (데이터 바꿔주기)
        $word.textContent = word; //입력한 단어를 span태그 안에 넣어준다 (화면 바꿔주기)
    }else{
        //제시어가 비어 있지 않은 경우의 코드 
    }
};

 

 

 

참가자가 3명이라면 3번째 순서에서 +1이 아니라 1번째 참가자로 돌아가야 한다 

 

if(order + 1 > number){
    $order.textContent = 1
}else{
    $order.textContent = order + 1
}

순서도를 잘 그려야 그 흐름대로 코드를 잘 짤 수 있다

순서도를 처음부터 끝까지 다 그리려고 하지 말고 하나씩 단계별로 큰 틀을 잡고

세부적인 로직을 생각해나가는게 좋다 (순서도에 익숙하지 않다면!)

 

 

태그의 내부 값을 가져올 때 사용하는 속성

input - value / select - value

button , div, span 그 외 태그 - textContent


 

 

 

순서도 최적화 하기

 

중복되는 코드 정리하기

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>끝말잇기</title>
    <style>

    </style>
</head>
<body>
    <div><span id="order">1</span>번째 참가자</div>
    <div>제시어 : <span id="word"></span></div>
    <input type="text">
    <button>입력</button>
    <div>
    </div>
</body>
</html>

 

<script>
        const number = parseInt(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; //입력한 단어를 span태그 안에 넣어준다 (화면 바꿔주기)
                const order = Number($order.textContent); //현재 순서
                if (order + 1 > number) {
                    $order.textContent = 1
                } else {
                    $order.textContent = order + 1
                }
                $input.value = ''; //input창을 비워준다
                $input.focus();
            } 
            else {//올바르지 않은가
                alert('틀렸습니다');
                $input.value = '';
                $input.focus();
            }
            
        };
        const onInput = (event) => {
            newWord = event.target.value;
        };
        $button.addEventListener('click', onClickButton);
        $input.addEventListener('input', onInput);
    </script>

 

 

순서도를 만들 때 사용자의 이벤트(버튼 클릭, 입력창 글자 입력 등)가 필요한 곳에서 순서도를 끊어야 함을 잊지 말자!

 


논리연산의 결과 추측하기 (AND와 OR)

 

true && false => false

false && true => false

false || true => true

true || false => true

 

 


연습문제

 

쿵쿵따 만들기

 

조건

0) 참가자를 입력해주세요 prompt에서 취소를 선택하면 다음 코드가 실행되지 않게 한다

 

1) 세글자인가?

2) 제시어가 비어있는가? (첫번째 참가자인가?)

3) 단어가 올바른가? => 첫번째 제시어의 끝글자와 새로 제시된 단어의 첫글자가 일치하는가?

 

if(!word && (newWord.length === 3 || word[word.length-1]===newWord[0])

조건 넣는 부분에서 처음에는 두글자 단어를 입력하면 에러가 떴고

처음에 세글자를 넣고 진행하면 다음에 앞글자가 똑같은 두글자를 입력해도 진행이 되길래 뭔가 이상했음

 

세 글자인가 AND (제시어가 비어 있는가 OR 입력한 단어가 올바른가)

 이렇게 조건을 세워야 했다

 

if(newWord.length === 3 && ( !word|| word[word.length-1]===newWord[0]))

따라서 조건을 이렇게 바꿔주고 나니까 처음 제시어에서 입력된 두글자는 틀렸습니다가 나온다

 

 


prompt에서 취소를 누르면 null 값이 나오는것 까진 알겠는데

취소를 누른 후 다음 코드를 실행 안되게 하려면 어떻게 짜야될 지 모르겠어서 이 부분은 건너뛰고 했는데

이것도 if문으로 분기를 나눠서 숫자가 있을 때 없을 때로 구분 해주면 되는 거였다...왜 이렇게 단순하게 생각 못했을까

 

prompt에서 취소 =  null

null 값이 Number함수에 들어가면 NaN이 된다

=> NaN은 if문에 들어가면 항상 false가 된다 (if문 조건에 부합하지 않아 실행X , else문이 있다면 여기로 넘어감)

 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>쿵쿵따 만들기</title>
</head>

<body>
    <div>쿵쿵따 게임</div>
    <div><span id="number">1</span>번째 참가자</div>
    <div>제시어: <span id="word"></span></div>
    <input type="text"><button>입력</button>
</body>

</html>

 

<script>
        const person = Number(prompt('참가자를 입력해주세요'));

        if (person) {
            const $number = document.querySelector('#number');
            const $button = document.querySelector('button');
            const $input = document.querySelector('input');
            const $word = document.querySelector('#word');

            let word; //제시어를 저장하는 변수
            let newWord; //새로 입력된 제시어를 저장
            const onClickButton = () => {
                //제시어가 비어있거나 세글자이거나 입력한 단어가 올바른지?
                if (newWord.length === 3 && (!word || word[word.length - 1] === newWord[0])) {
                    word = newWord;
                    $word.textContent = word;
                    const playOrder = Number($number.textContent); //참가자 순서
                    if (playOrder + 1 > person) {
                        $number.textContent = 1; //다시 첫번째 순서로 돌아간다
                    } else {
                        $number.textContent = playOrder + 1;
                    }
                }

                else {
                    alert('틀렸습니다');
                }
                $input.value = '';
                $input.focus();
            }

            //입력한 단어를 newWord에 저장
            const onInput = (event) => {
                newWord = event.target.value;
            }

            $button.addEventListener('click', onClickButton);
            $input.addEventListener('input', onInput);
        } else {
            alert('게임을 취소했습니다');
        }
    </script>

 

지금까지 js 공부하면서 한번도 순서도 그려본 적이 없었는데

이렇게 공부하니까 내가 왜 지금까지 문법을 알아도 로직을 제대로 못짜고 시간이 오래 걸렸는지 알겠다...😭

절차를 차근차근 생각 안하고 직관적으로 코드를 짜고 있어서 그랬던거였다 사람이 생각하는 것 처럼 그냥 이렇게 하면 당연하게 되니까 라는 식의 생각을 버리고 좀 더 컴퓨터적으로 생각하는 연습을 해야겠다

728x90

댓글