💙 들어가며
로또와 오목게임을 다지기 위한 초석.
배열의 배열, 2차 배열의 원리에 대해서 알아보자.
✏️ 학습내용 정리
#2차 배열이란?
지금까지는 1차 배열만을 가지고 여러 값을 하나의 변수에 담아서 사용하였다.
그런데 이제부터는 마치 1차 배열을 값처럼 다루는 상위 배열,
2차 배열에 대해서 알아볼 필요가 있겠다.
2차 배열은 왜 필요할까? 어떨 때 필요할까? 로또를 생각해보자.
로또 5,000원권을 구매하면 다음과 같이 A부터 E까지 6개의 값이 들어간 배열이 총 5줄 있었다.
여태까지 배운 1차 배열은 6개의 값을 한 번에 담을 수는 있었지만,
(A, B, C, D, E 배열 각각 독립적으로 존재)
각각의 배열로 존재했지, 5개의 배열을 다시 하나로 묶을 수는 없었다.
(원하는 것은 A, B, C, D, E 배열을 묶는 그 위의 상위 배열)
#2차 배열이 없다면?
실제로 매우 직관적이게도,
2차 배열이라는 개념이 없었을 때는 1차 배열을 옆으로 죽~ 늘어뜨리는 식으로 관리했다고 한다.
그런데 이렇게 되면 인덱스가 굉장히 모호해진다.
다음의 그림을 살펴보자, 만약 내가 lotto2의 3번째 값을 출력하고 싶다면 어떻게 해야 할까?
다음과 같이 매우 복잡한 수식이 필요하게 된다. lottos[3*1+2]
이것도 배열이 3개 단위이기 때문에 직관적으로 보이는 것이지,
만약 배열의 크기가 100개가 훌쩍 넘어가게 된다면 어떻게 될까? PPT에 그릴 수도 없을 것이다.
이렇게 1차 배열이 여러개 있을 때, 각각의 배열은 따로 또 같이 존재하기가 어려웠다.
그냥 연속되는 선 상에 올라와 있는 점들 같은 느낌.
그 선들을 또 나누고 구분해서 관리하기 위해 2차 배열을 사용하는 방법에 대해서 알아야겠다.
#1차 배열을 사용해서 오목판 출력
1차 배열과 2차 배열을 이용해서 값을 출력할 때 얼마나 큰 차이가 있는지 아래의 예시를 통해서 확인해보자.
바둑판을 출력하려고 한다. 바둑판은 x, y축이 있다.
이는 곧, x축 길이의 배열들이 y축만큼 존재한다고 생각할 수 있겠다. 12(x)*12(y)
그런데 이것을 1차 배열로 표시하려면 위에서 언급했듯이
12개짜리 배열을 일직선 상에 12번 늘어놓기 때문에
배열 크기는 우리의 원래 의도 12와는 다른 144개의 크기로 만들어야 하며,
그것을 구분하는 단위도 없기 때문에 인덱스를 일일이 12개 단위로 잘라서
하나씩 출력하게 해야 하는 계산식이 필요해진다.
🚨 배열을 1차 배열로 출력해라
배열 한 개당 값이 12개씩 있으니
총 144개 크기의 방을 만든다.
그리고 if조건을 걸어서 값을 대입한다.
//board 배열 만들고 값 임력하기
char[] board = new char[144];
//board에 값 입력
for(int i=0; i<12; i++)
for(int j=0; j<12; j++)
if(i == 0 && j == 0)
board[i*12+j] = '┌';
else if(i == 11 && j == 0)
board[i*12+j] = '└';
else if(i == 0 && j == 11)
board[i*12+j] = '┐';
else if(i == 11 && j == 11)
board[i*12+j] = '┘';
else if(i == 0)
board[i*12+j] = '┬';
else if(j == 0)
board[i*12+j] = '├';
else if(i == 11)
board[i*12+j] = '┴';
else if(j == 11)
board[i*12+j] = '┤';
else
board[i*12+j] = '┼';
//board 출력
for(int y=0; y<12; y++) {
for(int x=0; x<12; x++)
System.out.printf("%c", board[12*y+x]);
System.out.println();
}
┌┬┬┬┬┬┬┬┬┬┬┐
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
└┴┴┴┴┴┴┴┴┴┴┘
그런데 2차 배열을 사용하면 굉장히 단순해진다.
2차 배열의 성격 자체가 조건을 걸 필요 없이 이미 좌표를 가지고 있기 때문에,
그 좌표에 원하는 값을 바로 대입하면 된다.
🚨 배열을 2차 배열로 출력해라
2차 배열에 2개의 인덱스를 사용해서
바로 원하는 값을 대입할 수 있음.
//board 배열 만들고 값 임력하기
char[][] board = new char[12][12];
// ---------바둑판에 값 넣기-------------
for (int y = 0; y < 12; y++)
for (int x = 0; x < 12; x++)
board[y][x] = '┼';
board[y][11] = '┤';
board[0][x] = '┬';
board[11][x] = '┴';
board[y][0] = '├';
//여기 값들은 반복문 필요 없이 바로 대입할 수 있다.
//이미 조건을 걸 필요도 없이 좌표를 가지고 있기 때문!
board[0][0] = '┌';
board[0][11] = '┐';
board[11][0] = '└';
board[11][11] = '┘';
}
//board 출력
for(int y=0; y<12; y++) {
for(int x=0; x<12; x++) {
System.out.printf("%c", board[y][x]);
}
System.out.println();
}
┌┬┬┬┬┬┬┬┬┬┬┐
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┤
└┴┴┴┴┴┴┴┴┴┴┘
#배열 사용의 의의
1차 배열이든 2차 배열이든 먼저 이해해야 할 것은,
배열의 특징이 랜덤하게 값에 엑세스할 수 있다는 것이다.
때문에, 배열을 중간에 조작하는 경우가 있다면
데이터 제어와 화면 출력을 따로 분리하는 것이 바람직하다.
우리가 배열을 사용하는 이유는 출력을 바로 하지 않고,
앞으로 수많은 조작을 이어나갈 수 있다는 여지를 남기는 것이다.
(배열은 출력하기 전에 출력할 수 있는 공간을 만드는 것이다.)
그런데 대입과 동시에 출력을 같이 해버리면 배열의 의미가 사라지게 된다.
때문에, 배열을 사용할 시에는 두 가지를 분리하는 것이 좋다.
랜덤으로 바로 값을 꽂아넣는 것에 대해 이점을 활용하자.
그리고 이것 또한 값을 대입하는 개념이기 때문에 마지막에 넣은 값이 최종 대입값이 된다.
(이런식으로 조건문이나 반복문 없이 계속해서 유연하게 값을 제어할 수 있음)
🚨 배열의 바람직한 사용방법 flow
① 배열 선언 //char[] board = new char[144];
↓
② 배열 값 수정 //board[i] = '┐';
↓
③ 출력 //for문
💙 마치며
늘 배열을 다룰 때에는 입력과 출력을 구분하여 사용하자.
(입력하면서 동시에 출력하려고 하면 많은 오류를 직면하게 되더라..)
아직 2차 배열은 어렵고 낯설지만 알면 알수록 훨씬 간단하고 유용한 도구인 것 같다.
(1차 배열일 때 일렬로 주욱~ 나열하던 것에서 벗어나서
새롭게 계층을 나누게 되니 훨씬 이해하기가 좋았던 것 같기도?)
배열과 더욱 친해지기.. 도전💯
'JAVA' 카테고리의 다른 글
[뉴렉처 6기] JAVA│Random│랜덤 데이터 채우기│슈도(pseudo)(230623) (1) | 2023.07.01 |
---|---|
[뉴렉처 6기] JAVA│버블 정렬과 선택 정렬(230623) (1) | 2023.07.01 |
[뉴렉처 6기] JAVA│배열(Array)를 활용한 데이터 편집│최소값, 최대값, 자리바꾸기(230622) (1) | 2023.06.29 |
[뉴렉처 6기] JAVA│반복과 검사 do while│메뉴 switch(230620) (0) | 2023.06.27 |
[뉴렉처 6기] JAVA│메모리(stack, heap)│Garbage Collector│오류와 디버깅(230626) (0) | 2023.06.27 |