如何高效生成多维数组连续true值分组数值(仿Picross游戏)
问题
我有一个根据用户输入数字生成的多维数组,其中每个元素随机赋值为true或false,示例数组如下:
array [ [true, false, false, true, true], [false, false, false, false, true], [true, true, true, false, false], [false, true, true, false, true], [true, false, true, true, true] ]
我希望仿照Picross游戏的样式,为该数组的每行和每列生成连续true值的分组数值,示例效果如下:
array [ 1 1 1 2 1 2 3 1 2 1 2 [true, false, false, true, true], 1 [false, false, false, false, true], 3 [true, true, true, false, false], 2 1 [false, true, true, false, true], 1 3 [true, false, true, true, true] ]
我尝试了以下代码,但未能实现需求:
for(let i = 0; i < userInput; i++) { array[i].forEach(element => { if(element == true) { readInt++ } else { readInt = 0; readString += readInt + " "; } }); } document.getElementById("hint1").innerHTML = readString;
请问是否有更简便的实现方法?
解决方案
1. 封装通用分组函数
不管处理行还是列,核心逻辑都是提取连续true的计数,先写一个工具函数:
// 输入一维数组,返回连续true的分组数值数组 function getTrueGroups(arr) { const groups = []; let currentCount = 0; for (const val of arr) { if (val) { currentCount++; } else { if (currentCount > 0) { groups.push(currentCount); currentCount = 0; } } } // 处理数组末尾的连续true if (currentCount > 0) { groups.push(currentCount); } return groups; }
2. 生成行提示
直接遍历二维数组的每一行调用函数即可:
const rowHints = array.map(row => getTrueGroups(row)); // 示例输出:[[1,2], [1], [3], [2,1], [1,3]]
3. 生成列提示
先把数组转置(行变列),再用同样的函数处理:
// 转置二维数组:将列转为行 function transposeArray(arr) { return arr[0].map((_, colIndex) => arr.map(row => row[colIndex])); } const columnHints = transposeArray(array).map(col => getTrueGroups(col)); // 示例输出:[[1,1,1], [2], [3], [1,1], [2,1,3]]
4. 格式化对齐输出
要实现Picross的对齐样式,需要计算提示的最大长度,补空格对齐:
function formatPicross(array, rowHints, columnHints) { // 计算行提示的最大长度,用于左侧对齐 const maxRowHintLength = Math.max(...rowHints.map(h => h.join(' ').length)); // 计算列提示的最大行数,用于顶部对齐 const maxColHintRows = Math.max(...columnHints.map(h => h.length)); let output = "array [\n"; // 先输出列提示 for (let i = 0; i < maxColHintRows; i++) { // 留出行提示的位置 output += ' '.repeat(maxRowHintLength + 2); // 遍历每一列的提示,按单元格宽度对齐 columnHints.forEach(hint => { const num = hint[i] || ''; output += num.toString().padStart(6); }); output += "\n"; } // 输出每行的提示和对应数组行 array.forEach((row, idx) => { const hintStr = rowHints[idx].join(' ').padStart(maxRowHintLength); const rowStr = row.map(v => v.toString()).join(', '); output += ` ${hintStr} [${rowStr}],\n`; }); output += "]"; return output; } // 调用示例 console.log(formatPicross(array, rowHints, columnHints));
原代码的问题
- 遇到
false时把重置后的0加入字符串,逻辑错误,应该在连续true中断时记录之前的计数 - 没有处理数组末尾的连续
true(比如最后一个元素是true的情况) - 所有行的提示会拼接在一起,没有区分每行
- 完全没处理列的提示
内容的提问来源于stack exchange,提问作者Brandon Noel
相关产品推荐
相关产品推荐

