You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript实现俄罗斯方块:软降时方块消失问题求助

俄罗斯方块软降异常问题修复方案

问题现象

方块未完全显示在网格前触发软降,会中途消失;方块完全显示后软降正常,但按住向下键仍有异常。

核心问题与修复代码

1. 移除软降函数的不必要位置限制

softDrop函数中原有的this.y >= 1判断会阻止初始位置(y=1)的方块执行软降,直接触发锁定逻辑导致方块消失。

原代码:

Piece.prototype.softDrop = function() {
  if (this.y >= 1 && !this.collision(0, 1, this.activeTetromino)) {
    this.unDraw();
    this.y++;
    this.draw();
    score += 1; // add 1 point per row for soft drop
    updateScoreDisplay();
  } else {
    this.handleLockDelay();
  }
}

修改后:

Piece.prototype.softDrop = function() {
  if (!this.collision(0, 1, this.activeTetromino)) {
    this.unDraw();
    this.y++;
    this.draw();
    score += 1;
    updateScoreDisplay();
  } else {
    this.handleLockDelay();
  }
}

2. 完整擦除所有位置的方块

unDraw函数原只处理可见区域的方块,导致不可见区域的方块残留,干扰碰撞检测和锁定逻辑,必须完整擦除所有位置的方块。

原代码:

Piece.prototype.unDraw = function() {
  for (let r = 0; r < this.activeTetromino.length; r++) {
    for (let c = 0; c < this.activeTetromino.length; c++) {
      if (this.activeTetromino[r][c]) {
        let drawY = this.y + r;
        if (drawY >= 2) { // draw only visible rows
          drawSquare(this.x + c, drawY - 2, VACANT);
        }
      }
    }
  }
}

修改后:

Piece.prototype.unDraw = function() {
  for (let r = 0; r < this.activeTetromino.length; r++) {
    for (let c = 0; c < this.activeTetromino.length; c++) {
      if (this.activeTetromino[r][c]) {
        let drawY = this.y + r;
        const drawX = this.x + c;
        // 擦除可见区域的方块
        if (drawY >= 2) {
          drawSquare(drawX, drawY - 2, VACANT);
        }
        // 清空board中对应位置,避免残留干扰碰撞检测
        if (drawY >= 0 && drawY < ROW && drawX >= 0 && drawX < COL) {
          board[drawY][drawX] = VACANT;
        }
      }
    }
  }
}

3. 修正错误的游戏结束判定

lock函数中原有的this.y + r < 2会在方块部分处于不可见区域时直接触发游戏结束,这不符合逻辑,应该在新方块生成时判断是否无法放置才结束游戏。

修改lock函数中的游戏结束判断:

// 原代码片段
if (this.y + r < 2) {
  // game over
  alert('Game Over');
  gameOver = true;
  break;
}
board[this.y + r][this.x + c] = this.color;

替换为:

const visibleRowStart = 2;
// 仅当方块进入可见区域的部分无法放置时,才标记游戏结束待确认
if (this.y + r >= visibleRowStart) {
  board[this.y + r][this.x + c] = this.color;
} else {
  // 标记为待确认,后续生成新方块时检查
  gameOverPending = true;
}

添加新方块生成时的游戏结束检查:

function randomPiece() {
  // 假设你有定义pieces数组包含所有方块类型
  const pieces = [/* 你的方块类型集合 */];
  const randomIdx = Math.floor(Math.random() * pieces.length);
  const newPiece = new Piece(pieces[randomIdx].tetromino, pieces[randomIdx].color);
  
  // 检查新方块是否一开始就无法放置,才触发游戏结束
  if (gameOverPending || newPiece.collision(0, 0, newPiece.activeTetromino)) {
    alert('Game Over');
    gameOver = true;
    return null;
  }
  gameOverPending = false;
  return newPiece;
}

4. 处理按住向下键的重复触发问题

通过跟踪按键状态,使用定时器实现连续软降,避免按键重复触发导致的方块异常。

添加全局按键状态与事件监听:

let softDropInterval = null;
const keyStates = {
  arrowDown: false
};

document.addEventListener('keydown', (e) => {
  if (e.key === 'ArrowDown' && !keyStates.arrowDown && !gameOver && p) {
    keyStates.arrowDown = true;
    // 设置定时器控制软降速度
    softDropInterval = setInterval(() => {
      p.softDrop();
    }, 60);
  }
});

document.addEventListener('keyup', (e) => {
  if (e.key === 'ArrowDown') {
    keyStates.arrowDown = false;
    clearInterval(softDropInterval);
  }
});

总结

以上修改解决了软降限制、方块擦除不完整、错误游戏结束判定以及按键重复触发四个核心问题,能让方块在未完全显示时也能正常软降,不会中途消失。

内容的提问来源于stack exchange,提问作者j k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 22:09:50