반응형
- 04_직접이동02_그리드D11_dom_비동기실습_암기
- 01_스네이크
- 01_기본
- 스네이크는 중요하다.
- 알고리즘이 중요한게 많이 들어갔다.
- snake1.html
- <button id="playBtn" onclick="gameStart()">▷ Play</button>
- 이 gameStart()" 함수는 뱀의 속도만 빠르게 하는 함수이지. 키 이동은 사용자가 하는것
- 05 자동이동에 나온다.
- 사용자가 앞으로 화살표 버튼을 누르기 귀찮으니까 만든것 같다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<!--링크 걸면 css파일을 쓸 수 있다. -->
<title>Document</title>
</head>
<body>
<table id="header">
<tr>
<td colspan="3"><h1>Snake Game</h1></td>
</tr>
<tr>
<td id="imgTd">
<img id="appleImg" src="../apple.png">
</td>
<td id="scoreTd">
0
</td>
<td id="playTd">
<button id="playBtn" onclick="gameStart()">▷ Play</button>
</td>
</tr>
</table>
<table id="content">
<tr>
<td id="myGame" colspan="3"></td>
</tr>
</table>
<div id="msg"></div>
</body>
</html>
- style.css
#playBtn {
width: 180px;
height: 60px;
font-size: 20px;
font-weight: bold;
background-color: tomato;
color: white;
border-style: none;
border-radius: 8px;
margin: 30px 0px;
cursor: pointer;
}
#msg {
margin: 0 auto;
text-align: center;
font-size: 30px;
font-weight: bold;
margin-top: 20px;
width: 300px;
height: 80px;
color: tomato;
}
#imgTd {
width: 50px;
}
#scoreTd {
text-align: center;
width: 50px;
font-size: 30px;
font-weight: bold;
}
#playTd {
text-align: right;
}
#header {
margin: 0 auto;
margin-top: 30px;
text-align: center;
width: 700px;
height: 200px;
}
#content {
margin: 0 auto;
text-align: left;
}
#appleImg {
width: 50px;
}
#snake {
border-collapse: collapse;
width: 600px;
height: 600px;
}
#snake td {
border: 1px solid lightgray;
background-color: rgb(245, 244, 244);
}
#snake .snakeBody {
background-color: rgb(2, 191, 2);
}
#snake .snakeHead {
background-color: rgba(15, 117, 4, 0.84);
}
#snake .item {
background-color: tomato;
}
- 02_그리드
- snake2.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="style.css"><!--css링크 걸음 --><title>Document</title></head><body><table id="header"><tr><td colspan="3"><h1>Snake Game</h1></td></tr><tr><td id="imgTd"><img id="appleImg" src="../apple.png"></td><td id="scoreTd">0</td><td id="playTd"><button id="playBtn" onclick="gameStart()">▷ Play</button></td></tr></table>
<table id="content"><tr><td id="myGame" colspan="3"></td></tr></table>
<div id="msg"></div>
<script src="snake2.js"></script><!-- 자바스크립트 링크 걸음 --></body></html>
- snake2.js
-
//script는 쓰면 안된다.
let size = 15; //가로 . 세로 / 이 값은 뱀의 이동 범위 및 아이템 생성 위치의 범위를 결정합니다.let snakeSize = 4; // 뱀이 시작할 때. 4칸이다.
let data = []; //전체 그리드의 데이터 // 000000000000000000(0으로 되어 있다. )//뱀이 있는 곳에 1234를 그릴 거다. / 게임판의 상태를 저장하는 2차원 배열입니다./*123400000 (뱀이 있는 곳을 1234라고 가정할 거다. )000000000000000000000000000*///뱀이 있는 곳 . 위치let yList = [0, 0, 0, 0];let xList = [0, 1, 2, 3];
let item = 9; //아이템 총 갯수 // 아이템을 먹으면 꼬리가 길어진다.let itemCount = 0; // 현재 아이템let dir = 1; // 북(0) 동(1) 남(2) 서(3)
let gameOver = false;let count = 3; //게임오버에서 시작할때. 기다리는 시간
let myInterval = null; //인터벌. 자동으로 1초마다 움직임let myTimeout = null; //인터벌 정지
//위의것들 . 변수 세팅//-----------------------------------
function getTable() {$myGame = document.querySelector("#myGame");
$table = document.createElement("table");$table.id = "snake"; //테이블을 스네이크로 잡은것
for(let i=0; i<size; i++) {$tr = document.createElement("tr");for(let j=0; j<size; j++) {$td = document.createElement("td");$tr.append($td);}$table.append($tr);}
$myGame.append($table);
return $table;}
getTable();
- style.css
#playBtn {
width: 180px;
height: 60px;
font-size: 20px;
font-weight: bold;
background-color: tomato;
color: white;
border-style: none;
border-radius: 8px;
margin: 30px 0px;
cursor: pointer;
}
#msg {
margin: 0 auto;
text-align: center;
font-size: 30px;
font-weight: bold;
margin-top: 20px;
width: 300px;
height: 80px;
color: tomato;
}
#imgTd {
width: 50px;
}
#scoreTd {
text-align: center;
width: 50px;
font-size: 30px;
font-weight: bold;
}
#playTd {
text-align: right;
}
#header {
margin: 0 auto;
margin-top: 30px;
text-align: center;
width: 700px;
height: 200px;
}
#content {
margin: 0 auto;
text-align: left;
}
#appleImg {
width: 50px;
}
#snake {
border-collapse: collapse;
width: 600px;
height: 600px;
}
#snake td {
border: 1px solid lightgray;
background-color: rgb(245, 244, 244);
}
#snake .snakeBody {
background-color: rgb(2, 191, 2);
}
#snake .snakeHead {
background-color: rgba(15, 117, 4, 0.84);
}
#snake .item {
background-color: tomato;
}
- 03_초기화
- 계속 지우고 그리고를 하는것이다.
- snake3.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="style.css"><title>Document</title></head><body><table id="header"><tr><td colspan="3"><h1>Snake Game</h1></td></tr><tr><td id="imgTd"><img id="appleImg" src="../apple.png"></td><td id="scoreTd">0</td><td id="playTd"><button id="playBtn" onclick="gameStart()">▷ Play</button></td></tr></table>
<table id="content"><tr><td id="myGame" colspan="3"></td></tr></table>
<div id="msg"></div>
<script src="snake3.js"></script></body></html>
- snake3.js
let size = 15;let snakeSize = 4;
let data = [];//게임판의 상태를 저장하는 2차원 배열입니다.//나중에 init() 함수에서 15 x 15 크기의 배열로 초기화되며,// 0은 빈 칸// 1~N은 뱀의 몸통 (1이 꼬리, N이 머리)9는 아이템 위치등을 의미합니다.
//뱀의 현재 위치를 저장하는 배열입니다.let yList = [0, 0, 0, 0];let xList = [0, 1, 2, 3];
let item = 9; //아이템 갯수가 아니라. 색깔을 표현한것let itemCount = 0; // 지금까지 먹은 아이템의 개수입니다.let dir = 1; // 북(0) 동(1) 남(2) 서(3)
let gameOver = false;let count = 3;
let myInterval = null;let myTimeout = null;//----------------------------------------------//호출되면 게임에 사용할 HTML 테이블을 생성하고, DOM에 추가한 뒤 테이블 객체를 반환합니다.function getTable() {$myGame = document.querySelector("#myGame");
$table = document.createElement("table");$table.id = "snake";
for(let i=0; i<size; i++) {$tr = document.createElement("tr");for(let j=0; j<size; j++) {$td = document.createElement("td");$tr.append($td);}$table.append($tr);}
$myGame.append($table);
return $table;}//----------------------------------------//init() 함수는 게임의 초기 상태를 설정하는 함수function init() { //initialize"의 줄임말로, 게임을 시작하기 전에 뱀과 맵을 초기 설정하는 역할을 합니다.//전부 0의 값을 넣은것for(let i=0; i<size; i++) {let temp = [];//새로 한 행을 저장할 임시 배열입니다.//각 행마다 이 배열을 초기화해서, 나중에 data.push(temp)로 2차원 배열을 구성합니다.for(let j=0; j<size; j++) {temp.push(0);}data.push(temp); // 여기서 2차원 배열이 된다.}/*데이터에 뭘 칠할지를 모른다. 위치를 모른다.000000000000000000000000000000000000000000000000그리드에다가 데이터값을 넣어놓은것.한칸한칸을 0으로 넣은것*///------------------------------------------------//뱀이 있는곳을 찾아서 1234를 넣어준것//뱀 위치를 저장해놓음//let yList = [0, 0, 0, 0];//let xList = [0, 1, 2, 3];
let $table = document.querySelector("#snake");for(let i=0; i<snakeSize; i++) {//뱀 위치만큼 돌면서data[yList[i]][xList[i]] = i + 1; //뱀 위치에 1234 넣은것//1: 꼬리 4: 머리$table.children[[yList[i]]].children[xList[i]].setAttribute("class", "snakeBody");//css에 있다. 색깔을 넣어준것//클래스 값을 넣어서 색을 칠한다.//해당 위치의 <td> 셀을 찾아서 class="snakeBody"를 지정합니다.}$table.children[yList[snakeSize - 1]].children[xList[snakeSize - 1]].setAttribute("class", "snakeHead");//뱀의 머리. 머리에는 진한 초록색을 넣는다.//뱀의 맨 마지막 좌표가 머리이므로, snakeSize - 1번째 인덱스를 사용합니다.//해당 위치의 셀에 class="snakeHead"를 추가하여 CSS에서 머리 부분만 다른 색상 등으로 표현할 수 있습니다.}//------------------------------------//아이템 / 랜덤하게 아이템을 하나 생성하는 함수function setItem() {while(true) {//왜 while//랜덤으로 위치를 뽑음//스네이크 1234를 피해야 한다. 그리고 랜덤으로 위치를 찾아서 아이템을 넣는다.//1234를 피해서 찾을때까지. 그래서 while를 넣은것let y = Math.floor(Math.random() * size);let x = Math.floor(Math.random() * size);if(data[y][x] == 0) {//0이 비여있는거니까. 빈 로드를 찾을때까지 무한 반복한다.data[y][x] = item; //아이템은 9로 표현한것//item은 숫자 9로 정의되어 있으므로, data[y][x] = 9가 됩니다.//이 칸에 아이템이 있다는 의미로 9를 저장합니다.let $table = document.querySelector("#snake");$table.children[y].children[x].setAttribute("class", "item");// children 은 테이블에서만 쓸 수 있다.(키워드이다) tr td라고 보면 된다.// 첫번째 칠드런은 tr / 두번째 칠드런은 td이다.// 아이템 색칠한것
break;}}}
getTable();init();setItem();
- style.css
-
#playBtn {width: 180px;height: 60px;font-size: 20px;font-weight: bold;background-color: tomato;color: white;border-style: none;border-radius: 8px;margin: 30px 0px;cursor: pointer;}
#msg {margin: 0 auto;text-align: center;font-size: 30px;font-weight: bold;margin-top: 20px;width: 300px;height: 80px;color: tomato;}
#imgTd {width: 50px;}#scoreTd {text-align: center;width: 50px;font-size: 30px;font-weight: bold;}#playTd {text-align: right;}
#header {margin: 0 auto;margin-top: 30px;text-align: center;width: 700px;height: 200px;}#content {margin: 0 auto;text-align: left;}
#appleImg {width: 50px;}
#snake {border-collapse: collapse;width: 600px;height: 600px;}
#snake td {border: 1px solid lightgray;background-color: rgb(245, 244, 244);}
#snake .snakeBody {background-color: rgb(2, 191, 2);}#snake .snakeHead { /* 머리 */background-color: rgba(15, 117, 4, 0.84);}#snake .item {background-color: tomato;}
- 04_직접이동
- 함수
- function moveSnake(dir) {
- snake4.js
let size = 15;let snakeSize = 4;
let data = [];let yList = [0, 0, 0, 0]; // 머리 = xList[3]let xList = [0, 1, 2, 3]; // 머리 = yList[3]let item = 9;let itemCount = 0;let dir = 1; // 북(0) 동(1) 남(2) 서(3)
let gameOver = false;let count = 3;
let myInterval = null;let myTimeout = null;
function getTable() {$myGame = document.querySelector("#myGame");
$table = document.createElement("table");$table.id = "snake";
for(let i=0; i<size; i++) {$tr = document.createElement("tr");for(let j=0; j<size; j++) {$td = document.createElement("td");$tr.append($td);}$table.append($tr);}
$myGame.append($table);
return $table;}
function init() {for(let i=0; i<size; i++) {let temp = [];for(let j=0; j<size; j++) {temp.push(0);}data.push(temp);}
let $table = document.querySelector("#snake");for(let i=0; i<snakeSize; i++) {data[yList[i]][xList[i]] = i + 1; // <<< 여기에서 data에 뱀의 위치를 기록함//뱀의 각 위치를 몸통 순서로 저장하기 위해 숫자를 넣음// i + 1 : 0부터 시작하는 인덱스를 1부터 시작하는 몸통 번호로 바꿈$table.children[[yList[i]]].children[xList[i]].setAttribute("class", "snakeBody");}$table.children[yList[snakeSize - 1]].children[xList[snakeSize - 1]].setAttribute("class", "snakeHead");
}
function setItem() {while(true) {let y = Math.floor(Math.random() * size);let x = Math.floor(Math.random() * size);if(data[y][x] == 0) {data[y][x] = item; //위에서 변수 설정함. 9 // 즉 아이템 자리를 9로 바꾸겠다.let $table = document.querySelector("#snake");$table.children[y].children[x].setAttribute("class", "item");
break;}}}
//-------------------------------------------------//뱀을 움직이는 핵심 로직function moveSnake(dir) {//function moveSnake(dir)에서 dir은 **매개변수(parameter)**이고, 함수의 괄호 안에 매개변수를 넣는 건 외부에서 데이터를 전달받기 위해서입니다.//moveSnake 함수는 키보드 방향키를 눌렀을 때 뱀을 해당 방향(dir)으로 움직이게 하는 함
let $table = document.querySelector("#snake"); //스네이크 찾아서
// 스네이크 이동아님. 다음 위치 저장하기 / 왜냐 다음 위치를 갈 수 없을 수도 있으니까.let tempY = yList[snakeSize - 1]; // 머리 X 좌표let tempX = xList[snakeSize - 1]; // 머리 Y 좌표// 현재 머리 위치에서 다음 방향으로 이동하기 위해 tempX, tempY에 저장하는 거예요.if(dir == 0) {tempY -= 1;} else if(dir == 1) {tempX += 1;} else if(dir == 2) {tempY += 1;} else if(dir == 3) {tempX -= 1;}//가는지 못가는지 체크한것//위 아래 체크//💥 충돌 체크 (벽 또는 몸에 부딪힘)if(size <= tempY || tempY < 0) {gameOver = true;return; // moveSnake 함수 실행 종료 → 아래 코드 실행 안 함
//return;은 함수 실행을 즉시 중단시키고, 함수 밖으로 나간다는 뜻이에요.//moveSnake(dir) 함수 내부니까, 이 조건이 참이면 뱀 이동을 아예 안 하고 멈춤.}//좌우if(size <= tempX || tempX < 0) {gameOver = true;return;}//자기 몸에 붇히혔을 때 . 아이템은 아니고if(data[tempY][tempX] != 0 && data[tempY][tempX] != item) {gameOver = true;return;}//------------------------------------------------------------//우선 다 지움// 기존 위치 초기화 //현재 위치를 0으로 만든다. / 회색으로 칠한다.for(let i=0; i<snakeSize; i++) {$table.children[[yList[i]]].children[xList[i]].setAttribute("class", "");//회색으로 칠함data[yList[i]][xList[i]] = 0; //0으로 만듬}$table.children[yList[snakeSize - 1]].children[xList[snakeSize - 1]].setAttribute("class", "");////머리도 0으로 바꿈//-----------------------------------------//🍎 아이템 먹었을 때 처리// 아이템을 먹으면 //배열이 늘어난다.// 스네이크의 몸 길이가 늘어남//let yList = [0, 0, 0, 0]; //뒤에가 머리이다.//let xList = [0, 1, 2, 3];//앞쪽이 꼬리라서. 꼬리가 늘어나야 한다.if(data[tempY][tempX] == item) { //➡️ 만약 이동한 위치가 아이템이라면:yList.unshift(tempY); //unshift (앞의 저장) // 꼬리가 늘어나기 위해 //뒤의 저장은 puch이다.xList.unshift(tempX);//배열 늘리기 위해 저장
snakeSize += 1; // 4->5로 바꿈itemCount += 1; // 1 증가document.querySelector("#scoreTd").innerText = itemCount; //아이템 개수 바꿈
setItem(); //새아이템}//--------------------------------------//🐍 뱀 좌표 리스트 업데이트 (몸통 이동)// 스네이크 이동 . 다음위치로 이동for(let i=1; i<snakeSize; i++) {yList[i - 1] = yList[i];xList[i - 1] = xList[i];}yList[snakeSize - 1] = tempY;xList[snakeSize - 1] = tempX;// 스네이크 표시for(let i=0; i<snakeSize; i++) {//몸통 그리기$table.children[[yList[i]]].children[xList[i]].setAttribute("class", "snakeBody");data[yList[i]][xList[i]] = i + 1; //1234 넣기}$table.children[yList[snakeSize - 1]].children[xList[snakeSize - 1]].setAttribute("class", "snakeHead");//머리 그리기
}//------------------------------------------------//이렇게 키를 받을 수 있다.//키를 e에 들어온다.//우리는 화살표로 했다.//🟡 window 객체에 "keydown" 이벤트 리스너를 추가합니다.// keydown은 키보드 키를 눌렀을 때 발생하는 이벤트예요.// (e)는 이벤트 객체를 받기 위한 매개변수입니다. 어떤 키가 눌렸는지를 e에서 확인할 수 있어요.window.addEventListener("keydown", (e) => {let key = e.code;// 북(0) 동(1) 남(2) 서(3)console.log(key);if(key == "ArrowLeft") {dir = 3;moveSnake(dir); //무브 스네이크를 한번 해준것. 즉 함수를 실행한것} else if(key == "ArrowRight") {dir = 1;moveSnake(dir);} else if(key == "ArrowUp") {dir = 0;moveSnake(dir);} else if(key == "ArrowDown") {dir = 2;moveSnake(dir);}});
getTable();init();setItem();
- snake5.js
let size = 15;
let snakeSize = 4;
let data = [];
let yList = [0, 0, 0, 0];
let xList = [0, 1, 2, 3];
let item = 9;
let itemCount = 0;
let dir = 1; // 북(0) 동(1) 남(2) 서(3)
let gameOver = false;
let count = 3;
let myInterval = null;
let myTimeout = null;
function setItem() {
while(true) {
let y = Math.floor(Math.random() * size);
let x = Math.floor(Math.random() * size);
if(data[y][x] == 0) {
data[y][x] = item;
let $table = document.querySelector("#snake");
$table.children[y].children[x].setAttribute("class", "item");
break;
}
}
}
function init() {
for(let i=0; i<size; i++) {
let temp = [];
for(let j=0; j<size; j++) {
temp.push(0);
}
data.push(temp);
}
let $table = document.querySelector("#snake");
for(let i=0; i<snakeSize; i++) {
data[yList[i]][xList[i]] = i + 1;
$table.children[[yList[i]]].children[xList[i]].setAttribute("class", "snakeBody");
}
$table.children[yList[snakeSize - 1]].children[xList[snakeSize - 1]].setAttribute("class", "snakeHead");
setItem();
}
function getTable() {
$myGame = document.querySelector("#myGame");
$table = document.createElement("table");
$table.id = "snake";
for(let i=0; i<size; i++) {
$tr = document.createElement("tr");
for(let j=0; j<size; j++) {
$td = document.createElement("td");
$tr.append($td);
}
$table.append($tr);
}
$myGame.append($table);
return $table;
}
function setCount() {
if(count >= 0) {
document.querySelector("#msg").innerHTML = "Game Over<br>" + count;
} else {
clearInterval(myTimeout);
location.href = "snake5.html";
}
myTimeout = setTimeout(setCount, 1000);
count -= 1;
}
function moveSnake() {
// 게임 종료
if(gameOver) {
console.log("Game Over");
setCount();
clearInterval(myInterval);
}
let $table = document.querySelector("#snake");
// 스네이크 이동
let tempY = yList[snakeSize - 1];
let tempX = xList[snakeSize - 1];
if(dir == 0) {
tempY -= 1;
} else if(dir == 1) {
tempX += 1;
} else if(dir == 2) {
tempY += 1;
} else if(dir == 3) {
tempX -= 1;
}
if(size <= tempY || tempY < 0) {
gameOver = true;
return;
}
if(size <= tempX || tempX < 0) {
gameOver = true;
return;
}
if(data[tempY][tempX] != 0 && data[tempY][tempX] != item) {
gameOver = true;
return;
}
// 기존 위치 초기화
for(let i=0; i<snakeSize; i++) {
$table.children[[yList[i]]].children[xList[i]].setAttribute("class", "");
data[yList[i]][xList[i]] = 0;
}
$table.children[yList[snakeSize - 1]].children[xList[snakeSize - 1]].setAttribute("class", "");
// 아이템을 먹으면
if(data[tempY][tempX] == item) {
yList.unshift(tempY);
xList.unshift(tempX);
snakeSize += 1;
itemCount += 1;
document.querySelector("#scoreTd").innerText = itemCount;
setItem();
}
// 스네이크 이동
for(let i=1; i<snakeSize; i++) {
yList[i - 1] = yList[i];
xList[i - 1] = xList[i];
}
yList[snakeSize - 1] = tempY;
xList[snakeSize - 1] = tempX;
// 스네이크 표시
for(let i=0; i<snakeSize; i++) {
$table.children[[yList[i]]].children[xList[i]].setAttribute("class", "snakeBody");
data[yList[i]][xList[i]] = i + 1;
}
$table.children[yList[snakeSize - 1]].children[xList[snakeSize - 1]].setAttribute("class", "snakeHead");
}
function gameStart() {
myInterval = setInterval(moveSnake, 100); //moveSnake을 0.1초마다 움직여라 반복
//버튼 못눌리도록 막음
document.querySelector("#playBtn").setAttribute("disabled", true);
document.querySelector("#playBtn").style.background = "lightgray";
}
window.addEventListener("keydown", (e) => {
let key = e.code;
// 북(0) 동(1) 남(2) 서(3)
if(key == "ArrowLeft") {
dir = 3;
} else if(key == "ArrowRight") {
dir = 1;
} else if(key == "ArrowUp") {
dir = 0;
} else if(key == "ArrowDown") {
dir = 2;
}
});
getTable();
init();
반응형
'코딩 > 1-JavaScript' 카테고리의 다른 글
01_캔버스요소 => _00_canvas , _01_line (0) | 2025.06.11 |
---|---|
02_테트리스 (1) | 2025.06.10 |
03_클래스버전_전체스태틱 - _01_member (2) | 2025.06.09 |
D10_dom_SPA_암기 => 01_json버전 => _01_모듈화, _02_모둘화와html (0) | 2025.06.09 |
D10_dom_SPA_암기 => 01_json버전 => _00_basic => _01_json과함수, _02_json과Controller (0) | 2025.06.09 |