登录B站账号访问本页即可注册本Wiki,点击登录

背景色更换功能测试中
本Wiki注册达5000、20000人时,有额外奖励,快分享给好友吧!

登录B站账号访问本页即可注册本Wiki,点击登录
背景色更换功能请前往PC端使用
本Wiki注册达5000、20000人时,有额外奖励,快分享给好友吧!

全站通知:

Widget:小游戏消消乐

来自生死狙击2WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

<body>

       <button id="startButton" class="start-button">开始游戏</button>

分数: 0

剩余时间: 60

游戏结束

你的得分: 0

           <button id="restartButton" class="restart-button">再来一局</button>
 <style>

body {

   font-family: 'Arial', sans-serif;
   margin: 0;
   padding: 0;
   /*display: flex;*/
   justify-content: center;
   align-items: center;
   min-height: 100vh;
   background-color: #f0f0f0;

} .game-container {

   text-align: center;
   background-color: white;
   padding: 20px;
   border-radius: 10px;
   box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);

}

.game-board {

   display: grid;
   grid-template-columns: repeat(8, 1fr);
   gap: 5px;
   margin: 20px auto;
   width: 420px;
   position: relative;
   min-height: 420px;

}

.tile {

   width: 50px;
   height: 50px;
   background-color: #ddd;
   border-radius: 5px;
   display: flex;
   justify-content: center;
   align-items: center;
   cursor: pointer;
   transition: transform 0.2s, background-color 0.2s;

}

.tile:hover {

   transform: scale(1.05);

}

.tile.selected {

   background-color: #ffeb3b;
   transform: scale(1.2);
   transition: transform 0.2s ease;
   z-index: 10;

}

.tile.swapping {

   transition: all 0.3s ease;

}

.tile.shake {

   animation: shake 0.5s ease;

}

@keyframes shake {

   0%, 100% { transform: translateX(0); }
   20%, 60% { transform: translateX(-5px); }
   40%, 80% { transform: translateX(5px); }

}

.particle {

   position: absolute;
   width: 8px;
   height: 8px;
   border-radius: 50%;
   pointer-events: none;
   animation: particle-fly 0.5s ease-out forwards;
   z-index: 100;
   will-change: transform, opacity;

}

@keyframes particle-fly {

   0% {
       transform: translate(0, 0);
       opacity: 1;
   }
   100% {
       transform: translate(var(--tx), var(--ty));
       opacity: 0;
   }

}

.tile.matched {

   visibility: hidden;

}

.game-info {

   margin-top: 20px;
   font-size: 1.2em;

}

.start-button {

   padding: 10px 20px;
   font-size: 1.2em;
   background-color: #4CAF50;
   color: white;
   border: none;
   border-radius: 5px;
   cursor: pointer;
   margin-bottom: 20px;

}

.start-button:hover {

   background-color: #45a049;

}

.game-over-panel {

   position: absolute;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -50%);
   background-color: white;
   padding: 30px;
   border-radius: 10px;
   box-shadow: 0 0 20px rgba(0,0,0,0.2);
   text-align: center;
   display: none;
   z-index: 100;

}

.restart-button {

   padding: 10px 20px;
   font-size: 1em;
   background-color: #2196F3;
   color: white;
   border: none;
   border-radius: 5px;
   cursor: pointer;
   margin-top: 20px;

}

.restart-button:hover {

   background-color: #0b7dda;

}

.tile.falling {

   transition: transform 0.3s ease-out;
   transform: translateY(100%);

}

.tile.new {

   animation: appear 0.3s ease-out;

}

@keyframes appear {

   from { opacity: 0; transform: translateY(-20px); }
   to { opacity: 1; transform: translateY(0); }

}

 </style>
   <script>

// 游戏配置 const config = {

   rows: 8,
   cols: 8,
   tileTypes: 8,
   timeLimit: 60,

};

// 游戏状态 let state = {

   board: [],
   selectedTile: null,
   score: 0,
   timeLeft: config.timeLimit,
   timer: null,
   gameOver: false

};

// 初始化游戏 function initGame() {

   createBoard();
   renderBoard();
   addEventListeners();
   
   // 添加开始按钮事件
   document.getElementById('startButton').addEventListener('click', startGame);
   // 添加重新开始按钮事件
   document.getElementById('restartButton').addEventListener('click', restartGame);
   
   // 隐藏游戏结束面板
   document.getElementById('gameOverPanel').style.display = 'none';
   // 禁用游戏板交互
   document.getElementById('gameBoard').style.pointerEvents = 'none';

}

// 开始游戏 function startGame() {

   state.score = 0;
   state.timeLeft = config.timeLimit;
   state.gameOver = false;
   
   updateScore();
   updateTimer();
   startTimer();
   
   // 启用游戏板交互
   document.getElementById('gameBoard').style.pointerEvents = 'auto';
   // 隐藏开始按钮
   document.getElementById('startButton').style.display = 'none';

}

// 创建游戏板 function createBoard() {

   state.board = [];
   for (let i = 0; i < config.rows; i++) {
       state.board[i] = [];
       for (let j = 0; j < config.cols; j++) {
           state.board[i][j] = Math.floor(Math.random() * config.tileTypes);
       }
   }
   // 确保初始没有匹配
   while (checkAllMatches().length > 0) {
       createBoard();
   }

}

// 渲染游戏板 function renderBoard() {

   const gameBoard = document.getElementById('gameBoard');
   gameBoard.innerHTML = ;
   for (let i = 0; i < config.rows; i++) {
       for (let j = 0; j < config.cols; j++) {
           const tile = document.createElement('div');
           tile.className = 'tile';
           tile.dataset.row = i;
           tile.dataset.col = j;
           const img = document.createElement('img');
           const imageUrls = [
               'https://patchwiki.biligame.com/images/ssjj2/3/3a/o0s5wo6c8q3b8yv1wd3f0ubm3610ugh.png',
               'https://patchwiki.biligame.com/images/ssjj2/5/5b/spouyw399ah45k8yf3begza9lmvluwf.png',/*瑞秋*/
               'https://patchwiki.biligame.com/images/ssjj2/9/94/agav5py0sknjc6wn3qgqeeahep8s2y9.png',/*梦魇猎人*/
               'https://patchwiki.biligame.com/images/ssjj2/e/e9/cm79rw31uv9gxvbwqgheckdhe46miht.png',
               'https://patchwiki.biligame.com/images/ssjj2/6/69/5gpd9iz7u3f2btaqn8gu8nekctli9qb.png',/*方块A*/
               'https://patchwiki.biligame.com/images/ssjj2/9/9c/b88jcdwq7p86vr8mok43lm029kswdwz.png',
               'https://patchwiki.biligame.com/images/ssjj2/d/dc/38ct7onhztvefyo7k8wd39c5o0dk0c7.png',
               'https://patchwiki.biligame.com/images/ssjj2/6/66/g5zv1ynxoq29ffwqsph9ylrem2msat9.png' /*噩梦*/
           ];
           img.src = imageUrls[state.board[i][j]];
           img.style.width = '100%';
           img.style.height = '100%';
           img.style.objectFit = 'cover';
           img.style.willChange = 'transform';
           tile.appendChild(img);
           gameBoard.appendChild(tile);
       }
   }

}

// 添加事件监听器 function addEventListeners() {

   document.getElementById('gameBoard').addEventListener('click', handleTileClick);

}

// 处理点击事件 async function handleTileClick(event) {

   if (state.gameOver) return;
   const tile = event.target.closest('.tile');
   if (!tile) return;
   const row = parseInt(tile.dataset.row);
   const col = parseInt(tile.dataset.col);
   if (state.selectedTile === null) {
       // 第一次选择
       state.selectedTile = { row, col };
       tile.classList.add('selected');
   } else {
       // 第二次选择
       const firstTile = state.selectedTile;
       const secondTile = { row, col };
       // 检查是否相邻
       if (isAdjacent(firstTile, secondTile)) {
           // 交换位置
           const swapSuccess = await swapTiles(firstTile, secondTile);
           
           if (swapSuccess) {
               // 检查交换后是否形成匹配
               const matches = checkMatchesAfterSwap(firstTile, secondTile);
               if (matches.length > 0) {
                   // 有匹配,显示粒子特效
                   const tile1El = document.querySelector(`[data-row="${firstTile.row}"][data-col="${firstTile.col}"]`);
                   const tile2El = document.querySelector(`[data-row="${secondTile.row}"][data-col="${secondTile.col}"]`);
                   if (tile1El && tile2El) {
                       const rect1 = tile1El.getBoundingClientRect();
                       const rect2 = tile2El.getBoundingClientRect();
                       
                       createParticles(rect1.left + rect1.width/2, rect1.top + rect1.height/2);
                       createParticles(rect2.left + rect2.width/2, rect2.top + rect2.height/2);
                       
                       // 消除并计分
                       setTimeout(() => {
                           removeMatches(matches);
                           fillBoard();
                       }, 500);
                   }
               } else {
                   // 无匹配,抖动效果
                   const tile1El = document.querySelector(`[data-row="${firstTile.row}"][data-col="${firstTile.col}"]`);
                   const tile2El = document.querySelector(`[data-row="${secondTile.row}"][data-col="${secondTile.col}"]`);
                   if (tile1El && tile2El) {
                       tile1El.classList.add('shake');
                       tile2El.classList.add('shake');
                       
                       setTimeout(() => {
                           tile1El.classList.remove('shake');
                           tile2El.classList.remove('shake');
                           // 撤销交换
                           swapTiles(firstTile, secondTile);
                       }, 500);
                   }
               }
           }
       }
       // 重置选择
       document.querySelector('.selected')?.classList.remove('selected');
       state.selectedTile = null;
   }

}

// 检查两个方块是否相邻 function isAdjacent(tile1, tile2) {

   const rowDiff = Math.abs(tile1.row - tile2.row);
   const colDiff = Math.abs(tile1.col - tile2.col);
   return (rowDiff === 1 && colDiff === 0) || (rowDiff === 0 && colDiff === 1);

}

// 创建粒子特效 function createParticles(x, y, count = 20) {

   const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff'];
   for (let i = 0; i < count; i++) {
       const particle = document.createElement('div');
       particle.className = 'particle';
       particle.style.left = `${x}px`;
       particle.style.top = `${y}px`;
       particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
       
       const angle = Math.random() * Math.PI * 2;
       const distance = 20 + Math.random() * 50;
       particle.style.setProperty('--tx', `${Math.cos(angle) * distance}px`);
       particle.style.setProperty('--ty', `${Math.sin(angle) * distance}px`);
       
       document.body.appendChild(particle);
       particle.addEventListener('animationend', () => particle.remove());
   }

}

// 交换两个方块 async function swapTiles(tile1, tile2) {

   // 临时保存原始位置
   const originalTile1 = {row: tile1.row, col: tile1.col};
   const originalTile2 = {row: tile2.row, col: tile2.col};
   
   // 获取DOM元素
   const tile1El = document.querySelector(`[data-row="${tile1.row}"][data-col="${tile1.col}"]`);
   const tile2El = document.querySelector(`[data-row="${tile2.row}"][data-col="${tile2.col}"]`);
   
   if (!tile1El || !tile2El) return false;
   // 禁用交互
   tile1El.style.pointerEvents = 'none';
   tile2El.style.pointerEvents = 'none';
   
   // 添加交换动画
   tile1El.classList.add('swapping');
   tile2El.classList.add('swapping');
   
   // 获取位置信息
   const rect1 = tile1El.getBoundingClientRect();
   const rect2 = tile2El.getBoundingClientRect();
   
   // 计算移动距离
   const dx = rect2.left - rect1.left;
   const dy = rect2.top - rect1.top;
   
   // 执行动画
   tile1El.style.transform = `translate(${dx}px, ${dy}px)`;
   tile2El.style.transform = `translate(${-dx}px, ${-dy}px)`;
   
   try {
       // 等待动画完成
       await new Promise(resolve => setTimeout(resolve, 300));
       
       // 实际交换数据
       const temp = state.board[tile1.row][tile1.col];
       state.board[tile1.row][tile1.col] = state.board[tile2.row][tile2.col];
       state.board[tile2.row][tile2.col] = temp;
       
       // 更新DOM属性
       tile1El.dataset.row = originalTile2.row;
       tile1El.dataset.col = originalTile2.col;
       tile2El.dataset.row = originalTile1.row;
       tile2El.dataset.col = originalTile1.col;
       
       return true;
   } catch (error) {
       console.error('交换出错:', error);
       return false;
   } finally {
       // 重置样式
       tile1El.style.transform = ;
       tile2El.style.transform = ;
       tile1El.classList.remove('swapping');
       tile2El.classList.remove('swapping');
       
       // 重新启用交互
       tile1El.style.pointerEvents = 'auto';
       tile2El.style.pointerEvents = 'auto';
       
       // 重新渲染
       renderBoard();
   }

}

// 检查全盘所有匹配 function checkAllMatches() {

   const matches = [];
   
   // 检查水平匹配
   for (let i = 0; i < config.rows; i++) {
       for (let j = 0; j < config.cols - 2; j++) {
           const type = state.board[i][j];
           if (type === state.board[i][j + 1] && type === state.board[i][j + 2]) {
               let k = j + 2;
               while (k < config.cols && state.board[i][k] === type) k++;
               if (k - j >= 3) {
                   matches.push({ row: i, startCol: j, endCol: k - 1, direction: 'horizontal' });
               }
               j = k - 1;
           }
       }
   }
   
   // 检查垂直匹配
   for (let j = 0; j < config.cols; j++) {
       for (let i = 0; i < config.rows - 2; i++) {
           const type = state.board[i][j];
           if (type === state.board[i + 1][j] && type === state.board[i + 2][j]) {
               let k = i + 2;
               while (k < config.rows && state.board[k][j] === type) k++;
               if (k - i >= 3) {
                   matches.push({ col: j, startRow: i, endRow: k - 1, direction: 'vertical' });
               }
               i = k - 1;
           }
       }
   }
   
   return matches;

}

// 检查交换后是否形成匹配 function checkMatchesAfterSwap(tile1, tile2) {

   const matches = [];
   
   // 检查tile1周围
   checkAroundTile(tile1.row, tile1.col, matches);
   // 检查tile2周围 
   checkAroundTile(tile2.row, tile2.col, matches);
   
   return matches;

}

// 检查指定方块周围的匹配 function checkAroundTile(row, col, matches) {

   const type = state.board[row][col];
   
   // 检查水平方向
   let left = col;
   while (left > 0 && state.board[row][left-1] === type) left--;
   
   let right = col;
   while (right < config.cols-1 && state.board[row][right+1] === type) right++;
   
   if (right - left >= 2) { // 至少3个连续
       matches.push({ 
           row: row,
           startCol: left,
           endCol: right,
           direction: 'horizontal' 
       });
   }
   
   // 检查垂直方向
   let top = row;
   while (top > 0 && state.board[top-1][col] === type) top--;
   
   let bottom = row;
   while (bottom < config.rows-1 && state.board[bottom+1][col] === type) bottom++;
   
   if (bottom - top >= 2) { // 至少3个连续
       matches.push({
           col: col,
           startRow: top,
           endRow: bottom, 
           direction: 'vertical'
       });
   }

}

// 消除匹配的方块 function removeMatches(matches) {

   let totalRemoved = 0;
   
   for (const match of matches) {
       if (match.direction === 'horizontal') {
           const count = match.endCol - match.startCol + 1;
           // 计分规则:3个=3分,每多1个加2分
           const points = 3 + (count - 3) * 2;
           state.score += points;
           
           for (let j = match.startCol; j <= match.endCol; j++) {
               state.board[match.row][j] = -1; // 标记为待消除
               totalRemoved++;
           }
       } else {
           const count = match.endRow - match.startRow + 1;
           const points = 3 + (count - 3) * 2;
           state.score += points;
           
           for (let i = match.startRow; i <= match.endRow; i++) {
               state.board[i][match.col] = -1; // 标记为待消除
               totalRemoved++;
           }
       }
   }
   
   updateScore();
   return totalRemoved;

}

// 填充空白位置 function fillBoard() {

   // 下落现有方块
   for (let j = 0; j < config.cols; j++) {
       let emptyRow = config.rows - 1;
       
       for (let i = config.rows - 1; i >= 0; i--) {
           if (state.board[i][j] !== -1) {
               state.board[emptyRow][j] = state.board[i][j];
               if (emptyRow !== i) {
                   state.board[i][j] = -1;
                   // 添加下落动画
                   const tile = document.querySelector(`[data-row="${i}"][data-col="${j}"]`);
                   if (tile) {
                       tile.classList.add('falling');
                       setTimeout(() => {
                           tile.classList.remove('falling');
                       }, 300);
                   }
               }
               emptyRow--;
           }
       }
       
       // 从顶部补充新方块
       for (let i = emptyRow; i >= 0; i--) {
           state.board[i][j] = Math.floor(Math.random() * config.tileTypes);
           // 添加出现动画
           setTimeout(() => {
               const tile = document.querySelector(`[data-row="${i}"][data-col="${j}"]`);
               if (tile) {
                   tile.classList.add('new');
                   setTimeout(() => {
                       tile.classList.remove('new');
                   }, 300);
               }
           }, (emptyRow - i) * 100);
       }
   }
   
   // 检查是否有新的匹配
   const newMatches = checkAllMatches();
   if (newMatches.length > 0) {
       setTimeout(() => {
           removeMatches(newMatches);
           fillBoard();
           renderBoard();
       }, 500);
   } else {
       renderBoard();
   }

}

// 更新分数 function updateScore() {

   document.getElementById('score').textContent = state.score;

}

// 开始计时器 function startTimer() {

   updateTimer();
   state.timer = setInterval(() => {
       state.timeLeft--;
       updateTimer();
       if (state.timeLeft <= 0) {
           endGame();
       }
   }, 1000);

}

// 更新计时器显示 function updateTimer() {

   document.getElementById('time').textContent = state.timeLeft;

}

// 结束游戏 function endGame() {

   clearInterval(state.timer);
   state.gameOver = true;
   
   // 显示游戏结束面板
   document.getElementById('finalScore').textContent = state.score;
   document.getElementById('gameOverPanel').style.display = 'block';
   // 禁用游戏板交互
   document.getElementById('gameBoard').style.pointerEvents = 'none';

}

// 重新开始游戏 function restartGame() {

   // 隐藏游戏结束面板
   document.getElementById('gameOverPanel').style.display = 'none';
   // 重新初始化游戏
   initGame();
   startGame();

}

// 初始化游戏 document.addEventListener('DOMContentLoaded', initGame);

 </script>

</body>