항상 원래 위치로 돌아가는 랜덤 워크 샘플

개요



일정량의 이동폭을 가지는 랜덤 워크를 끝마쳤을 때, 반드시 원래의 장소로 돌아오는 코드의 샘플입니다.

원리



플러스 방향으로 이동한 만큼 마이너스 방향으로도 움직이는(어느 타이밍으로 역의 움직임을 하는지는 랜덤)함으로써, 이동량의 합계가 0으로 돌아오는 구조입니다.

데모





이런 식으로 옆으로 이동 한 후 첫 번째 위치로 돌아갑니다.

데모 페이지:
h tp // 코데펜. 이오 / 부 t 치 / 펜 / XM 쿠 vj

샘플 코드



셔플에는 Fisher–Yates 알고리즘을 사용했지만,
Underscore 의 _.shuffle등으로 대용할 수 있으므로 읽어 날리면 OK.
const LENGTH = 25; // 25×2の50回ランダムウォークする
const MAGNITUDE = 10; // 振動ピクセル幅

// 入力した正の数を正負両方含む配列(倍のサイズ)として返す
function double(arr) {
  let ret = [];

  arr.forEach((num) => {
    ret.push(num);
    ret.push(-num);
  });

  return ret;
}

// Fisher–Yatesアルゴリズムによる配列シャッフル
function shuffle(arr) {
  let ret = [].concat(arr);

  for(let i = ret.length - 1; i > 0; i--){
    let r = Math.floor(Math.random() * (i + 1));
    let tmp = ret[i];
    ret[i] = ret[r];
    ret[r] = tmp;
  }

  return ret;
}

// ランダムウォークの対象要素
let walkerElm = document.querySelector('.walker')

// ランダムウォークを始めるボタン
let startBtn = document.querySelector('.btn-start');

startBtn.addEventListener('click', () => {
  // ランダム数値配列(mapを有効にするため一旦0で初期化)
  let deltaXArr = (new Array(LENGTH)).fill(0).map(() => {
    return Math.random() * MAGNITUDE;
  });

  let deltaXArr2 = double(deltaXArr);
  let shuffleXArr = shuffle(deltaXArr2);

  // 累積変動量
  let deltaX = 0;

  for(let i = 0; i < LENGTH * 2; i++) {
    setTimeout(() => {
      deltaX += shuffleXArr[i];
      walkerElm.style.transform = `translateX(${deltaX}px)`;
    }, i * 50);
  }
});

이번은 간단하기 위해 가로축만 이동으로 했습니다만,
X축과 Y축이거나 절대치(abs)와 편각(arg)의 2개의 배열로 처리하면 평면상의 랜덤 워크도 구현할 수 있습니다.

좋은 웹페이지 즐겨찾기