Silverback9

#야생으로

Creative Coding 독학 제196일 2024년10월09일(수)

오늘은! 가장자리에 있는 <우리의 세포>에게 이웃 세포를 찾아 주는 날이예요~~!!!

YEAH~~!!!

<우리의 세포> grid[ i ][ j ]의

왼쪽 이웃은 [ i – 1 ][ j ]이고 오른쪽 이웃은 [ i + 1 ][ j ]인데요…

위쪽 이웃은 [ i ][ j – 1 ]이고 아래쪽 이웃은 [ i ][ j + 1 ]인데요…

  • cols: 세로기둥 총 갯수 (x축 배열 구성원 총 갯수)
  • rows: 칸 총 갯수 rows (y축 배열 구성원 총 갯수)

<우리의 세포>

왼쪽 가장자리 grid[0][j]에 있으면, 

왼쪽에 아무도 없으니까...

가로줄 제일 끝에 있는 세포 grid[cols-1][j]
오른쪽 가장자리 grid[cols -1][j]에 있으면, 

오른쪽에 아무도 없으니까...

가로줄 제일 앞에 있는 세포 grid[0][j]
위쪽 가장자리 grid[i][0]에 있으면, 

위쪽에 아무도 없으니까...

세로줄 제일 끝에 있는 세포 grid[i][rows-1]
아래쪽 가장자리 grid[i][rows-1]에 있으면, 

아래쪽에 아무도 없으니까...

세로줄 제일 앞에 있는 세포 grid[i][0]

이웃세포로 연결해 줄게요~^^*

지난 번 일차원 배열의 가장자리 구성요소의 이웃을 찾아 주던 작업이 혹시 기억나시나요?

그때 우리는 나머지 연산자의 유용성에 깜짝! 놀랐었는데요~~^^*

A라는 수에 B라는 수를 더한 후 B로 나눈 나머지 값은 항상 A가 된다!
(1 + 5) % 5 = 1  (6 / 5 의 몫은 1이고 나머지는 1이다) 
(2 + 7) % 7 = 2  (9 / 7 의 몫은 1이고 나머지는 2이다)

이 원리를 이용해서, 왼쪽 이웃 -오른쪽 이웃 – 위쪽 이웃 – 아래쪽 이웃을 구할 수 있을 것 같아요.

  • cols: 세로기둥 총 갯수 (x축 배열 구성원 총 갯수)
  • rows: 칸 총 갯수 rows (y축 배열 구성원 총 갯수)

(1) 왼쪽 이웃은 grid[ ( ( i – 1 ) + cols ) % cols ][ j ]

x축 배열 구성원이 10개인 경우

x축 배열 맨 앞 구성원인 grid[ 0 ][ j ]의
왼쪽 이웃 
= grid[(0 - 1 + 10) % 10][j]
= grid[9 % 10][j]
= grid[9][j] 
= x축 배열 맨 마지막 구성원

(2) 오른쪽 이웃은 grid[ ( ( i + 1 ) + cols ) % cols ][ j ]

x축 배열 구성원이 10개인 경우

x축 배열 맨 뒤 구성원인 grid[ 9 ][ j ]의 
오른쪽 이웃
= grid[( 9 + 1 + 10 ) % 10][j]
= grid[20 % 10][j]
= grid[0][j]
= x축 배열 맨 앞 구성원  

(3) 위쪽 이웃은 grid[ i ][( ( j – 1 ) + rows ) % rows ]

y축 배열 구성원이 10개인 경우

y축 배열 맨 앞 구성원인 grid[ i ][ 0 ]의
위쪽 이웃 
= grid[i][(0 - 1 + 10) % 10]
= grid[i][9 % 10]
= grid[i][9] 
= y축 배열 맨 아래 구성원

(4) 아래쪽 이웃은 grid[ i ][ ( ( j + 1 ) + rows ) % rows ]

y축 배열 구성원이 10개인 경우

y축 배열 맨 뒤 구성원인 grid[ i ][ 9 ]의 
아래쪽 이웃
= grid[i][( 9 + 1 + 10) % 10]
= grid[i][20 % 10]
= grid[i][0]
= y축 배열 맨 위 구성원  

이 과정을 살펴 보니, grid[i][j]의 이웃세포는 나눗셈 연산을 하여 구할 수 있고, 맨 앞 구성원과 맨 뒤 구성원이 서로 연결되어 진다는 것을 다시금 확인할 수 있는 것 같아요!

그러면 우리, 살아있는 이웃세포의 총 합을 구하는 함수 countNeighbor( )를 개선해 볼까요?


function countNeighbors(grid, x, y) {
  let sum = 0;
  for (let i = -1; i < 2; i++) {
    for (let j = -1; j < 2; j++) {
      let col = (x + i + cols) % cols;
      let row = (y + j + rows) % rows;
      sum += grid[col][row];
    }
  }
  sum -= grid[x][y];
  return sum;
}

와우!! 드디어 전체 코드를 완성해서 프로그램을 실행해 볼 수 있을 것 같아요~~^^*

function make2DArray(cols, rows) {
  let arr = new Array(cols);
  for (let i = 0; i < arr.length; i++) {
    arr[i] = new Array(rows);
  }
  return arr;
}

let grid;
let cols;
let rows;
let resolution = 10;

function setup() {
  createCanvas(600, 400);
  cols = width / resolution;
  rows = height / resolution;

  grid = make2DArray(cols, rows);
  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      grid[i][j] = floor(random(2));
    }
  }
}

function draw() {
  background(0);

  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      let x = i * resolution;
      let y = j * resolution;
      if (grid[i][j] == 1) {
        fill(255);
        stroke(0);
        rect(x, y, resolution - 1, resolution - 1);
      }
    }
  }

  let next = make2DArray(cols, rows);

  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      let state = grid[i][j];
      // Count live neighbors!
      let sum = 0;
      let neighbors = countNeighbors(grid, i, j);

      if (state == 0 && neighbors == 3) {
        next[i][j] = 1;
      } else if (state == 1 && (neighbors < 2 || neighbors > 3)) {
        next[i][j] = 0;
      } else {
        next[i][j] = state;
      }

    }
  }
  grid = next;
}


function countNeighbors(grid, x, y) {
  let sum = 0;
  for (let i = -1; i < 2; i++) {
    for (let j = -1; j < 2; j++) {
      let col = (x + i + cols) % cols;
      let row = (y + j + rows) % rows;
      sum += grid[col][row];
    }
  }
  sum -= grid[x][y];
  return sum;
}

이제 가장자리 이웃들이 서로를 만나서 아름다운 모눈종이 풍경을 완성하는 Game of Life를 감상하러 저와 함께 가실까요~^^*

가장자리의 이웃들이 서로의 이웃이 되어주는 아름다운 관계! 나머지 연산자가 완성시킨 이 아름다운 관계가 Game of Life 전체 풍경을 참 자연스럽게 보이도록 만들어 주네요.

관심사가 같다면, 세상 가장자리에 있어도 반대편 가장자리에 있는 이웃을 만나, 아름다운 대화를 나눌 수 있다는 것. 그것이 나머지 연산자의 힘이고, 언어의 힘이고, 통신의 힘이고, 교통의 힘인 것 같아요~^^*

우리들의 나머지 연산자 %도 감사하고,

어떤 것에 관심을 가지게 된 계기들도 감사하고,

이 관심을 키워나갈 수 있도록 도와주시는 가족과 이웃과 친구와 선생님도 감사하고,

이 관심을 표현할 수 있도록 도와주는 모국어도 외국어들도 감사하고,

지구 반대편 친구와 토론을 즐겁게 나눌 수 있도록 도와주는 인터넷 통신도 감사하고,

지구 곳곳 친구들을 직접 만날 수 있도록 도와주는 세계 교통 체계도 새삼 감사하네요~^^*

네~^^* 그렇죠~~^^*

맞아요~^^*

자신의 관심사를 나눌 땐, 마음이 즐겁고 편안하고 활발해져서, 말도 술술 나오죠~^^*

네~~^^* 저도 그래요~~^^*

우리는

관심사에 대한 자신의 기량을 키워서,

지구 친구들과의 대화와 토론의 즐거움을 넘어,

세상의 문제를 해결하는 데 실질적인 기여를 할 수 있는 순간들을

항상 꿈꾸게 되는데요~^^*

오늘 Game of Life 프로그램을 완성하고 나니,

우리 각자의 그리고/또는 공통된 관심사의

거대한 지구 생태계 속에서,

지구 친구들과 생명력을 함께 나누는 모습도

컴퓨터 화면 위에 펼쳐지고 있는 것 같아서 참 기분이 좋은데요~^^*

세상과 관심사를 나누고 또 관심사를 통해서 세상에 기여할 수 있다는 믿음과 감사함이 한 층 더 쌓이는 것 같아요^^*

오늘 저와 함께 Game of Life를 완성해 주셔서 감사합니다!

내일 우리 또 만나서, 코딩 공부 함께 할까요~~^^*

그 무엇도 우리의 코딩 공부를 멈출 수는 없으니까요! YEAH!!!

오늘도 맛있는 점심 드시고요!! 멋진 하루 보내시고요!!

내일 우리 또 다시 만나요!!

네!! 꿈은 이루어 집니다!!

댓글 남기기