Skip to content

Instantly share code, notes, and snippets.

@jinhoyim
Created February 17, 2019 16:09
Show Gist options
  • Save jinhoyim/05ca6b8372ec576d3810285b2e66dbb7 to your computer and use it in GitHub Desktop.
Save jinhoyim/05ca6b8372ec576d3810285b2e66dbb7 to your computer and use it in GitHub Desktop.
한 붓 그리기 S80-Day1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
.block {
width: 80px;
height: 80px;
cursor: pointer;
}
.block-type0 {
background-image: url("img/0.png");
}
.block-type1 {
background-image: url("img/1.png");
}
.block-type2 {
background-image: url("img/2.png");
}
.block-type3 {
background-image: url("img/3.png");
}
.block-type4 {
background-image: url("img/4.png");
}
.block-selected {
background-color: #ffff00;
}
</style>
</head>
<body>
<section style="text-align:center">
<h1 style="color:#208AFB">한 붓 그리기</h1>
<table id="stage"></table>
</section>
<script>
"use strict";
const Block = class {
constructor(type) {
this._type = type;
this._isDown = false;
}
static get numberOfTypes() {
return 5;
}
// css 클래스 목록 출력
get classList() {
const classes = ["block", `block-type${this.type}`];
if (this._isDown) classes.push("block-selected");
return classes;
}
get type() {
return this._type;
}
down() {
this._isDown = true;
}
up() {
this._isDown = false;
}
};
Block.GET = (type = parseInt(Math.random() * Block.numberOfTypes)) => new Block(type);
const Game = (_ => {
const column = 8,
row = 8,
blockSize = 80;
const data = [];
let table;
let startBlock,
currBlock,
selected = [],
isDown;
const getBlock = (x, y) => {
const { top: T, left: L } = table.getBoundingClientRect();
if (x < L || x > L + blockSize * row || y < T || y > T + blockSize * column) return null;
return data[parseInt((y - T) / blockSize)][parseInt((x - L) / blockSize)];
};
const down = ({ pageX: x, pageY: y }) => {
if (isDown) return;
const curr = getBlock(x, y);
if (!curr) return;
isDown = true;
curr.down();
selected.length = 0;
selected[0] = startBlock = currBlock = curr;
render();
};
const move = ({ pageX: x, pageY: y }) => {
if (!isDown) return;
const curr = getBlock(x, y);
if (!curr || curr.type != startBlock.type || !isNext(curr)) return;
if (selected.indexOf(curr) == -1) {
selected.push(curr);
curr.down();
} else if (selected[selected.length - 2] == curr) {
selected.pop().up();
}
currBlock = curr;
render();
};
const isNext = curr => {
let r0,
c0,
r1,
c1,
cnt = 0;
data.some((row, i) => {
let j;
if ((j = row.indexOf(currBlock)) != -1) (r0 = i), (c0 = j), cnt++;
if ((j = row.indexOf(curr)) != -1) (r1 = i), (c1 = j), cnt++;
return cnt == 2;
});
return (curr != currBlock && Math.abs(r0 - r1) == 1) || Math.abs(c0 - c1) == 1;
};
const up = _ => (selected.length > 2 ? remove() : reset());
const reset = _ => {
startBlock = currBlock = null;
selected.forEach(b => b.up());
selected.length = 0;
isDown = false;
render();
};
const remove = _ => {
data.forEach(r => {
selected.forEach(v => {
let i;
if ((i = r.indexOf(v)) != -1) r[i] = null;
});
});
render();
setTimeout(drop, 300);
};
const drop = _ => {
let isNext = false;
for (let j = 0; j < column; j++) {
for (let i = row - 1; i > -1; i--) {
if (!data[i][j] && i) {
let k = i,
isEmpty = true;
while (k--)
if (data[k][j]) {
isEmpty = false;
break;
}
if (isEmpty) break;
isNext = true;
while (i--) {
data[i + 1][j] = data[i][j];
data[i][j] = null;
}
break;
}
}
}
render();
isNext ? setTimeout(drop, 300) : readyToFill();
};
const fills = [];
let fillCnt = 0;
const readyToFill = _ => {
fills.length = 0;
data.some(row => {
if (row.indexOf(null) == -1) return true;
const r = [...row].fill(null);
fills.push(r);
row.forEach((v, i) => !v && (r[i] = Block.GET()));
});
fillCnt = 0;
setTimeout(fill, 300);
};
const fill = _ => {
if (fillCnt > fills.length) {
isDown = false;
return;
}
for (let i = 0; i < fillCnt; i++) {
fills[fills.length - i - 1].forEach((v, j) => {
if (v) data[fillCnt - i - 1][j] = v;
});
}
fillCnt++;
render();
setTimeout(fill, 300);
};
const init = tid => {
table = document.querySelector(tid);
for (let i = 0; i < row; i++) {
const r = [];
data.push(r);
for (let j = 0; j < column; j++) r[j] = Block.GET();
}
table.addEventListener("mousedown", down);
table.addEventListener("mouseup", up);
table.addEventListener("mouseleave", up);
table.addEventListener("mousemove", move);
buildTable();
render();
};
const el = tag => document.createElement(tag);
const buildTable = _ => {
table.innerHTML = "";
data.forEach(row =>
table.appendChild(
row.reduce((tr, block) => {
tr.appendChild(el("td"));
return tr;
}, el("tr"))
)
);
};
const render = _ => {
let td;
data.forEach((row, rowIndex) => {
row.forEach((block, colIndex) => {
td = table.rows[rowIndex].cells[colIndex];
td.className = "";
if (block) {
td.classList.add(...block.classList);
}
});
});
};
return init;
})();
Game("#stage");
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment