틱택토는 삼목게임이다.
이런식으로 상대방과 O, X를 번갈아 놓으면서 먼저 한 줄로 놓으면 승리하게 된다.
구현해야 될 것들.
1. 화면을 클릭한다.
2. 클릭된 화면에 O가 나온다
3. 그 다음 클릭에서는 X가 나오고 계속 반복된다.
4. 만약 한 줄로 만들었다면 누가 승리했는지 알 수 있어야한다.
5. 게임이 끝나면 다시하기버튼이 나와서 클릭시 다시 처음부터 게임을 시작하게 한다.
<body>
<img class="main-logo" src="./images/vc.png" alt="Vanilla Coding Logo" />
<h1>Tick Tack Toe</h1>
<form action="" class="start-button">
<button>게임시작</button>
</form>
<div class="check-box">
<div class="check-o">⭕️ 차례</div>
<div class="check-x">❌ 차례</div>
</div>
<form action="" class="reset-button">
//<button onclick="location.reload()">다시시작</button> js파일로 옮겨서 이벤트처리로 변경
<button>다시시작</button>
</form>
<section>
<div class="board">
</div>
</section>
<script src="./app/index.js"></script>
</body>
html에서 특별한 부분은 없다. 저렇게 삼목이 나오는 부분은 table로 해서 만들어 줬는데 자바스크립트에서 DOM으로 작업을 했다. 그리고 승리하는 사람이 나오거나 무승부가 되면은 다시하기가 나와야되서 그 부분을 onClick을 줘서 페이지를 reload하게 해주었다. 더 나은 방법이 없나 고민해보자.
table {
border-collapse: collapse;
}
td {
width: 200px;
height: 200px;
border: 1px solid black;
text-align: center;
}
.start-button {
text-align: center;
margin-bottom: 20px;
}
.start-button button {
width: 75px;
height: 50px;
}
.reset-button {
display: none;
}
.check-o,
.check-x {
display: none;
}
.active {
font-size: 45px;
text-align: center;
margin: 10px;
}
display: none은 아예 안보인다. 그 안에 어떤 효과를 넣어줘도 display: none이기 때문에 화면에 보이지 않는다. 자바스크립트에서 클래스를 지웠다가, 넣었다가 할 수 있는게 있는데 Classlist.add() / Classlist.remove()로 클래스를 지우기도, 다시 추가해주기도 할 수 있다. 두 개의 키워드를 이용해 O, X를 누가 누를지에 대해 화면에 나오게 하는 부분을 구현해주었다.
const startButton = document.querySelector(".start-button");
function hadnleGameStart(event) {
event.preventDefault();
//게임버튼을 눌러야 게임이 시작, 그전에 칸을 눌러도 아무런 동작을 하지 않는다.
if (event.target.textContent === "게임시작") {
onFirstTurn.classList.remove(first);
onFirstTurn.classList.add(active);
startButton.classList.add(first);
table.addEventListener("click", handleCheck);
}
}
let myTurn = "⭕️";
let rows = [];
let squares = [];
const first = "check-o";
const second = "check-x";
const active = "active";
const whiteBoard = document.querySelector(".board");
const onFirstTurn = document.querySelector(".check-o");
const onSecondTurn = document.querySelector(".check-x");
const checkBox = document.querySelector(".check-box");
const resetBox = document.querySelector(".reset-button");
const table = document.createElement("table");
const result = document.createElement("div");
//이중반복문의 가장 기초적인부문, rows의 cells을 넣어주고, cells의 td를 넣어준다
//rows 줄, cells 칸
for (let i = 0; i < 3; i++) {
let cells = [];
rows.push(cells);
const tr = document.createElement("tr");
table.append(tr);
for (let j = 0; j < 3; j++) {
const td = document.createElement("td");
cells.push(td);
tr.append(td);
}
}
whiteBoard.append(table);
checkBox.append(result);
const oneRows = rows.flat();
let count = 0;
function finishMessage() {
result.classList.add(active);
table.removeEventListener("click", handleCheck);
onFirstTurn.classList.add(first);
onSecondTurn.classList.add(second);
resetBox.classList.remove("reset-button");
resetBox.classList.add("start-button");
return;
}
function handleCheck(event) {
if (event.target.textContent !== "") {
return;
}
event.target.textContent = myTurn;
for (let i = 0; i < oneRows.length; i++) {
squares[i] = oneRows[i].textContent;
}
// for문을 이용해 oneRows의 요소들을 squares라는 변수에 넘겨주고
// O, X가 몇 번째 칸에 있는지를 알 수 있게한다.
// 또는 map 메소드를 이용해서
// const squares = oneRows.map((el) => {
// return el.textContent
// });
const whoIsWin = calculateWinner(squares);
if (whoIsWin) {
result.textContent = `${myTurn}님의 승리!!`;
finishMessage();
}
if (count !== 9) {
count += 1;
if (count === 9) {
result.textContent = `무승부입니다.`;
finishMessage();
}
}
if (myTurn === "⭕️") {
myTurn = "❌";
onFirstTurn.classList.add(first);
onFirstTurn.classList.toggle(active);
onSecondTurn.classList.remove(second);
onSecondTurn.classList.toggle(active);
} else {
myTurn = "⭕️";
onFirstTurn.classList.remove(first);
onFirstTurn.classList.toggle(active);
onSecondTurn.classList.add(second);
onSecondTurn.classList.toggle(active);
}
}
startButton.addEventListener("click", hadnleGameStart);
resetButton.addEventListener("click", () => {
window.location.reload();
});
calculatorWinner()함수가 없는데 따로 구현되어 있는 부분을 가지고와서 작업했던거라 그 부분은 뺐다.
이번 과제에서 가장 어려웠던 부분은
1. 클릭 했을 때, 내가 몇 번째 칸을 클릭했는가
2. 클릭이 되었다면 O가 들어가고 그 다음에 X가 나오게하고 번갈아 들어가게 하는 것
3. for문과 map을 이용해서 작업했던 클릭을 했다면 그것을 배열에 넣어서 배열안에 요소들을 알 수 있는 법
3번이 특히나 어려웠다. 그 문제로 삼일은 끙끙 앓았던 것 같다. 배열과 문자열에 대한 공부가 많이 부족해서 생긴 문제였기도 했다. 정답을 찾으려는 것보다 정답을 찾아가는 길을 잘 알아보자 계속 그 문제 때문에 문제를 겪고 있으니.. 누군가에게 물어 볼 때도 문제에 대한 인식과 문제를 찾아가는 방향에 대해서 묻자
코드리뷰
1. event.target - event.currentTarget 에 대한 차이점
- event.target은 부모로부터 이벤트가 위임되어 발생하는 자식의 위치, 내가 클릭한 자식요소를 반환 / 가장 마지막 위치한 최하위의 요소를 반환
- event.currentTarget은 이벤트가 부착된 부모의 위치를 반환한다.
2. Inlin으로 로직을 작성하는 것보다는 스트립트 로직은 js 파일 내에서 사용하는게 좋다.
- location.reload()를 html에서 넣어줬던 부분을 빼서, js에서 이벤트로 처리로 변경
3. 변수명은 늘 명확하게! 숫자를 사용할 때는 불분명하게 사용되면 매직 넘버라고 불리는 안티 패턴이다! 변수 선언해서 사용!
- 변수명 변경 및 숫자를 spaceNumber로 변경
4. html태그네임을 사용할 때는 명확하게 지어주자
- 태그들 앞에 $를 붙여줬음
5. 메소드의 사용법을 익히는 방법은 기초 알고리즘을 많이 풀자 !
6. 무승부를 이용해줄 때 count 를 if문을 중첩해주었는데 그것보다는 count 를 먼저 1을 더해주고 9가 되었을 때 로직이 돌아가게 되고 reutrn 을 이용해 early return을 사용해서 중첩된 if문을 줄이자 !
7. reset 을 페이지가 새로고침되게 해주었는데 내가 필요한 부분만 초기화시키는 함수 로직을 만들어서 사용해보자. (8월 2주 수정할 예정)
'바닐라코딩' 카테고리의 다른 글
3주차 과제 카드퀴즈만들기 (0) | 2021.08.11 |
---|---|
3주차 강의 ES2015 & beyond (0) | 2021.08.07 |
2주차 강의 (0) | 2021.07.25 |
1주 - 첫 과제 (0) | 2021.07.23 |
1주차 JavaScript Review (0) | 2021.07.20 |