commit b2ba582cecac45cbea3af998ace0d6b4b958ced1 Author: hkri Date: Sun Jul 25 22:26:58 2021 +0800 Add initial codes. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3d7b8f5 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# Number Slide + +Simple number slide game using HTML and vanila JavaScript. + +
+ +
+ +## Development + +- Open `index.html` on a modern browser. +- Edit the files on your favorite text editor. \ No newline at end of file diff --git a/dist/app.css b/dist/app.css new file mode 100644 index 0000000..d5a472a --- /dev/null +++ b/dist/app.css @@ -0,0 +1,115 @@ +body { + padding: 0; + margin: 0; + background-color: rgb(240, 240, 244); + font-family: sans-serif; +} + +main { + background-color: rgb(230, 230, 234); + border-radius: 8px; +} + +h1 { + font-size: 2.5em; + color: rgb(57, 57, 61); + margin: 0; + width: 100%; +} + +footer { + text-align: center; + font-size: 12px; + color: rgb(110, 110, 114); + text-transform: uppercase; +} + +footer a { + color: rgb(110, 110, 114); + text-decoration: none; +} + +footer a:hover { + text-decoration: underline; +} + +#wrapper { + margin: 0 auto; + max-width: 500px; + width: 100%; + margin: 0 auto; + padding: 0 2em; + box-sizing: border-box; +} + +#controls { + display: flex; + margin: 2em 0 1em 0; + justify-content: center; + align-items: center; +} + +#controls button { + background-color: rgb(220, 220, 224); + border: 0; + border-radius: 6px; + padding: 0.7em 1.5em; + transition: all 0.12s ease-out; +} + +#controls button:not([disabled]):hover { + cursor: pointer; + background-color: #04bbd9; + color: white; +} + +#stage { + margin: 4em auto 6em auto; +} + +#stage section { + width: 100%; + min-height: 130px; + border-radius: 8px; + position: relative; + display: grid; + grid-template-columns: [c1] 33.33% [c2] 33.33% [c3] 33.33% [c-end]; + grid-template-rows: [r1] 33.33% [r2] 33.33% [r3] 33.33% [r-end]; + filter: drop-shadow(0 0 8px rgba(0, 0, 0, 0.15)); +} + +#stage button { + margin: 0; + padding: 0; + font-size: 3em; + background: rgb(250, 250, 252); + color: rgb(50, 50, 55); + overflow: hidden; + transition: transform 0.12s ease-out, background-color 0.12s ease-out; + border-radius: 8px; + border: 1px solid rgb(198, 198, 201); + grid-column-start: c1; + grid-row-start: r1; + z-index: 1; +} + +#stage button.fast { + transition: transform 0.08s ease-out; +} + +#stage.done button[disabled] { + background-color: #20a076; + color: white; +} + +.c1.r1 { transform: translate(0, 0); } +.c1.r2 { transform: translate(0, 100%); } +.c1.r3 { transform: translate(0, 200%); } + +.c2.r1 { transform: translate(100%, 0); } +.c2.r2 { transform: translate(100%, 100%); } +.c2.r3 { transform: translate(100%, 200%); } + +.c3.r1 { transform: translate(200%, 0); } +.c3.r2 { transform: translate(200%, 100%); } +.c3.r3 { transform: translate(200%, 200%); } \ No newline at end of file diff --git a/dist/app.js b/dist/app.js new file mode 100644 index 0000000..cb45723 --- /dev/null +++ b/dist/app.js @@ -0,0 +1,249 @@ +var grid = [1, 2, 3, 4, 5, 6, 7, 8, 0 ]; +var COLS = 3; +var ROWS = grid.length / COLS; +var SHUFFLES = 35; + +var MOV_LEFT = 0; +var MOV_RIGHT = 1; +var MOV_UP = 2; +var MOV_DOWN = 3; + +var tiles = document.querySelectorAll('#stage button'); +var textTime = document.getElementById('time'); +var buttonShuffle = document.getElementById('shuffle'); +var stage = document.getElementById('stage'); +var stageSection = document.querySelector('#stage section'); +var wrapper = document.getElementById('wrapper'); + +var timer = null; +var startTime = 0; + +function getRow(index) { + return Math.floor(index / COLS); +} + +function getCol(index) { + return (index % COLS); +} + +function render() { + grid.forEach(function (value, index) { + var col = getCol(index) + 1; + var row = getRow(index) + 1; + var element = document.getElementById(value); + if (element === null) { + return; + } + element.classList.remove('c1', 'c2', 'c3', 'r1', 'r2', 'r3'); + element.classList.add('c' + col, 'r' + row); + }); +} + +function swap(a, b) { + var tmp = grid[a]; + grid[a] = grid[b]; + grid[b] = tmp; +} + +function getSpacePossibleMoves(reverseDir) { + var index = grid.indexOf(0); + var possibleMoves = new Set([MOV_LEFT, MOV_RIGHT, MOV_UP, MOV_DOWN]); + if (index % COLS == COLS - 1) + possibleMoves.delete(MOV_RIGHT); + if (index % COLS == 0) + possibleMoves.delete(MOV_LEFT); + if (Math.floor(index / ROWS) == 0) + possibleMoves.delete(MOV_UP); + if (Math.floor(index / ROWS) == ROWS - 1) + possibleMoves.delete(MOV_DOWN); + possibleMoves.delete(reverseDir); + return Array.from(possibleMoves); +} + +function moveSpace(direction) { + var index = grid.indexOf(0); + var step = 0; + switch (direction) { + case MOV_LEFT: case MOV_UP: + step = -1; + break; + case MOV_RIGHT: case MOV_DOWN: + step = 1; + break; + default: + step = 0; + } + if ([MOV_LEFT, MOV_RIGHT].indexOf(direction) > -1) { + // horizontal + var inc = index + step; + if (inc < 2 || inc >= 0) { + swap(index, inc); + } + } else { + // vertical + var inc = index + (ROWS * step); + if (inc < grid.length || inc >= 0) { + swap(index, inc); + } + } + render(); +} + +function moveHorizontal(index) { + var col = getCol(index); + if (col == 0) { + if (grid[index + 1] == 0) + swap(index, index + 1); + } else if (col == COLS - 1) { + if (grid[index - 1] == 0) + swap(index, index - 1); + } else { + if (grid[index + 1] == 0) + swap(index, index + 1); + else if (grid[index - 1] == 0) + swap(index, index - 1); + } +} + +function moveVertical(index) { + var row = getRow(index); + if (row == 0) { + if (grid[index + ROWS] == 0) + swap(index, index + ROWS); + } else if (row == ROWS - 1) { + if (grid[index - ROWS] == 0) + swap(index, index - ROWS); + } else { + if (grid[index + ROWS] == 0) + swap(index, index + ROWS); + else if (grid[index - ROWS] == 0) + swap(index, index - ROWS); + } +} + +function shuffle(steps) { + var i = 0; + var prevDir = -1; + tiles.forEach(function (tile) { + tile.classList.add('fast'); + }); + var loop = setInterval(function () { + var reverseDir = -1; + if (prevDir == MOV_DOWN) + reverseDir = MOV_UP; + if (prevDir == MOV_UP) + reverseDir = MOV_DOWN; + if (prevDir == MOV_LEFT) + reverseDir = MOV_RIGHT; + if (prevDir == MOV_RIGHT) + reverseDir = MOV_LEFT; + var possibleMoves = getSpacePossibleMoves(reverseDir); + var dir = possibleMoves[Math.floor(Math.random() * possibleMoves.length)]; + moveSpace(dir); + prevDir = dir; + i++; + if (i >= steps) { + clearInterval(loop); + enableTiles(); + document.getElementById('stage').classList.remove('done'); + buttonShuffle.disabled = false; + tiles.forEach(function (tile) { + tile.classList.remove('fast'); + }); + return; + } + }, 90); + disableTiles(); + buttonShuffle.disabled = true; +} + +function formatTime(time) { + var minutes = Math.floor(time / 60).toString().padStart(2, '0'); + var seconds = Math.floor(time % 60).toString().padStart(2, '0'); + var millis = Math.floor((time % 1) * 100).toString().padStart(2, '0'); + return minutes + ':' + seconds + '.' + millis + ''; +} + +function startTimer() { + if (timer !== null) { + return; + } + startTime = (new Date()).getTime(); + timer = setInterval(function () { + var diff = ((new Date()).getTime() - startTime) / 1000; + textTime.innerHTML = formatTime(diff); + }, 16); +} + +function stopTimer() { + clearInterval(timer); + timer = null; +} + +function resetTimer() { + stopTimer(); + startTime = 0; + textTime.innerHTML = formatTime(0); +} + +function checkCompleted() { + for (var i = 0; i < grid.length - 2; ++i) { + if (grid[i + 1] < grid[i]) { + return; + } + } + document.getElementById('stage').classList.add('done'); + disableTiles(); + stopTimer(); +} + +function disableTiles() { + tiles.forEach(function (button) { + button.disabled = true; + }); +} + +function enableTiles() { + tiles.forEach(function (button) { + button.disabled = false; + }); +} + +function resizeStage() { + var wrapperStyle = getComputedStyle(wrapper); + var paddingLeft = parseInt(wrapperStyle.getPropertyValue('padding-left')); + var paddingRight = parseInt(wrapperStyle.getPropertyValue('padding-right')); + var width = parseInt(wrapperStyle.getPropertyValue('width')); + var adjustedWidth = width - paddingLeft - paddingRight; + while (adjustedWidth % 3 != 0) { + adjustedWidth--; + } + stage.style.fontSize = (adjustedWidth / 24) + 'px'; + stage.style.width = adjustedWidth + 'px'; + stageSection.style.height = adjustedWidth + 'px'; +} + +tiles.forEach(function (button) { + button.onclick = function (e) { + var tileId = e.target.id; + var index = grid.indexOf(parseInt(tileId)); + moveHorizontal(index); + moveVertical(index); + render(); + startTimer(); + checkCompleted(); + } +}); + +buttonShuffle.onclick = function () { + resetTimer(); + shuffle(SHUFFLES); +} + +window.onload = function () { + resizeStage(); + render(); + shuffle(SHUFFLES); +}; + +window.onresize = resizeStage; diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..c989ea7 --- /dev/null +++ b/dist/index.html @@ -0,0 +1,34 @@ + + + + + + + + Number Slide + + +
+
+

00:00.00

+ +
+
+
+ + + + + + + + +
+
+ +
+ + + \ No newline at end of file diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..c4fe0cc Binary files /dev/null and b/screenshot.png differ