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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 17:24:09