2048 Game

2048

矢印キーで操作してください

2048 hi0a.com

view source

JavaScript

const board = [];
const size = 4;

window.onload = () => {
  initBoard();
  drawBoard();
  addNumber();
  addNumber();
};

function initBoard() {
  for (let i = 0; i < size; i++) {
    board[i] = [];
    for (let j = 0; j < size; j++) {
      board[i][j] = 0;
    }
  }
}

function drawBoard() {
  const boardElement = document.getElementById('game-board');
  boardElement.innerHTML = '';
  for (let i = 0; i < size; i++) {
    for (let j = 0; j < size; j++) {
      const tile = document.createElement('div');
      const val = board[i][j];
      tile.className = `tile tile-${val}`;
      tile.textContent = val !== 0 ? val : '';

      if (val >= 8) {
        tile.classList.add('merged'); // 合体アニメーション
      }
      boardElement.appendChild(tile);
    }
  }
}


function addNumber() {
  let options = [];
  for (let i = 0; i < size; i++) {
    for (let j = 0; j < size; j++) {
      if (board[i][j] === 0) {
        options.push({ x: i, y: j });
      }
    }
  }

  if (options.length > 0) {
    let spot = options[Math.floor(Math.random() * options.length)];
    board[spot.x][spot.y] = Math.random() < 0.9 ? 2 : 4;
    drawBoard();
  }
}

function slide(row) {
  let newRow = row.filter(val => val !== 0);
  let mergedRow = [];
  for (let i = 0; i < newRow.length; i++) {
    if (newRow[i] === newRow[i + 1]) {
      mergedRow.push(newRow[i] * 2);
      newRow[i + 1] = 0;
    } else {
      mergedRow.push(newRow[i]);
    }
  }
  mergedRow = mergedRow.filter(val => val !== 0);
  while (mergedRow.length < size) {
    mergedRow.push(0);
  }
  return mergedRow;
}
/*
function slide(row) {
  row = row.filter(val => val);
  for (let i = 0; i < row.length - 1; i++) {
    if (row[i] === row[i + 1]) {
      row[i] *= 2;
      row[i + 1] = 0;
    }
  }
  row = row.filter(val => val);
  while (row.length < size) {
    row.push(0);
  }
  return row;
}
*/

function rotateLeft(matrix) {
  let result = [];
  for (let i = 0; i < size; i++) {
    result[i] = [];
    for (let j = 0; j < size; j++) {
      result[i][j] = matrix[j][size - i - 1];
    }
  }
  return result;
}

function rotateRight(matrix) {
  let result = [];
  for (let i = 0; i < size; i++) {
    result[i] = [];
    for (let j = 0; j < size; j++) {
      result[i][j] = matrix[size - j - 1][i];
    }
  }
  return result;
}

function flipRows(matrix) {
  return matrix.map(row => row.slice().reverse());
}

document.addEventListener('keydown', (e) => {
  let flipped = false;
  let rotated = false;

  if (e.key === 'ArrowLeft') {
    // nothing
  } else if (e.key === 'ArrowRight') {
    flipped = true;
    for (let i = 0; i < size; i++) {
      board[i] = board[i].reverse();
    }
  } else if (e.key === 'ArrowUp') {
    rotated = true;
    board = rotateLeft(board);
  } else if (e.key === 'ArrowDown') {
    rotated = true;
    board = rotateRight(board);
  } else {
    return;
  }

  let oldBoard = JSON.stringify(board);
  for (let i = 0; i < size; i++) {
    board[i] = slide(board[i]);
  }

  if (flipped) {
    for (let i = 0; i < size; i++) {
      board[i] = board[i].reverse();
    }
  }

  if (rotated) {
    board = e.key === 'ArrowUp' ? rotateRight(board) : rotateLeft(board);
  }

  if (oldBoard !== JSON.stringify(board)) {
    addNumber();
  }
});

CSS

html,body{
  overflow:hidden;
}

body {
  font-family: sans-serif;
  text-align: center;
  background-color: #faf8ef;
  color: #776e65;
}

#game-board {
  width: 400px;
  height: 400px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 5px;
  background-color: #bbada0;
  padding: 5px;
  border-radius: 10px;
}

.tile {
  width: 90px;
  height: 90px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  font-weight: bold;
  border-radius: 5px;
  transition: all 0.2s ease-in-out;
  animation: pop 0.2s;
}

@keyframes pop {
  0% {
    transform: scale(0.6);
  }
  100% {
    transform: scale(1);
  }
}

/* タイルごとの色指定 */
.tile-0    { background-color: #cdc1b4; color: transparent; }
.tile-2    { background-color: #eee4da; color: #776e65; }
.tile-4    { background-color: #ede0c8; color: #776e65; }
.tile-8    { background-color: #f2b179; color: white; }
.tile-16   { background-color: #f59563; color: white; }
.tile-32   { background-color: #f67c5f; color: white; }
.tile-64   { background-color: #f65e3b; color: white; }
.tile-128  { background-color: #edcf72; color: white; font-size: 24px; }
.tile-256  { background-color: #edcc61; color: white; font-size: 24px; }
.tile-512  { background-color: #edc850; color: white; font-size: 24px; }
.tile-1024 { background-color: #edc53f; color: white; font-size: 20px; }
.tile-2048 { background-color: #edc22e; color: white; font-size: 20px; }



.tile {
  position: relative;
  transition: transform 0.15s ease-in-out;
  animation: appear 0.2s ease;
}

@keyframes appear {
  0% {
    transform: scale(0.5);
    opacity: 0.5;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.merged {
  animation: merge 0.2s ease;
}

@keyframes merge {
  0% {
    transform: scale(1.3);
  }
  100% {
    transform: scale(1);
  }
}

HTML

ページのソースを表示 : Ctrl+U , DevTools : F12

view-source:https://hi0a.com/game/game-puzzle2048/

ABOUT

hi0a.com 「ひまあそび」は無料で遊べるミニゲームや便利ツールを公開しています。

プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。

必要な機能の関数をコピペ利用したり勉強に活用できます。

プログラムの動作サンプル結果は画面上部に出力表示されています。

環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。

画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。

仕様変更、API廃止等、実験途中で動かないページもあります。