俄罗斯方块类游戏随机新形状生成问题及代码调试求助
俄罗斯方块随机形状生成问题修复方案
针对你遇到的形状不居中、不连续、重复生成三个核心问题,以下是具体修复方案和优化后的代码:
核心问题根源
- 不连续形状:原代码随机填充方块,未保证所有方块连通,导致出现分离的多个块。
- 居中失效:原逻辑基于原始形状的边界计算偏移,对不对称形状无法保证视觉居中;且偏移计算逻辑有误,直接对原始坐标加偏移而非基于边界调整。
- 重复形状:未维护已生成形状的记录,无法避免重复生成相同形状。
修复后的完整代码
// 全局存储已生成的形状字符串,用于去重 const generatedShapes = new Set(); function randomShape(score) { const maxSize = 12; // 每个形状最多方块数 const maxComplexity = Math.min(Math.floor(score / 100), 6); // 基于分数的复杂度上限 // 动态确定当前分数下的方块数范围 const minSize = 1; const maxPossibleSize = Math.min(maxComplexity + 1, maxSize); const targetSize = Math.floor(Math.random() * (maxPossibleSize - minSize + 1)) + minSize; let centeredShape; do { // 生成连通的随机形状 const shape = Array.from({ length: 4 }, () => Array(4).fill(0)); // 随机选起始方块位置 const startRow = Math.floor(Math.random() * 4); const startCol = Math.floor(Math.random() * 4); shape[startRow][startCol] = 1; let placed = 1; // 用随机BFS方式扩展,保证形状连通且多样 const queue = [{ r: startRow, c: startCol }]; while (placed < targetSize) { // 随机选择队列中的点进行扩展,避免生成单一直线型 const randomIdx = Math.floor(Math.random() * queue.length); const { r, c } = queue.splice(randomIdx, 1)[0]; // 上下左右四个方向,打乱顺序增加随机性 const directions = [[-1,0], [1,0], [0,-1], [0,1]].sort(() => Math.random() - 0.5); for (const [dr, dc] of directions) { const newR = r + dr; const newC = c + dc; if (newR >= 0 && newR < 4 && newC >= 0 && newC < 4 && shape[newR][newC] === 0) { shape[newR][newC] = 1; queue.push({ r: newR, c: newC }); placed++; if (placed === targetSize) break; } } // 当前点无法扩展时放回队列,避免死循环 if (placed < targetSize) queue.push({ r, c }); } // 计算形状质心,实现精确居中 const filledPositions = []; for (let r = 0; r < 4; r++) { for (let c = 0; c < 4; c++) { if (shape[r][c] === 1) filledPositions.push({ r, c }); } } // 计算所有方块的平均坐标(质心) const avgRow = filledPositions.reduce((sum, p) => sum + p.r, 0) / filledPositions.length; const avgCol = filledPositions.reduce((sum, p) => sum + p.c, 0) / filledPositions.length; // 4x4网格的视觉中心是(1.5,1.5),计算偏移量 const rowOffset = Math.round(1.5 - avgRow); const colOffset = Math.round(1.5 - avgCol); // 生成居中后的形状,处理偏移出界的情况 centeredShape = Array.from({ length: 4 }, () => Array(4).fill(0)); filledPositions.forEach(({ r, c }) => { let newR = r + rowOffset; let newC = c + colOffset; // 偏移后出界时,反向调整1位保证形状在网格内 if (newR < 0) newR += 1; if (newR >= 4) newR -= 1; if (newC < 0) newC += 1; if (newC >= 4) newC -= 1; centeredShape[newR][newC] = 1; }); // 转换为字符串检查是否重复 const shapeStr = JSON.stringify(centeredShape); if (!generatedShapes.has(shapeStr)) { generatedShapes.add(shapeStr); break; } } while (true); return centeredShape; }
关键修复说明
- 连通性保证:采用随机BFS方式生成形状,从起始点向相邻空位扩展,确保所有方块连通,不会出现分离块。
- 精确居中:基于形状质心计算偏移量,让视觉中心对齐4x4网格中心,同时处理偏移出界的情况,保证形状完整。
- 去重机制:通过全局集合存储已生成形状的字符串表示,每次生成后检查是否重复,避免出现相同形状。
- 复杂度适配:根据分数动态调整形状的最大方块数,分数越高,形状可能越大(最多12块)。
内容的提问来源于stack exchange,提问作者todd
相关产品推荐
相关产品推荐

