길이가 4 X 4인 int형 2차원 배열을 선언하고, 모든 요소를 1~16 순서대로 초기화하자.
그리고 배열의 요소들을 오른쪽 방향으로 90°씩 이동시켜서 그 결과를 출력하는 프로그램을 작성해보자.
![]() | 👉 | ![]() |
---|---|---|
초기화 | 오른쪽 방향 90°회전 후 |
#include <stdio.h>
void Rotate(int(*arr)[4], int repeat)
{
int alter[4][4] = {0};
for(int z = 0; z<repeat; z++)
{
for(int i = 0; i<4;i++)
for(int j = 0; j<4; j++)
alter[i][j] = arr[i][j];
for(int i = 0; i<4; i++)
for(int j = 0; j<4; j++)
arr[j][3-i] = alter[i][j]; // 위치 변경
for(int i = 0; i<4; i++)
{
for(int j = 0; j<4; j++)
printf("%d ", arr[i][j]); // 4x4 배열 출력
printf("\n");
}
printf("\n");
}
}
int main()
{
int arr[][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
Rotate(arr,3); // 회전 3회 진행
return 0;
}
>출력
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
16 15 14 13
12 11 10 9
8 7 6 5
4 3 2 1
4 8 12 16
3 7 11 15
2 6 10 14
1 5 9 13
-풀이-
처음 배열을 적어보고 두 번재 배열을 적어보면 눈에 보이기 시작한다.
배열을 4x4로 정의해놓고 이 크기가 변하지 않는 것을 이용해서 계산할 수 있게 했다.
사실 적어놓고도 아이디어가 생각나지 않아서 서칭을 했다...ㅎ 참고 자료로 아래에 적어두겠다.
달뱅이 배열을 만들어서 이를 출력하는 프로그램을 작성하고자 한다.
여기서 말하는 달팽이 배열은 다음과 같다.
위 그림에서는 5X5의 달팽이 배열을 보여주고 있다.
이 내용을 참조하여 프로그램 사용자로부터 하나의 숫자 n을 입력 받아서 nXn의 길이에 해당하는 달팽이 배열을 출력해주는 프로그램을 작성해 보자.
#include <stdio.h>
void Snail(int(*arr)[100], int num);
void Output(int (*arr)[100], int num);
int main()
{
int num;
printf("100이하의 자연수 입력: ");
scanf("%d", &num); // 배열 크기 입력
int arr[100][100]; // 4x4 배열 선어
Snail(arr, num); // 달팽이 배열 숫자 저장
Output(arr, num); // 2차원 배열 출력
return 0;
}
void Snail(int (*arr)[100], int num)
{
int i = 0, j = 0;
int count = 1;
int re = 0;
if(num%2 == 0) // 입력한 숫자가 짝수일 경우 (한바퀴씩 도는거 -> 마지막엔 '그' 모양으로 마무리.)
re = (num/2)-1;
else // 입력한 숫자가 홀수일 경우 (한바퀴씩 도는거 -> 마지막엔 '.' 모양으로 마무리.)
re = num/2;
int round1_num = num-1;
int round2_num = 0;
for (int z = 0; z < re; z++)
{
for (; j < round1_num; j++) // 가로 + (한바퀴 부분에서 → 방향)
{
arr[i][j] = count;
count++;
}
for (; i < round1_num; i++) // 세로 + (한바퀴 부분에서 ↓ 방향)
{
arr[i][j] = count;
count++;
}
for (; j > round2_num; j--) // 가로 - (한바퀴 부분에서 ← 방향)
{
arr[i][j] = count;
count++;
}
for (; i > (round2_num+1); i--) // 세로 - (한바퀴 부분에서 ↑ 방향)
{
arr[i][j] = count;
count++;
}
round1_num--;
round2_num++;
}
if(num%2==0) // 짝수일 경우 '그' 모양으로 마무리.
{
for(; j<round1_num; j++) // 가로 +
{
arr[i][j] = count;
count++;
}
for(; i<round1_num; i++) // 세로 +
{
arr[i][j] = count;
count++;
}
arr[i][j] = count;
count++;
arr[i][j-1] = count;
}
else // 홀수일 경우 '.' 모양으로 마무리.
{
arr[i][j] = count;
count++;
arr[i][j+1] = count;
}
}
void Output(int (*arr)[100], int num) // 출력
{
for (int i = 0; i < num; i++)
{
for (int j = 0; j < num; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
>출력
1 2 3 4 5 6 7
24 25 26 27 28 29 8
23 40 41 42 43 30 9
22 39 48 49 44 31 10
21 38 47 46 45 32 11
20 37 36 35 34 33 12
19 18 17 16 15 14 13
-풀이-
이것도 다른분의 풀이를 참고해서 풀었다.
우선 입력 받은 숫자를 짝수와 홀수로 나누고 채워지는 패턴을 분석했다.
짝수의 경우, 시계방향으로 다 채워지는 것이 계속 되다가 (이 횟수는 입력하는 값의 절반 정도) 마지막에 '그' 모양으로 저장이 되며 마무리 된다.
홀수의 경우, 시계방향으로 다 채워지다가, 마지막에 '.' 모양으로 저장이 되며 마무리 된다.
시계방향으로 채워지는 것을 for문으로 → ↓ ← ↑ 순으로 채웠고 이때 행렬의 자리 수가 중요하다.
예를 들면 방향 채워지는 걸 나누는걸 입력값이 4여서 4X4 배열을 채워야한다면
arr[i][j]
)![]() | ![]() |
---|---|
배열 | 채우는 순서 |
① → 방향 : 00 01 02 (가로 +; j 증가)
② ↓ 방향 : 03 13 23 (세로 +; i 증가)
③ ← 방향 : 33 32 31 (가로 -; j 감소)
④ ↑ 방향 : 30 20 10 (세로 -; i 감소)
로 시계방향 한바퀴가 채워지고 마지막으로 '그' 모양에서
① → 방향 : 11 12 (가로 +; j 증가)
② ← 방향 : 22 21 (가로 -; j 감소)
이 이루어진다.
예를 들어, 5를 입력하여 5X5 배열을 채워야한다면
짝수 채우는 방법과 동일하게 채우다가
마지막에 '.' 모양만 하나 채워주면 된다.
마지막 i와 j가 어디까지 count 되어있는지 어디까지 와있는지만 잘 파악하면 문제는 마무리 지을 수 있다...
프로그램을 구현하다 보면 난수(Random Number)를 발생시켜야 하는 경우가 종종 있다. 여기서 말하는 난수란 임의의, 정해지지 않은, 무엇이 될지 모르는 수를 의미한다.
ANSI 표준에서 난수를 생성할 때 호출할 수 있는 함수를 제공한다.
#include <stdlib.h>
int rand(void); // 의사 난수(pseudo-random number)를 반환
rand 함수
를 제공하고 이 함수의 사용방법은 다음과 같다.
// RandomNum.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
printf("난수의 범위: 0부터 %d까지 \n", RAND_MAX);
for(i=0;i<5;i++)
printf("난수 출력: %d \n", rand());
return 0;
}
> 출력
난수의 범위: 0부터 32767까지
난수 출력: 41
난수 출력: 18467
난수 출력: 6334
난수 출력: 26500
난수 출력: 19169
이 예제를 적절히 변경해서 0 이상 99 이하의 난수를 총 5개 생성하는 프로그램을 작성해보자.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i=0, random;
printf("난수의 범위: 0부터 %d까지 \n", RAND_MAX);
while(i<5)
{
random = rand()%100;
if(random<100)
{
printf("99이하 난수 출력: %d \n", random);
i++;
}
}
return 0;
}
>출력
난수의 범위: 0부터 32767까지
99이하 난수 출력: 41
99이하 난수 출력: 67
99이하 난수 출력: 34
99이하 난수 출력: 0
99이하 난수 출력: 69
-풀이-
RAND_MAX 자체를 바꾸려고 했지만 이미 고정되어있는 상수라 바꿀 수 없었고 대신 무작위로 숫자를 생성하는 rand()
함수를 이용해 99이하의 숫자를 출력할 수 있도록 했다.
도전 3에서 제시한 예제를 여러 번 실행해보면 출력되는 난수가 규칙적이라는 것을 알 수 있다. (동일한 숫자가 계속 출력된다.) 예측 가능한 숫자기 때문에 난수가 될 수 없고 따라서 이 rand 함수가 반환하는 난수를 가리켜 '의사 난수(pseudo-random number)'라 한다. 즉, 가짜 난수라는 의미다.
ANSI 표준에서는 이러한 문제를 어느 정도 해결할 수 있도록 srand라는 함수를 정의하였다.
#include <stdlib.h>
void srand(unsigned int seed); // 발생할 난수의 씨드 값 지정
위의 함수는 하나의 값을 전달받는다. 그리고 그 전달된 값은 난수를 생성하는데 필요한 씨드(seed)가 되고 이 씨드 값이 무엇이냐에 따라서 rand 함수가 반환하는 난수의 형태가 달라진다. 다음 예제를 통해서 난수 생성에 필요한 씨앗(씨드_seed)를 심어보겠다.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int seed, i;
printf("씨드 값 입력: ");
scanf("%d", &seed);
srand(seed); // 씨앗 심기.
for(i=0;i<5;i++)
printf("정수 출력: %d \n", rand()); // 열매 수확.
return 0;
}
> 출력
씨드 값 입력: 15
정수 출력: 87
정수 출력: 5105
정수 출력: 27056
정수 출력: 2938
정수 출력: 32501
우리는 씨드 값을 입력 받아 사용하는 것이 아닌 시스템 시간을 이용할 것이다. 컴퓨터 시간 값을 얻어와서 srand 함수의 인자로 전달하는 것이다. 컴퓨터의 시간은 계속 변하기 대문에 매번 다른 씨드 값을 얻는 도구로 활용이 가능하다.
컴퓨터의 현재 시간은 헤더파일 time.h
에 선언되어 있는 time
이라는 함수를 사용하면 된다.
이 함수는 컴퓨터의 현재시간과 1970년 1월 1일 이후의 시간적 차를 초단위로 계산해서 반환해 준다.
우리는 정확한 시간을 얻는 것이 아니라 프로그램 실행 시마다 다른 정수 하나를 얻기 위함이기 때문에 충분하다.
이를 사용한 예제는 아래와 같다.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int i;
srand((int)time(NULL)); // 현재 시간을 이용해서 씨드 설정
for(i=0; i<5; i++)
printf("정수 출력: %d \n", rand());
return 0;
}
> 출력
정수 출력: 19512
정수 출력: 14230
정수 출력: 20331
정수 출력: 13519
정수 출력: 3561
time 함수
에서 단순히 시간정보를 반환 받는 것이 목적이라면 NULL을 인자로 전달하면 된다.
위 예제들을 이용해 두 개의 주사위를 던졌을 때의 결과를 출력하는 프로그램을 만들어보자.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i, random;
srand((int)time(NULL));
for(i=0; i<2; i++)
{
random = rand()%6+1;
printf("주사위 %d의 결과 %d \n", i+1, random);
}
return 0;
}
>출력
주사위 1의 결과 5
주사위 2의 결과 4
-풀이-
도전 3에서 사용한 것을 응용하는 문제였다...!
이런 문제 조항 오홍홍🥰
가위 바위 보 게임을 만들어 보자.
사용자로부터 가위 바위 보 중에서 하나를 입력 받는다. 그리고 컴퓨터는 난수 생성을 통해서 가위 바위 보 중에서 하나를 선택하게 한다.
이 둘을 비교해서 승자와 패자를 가려주는 프로그램을 작성해 보자. 단 프로그램의 진행은 사용자가 질 때까지 계속되어야 하고, 마지막에 가서는 게임의 결과(예: 4승 3무)까지 출력해 주도록 하자.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int select=0, com, win = 0, same = 0, lose = 0;
srand((int)time(NULL)); // 컴퓨터 시간을 정수로 반환. 랜덤 수를 넣기 위함.
while(1)
{
com = (rand()%3)+1; // 컴퓨터가 내는 가위 바위 보
printf("1. 바위 2. 가위 3. 보: ");
scanf("%d",&select);
/*
com | select
1 | 1 (same)
1 | 2 (lose)
1 | 3 (win)
2 | 1 (win)
2 | 2 (same)
2 | 3 (lose)
3 | 1 (lose)
3 | 2 (win)
3 | 3 (same)
*/
if(com==1)
{
if(com==select)
{
printf("당신은 바위 선택, 컴퓨터는 바위 선택, 비겼습니다!\n");
same++;
} else if(select==2)
{
printf("당신은 가위 선택, 컴퓨터는 바위 선택, 당신이 졌습니다!\n");
lose++;
} else
{
printf("당신은 보 선택, 컴퓨터는 바위 선택, 당신이 이겼습니다!\n");
win++;
}
} else if(com==2)
{
if(select==1)
{
printf("당신은 바위 선택, 컴퓨터는 가위 선택, 이겼습니다!\n");
win++;
} else if(select==com)
{
printf("당신은 가위 선택, 컴퓨터는 가위 선택, 당신이 비겼습니다!\n");
same++;
} else
{
printf("당신은 보 선택, 컴퓨터는 가위 선택, 당신이 졌습니다!\n");
lose++;
}
} else
{
if(select==1)
{
printf("당신은 바위 선택, 컴퓨터는 보 선택, 졌습니다!\n");
lose++;
} else if(select==2)
{
printf("당신은 가위 선택, 컴퓨터는 보 선택, 당신이 이겼습니다!\n");
win++;
} else
{
printf("당신은 보 선택, 컴퓨터는 보 선택, 당신이 비겼습니다!\n");
same++;
}
}
if(lose>0)
{
printf("\n게임의 결과: %d승, %d무", win, same);
break;
}
}
}
>출력
1. 바위 2. 가위 3. 보: 3
당신은 보 선택, 컴퓨터는 바위 선택, 당신이 이겼습니다!
1. 바위 2. 가위 3. 보: 2
당신은 가위 선택, 컴퓨터는 보 선택, 당신이 이겼습니다!
1. 바위 2. 가위 3. 보: 3
당신은 보 선택, 컴퓨터는 가위 선택, 당신이 졌습니다!
게임의 결과: 2승, 0무
-풀이-
이런 간단한 게임 만드는 코딩이 제일 재밌다 ㅎㅎ
우선 컴퓨터가 내는 것을 도전 5의 난수를 얻는 방법을 가져왔다.
사용자가 질 때까지 계속해야하므로 반복문은 while을 사용했다.
lose라는 변수가 1이라도 올라가는 순간 break되어 반복문을 탈출할 수 있게 했다.
이거보다 간결하게 짤 수 있을 거 같은데,,, 함수를 활용하는 방법일까?
친구와 둘이서 숫자 맞추기 게임을 해 본적이 있을 것이다(야구 게임). 이것을 컴퓨터와 할 수 있도록 프로그램을 작성해보자. 게임의 방식은 다음과 같다.
컴퓨터는 0에서 9사이의 숫자 중에서 서로 다른 세 개의 숫자를 고르고, 사용자는 이것을 맞춰야한다.
숫자만 맞추는 것이 아닌 순서도 맞춰야한다.
단 사용자가 예상한 숫자를 입력할 때마다 컴퓨터는 입력된 숫자와 컴퓨터 자신이 생각한 숫자가 얼마나 비슷한지를 알려줘야한다.
예를 들어서 컴퓨터가 고른 숫자가 1 4 9고,
사용자가 입력한 숫자가 4 0 9이면, 두 개의 숫자 4와 9가 일치한다. 9는 숫자와 위치까지 일치하지만 (1 strike), 4는 숫자만 일치한다 (1 ball).
이런 경우 컴퓨터는 다음과 같은 메시지를 출력한다.
"1 strike, 1 ball"
만약에 사용자가 1 4 9를 입력해 맞췄다면
"3 strike, 0 ball"이 출력되며 프로그램이 종료된다.
이 때 몇 번 만에 3 strike를 얻어냈는지에 대해서 출력해주기로 하자. ("몇 번째 도전입니다."라는 방식으로)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int com[3]={0}, user[3]={0}, count = 1;
srand((int)time(NULL));
// Generate random numbers for computer's choice
for(int i=0; i<3; i++)
{
com[i]=rand()%10;
}
if(com[0]==com[1])
{
com[1]++;
if(com[1]==10)
com[1]=0;
} else if(com[0]==com[2])
{
com[2]++;
if(com[2]==10)
com[2]=rand()%10;
} else if(com[1]==com[2])
{
com[2]++;
if(com[0]==10)
com[0]=rand()%10;
}
// Game Start
printf("Start Game!\n");
while(1)
{
int strike = 0, ball = 0;
printf("3개의 숫자 선택: ");
scanf("%d %d %d", &user[0], &user[1], &user[2]);
for(int i = 0; i<3 ;i++)
{
for(int j=i+1;j<3;j++) //strike와 중복되면 안되기 때문에 j=i+1로 설정
if(user[i]==com[j])
ball++;
if(user[i]==com[i]) //숫자랑 위치까지 맞는지 확인하는 ball 함수
strike++;
}
if(strike==3)
{
printf("%d번째 도전 결과: 3 strike, 0 ball!!\n\nGame Over!", count);
break;
}
else
printf("%d번째 도전 결과: %d strike, %d ball!!\n", count, strike, ball);
count++;
}
}
>출력
Start Game!
3개의 숫자 선택: 1 2 3
1번째 도전 결과: 1 strike, 0 ball!!
3개의 숫자 선택: 1 4 5
2번째 도전 결과: 1 strike, 0 ball!!
3개의 숫자 선택: 1 6 7
3번째 도전 결과: 2 strike, 0 ball!!
3개의 숫자 선택: 1 6 8
4번째 도전 결과: 2 strike, 0 ball!!
3개의 숫자 선택: 1 6 9
5번째 도전 결과: 3 strike, 0 ball!!
-풀이-
사실 이 풀이가 완벽하게 모든 숫자를 커버할 수 있다고 말할 수 없다...
난수 3개가 같으면 안되는데 어떻게 하면 같지 않게 뽑아낼 수 있는지 모르겠고.. 일단 조건문을 넣어놨지만 이게 딱 맞는 건지 모르겠다 ㅎㅎ
<Review>
배열로 들어가니 2차원적으로 생각해야해서 생각보다 복잡했다...
배열의 원리에 대해서 기본적으로 잘 알아야겠다.
이제 빨리 다음 chapter를 풀러~! 고고씽~