반응형
- 그리드를 만들어서 . 그림을 그려서 꼼수로 할꺼다.
- 실제로는 움직이는 않는다.
- 그리드를 만들어서 . 색칠하는거다.
- 스네이크는 검사를 4군대만 하면 된다. 위 아래 왼쪽 오른쪽
- 테트리스 왼쪽은 3개. 아래는 3개. 오른쪽은 1개를 검사해야해서. 어렵다.
- 02_테트리스
- _01_초기화
- tetris01.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Tetris Game</title>
<style>#center {margin: 0 auto;text-align: center;}#myTetris {border-collapse: collapse;}#myTetris td {border: 1px solid black;width: 30px;height: 30px;}.gray { background-color: gray; }</style>
</head><body><table id="center"><tr><td><h1>테트리스</h1></td></tr><tr><td id="tetrisCenter"></td></tr></table>
<script src="tetris01.js"></script></body></html>
- tetris01.js
let row = 22; // 세로 길이let col = 12; // 가로 길이//외각선을 줄려고 2를 더 한것//벽(gray)을 추가하기 위해 12칸을 설정한 것으로 보입니다.
let dataList = []; // 테트리스의 숫자구성//- 이 배열은 테트리스의 **게임 상태를 저장**하는 2차원 배열입니다.// - `dataList[i][j]` 형태로 각 셀에 접근할 수 있으며, 그 셀의 상태(빈칸인지, 벽인지, 블록인지 등)를 숫자로 저장합니다.// - 예: `0`이면 빈칸, `8`이면 회색 벽, `1~7`은 블록 종류 등/*00000000000000000000000000000000000000000000000000테트리스 표현*/let colorList = ["white", "green", "red", "purple", "orange", "blue", "yellow", "skyblue", "gray", "black"];//// 뜷린것 white//테트리스 색깔 : "green", "red", "purple", "orange", "blue", "yellow", "skyblue",//외각선 : gray//죽은 테트리스 : black
// 자주 사용하는 값을 상수화const WHITE = 0; //뚫린것//- `WHITE`라는 이름으로 상수(변하지 않는 값) 선언// 의미: 빈칸(0)을 표현할 때 코드 가독성을 높이기 위해 `0` 대신 `WHITE`를 씁니다.const GRAY = 8; //외각선const BLACK = 9; //죽은 테트리스
//✅ **요약**// 이 변수들과 상수는 테트리스 게임의 **보드 크기와 셀의 상태, 시각적 표현을 준비**하는 부분입니다.// dataList`는 전체 상태를 저장하고, `colorList`는 숫자 상태를 색으로 변환할 수 있게 도와줍니다.// `WHITE`, `GRAY`, `BLACK`은 숫자에 의미를 부여해서 코드 가독성을 높이는 역할입니다.
//---------------------------------------------// 초기화// 게임을 시작할 때 테트리스 판을 만들고, 데이터를 초기 상태로 설정하는 역할을 합니다.function init() {
// 테트리스 표 그리기, dataList 0으로 채우기let $tetrisCenter = document.querySelector("#tetrisCenter");let $myTetris = document.createElement("table");$myTetris.id = "myTetris";for(let i=0; i<row; i++) { //세로 방향으로 반복합니다. (총 22줄)let temp = []; //이 행에 해당하는 한 줄의 데이터를 저장할 배열을 만듭니다.let $tr = document.createElement("tr");for(let j=0; j<col; j++) { //가로 방향으로 반복합니다. (총 12칸)let $td = document.createElement("td");$tr.append($td);temp.push(0);//이 셀의 데이터 상태를 `0`으로 초기화하고 `temp` 배열에 저장합니다.//`0`은 빈칸을 의미합니다.}dataList.push(temp);// 완성된 한 줄의 데이터(`temp`)를 `dataList`에 추가합니다.// 결과적으로 `dataList`는 `2차원 배열`이 되며, 테트리스의 전체 상태를 담습니다.
$myTetris.append($tr);//만들어진 <tr> 행을 테이블에 추가합니다.}$tetrisCenter.append($myTetris);//완성된 테이블을 실제 HTML 문서의 #tetrisCenter 영역에 추가하여 화면에 보이게 합니다.//-------------------------------------------------------// 첫 번째 for 반복문: 세로 벽(좌우 끝 줄)을 GRAY로 설정// 테트리스 세로 8(gray)으로 채우기 + class이름을 gray로 설정// 왼쪽 오른쪽 벽 회색for(let i=0; i<row; i++) {dataList[i][0] = GRAY; //외각선 넣기dataList[i][col - 1] = GRAY;
$myTetris.children[i].children[0].className = colorList[GRAY];$myTetris.children[i].children[col-1].className = colorList[GRAY];}
// 테트리스 가로 8(gray)으로 채우기 + class이름을 gray로 설정// 위 아래 벽for(let i=0; i<col; i++) {dataList[0][i] = GRAY;dataList[row - 1][i] = GRAY;
$myTetris.children[0].children[i].className = colorList[GRAY];$myTetris.children[row - 1].children[i].className = colorList[GRAY];}
// dataList 화면에 표시하기for(let i=0; i<row; i++) {for(let j=0; j<col; j++) {$myTetris.children[i].children[j].innerText = dataList[i][j];}}
}
init();
- tetris02.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Tetris Game</title>
<style>#center {margin: 0 auto;text-align: center;}#myTetris {border-collapse: collapse;}#myTetris td {border: 1px solid black;width: 30px;height: 30px;}/* 테트리스 색깔 */.gray { background-color: gray; }.green { background-color: green; }.red { background-color: red; }.purple { background-color: purple; }.orange { background-color: orange; }.blue { background-color: blue; }.yellow { background-color: yellow; }.skyblue { background-color: skyblue; }.black { background-color: black; }</style>
</head><body><table id="center"><tr><td><h1>테트리스</h1></td></tr><tr><td id="tetrisCenter"></td></tr></table>
<script src="tetris02.js"></script></body></html>
- tetris02.js
let row = 22; // 세로 길이let col = 12; // 가로 길이let dataList = []; // 테트리스의 숫자구성let colorList = ["white", "green", "red", "purple", "orange", "blue", "yellow", "skyblue", "gray", "black"];
// 자주 사용하는 값을 상수화// 상수 값이 변하지 않도록 고정된 변수 / 다시는 바꿀 수 없습니다.// if (data[i][j] === 0) // ❌ 0이 무슨 의미인지 모름// if (data[i][j] === WHITE) // ✅ 흰색이라는 의미가 명확함// const => 변수 선언 할 때 사용하는거다. let과 마찬가지로. 하지만 변경이 불가const WHITE = 0;const GRAY = 8;const BLACK = 9;
//현재위치let curY = 0; // 처음 생성되는 블럭의 시작 y좌표let curX = 0; // 처음 생성되는 블럭의 시작 x좌표
let curBlock = null; //현재 블럭 // 현재 블럭의 정보 저장
let blockList = [ //블럭 종류{name: "s",color: 1, //인덱스.shape:[[0, 0, 0],[0, 1, 1],[1, 1, 0]]},{name: "z",color: 2,shape:[[0, 0, 0],[1, 1, 0],[0, 1, 1]]},{name: "t",color: 3,shape:[[0, 0, 0],[1, 1, 1],[0, 1, 0]]},{name: "l",color: 4,shape:[[0, 1, 0],[0, 1, 0],[0, 1, 1]]},{name: "j",color: 5,shape:[[0, 1, 0],[0, 1, 0],[1, 1, 0]]},{name: "o",color: 6,shape:[[1, 1],[1, 1]]},{name: "i",color: 7,shape:[[0, 0, 0, 0],[1, 1, 1, 1],[0, 0, 0, 0],[0, 0, 0, 0],]}];//-------------------------------------------------------------------// 초기화function init() {
// 테트리스 표 그리기, dataList 0으로 채우기let $tetrisCenter = document.querySelector("#tetrisCenter");let $myTetris = document.createElement("table");$myTetris.id = "myTetris";for(let i=0; i<row; i++) {let temp = [];let $tr = document.createElement("tr");for(let j=0; j<col; j++) {let $td = document.createElement("td");$tr.append($td);temp.push(0);}dataList.push(temp);$myTetris.append($tr);}$tetrisCenter.append($myTetris);
// 테트리스 세로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<row; i++) {dataList[i][0] = GRAY;dataList[i][col - 1] = GRAY;
$myTetris.children[i].children[0].className = colorList[GRAY];$myTetris.children[i].children[col-1].className = colorList[GRAY];}
// 테트리스 가로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<col; i++) {dataList[0][i] = GRAY;dataList[row - 1][i] = GRAY;
$myTetris.children[0].children[i].className = colorList[GRAY];$myTetris.children[row - 1].children[i].className = colorList[GRAY];}
// dataList 화면에 표시하기for(let i=0; i<row; i++) {for(let j=0; j<col; j++) {$myTetris.children[i].children[j].innerText = dataList[i][j];}}
}//------------------------------------------------------------------------// 랜덤으로 블럭 생성function setNewBlock() {
//현재위치는 이것으로 고정한것//이것을 기준으로 9칸을 그린거다.curY = 1;curX = 4;
let r = Math.floor(Math.random() * blockList.length);//let blockList 여기서 한개 뽑은것
//r = 1;curBlock = blockList[r];// 현재 블럭에 랜덤블럭 집어 넣기//이후 게임에서 이 블록을 움직이거나 회전할 때 사용함
//그리기let shape = curBlock.shape;//.shape는 위의 객체의 shape이다. 즉 여러개의 블록의 shape// shape.length란? shape에는 위의 2차원 배열이 들어가 있으므로//이 상태에서 shape.length를 출력하면 3입니다.👉 행(row)의 개수, 즉 세로 길이를 말해요.
for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {//그리기에서 1인것만 그린거다. //0일때는 색칠을 안함// curY = 1;// curX = 4;// 1,4 , 1,5 , 2,4 , 2,5// curY = 1// 1 + 0 , 1 + 1dataList[curY + y][curX + x] = blockList[r].color;//dataList[ y][ x] = blockList[r].color;}}}}//-------------------------------------------------------------// 화면 새로 색칠하기// 그냥 화면 전체를 다 지우고. 다시 그리는것 // 코드를 쉽게 하기 위해서. //다시 색칠하는 것function draw() {let $myTetris = document.querySelector("#myTetris");
for(let y=0; y<row; y++) {for(let x=0; x<col; x++) {let index = dataList[y][x];
$myTetris.children[y].children[x].className = colorList[index];//myTetris => 테이블//children => tr// children => td//index에서 .gray 이걸 클래스. => className$myTetris.children[y].children[x].innerText = dataList[y][x];}}}
init();setNewBlock(); //새로운 블럭draw();
- tetris03.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Tetris Game</title>
<style>#center {margin: 0 auto;text-align: center;}#myTetris {border-collapse: collapse;}#myTetris td {border: 1px solid black;width: 30px;height: 30px;}.gray { background-color: gray; }.green { background-color: green; }.red { background-color: red; }.purple { background-color: purple; }.orange { background-color: orange; }.blue { background-color: blue; }.yellow { background-color: yellow; }.skyblue { background-color: skyblue; }.black { background-color: black; }</style>
</head><body><table id="center"><tr><td><h1>테트리스</h1></td></tr><tr><td id="tetrisCenter"></td></tr></table>
<script src="tetris03.js"></script></body></html>
- tetris03.js
-
let row = 22; // 세로 길이let col = 12; // 가로 길이let dataList = []; // 테트리스의 숫자구성let colorList = ["white", "green", "red", "purple", "orange", "blue", "yellow", "skyblue", "gray", "black"];
// 자주 사용하는 값을 상수화const WHITE = 0;const GRAY = 8;const BLACK = 9;const BLOCK = GRAY;
let curY = 0; // 처음 생성되는 블럭의 시작 y좌표let curX = 0; // 처음 생성되는 블럭의 시작 x좌표let curBlock = null; // 현재 블럭의 정보 저장
let blockList = [{name: "s",color: 1,shape:[[0, 0, 0],[0, 1, 1],[1, 1, 0]]},{name: "z",color: 2,shape:[[0, 0, 0],[1, 1, 0],[0, 1, 1]]},{name: "t",color: 3,shape:[[0, 0, 0],[1, 1, 1],[0, 1, 0]]},{name: "l",color: 4,shape:[[0, 1, 0],[0, 1, 0],[0, 1, 1]]},{name: "j",color: 5,shape:[[0, 1, 0],[0, 1, 0],[1, 1, 0]]},{name: "o",color: 6,shape:[[1, 1],[1, 1]]},{name: "i",color: 7,shape:[[0, 0, 0, 0],[1, 1, 1, 1],[0, 0, 0, 0],[0, 0, 0, 0],]}];
// 초기화 + 이벤트 등록function init() {
// 테트리스 표 그리기, dataList 0으로 채우기let $tetrisCenter = document.querySelector("#tetrisCenter");let $myTetris = document.createElement("table");$myTetris.id = "myTetris";for(let i=0; i<row; i++) {let temp = [];let $tr = document.createElement("tr");for(let j=0; j<col; j++) {let $td = document.createElement("td");$tr.append($td);temp.push(0);}dataList.push(temp);$myTetris.append($tr);}$tetrisCenter.append($myTetris);
// 테트리스 세로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<row; i++) {dataList[i][0] = GRAY;dataList[i][col - 1] = GRAY;
$myTetris.children[i].children[0].className = colorList[GRAY];$myTetris.children[i].children[col-1].className = colorList[GRAY];}
// 테트리스 가로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<col; i++) {dataList[0][i] = GRAY;dataList[row - 1][i] = GRAY;
$myTetris.children[0].children[i].className = colorList[GRAY];$myTetris.children[row - 1].children[i].className = colorList[GRAY];}
// dataList 화면에 표시하기for(let i=0; i<row; i++) {for(let j=0; j<col; j++) {$myTetris.children[i].children[j].innerText = dataList[i][j];}}//---------------------------------------------------------// 이벤트 등록// 이게 함수 밖에 있으면 widow인데 안에 있어서. document 이다.document.addEventListener("keydown", function(e) {if(e.code == "ArrowLeft") {// 왼쪽left(); //왼쪽으로 가고. 지우기} else if(e.code == "ArrowRight") {// 오른쪽right();} else if(e.code == "ArrowDown") {// 아래if(down() == false) { //false가 나오면 못 움직인다. / true가 나오면 움직임setNewBlock(); //false가 나오면 새로운 블럭을 그리면 된다.}} else if(e.code == "ArrowUp") {// 회전} else if(e.code == "Space") {// 아래로 한번에 이동while(down()) {}
setNewBlock(); // 다 내려가면 새로운 블럭}
draw();//지우고 다시 그림});
}
// 랜덤으로 블럭 생성 + curBlock 초기화function setNewBlock() {
curY = 1;curX = 4;
let r = Math.floor(Math.random() * blockList.length);
curBlock = blockList[r];let shape = curBlock.shape;for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {dataList[curY + y][curX + x] = blockList[r].color;}}}}
// 화면 새로 색칠하기function draw() {let $myTetris = document.querySelector("#myTetris");
for(let y=0; y<row; y++) {for(let x=0; x<col; x++) {let index = dataList[y][x];
$myTetris.children[y].children[x].className = colorList[index];$myTetris.children[y].children[x].innerText = dataList[y][x];}}}//-------------------------------------------------------// 왼쪽 이동function left() {//미리 다음 위치let nextY = 0;let nextX = -1;
let shape = curBlock.shape; //현재 블록let realBlock = getRealBlock(shape);// 실제 블럭이 있는 위치만 가져오기// 현재 블록에 리얼블록을 가져온다. //실제 블록의 위치만 가져온다.// 진짜 갈 수 있는지 없는지 판정이 됨// 만약 가져올때 0 과 1을 다 가져오면. 0때문에 이동을 못 할 수 있다.// getRealBlock => 모양에 1만 있는것
let movable = isMovable(realBlock, nextY, nextX);//진짜 왼쪽으로 갈 수 있는지// nextY, nextX => 다음 위치를 넣어 준것
if(movable == true) { //갈 수 있는것// dataList 값을 전부 WHITE로 변경
setData(realBlock, 0, 0, WHITE);// 지운것 . 자기 위치 전부 지우기 / 현재위치 전부 지우기// dataLIST에 현재위치를 0,0을 넣어주는것// 이동 후의 위치로 dataList 값 변경// 아직까지는 데이터만 넣은것
setData(realBlock, nextY, nextX, curBlock.color);//다음 위치 칠하기curX -= 1; //현재위치 수정}}//------------------------------------------------// 오른쪽 이동function right() {let nextY = 0;let nextX = 1;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curX += 1;}}//-------------------------------------------------// 아래로 이동function down() {let nextY = 1;let nextX = 0;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curY += 1;} else if(movable == false) {// 블럭이 바닥에 닿으면 //죽으면 검정으로 칠하기setData(realBlock, 0, 0, BLACK);}
return movable;}//------------------------------------------// 실제 블럭이 있는 위치. 즉 1만 있는것 / 가져온것 위치만 가져오는것 . 위치 저장해서// block배열에서 숫자1의 값 저장function getRealBlock(shape) {let realBlock = [];for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {realBlock.push([curY + y, curX + x]);}}}return realBlock;}//----------------------------------------// 이동가능한지 확인function isMovable(realBlock, nextY, nextX) {for(let i=0; i<realBlock.length; i++) {let y = realBlock[i][0];let x = realBlock[i][1];
if(dataList[y + nextY][x + nextX] >= BLOCK) {return false;//BLOCK이면 갈 수 없다.}}return true; //블럭이 아니면 갈 수 있다.}
// 이동 후 dataList 값 수정function setData(realBlock, nextY, nextX, color) {for(let i=0; i<realBlock.length; i++) {let y = realBlock[i][0];let x = realBlock[i][1];
dataList[y + nextY][x + nextX] = color;}}
init();setNewBlock();draw();
_04_회전
- tetris04.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Tetris Game</title>
<style>#center {margin: 0 auto;text-align: center;}#myTetris {border-collapse: collapse;}#myTetris td {border: 1px solid black;width: 30px;height: 30px;}.gray { background-color: gray; }.green { background-color: green; }.red { background-color: red; }.purple { background-color: purple; }.orange { background-color: orange; }.blue { background-color: blue; }.yellow { background-color: yellow; }.skyblue { background-color: skyblue; }.black { background-color: black; }</style>
</head><body><table id="center"><tr><td><h1>테트리스</h1></td></tr><tr><td id="tetrisCenter"></td></tr></table>
<script src="tetris04.js"></script></body></html>
- tetris04.js
-
let row = 22; // 세로 길이let col = 12; // 가로 길이let dataList = []; // 테트리스의 숫자구성let colorList = ["white", "green", "red", "purple", "orange", "blue", "yellow", "skyblue", "gray", "black"];
// 자주 사용하는 값을 상수화const WHITE = 0;const GRAY = 8;const BLACK = 9;const BLOCK = GRAY;
let curY = 0; // 처음 생성되는 블럭의 시작 y좌표let curX = 0; // 처음 생성되는 블럭의 시작 x좌표let curBlock = null; // 현재 블럭의 정보 저장
let blockList = [{name: "s",color: 1,shape:[[0, 0, 0],[0, 1, 1],[1, 1, 0]]},{name: "z",color: 2,shape:[[0, 0, 0],[1, 1, 0],[0, 1, 1]]},{name: "t",color: 3,shape:[[0, 0, 0],[1, 1, 1],[0, 1, 0]]},{name: "l",color: 4,shape:[[0, 1, 0],[0, 1, 0],[0, 1, 1]]},{name: "j",color: 5,shape:[[0, 1, 0],[0, 1, 0],[1, 1, 0]]},{name: "o",color: 6,shape:[[1, 1],[1, 1]]},{name: "i",color: 7,shape:[[0, 0, 0, 0],[1, 1, 1, 1],[0, 0, 0, 0],[0, 0, 0, 0],]}];
// 초기화 + 이벤트 등록function init() {
// 테트리스 표 그리기, dataList 0으로 채우기let $tetrisCenter = document.querySelector("#tetrisCenter");let $myTetris = document.createElement("table");$myTetris.id = "myTetris";for(let i=0; i<row; i++) {let temp = [];let $tr = document.createElement("tr");for(let j=0; j<col; j++) {let $td = document.createElement("td");$tr.append($td);temp.push(0);}dataList.push(temp);$myTetris.append($tr);}$tetrisCenter.append($myTetris);
// 테트리스 세로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<row; i++) {dataList[i][0] = GRAY;dataList[i][col - 1] = GRAY;
$myTetris.children[i].children[0].className = colorList[GRAY];$myTetris.children[i].children[col-1].className = colorList[GRAY];}
// 테트리스 가로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<col; i++) {dataList[0][i] = GRAY;dataList[row - 1][i] = GRAY;
$myTetris.children[0].children[i].className = colorList[GRAY];$myTetris.children[row - 1].children[i].className = colorList[GRAY];}
// dataList 화면에 표시하기for(let i=0; i<row; i++) {for(let j=0; j<col; j++) {$myTetris.children[i].children[j].innerText = dataList[i][j];}}
// 이벤트 등록document.addEventListener("keydown", function(e) {if(e.code == "ArrowLeft") {// 왼쪽left();} else if(e.code == "ArrowRight") {// 오른쪽right();} else if(e.code == "ArrowDown") {// 아래if(down() == false) {setNewBlock();}} else if(e.code == "ArrowUp") {// 회전~~~~~~~~~rotate();} else if(e.code == "Space") {// 아래로 한번에 이동while(down()) {}
setNewBlock();}
draw();});
}
// 랜덤으로 블럭 생성 + curBlock 초기화function setNewBlock() {
curY = 1;curX = 4;
let r = Math.floor(Math.random() * blockList.length);
curBlock = blockList[r];let shape = curBlock.shape;for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {dataList[curY + y][curX + x] = blockList[r].color;}}}}
// 화면 새로 색칠하기function draw() {let $myTetris = document.querySelector("#myTetris");
for(let y=0; y<row; y++) {for(let x=0; x<col; x++) {let index = dataList[y][x];
$myTetris.children[y].children[x].className = colorList[index];$myTetris.children[y].children[x].innerText = dataList[y][x];}}}
// 왼쪽 이동function left() {let nextY = 0;let nextX = -1;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curX -= 1;}}
// 오른쪽 이동function right() {let nextY = 0;let nextX = 1;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curX += 1;}}
// 아래로 이동function down() {let nextY = 1;let nextX = 0;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curY += 1;} else if(movable == false) {// 블럭이 바닥에 닿으면setData(realBlock, 0, 0, BLACK);}
return movable;}//----------------------------------------------------// 회전function rotate() {let curShape = curBlock.shape;let nextShape = getNextShape(curShape);// curShape => 현재블록// 현재블럭에 다음 모양을 가져오는 함수// nextShape => 회전후 모양
let realBlock = getRealBlock(curShape);// 현재 모양의 진짜 블럭 위치
let nextRealBlock = getRealBlock(nextShape);//회전한 모양의 진짜 블럭위치
let movable = isMovable(nextRealBlock, 0, 0);//회전이 가능하니??
if(movable) {setData(realBlock, 0, 0, WHITE);//현재위치 지우고
setData(nextRealBlock, 0, 0, curBlock.color);//새위치 그리고curBlock.shape = nextShape;//회전시키는것//현재블럭을 회전한 블럭으로 대체}}//--------------------------------------------// 회전 상태의 모양function getNextShape(curShape) {let tempBlock = [];for(let i=0; i<curShape.length; i++) {let temp = [];for(let j=0; j<curShape[i].length; j++) {temp.push(0);}tempBlock.push(temp);}
let index = curShape.length - 1;for(let y=0; y<curShape.length; y++) {for(let x=0; x<curShape[y].length; x++) {tempBlock[x][index] = curShape[y][x];}index -= 1;}
return tempBlock;}
// block배열에서 숫자1의 값 저장function getRealBlock(shape) {let realBlock = [];for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {realBlock.push([curY + y, curX + x]);}}}return realBlock;}
// 이동가능한지 확인function isMovable(realBlock, nextY, nextX) {for(let i=0; i<realBlock.length; i++) {let y = realBlock[i][0];let x = realBlock[i][1];
if(dataList[y + nextY][x + nextX] >= BLOCK) {return false;}}return true;}
// 이동 후 dataList 값 수정function setData(realBlock, nextY, nextX, color) {for(let i=0; i<realBlock.length; i++) {let y = realBlock[i][0];let x = realBlock[i][1];
dataList[y + nextY][x + nextX] = color;}}
init();setNewBlock();draw();
_05_삭제
- tetris05.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Tetris Game</title>
<style>#center {margin: 0 auto;text-align: center;}#myTetris {border-collapse: collapse;}#myTetris td {border: 1px solid black;width: 30px;height: 30px;}.gray { background-color: gray; }.green { background-color: green; }.red { background-color: red; }.purple { background-color: purple; }.orange { background-color: orange; }.blue { background-color: blue; }.yellow { background-color: yellow; }.skyblue { background-color: skyblue; }.black { background-color: black; }</style>
</head><body><table id="center"><tr><td><h1>테트리스</h1></td></tr><tr><td id="tetrisCenter"></td></tr></table>
<script src="tetris05.js"></script></body></html>
- tetris05.js
-
let row = 22; // 세로 길이let col = 12; // 가로 길이let dataList = []; // 테트리스의 숫자구성let colorList = ["white", "green", "red", "purple", "orange", "blue", "yellow", "skyblue", "gray", "black"];
// 자주 사용하는 값을 상수화const WHITE = 0;const GRAY = 8;const BLACK = 9;const BLOCK = GRAY;
let curY = 0; // 처음 생성되는 블럭의 시작 y좌표let curX = 0; // 처음 생성되는 블럭의 시작 x좌표let curBlock = null; // 현재 블럭의 정보 저장
let blockList = [{name: "s",color: 1,shape:[[0, 0, 0],[0, 1, 1],[1, 1, 0]]},{name: "z",color: 2,shape:[[0, 0, 0],[1, 1, 0],[0, 1, 1]]},{name: "t",color: 3,shape:[[0, 0, 0],[1, 1, 1],[0, 1, 0]]},{name: "l",color: 4,shape:[[0, 1, 0],[0, 1, 0],[0, 1, 1]]},{name: "j",color: 5,shape:[[0, 1, 0],[0, 1, 0],[1, 1, 0]]},{name: "o",color: 6,shape:[[1, 1],[1, 1]]},{name: "i",color: 7,shape:[[0, 0, 0, 0],[1, 1, 1, 1],[0, 0, 0, 0],[0, 0, 0, 0],]}];
// 초기화 + 이벤트 등록function init() {
// 테트리스 표 그리기, dataList 0으로 채우기let $tetrisCenter = document.querySelector("#tetrisCenter");let $myTetris = document.createElement("table");$myTetris.id = "myTetris";for(let i=0; i<row; i++) {let temp = [];let $tr = document.createElement("tr");for(let j=0; j<col; j++) {let $td = document.createElement("td");$tr.append($td);temp.push(0);}dataList.push(temp);$myTetris.append($tr);}$tetrisCenter.append($myTetris);
// 테트리스 세로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<row; i++) {dataList[i][0] = GRAY;dataList[i][col - 1] = GRAY;
$myTetris.children[i].children[0].className = colorList[GRAY];$myTetris.children[i].children[col-1].className = colorList[GRAY];}
// 테트리스 가로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<col; i++) {dataList[0][i] = GRAY;dataList[row - 1][i] = GRAY;
$myTetris.children[0].children[i].className = colorList[GRAY];$myTetris.children[row - 1].children[i].className = colorList[GRAY];}
// dataList 화면에 표시하기for(let i=0; i<row; i++) {for(let j=0; j<col; j++) {$myTetris.children[i].children[j].innerText = dataList[i][j];}}
// 이벤트 등록document.addEventListener("keydown", function(e) {if(e.code == "ArrowLeft") {// 왼쪽left();} else if(e.code == "ArrowRight") {// 오른쪽right();} else if(e.code == "ArrowDown") {// 아래if(down() == false) {lineClear();setNewBlock();}} else if(e.code == "ArrowUp") {// 회전rotate();} else if(e.code == "Space") {// 아래로 한번에 이동while(down()) {}
lineClear();setNewBlock();}
draw();});
}
// 랜덤으로 블럭 생성 + curBlock 초기화function setNewBlock() {
curY = 1;curX = 4;
let r = Math.floor(Math.random() * blockList.length);
curBlock = blockList[r];let shape = curBlock.shape;for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {dataList[curY + y][curX + x] = blockList[r].color;}}}}
// 화면 새로 색칠하기function draw() {let $myTetris = document.querySelector("#myTetris");
for(let y=0; y<row; y++) {for(let x=0; x<col; x++) {let index = dataList[y][x];
$myTetris.children[y].children[x].className = colorList[index];$myTetris.children[y].children[x].innerText = dataList[y][x];}}}
// 왼쪽 이동function left() {let nextY = 0;let nextX = -1;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curX -= 1;}}
// 오른쪽 이동function right() {let nextY = 0;let nextX = 1;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curX += 1;}}
// 아래로 이동function down() {let nextY = 1;let nextX = 0;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curY += 1;} else if(movable == false) {// 블럭이 바닥에 닿으면setData(realBlock, 0, 0, BLACK);}
return movable;}
// 회전function rotate() {let curShape = curBlock.shape;let nextShape = getNextShape(curShape);
let realBlock = getRealBlock(curShape);let nextRealBlock = getRealBlock(nextShape);let movable = isMovable(nextRealBlock, 0, 0);
if(movable) {setData(realBlock, 0, 0, WHITE);
setData(nextRealBlock, 0, 0, curBlock.color);curBlock.shape = nextShape;}}
// 회전 상태의 모양function getNextShape(curShape) {let tempBlock = [];for(let i=0; i<curShape.length; i++) {let temp = [];for(let j=0; j<curShape[i].length; j++) {temp.push(0);}tempBlock.push(temp);}
let index = curShape.length - 1;for(let y=0; y<curShape.length; y++) {for(let x=0; x<curShape[y].length; x++) {tempBlock[x][index] = curShape[y][x];}index -= 1;}
return tempBlock;}
// block배열에서 숫자1의 값 저장function getRealBlock(shape) {let realBlock = [];for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {realBlock.push([curY + y, curX + x]);}}}return realBlock;}
// 이동가능한지 확인function isMovable(realBlock, nextY, nextX) {for(let i=0; i<realBlock.length; i++) {let y = realBlock[i][0];let x = realBlock[i][1];
if(dataList[y + nextY][x + nextX] >= BLOCK) {return false;}}return true;}
// 이동 후 dataList 값 수정function setData(realBlock, nextY, nextX, color) {for(let i=0; i<realBlock.length; i++) {let y = realBlock[i][0];let x = realBlock[i][1];
dataList[y + nextY][x + nextX] = color;}}//--------------------------------------------// 한 줄 완성되면 삭제function lineClear() {let del = [];for(let y=1; y<row-1; y++) {let count = 0;for(let x=1; x<col-1; x++) {if(dataList[y][x] == BLACK) {count += 1;}}if(count == 10) {del.push(y);}}//한줄 다 됬는지//----------------------------//카운트가 10개면for(let i=0; i<del.length; i++) {
dataList.splice(del[i], 1);dataList.splice(0, 1);//지우고
//붙여넣고 / 지운만큼 다시 그려 넣은것dataList.unshift([BLOCK,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,BLOCK]);dataList.unshift([BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK]);}}
init();setNewBlock();draw();
- _06_게임플레이어
- 다운을 1초마다 한것
- tetris06.html
-
<!DOCTYPE html><html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Tetris Game</title>
<style>#center {margin: 0 auto;text-align: center;}#myTetris {border-collapse: collapse;}#myTetris td {border: 1px solid black;width: 30px;height: 30px;}.gray { background-color: gray; }.green { background-color: green; }.red { background-color: red; }.purple { background-color: purple; }.orange { background-color: orange; }.blue { background-color: blue; }.yellow { background-color: yellow; }.skyblue { background-color: skyblue; }.black { background-color: black; }</style>
</head><body><table id="center"><tr><td><h1>테트리스</h1></td></tr><tr><td id="tetrisCenter"></td></tr></table>
<script src="tetris06.js"></script></body></html>
- tetris06.js
-
let row = 22; // 세로 길이let col = 12; // 가로 길이let dataList = []; // 테트리스의 숫자구성let colorList = ["white", "green", "red", "purple", "orange", "blue", "yellow", "skyblue", "gray", "black"];
// 자주 사용하는 값을 상수화const WHITE = 0;const GRAY = 8;const BLACK = 9;const BLOCK = GRAY;
let curY = 0; // 처음 생성되는 블럭의 시작 y좌표let curX = 0; // 처음 생성되는 블럭의 시작 x좌표let curBlock = null; // 현재 블럭의 정보 저장
let gameOver = false;let intervalId = null;
let blockList = [{name: "s",color: 1,shape:[[0, 0, 0],[0, 1, 1],[1, 1, 0]]},{name: "z",color: 2,shape:[[0, 0, 0],[1, 1, 0],[0, 1, 1]]},{name: "t",color: 3,shape:[[0, 0, 0],[1, 1, 1],[0, 1, 0]]},{name: "l",color: 4,shape:[[0, 1, 0],[0, 1, 0],[0, 1, 1]]},{name: "j",color: 5,shape:[[0, 1, 0],[0, 1, 0],[1, 1, 0]]},{name: "o",color: 6,shape:[[1, 1],[1, 1]]},{name: "i",color: 7,shape:[[0, 0, 0, 0],[1, 1, 1, 1],[0, 0, 0, 0],[0, 0, 0, 0],]}];
// 초기화 + 이벤트 등록function init() {
dataList = [];curY = 0;curX = 0;curBlock = null;gameOver = false;intervalId = null;
if(document.querySelector("#myTetris") != null) {document.querySelector("#myTetris").remove();}
// 테트리스 표 그리기, dataList 0으로 채우기let $tetrisCenter = document.querySelector("#tetrisCenter");let $myTetris = document.createElement("table");
$myTetris.id = "myTetris";for(let i=0; i<row; i++) {let temp = [];let $tr = document.createElement("tr");for(let j=0; j<col; j++) {let $td = document.createElement("td");$tr.append($td);temp.push(0);}dataList.push(temp);$myTetris.append($tr);}$tetrisCenter.append($myTetris);
// 테트리스 세로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<row; i++) {dataList[i][0] = GRAY;dataList[i][col - 1] = GRAY;
$myTetris.children[i].children[0].className = colorList[GRAY];$myTetris.children[i].children[col-1].className = colorList[GRAY];}
// 테트리스 가로 8(gray)으로 채우기 + class이름을 gray로 설정for(let i=0; i<col; i++) {dataList[0][i] = GRAY;dataList[row - 1][i] = GRAY;
$myTetris.children[0].children[i].className = colorList[GRAY];$myTetris.children[row - 1].children[i].className = colorList[GRAY];}
// dataList 화면에 표시하기for(let i=0; i<row; i++) {for(let j=0; j<col; j++) {$myTetris.children[i].children[j].innerText = dataList[i][j];}}
intervalId = setInterval(playGame, 500);//다운을 1초마다 하면 된다. //움직이는 테트리스//다운을 setInterval에다가 넣으면 된다.}
// 랜덤으로 블럭 생성 + curBlock 초기화 + 게임종료 확인function setNewBlock() {
curY = 1;curX = 4;
let r = Math.floor(Math.random() * blockList.length);
curBlock = blockList[r];let shape = curBlock.shape;
// 게임 종료여부 확인isGameOver();
for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {dataList[curY + y][curX + x] = blockList[r].color;}}}}
// 화면 새로 색칠하기function draw() {let $myTetris = document.querySelector("#myTetris");
for(let y=0; y<row; y++) {for(let x=0; x<col; x++) {let index = dataList[y][x];
$myTetris.children[y].children[x].className = colorList[index];$myTetris.children[y].children[x].innerText = dataList[y][x];}}}
// 왼쪽 이동function left() {let nextY = 0;let nextX = -1;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curX -= 1;}}
// 오른쪽 이동function right() {let nextY = 0;let nextX = 1;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curX += 1;}}
// 아래로 이동function down() {let nextY = 1;let nextX = 0;
let shape = curBlock.shape;let realBlock = getRealBlock(shape);let movable = isMovable(realBlock, nextY, nextX);
if(movable == true) {// dataList 값을 전부 WHITE로 변경setData(realBlock, 0, 0, WHITE);// 이동 후의 위치로 dataList 값 변경setData(realBlock, nextY, nextX, curBlock.color);curY += 1;} else if(movable == false) {// 블럭이 바닥에 닿으면setData(realBlock, 0, 0, BLACK);}
return movable;}
// 회전function rotate() {let curShape = curBlock.shape;let nextShape = getNextShape(curShape);
let realBlock = getRealBlock(curShape);let nextRealBlock = getRealBlock(nextShape);let movable = isMovable(nextRealBlock, 0, 0);
if(movable) {setData(realBlock, 0, 0, WHITE);
setData(nextRealBlock, 0, 0, curBlock.color);curBlock.shape = nextShape;}}
// 회전 상태의 모양function getNextShape(curShape) {let tempBlock = [];for(let i=0; i<curShape.length; i++) {let temp = [];for(let j=0; j<curShape[i].length; j++) {temp.push(0);}tempBlock.push(temp);}
let index = curShape.length - 1;for(let y=0; y<curShape.length; y++) {for(let x=0; x<curShape[y].length; x++) {tempBlock[x][index] = curShape[y][x];}index -= 1;}
return tempBlock;}
// block배열에서 숫자1의 값 저장function getRealBlock(shape) {let realBlock = [];for(let y=0; y<shape.length; y++) {for(let x=0; x<shape[y].length; x++) {if(shape[y][x] == 1) {realBlock.push([curY + y, curX + x]);}}}return realBlock;}
// 이동가능한지 확인function isMovable(realBlock, nextY, nextX) {for(let i=0; i<realBlock.length; i++) {let y = realBlock[i][0];let x = realBlock[i][1];
if(dataList[y + nextY][x + nextX] >= BLOCK) {return false;}}return true;}
// 이동 후 dataList 값 수정function setData(realBlock, nextY, nextX, color) {for(let i=0; i<realBlock.length; i++) {let y = realBlock[i][0];let x = realBlock[i][1];
dataList[y + nextY][x + nextX] = color;}}
// 한 줄 완성되면 삭제function lineClear() {let del = [];for(let y=1; y<row-1; y++) {let count = 0;for(let x=1; x<col-1; x++) {if(dataList[y][x] == BLACK) {count += 1;}}if(count == 10) {del.push(y);}}
for(let i=0; i<del.length; i++) {dataList.splice(del[i], 1);dataList.splice(0, 1);
dataList.unshift([BLOCK,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,BLOCK]);dataList.unshift([BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK]);}}
// 게임 시작function playGame() {if(gameOver == true) {clearInterval(intervalId);
alert("게임종료!");init();setNewBlock();draw();
return;}
if(down() == false) {lineClear();setNewBlock();}draw();}
// 게임 종료// 게임 오버됬는지 확인하는것function isGameOver() {let realBlock = getRealBlock(curBlock.shape);
for(let y=0; y<realBlock.length; y++) {if(dataList[realBlock[y][0]][realBlock[y][1]] == BLACK) {gameOver = true;break;}}
console.log(gameOver);}
// 이벤트 등록document.addEventListener("keydown", function(e) {if(e.code == "ArrowLeft") {// 왼쪽left();} else if(e.code == "ArrowRight") {// 오른쪽right();} else if(e.code == "ArrowDown") {// 아래if(down() == false) {lineClear();setNewBlock();}} else if(e.code == "ArrowUp") {// 회전rotate();} else if(e.code == "Space") {// 아래로 한번에 이동while(down()) {}
lineClear();setNewBlock();}
draw();});
init();setNewBlock();draw();
반응형
'코딩 > 1-JavaScript' 카테고리의 다른 글
_02_grid , _03_rect , _04_arc , _05_text (1) | 2025.06.11 |
---|---|
01_캔버스요소 => _00_canvas , _01_line (0) | 2025.06.11 |
01_스네이크 ( 1 ~ 3 ) (1) | 2025.06.10 |
03_클래스버전_전체스태틱 - _01_member (2) | 2025.06.09 |
D10_dom_SPA_암기 => 01_json버전 => _01_모듈화, _02_모둘화와html (0) | 2025.06.09 |