Web Front-end 공부/Java script
Js 끝말잇기 게임 만들기
Hanachoi
2022. 5. 24. 16:30
- 끝말잇기 게임의 대략적인 순서도
- 몇 명이 참가할지 선택한다
- 참가자 순서를 정한다
- 첫 번째 사람이 제시어를 말한다
- 다음사람이 단어를 말한다
- 단어가 올바른가? 판단해본다
- 올바르다면 : 다시 4번으로 올라가 다음사람이 단어를 말한다. 4-5-5.1 계속 반복
- 틀렸다면 : 틀렸다고 표시한다 -> 끝
- 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문 밖으로 빼내버렸다.