Web/javascript

[JS] 모던 자바스크립트 입문- 생명 게임 시뮬레이터 (2차원 배열의 생성)

Razelo 2021. 2. 24. 10:56

모던 자바스크립트 입문의 17장에는 생명 게임 시뮬레이터 예제가 있다. 

 

이 예제에서 화면의 view에 나타낼 픽셀을 배열로써 생성하는 파트가 있다. 코드는 다음과 같다. 

 

// 격자의 크기
	state.nx = nx;
	state.ny = ny;
	// 셀의 상태를 저장하는 2차원 배열을 생성하고 초기화한다
	state.cells = new Array(ny);
	for(var ix=0; ix<nx; ix++) {
		state.cells[ix] = new Array(ny);
		for(var iy=0; iy<ny; iy++) {
			state.cells[ix][iy] = 0;
		}
	}

여기서 nx와 ny의 초깃값은 특정 함수에 의해 78과 60으로 지정된다. 78은 가로 픽셀의 개수를 의미하고, 60은 세로 픽셀의 개수를 의미한다. 가로로 조금 더 긴 view 가 생성된다. 

 

그런데 여기서 의문이 생긴다. 가로로 78이고 세로로60인데 즉 

 

state.cells = new Array(ny); 로 처음으로 배열을 생성했는데, 

이어 for문에서는 ix를 0부터 nx까지 돌리고 있다. 즉 배열의 크기가 60으로 생성되었는데, 밑에서는 for문에서 ix를 0부터 78까지 돌리면서 심지어 state.cells[ix] 를 통해서 60을 넘어서는 인덱스 77까지 접근하고 있다. 

 

이 부분이 처음 혼란스러웠던 부분이다. 아마 자바스크립트를 배우기 전에 다른 정적 타입 언어에 익숙해져있었기 때문에 자바스크립트의 특수함에 혼란스러웠던 것 같다. 실제로 배우면서 좀 이상하다 싶은 구문들이 있었다. 이전에는 허용되지 않았던 구문들이 자바스크립트에서는 허용되는? 그래서 헷갈리지 않으려고(특히 다시 정적 타입을 쓰게 될 경우에 실수하지 않기 위해) 노력하고 있다. 

 

아무튼 말이 길어졌고, 어떻게 배열의 길이를 넘어서는데도 할당할 수가 있는지가 궁금해서 자스의 배열의 할당방법을 찾아봤고, 길이가 별로 상관이 없다는 것을 알게 되었다. 보통같으면 arrayindexoutofboundexception이 일어났을 법한 상황에서도 자스의 경우 그냥 그 중간의 값들을 모두 undefind로 할당해서 무난히 넘겨버리는 경우도 존재했다. 

 

그리고 직접 테스트를 해본 결과 다음과 같은 결과가 나왔다. 

 

포스팅 첫 코드에서 각 변수에 실제 값을 할당해서 테스트한 결과이다. iy가 더 작음에도 불구하고 ix만큼 그냥 요소들을 생성해버렸다. 결국 iy값이 얼마인지와는 상관없이 그냥 for문 횟수만큼 요소를 생성했다. 

 

그래서 사진에 있는 코드에서 var arr = new Array(iy); 가 왜 존재할까? 라는 생각을 하게 되었는데, 아마 굳이 소용없지는 않을거다 라는 생각에 이르렀다. 그래서 내린 결론은 이 (쓸모없다고 여기지는 코드는) 코드는 쓸모가 있다. 반드시 필요하다. 왜냐면 var arr 가 일단은 배열이여야 하기 때문이다. 대신 new Array() 에서 괄호안의 인수는 아무거나 넣어도 상관없다. var arr가 배열임을 나타내는 어떠한 코드가 반드시 필요한 것이다. (그래야만 배열로써 동작할테니까 ) 

 

아무튼 여기까지가 서두였고, 이제 본격적으로 의문이 들었던 부분에 대해 정리하겠다. 

 

포스팅 맨 처음의 코드로 돌아가보자. 

 

for문을 통해서 state.celles[ix] = new Array(ny); 로 생성하고 있다. 즉 가로 값 78만큼 배열을 생성한다. 

그리고 중첩 for문을 통해서 iy만큼 state.cells[ix][iy] = 0으로 초기화 하고 있다. 즉 78개의 각 요소마다 60개의 요소를 가진 배열이 또다시 생겨난 것이다. (2차원 배열로써 말이다,) 

 

그런데 여기서 자세히 살펴보면 의문이 든다. 

 

만들어진 배열의 구조는 다음과 같다. 

60자리 배열이 78개 있다. 그런데 가로가 60개다? 세로가 78개고? 그러니까 우리가 원래 만들려고 했던 셀의 경우 가로가 78개고 세로가 60개여야 한다. 그런데 정작 코드를 통해 생겨난건 행열이 반전된 배열이다. 

 

코드가 틀린건 아닐텐데 (아니 혹시 틀린건가?) 하고 생각했는데, 정작 실행해보면 아~주 정상적으로 표시된다. 

 

그래서 고민했는데, 얼마 안가서 해답을 얻게 된다. 

 

그 직접적인 이유는 바로 다음과 같다. 우리가 2차원 배열을 생성하고 그 배열에서 특정 요소를 call할 때의 방식과 view 에서 특정 셀의 좌표를 call하는 방식에 있어서의 차이다. 

 

2차원 배열이 있다고 가정하자. 

배열  arr가 위 배열을 생성했다고 가정하면 첫번째 행의 3번째 요소에 접근할 때 우리는 다음과 같이 쓴다. 

arr[0][2]

만약 두번째 행의 4번째 요소라면 다음과 같다. 

arr[1][3]

 

이제 슬슬 감이 올 수도 있다. 

 

자 그러면 이제 view 즉 화면에 픽셀에서 접근할 때 우리는 좌표를 어떻게 찍냐면 다음과 같이 찍는다. 

2,0

3,1

즉 첫자리가 x이고, 두번째가 y이다. (그 이유는 픽셀은 좌상단이 0,0이고 오른쪽, 하단 으로 진행할 수록 각 자리의 값이 증가하기 때문이다. )

 

그러므로 픽셀에서 좌표를 표시하는 방식과 픽셀의 정보를 담기위해 생성한 배열의 요소를 부를 때 그 방식이 서로 반대라는 것이다. (x,y가 반대된다. ) 

 

그렇다면 우리가 생성한 state.cells 가 어떻게 view의 픽셀에서 작동하는 지 마지막으로 알아보고 마무리 하겠다. 

(빨간 글씨는 인덱스를 나타내는게 아니다. 절대!, 빨간 글씨는 실제 view픽셀일 경우 어떻게 나타내는지를 의미한다.)

픽셀에서의 x,y 호출 방식과 정확히 맞어떨어지는 것을 알 수 있다. 

 

음... 이것 때문에 이해가 안되서 계속 고민했는데, 역시나 특정 좌표를 머릿속으로 가정하고, 배열부터 픽셀까지 어떻게 흐르는 지 생각해보니 해결되었다... 

 

근데 이런 방식으로 사용하는 건 처음 봤다. 이것도 아직 경험이 없어서 그런듯하다. 이래서 실무자들과 학생이 배우는 수준이 다르다고 한 게 왜그런지 알 것 같다. 각 요소의 컨트롤 방식과 특정 상황에서 사용하는 프로그래밍 기법 등... 그런 건 직접 짜보지 않는 이상 모르는 거니까. 책에 안나와있으니까 왜인지 계속 고민해야하는 거니까. 

 

아무튼 정말 몇줄되지도 않는 코드였는데, 재밌었다. 배운것도 많았고, 자바스크립트는 볼수록 특이한 언어라는 느낌을 많이 받는다. 아무튼 꽤 재밌는 기법을 보게 되어서 좋았다. (음... 기법? 조금만 생각해보면 나올 수 있는 거긴 하다. 대신 내가 너무 빙빙 돌았다. 픽셀좌표를 전혀 고려하지 못한게 시간이 오래 걸린 이유다. )

 

책도 정말 괜찮은 책이다. 

반응형