JavaScript中如何检测组合音乐节奏生成序列的重复触发时机
多节拍组合序列重复检测方案
核心思路
你的序列生成逻辑是确定性的,下一个输出完全由所有乐器的当前position组合决定。只要所有乐器的位置组合回到之前出现过的状态,后续生成的序列就会完全重复,不需要依赖公因数等数学计算,只需要记录每一步的状态快照即可完成检测。
实现逻辑
- 每次更新乐器位置后,生成当前所有乐器
position的拼接字符串作为唯一状态标识 - 用Set存储已经出现过的状态标识
- 每次生成新状态后先判断是否已存在:
- 存在则说明进入循环,直接终止生成
- 不存在则记录状态,继续生成序列
该方案天然支持任意数量乐器、任意节拍长度、任意字符集的扩展需求,你提到的3拍+4拍、3拍+5拍、多拍组合等所有重复场景都可以自动覆盖。
调整后的可运行代码
const alphabet = `abcdefghijklmnopqrstuvwxyz`.split('') const baseDrum = { rhythm: [1, 0, 0], position: 2, } const hiHat = { rhythm: [1, 2, 2, 2], position: 3, } const flute = { rhythm: [1, 0, 1, 0, 0], position: 4, } const instruments = [flute, baseDrum, hiHat] const update = () => { instruments.forEach(instrument => { if (instrument.position == instrument.rhythm.length - 1) { instrument.position = 0 } else { instrument.position++ } }) } const sequence1 = [] const sequence2 = [] const sequence3 = [] const sequence4 = [] const sequence5 = [] // 新增状态历史存储集合 const stateHistory = new Set() function generate() { const numbers = [ baseDrum.position + 1, hiHat.position + 1, flute.position + 1, ] const playNumbers = [ baseDrum.rhythm[baseDrum.position], hiHat.rhythm[hiHat.position] - 1, flute.rhythm[flute.position], ] const lettersString = numbers.map(x => alphabet[x]).join('') const numbersString = numbers.join('') const playNumbersDigit = parseInt(playNumbers.join(''), 2) const playLettersString = alphabet[playNumbersDigit] const playNumbersString = playNumbers.join('') sequence1.push(lettersString) sequence2.push(numbersString) sequence3.push(playNumbersDigit) sequence4.push(playLettersString) sequence5.push(playNumbersString) } // 移除固定循环次数,检测到重复自动终止 while (true) { update() // 生成当前状态唯一标识 const currentState = instruments.map(inst => inst.position).join(',') // 状态重复,跳出循环 if (stateHistory.has(currentState)) break stateHistory.add(currentState) generate() } console.log(JSON.stringify({ sequence1, sequence2, sequence3, sequence4, sequence5 }, null, 2))
补充说明
首次重复的起始位置就是序列数组的长度,当检测到状态重复时,当前状态对应的输出和该状态第一次出现时的输出完全一致,整个序列会从第一次出现该状态的位置开始循环。如果后续需要扩展其他序列生成规则,只需要把状态标识调整为对应生成逻辑的完整状态快照即可。
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

