본문 바로가기
p5.js

[p5.js/The Nature of Code] 0. Randomness(무작위성) - 0.2 The Random Walker Class (Walker 클래스)

by the_cat_Soy 2024. 4. 11.

차례

 

Nature of Code

 

natureofcode.com

 

Random Walker 클래스

자바스크립트에서 객체는 데이터와 기능을 모두 가진 개체입니다. 이 경우, Walker 객체는 캔버스 상의 위치에 대한 데이터와 그 자체를 그리거나 한 걸음을 따라가는 기능과 같은 기능을 가져야 합니다.

클래스는 실제 객체의 인스턴스를 구축하는 템플릿입니다. 클래스를 쿠키 커터로, 객체를 쿠키로 생각할 수 있습니다. Walker 객체를 만들기 위해 Walker 클래스를 정의하여 객체가 무엇인지를 정의할 것입니다.

Walker는 두 가지 데이터만 필요합니다: x-위치를 나타내는 숫자와 y-위치를 나타내는 숫자입니다. 시작 위치를 설정하기 위해 생성자 함수인 constructor()에서 이를 초기화할 것입니다. 이를 클래스의 생성자 함수로 정의하고, 적절하게 constructor()라고 이름을 붙입니다. 이것은 객체의 설정() 함수와 유사하게 초기 속성을 정의합니다:

 

class Walker {
  constructor() {
    // 객체가 초기화되는 생성자가 있습니다.

    this.x = width / 2;
    this.y = height / 2;
    // 객체가 데이터를 가집니다.

  }
}


새롭게 생성된 객체 자체에 속성(변수)을 연결하기 위해 this 키워드를 사용하여 속성을 연결했습니다: this.x 및 this.y.

데이터 외에도 클래스에 기능을 정의할 수 있습니다. 이 예제에서 Walker 객체에는 두 가지 함수, 즉 객체에서 사용되는 기능이 있습니다. 메서드는 사실상 함수이지만 메서드는 클래스 내에서 정의되며 따라서 객체나 클래스와 관련이 있습니다. 반면 함수는 그렇지 않습니다. 함수 키워드는 좋은 단서입니다: 단독 함수를 정의할 때 볼 수 있지만 클래스 내부에는 나타나지 않습니다. 이 책에서 용어를 일관되게 사용하려고 노력하지만, 프로그래머가 함수와 메서드를 상호 교환하여 사용하는 것은 일반적입니다.

첫 번째 메서드인 show()에는 객체를 그리는 코드(검은 점으로)가 포함되어 있습니다. 이 때문에 객체의 속성(변수)을 참조할 때 this를 잊지 마십시오:

show() {
  stroke(0);
  point(this.x, this.y);
}


다음 메서드인 step()은 Walker 객체가 한 걸음을 따라가도록 지시합니다. 이 부분이 조금 더 흥미로운 부분입니다. 바닥에서 무작위 방향으로 걸음을 따라간 기억을 하십니까? 이제 p5.js 캔버스를 사용하여 그 바닥을 나타낼 것입니다. 네 가지 가능한 걸음이 있습니다. 오른쪽으로의 걸음은 x를 x++로 증가시키면 되고, 왼쪽으로의 걸음은 x를 x--로 감소시키면 됩니다. 앞으로는 위쪽으로 한 픽셀 이동하면 됩니다(y--); 뒤로는 아래쪽으로 한 픽셀 이동하면 됩니다(y++). 그런데 코드에서 이 네 가지 선택지 중에서 어떻게 고를 수 있을까요?

이전에 두 개의 동전을 던질 수 있다고 말했었죠. 그러나 p5.js에서는 목록에서 무작위로 선택하고 싶을 때 random() 함수를 사용하여 간단히 무작위 숫자를 생성할 수 있습니다. 이 함수는 원하는 범위 내에서 무작위 부동 소수점(소수) 값을 선택합니다. 여기서는 0부터 4까지의 범위를 나타내기 위해 4를 사용했습니다:

let choice = floor(random(4));


choice라는 변수를 선언하고 floor()를 사용하여 무작위 부동 소수점 숫자에서 소수 부분을 제거하여 무작위 정수(정수)를 할당했습니다. 기술적으로 random(4)에 의해 생성된 숫자는 0 (포함)에서 4 (제외)까지의 범위 내에 있으며, 실제로 4.0이 될 수 없습니다. 생성될 수 있는 최대 숫자는 4 미만인 3.999999999 (JavaScript가 허용하는 만큼의 9가지)로, floor()가 소수 부분을 제거하여 3으로 줄이기 때문에, 소수 부분을 제거합니다. 따라서, 나는 choice에 0, 1, 2 또는 3의 값을 할당했습니다.

 

JavaScript의 Math.floor() 함수는 매개변수로 전달된 숫자의 소수 부분을 제거하고 내림하여 가장 가까운 정수를 반환
console.log(Math.floor(3.9)); // 출력 결과: 3
console.log(Math.floor(5.7)); // 출력 결과: 5
console.log(Math.floor(-2.1)); // 출력 결과: -3

 

Coding Conventions

자바스크립트에서 변수는 let 또는 const를 사용하여 선언할 수 있습니다. 일반적인 접근 방식은 const로 모든 변수를 선언하고 필요할 때 let으로 변경하는 것입니다. 이 예에서는 choice를 선언할 때 const가 적절할 것입니다. 왜냐하면 step() 내에서 각 호출의 수명 중에 새 값을 할당받지 않기 때문입니다. 이러한 차이는 중요하지만, 나는 p5.js 예제 규약을 따르고 모든 변수를 let으로 선언하기로 선택했습니다.

자바스크립트의 엄격한 등호 (===) 연산자 (그리고 부등호 상반되는 !==)를 사용하기로 선택했습니다. 이 부울 연산자는 값

 및 유형의 일치를 테스트합니다. 예를 들어, 3 === '3'은 유형이 다르기 때문에 false로 평가됩니다 (숫자 대 문자열), 비록 그 모양이 비슷해 보입니다. 반면에 3 == '3'의 느슨한 등호 연산자를 사용하면 두 가지 다른 유형이 비교 가능하도록 변환되기 때문에 true가 됩니다. 느슨한 비교는 종종 잘 작동하지만 때로는 예상치 못한 결과를 가져올 수 있으므로 ===가 더 안전한 선택입니다.

 

그 다음, walker는 선택된 무작위 숫자에 따라 적절한 걸음을 밟습니다. 다음은 Walker 클래스를 완전히 정리하는 step() 메서드입니다:

step() {
  let choice = floor(random(4));
  // 0, 1, 2, 또는 3. 무작위 선택이 걸음을 결정합니다.

  if (choice === 0) {
    this.x++;
  } else if (choice === 1) {
    this.x--;
  } else if (choice === 2) {
    this.y++;
  } else {
    this.y--;
  }
}


클래스를 작성했으므로 이제 실제 Walker 객체를 스케치 자체에서 만들어야 합니다. 단일 무작위 이동을 모델링하려면 다음과 같이 단일 전역 변수로 시작하세요:

let walker;
// Walker 객체

function setup() {
  // p5.js의 작동 방식을 기억하십니까? setup()은 스케치가 시작될 때 한 번 실행됩니다.

  createCanvas(640, 240);
  walker = new Walker();
  background(255);
  // Walker를 만듭니다.

}


마지막으로 각 draw() 사이클마다 walker가 한 걸음을 따라가고 점을 그립니다.

https://editor.p5js.org/natureofcode/sketches/5C69XyrlsR

 

function draw() {
  // 그러면 draw()는 영원히 반복됩니다(종료할 때까지).

  walker.step();
  walker.show();
  // Walker 객체의 함수를 호출합니다.

}

 

배경을 계속해서 지우는 대신 setup()에서 한 번만 그리기 때문에 무작위 이동의 흔적이 캔버스에 보입니다.

무작위 walker의 몇 가지 조정을 할 수 있습니다. 첫째로, 이 Walker 객체의 단계는 위, 아래, 왼쪽, 오른쪽으로 제한됩니다. 그러나 캔버스의 각 픽셀은 대각선을 포함하여 여덟 가지 이웃이 될 수 있습니다(그림 0.1 참조). 그리고 같은 위치에 머무르는 것도 가능합니다.

 

 

 

대각선을 포함한 이웃 픽셀로 이동할 수 있는 Walker 객체를 구현하기 위해 0부터 8까지 (아홉 가지 선택지)의 숫자를 선택할 수 있습니다. 그러나 코드를 작성하는 다른 방법은 x축을 따라 세 가지 가능한 단계(–1, 0 또는 1)와 y축을 따라 세 가지 가능한 단계를 선택하는 것입니다:

 

  step() {
    let xstep = floor(random(3)) - 1;
    let ystep = floor(random(3)) - 1;
    // –1, 0 또는 1을 생성합니다.

    this.x += xstep;
    this.y += ystep;
  }

 

 

이를 더 발전시켜서 floor()를 제거하고 random() 함수의 원래 부동 소수점 숫자를 사용하여 –1부터 1까지의 가능한 단계 길이를 연속적으로 만들 수 있습니다.

 

  step() {
    let xstep = random(-1, 1);
    let ystep = random(-1, 1);
    // -1에서 1까지의 임의의 부동 소수점 숫자

    this.x += xstep;
    this.y += ystep;
  }

 

 

전통적인 무작위 이동에 대한 이러한 변형은 모두 한 가지 공통점이 있습니다: 어떤 순간에도 walker가 특정 방향으로 걸음을 내딛을 확률은 walker가 다른 방향으로 걸음을 내딛을 확률과 같습니다. 즉, 네 가지 가능한 걸음이 있는 경우 walker가 특정 걸음을 내딛을 확률은 4분의 1 (또는 25%)이 됩니다. 아홉 가지 가능한 걸음이 있는 경우 9분의 1의 확률이 됩니다(약 11.1%).

편리하게도, 이것이 random() 함수의 작동 방식입니다. p5.js의 무작위 숫자 생성기(내부적으로 작동)는 숫자의 균일한 분포를 생성합니다. 이 분포를 테스트하려면 임의의 숫자가 선택될 때마다 해당 값을 계산하고 그 값을 그래프로 그릴 수 있습니다.

 

 

Links

https://youtu.be/l__fEY1xanY?si=RoTCZugXXHovXsdS

 

 

https://youtu.be/POn4cZ0jL-o?si=F_hYTJjAjbKcCSUg