배열이란 같은 데이터타입의 여러 변수를 하나의 묶음으로 나타낸 것이다.
배열의 데이터타입에 대한 동일한 크기로 메모리상에 연속된 공간이 할당된다.
배열명이 메모리 시작 주소이다.
int nums[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 12};
위와 같이 표현 할 수 있다.
int nums[10];
처럼 초기화하지 않으면, 배열 내부의 값은 0이고 식을 통하여 값을 대입할 수 있다.
cout << nums << endl; for (int i = 0; i < 10; i++) { cout << &(nums[i]) << endl; }
배열명이 메모리 시작 주소이기 때문에, 배열명을 출력하면 해당 배열의 시작 메모리 주소가 출력된다. &를 이용하여 각각 배열의 메모리 주소를 출력할 수도 있다.
1. string형 배열변수 5개짜리를 선언하고, 반복문을 통해 학생의 이름을 입력받는다.
입력을 다 받고나서 1 ~ 5 사이의 값을 입력하면 해당학생의 이름이 출력된다.
ex) 1번째 학생의 이름을 입력하세요 :
2번째 학생의 이름을 입력하세요 :
3번째 학생의 이름을 입력하세요 :
4번째 학생의 이름을 입력하세요 :
5번째 학생의 이름을 입력하세요 :
1 ~ 5 사이의 번호를 입력하세요 : 3
3번째 학생의 이름은 ... 입니다.
string형 배열변수를 이용하여 값을 입력받는다.
string name[5] = { }; int nameNum; for (int i = 0; i < 5; i++) { cout << i + 1 << "번째 학생의 이름을 입력하세요 : "; cin >> name[i]; cout << endl; }
5명의 학생이름을 입력받기 위하여 for문을 이용하였다.
배열을 불러오기 위해선 1 ~ 5가아닌 0 ~ 4로 불러와야 한다.
그렇게 되면 0번째 부터 출력되므로, i + 1로 출력하였다.
cout << "1 ~ 5 사이의 번호를 입력하세요 : "; cin >> nameNum; cout << endl; cout << nameNum << "번째 학생의 이름은 " << name[nameNum - 1] << "입니다!" << endl;
앞서 i + 1로 출력한 것과 같이, 입력 받는 번호는 1 ~ 5인데, 출력하기 위해선 name[0 ~ 4] 를 이용해야 하므로,
name[nameNum -1]이라고 출력해주었다.
배열이 (*개념적으로 = 실제로는 1차원으로 배열됨.) 2중으로, 다중으로 구성되어 있는 것.
1차원 배열 : int student_nums[5]; // 5개의 int
-> 5명의 학생이 있다.
2차원 배열 : int student_nums[3][5]; // 15개의 int
-> 3개 반에 각각 5명의 학생이 있다.
3차원 배열 : int student_nums[4][3][5]; // 60개의 int
-> 4개 학년에 각각 3개 반이 존재, 각 반에 5명의 학생이 있다.
int student_nums[3][5] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15} };
위와같이 표현 할 수 있다.
cout << student_nums[0][7] << endl; // [1][2]
정상적인 사용방법은 아니나, 시작 주소로 부터 떨어져있는 거리를 계산하여 값을 출력할수도 있다.
for (int j = 0; j < 3; j++) { for (int i = 0; i < 5; i++) { cout << student_nums[j][i] << endl; cout << &(student_nums[j][i]) << endl; } }
순서대로 출력하는 코드 (※ 변수이름이 같은 것이 메모리가 같다는 것을 의미하지는 않는다.)
구구단의 결과를 저장하는 2차원 배열을 하나 선언하고,
이중 for문을 이용해서 배열 변수에 구구단의 결과값을 저장하고,
두 수를 입력받아서 적합한 결과값을 출력해보자.
ex)
(결과 저장 완료)
몇 단을 볼까요? : _
몇을 곱할까요? : _
0 * 0 = 28
int gugu[8][9]; int guguDan; int guguNum;
우선 구구단의 결과를 저장할 2차원 배열과 구구단의 단과 곱할 수의 변수를 선언해준다.
for (guguDan = 0; guguDan < 8; guguDan++) { for (guguNum = 0; guguNum < 9; guguNum++) { gugu[guguDan][guguNum] = (guguDan + 2) * (guguNum + 1); }
구구단의 결과를 이중 for문을 이용하여 저장한다.
gugu[guguDan][guguNum] = (guguDan + 2) * (guguNum + 1);
단은 2단부터 시작하고, 곱할 수는 1 ~ 9 이므로, 단 변수에는 + 2, 곱 변수에는 + 1을 추가해준다.
구구단의 결과값을 저장했다면, 제대로 저장이 되었는지 출력해보아야 한다.
cout << "몇 단을 볼까요? : "; cin >> guguDan; cout << "몇을 곱할까요? : "; cin >> guguNum; cout << guguDan << " * " << guguNum << " = " << gugu[guguDan - 2 ][guguNum - 1];
최초 요구사항대로 출력값과 입력값을 저장한 후에, 불러올 변수와 입력받는 변수가 다르기 때문에
gugu[guguDan - 2 ][guguNum - 1] 와 같이 출력해준다.
위와 같이 정상적인 값이 나오는 것을 확인할 수 있다.
++ 입력된 값이 대소문자 구분없이 처리될 수 있도록 수정해보자.
srand(time(NULL)); char answerNum; int correctNum = ((rand() % 26) + 65); cout << "알파벳 맞추기 게임에 오신것을 환영합니다!" << endl << endl << "정답을 입력해주세요!" << endl << endl;
랜덤한 값을 출력해야하므로, srand 타임변수를 지정해주고, 알파벳을 출력하기 위하여
int correctNum = ((rand() % 26) + 65); 로 정답을 지정해준다.
※아스키 코드로 알파벳 대문자 65 ~ 90 이기때문에.
for (int i = 5; i > 0; i--) { cout << "미리보는 정답 : " << (char)correctNum << endl << endl; answerNum = _getch(); cout << "정답 : " << answerNum << endl << endl;
기회는 총 5번이므로 for의 변수 i는 반복횟수는 5번으로 지정한다.
남은 기회를 i - 1로 표현하기 위하여 감소로 표현하여
for (int i = 5; i > 0; i--) 와 같이 표현하였다.
※입력값을 엔터입력없이 바로 입력하는 명령어 : _getch()
-> #include <conio.h>로 호출필요.![](https://velog.velcdn.com/images/fukoyjh/post/9ae7e8ca-8cb6-4ff1-9463-5d6f930aae7d/image.png)
위와 같이 출력되는 것을 확인할 수 있다.
if (answerNum < 95) { if (correctNum == answerNum) { cout << "승리하셨습니다!" << endl; break; } else if (i == 1) { cout << "GAME OVER... 정답은 " << (char)correctNum << "였습니다." << endl << endl; } else if (correctNum != answerNum) { cout << "오답입니다..." << i - 1 << "번 기회 남으셨습니다." << endl << endl; if (answerNum > correctNum) { cout << "HINT! 정답은 " << answerNum << "보다 앞에 있습니다." << endl << endl; } else if (answerNum < correctNum) { cout << "HINT! 정답은 " << answerNum << "보다 뒤에 있습니다." << endl << endl; } } }
correctNum과 answerNum이 같으면 승리멘트와 함께 종료.
i가 1이 되어 모든 기회를 소진하면 게임오버.
그리고 correctNum과 answerNum 이 같으면 남은 횟수와 힌트로 정답의 위치를 표현하였다.
-> 승리 멘트 출력
-> 오답 시 남은 횟수와 힌트 출력.
-> 게임 오버 시, 정답과 함께 멘트 출력
else if (answerNum > 95) { if (correctNum == (answerNum - 32)) { cout << "승리하셨습니다!" << endl; break; } else if (i == 1) { cout << "GAME OVER... 정답은 " << (char)correctNum << "였습니다." << endl << endl; } else if (correctNum != (answerNum - 32)) { cout << "오답입니다..." << i - 1 << "번 기회 남으셨습니다." << endl << endl; if ((answerNum - 32) > correctNum) { cout << "HINT! 정답은 " << answerNum << "보다 앞에 있습니다." << endl << endl; } else if ((answerNum - 32) < correctNum) { cout << "HINT! 정답은 " << answerNum << "보다 뒤에 있습니다." << endl << endl; } } cout << endl; } }
위와 동일하게 표현한 코드이며 answerNum이 대,소문자 구분이 없이 작동하도록 answerNum이 95보다 크면 answerNum - 32가 동작하도록 if문을 이용하여 추가하였다.
※아스키 코드로 알파벳 소문자 97 ~ 122 이기 때문에.
-> 대,소문자 구별없이 동작함.
콘솔용 탈출게임.
1. 10 * 10 크기의 맵을 구성한다. (2차원 배열)
#O########
##########
##########
##########
##########
##########
##########
#######E##
##########
##########
2. 플레이어가 존재한다.(0,0)
3. 탈출지점이 존재한다.(0,0) 제외 랜덤 설정
4. WASD 키입력을 통해 플레이어를 이동시킨다.
5. 플레이어가 탈출지점에 도달하면 "탈출에 성공했습니다!" 프로그램 종료.
※ 화면갱신 명령어 : system("cls");
int mapNum[10][10]; srand(time(NULL)); int playerX = 0; int playerY = 0; int escapeX = (rand() % 10); int escapeY = (rand() % 10); int button; int upButton = 119; int downButton = 115; int leftButton = 97; int rightButton = 100;
10 * 10의 맵을 표현하기 위한 2차배열과 랜덤변수, 플레이어/탈출구 위치변수와 WASD에 맞는 버튼, 그리고 버튼 입력변수를 초기화 한다.
while(escapeX == 0 && escapeY == 0) { escapeX = (rand() % 10); escapeY = (rand() % 10); }
플레이어와 탈출구의 시작 위치가 (0, 0)으로 같으면 안되므로, 위와 같이 while문으로 escapeX가 0일때 탈출구의 위치를 재지정 할 수 있게 해준다.
while(1) { for (int x = 0; x < 10; x++) { for (int y = 0; y < 10; y++) { mapNum[x][y] = 35; mapNum[playerX][playerY] = 80; mapNum[escapeX][escapeY] = 69; cout << (char)mapNum[x][y]; if (y == 9) { cout << endl; } } }
탈출 지점 도착전까지 반복해야하므로, while문을 사용하고, 이중 for문으로 맵은 mapNum[x][y] = 35;, 플레이어의 위치는 mapNum[playerX][playerY] = 80;, 탈출구의 위치는 mapNum[escapeX][escapeY] = 69; 로 초기화해준다.
cout << (char)mapNum[x][y];로 맵을 출력해주면
위와 같이 출력이 된다.
button = _getch(); system("cls"); if (button == upButton) { playerX -= 1; if (playerX < 0) { playerX = 0; } } if (button == downButton) { playerX += 1; if (playerX > 9) { playerX = 9; } } if (button == leftButton) { playerY -= 1; if (playerY < 0) { playerY = 0; } } if (button == rightButton) { playerY += 1; if (playerY > 9) { playerY = 9; } }
button 변수를 _getch()로 입력 받고, button 변수가 각각 wasd와 일치한다면 움직일 수 있도록 if문으로 제어해준다.
만약 d를 눌러 if (button == rightButton)가 동작한다면, playerY의 값이 += 1이 되어
이와 같이 오른쪽으로 이동한다.
mapNum[playerX][playerY] 가 mapNum[playerX][playerY += 1] 되었기 때문에
mapNum[0][0]의 값은 35(#)이되고, mapNum[0][1]가 80(P)의 값을 가짐으로써 움직인다.
또한, if (playerY > 9) 에 playerY = 9; 라는 if 문을 추가함으로써 맵 밖으로 P가 나가지 못하게 한다.
if (mapNum[playerX][playerY] == mapNum[escapeX][escapeY]) { cout << "축하합니다! 승리하셨습니다!"; break; } }
}
이후 mapNum[playerX][playerY]과 mapNum[escapeX][escapeY] 가 같으면 탈출구에 플레이어가 도착한 것임으로 축하멘트와 break문으로 whlie문을 종료해준다.
처음 이 문제를 해결하려고 했을 때는 맵을 for문 내에서 표현했기 때문에, 이동을 어떻게 표현할지가 가장 난관이었다.
while문으로 입력을 반복해주면서, 이동을 플레이어 위치변수의 값 변환하는 if문으로 작동하는 아이디어를 떠올린 후에 해결할 수 있었다.
아직 부족하지만, 제법 모양이 잡힌 결과물이 나오니 뿌듯하지 아니할수가 없다.
P.S. 저녁도 거르면서 집중한 나를 칭찬한다! But, 오늘 저녁은 맛있는거 먹자.