#include <stdio.h>
int main(void) {
int n, arr[10][10];
int j, num = 1;
printf("숫자를 입력하시오 : ");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
int k = i / 2;
if (i == n - 1) {
int l = n / 2;
if (n % 2 == 0) {
arr[l][l - 1] = num;
}
else {
arr[l][l] = num;
}
break;
}
if(i % 2 == 0){
for(j = k; j < n - k; j++){
arr[k][j] = num++;
}
for (int m = k + 1; m < j; m++) {
arr[m][j - 1] = num++;
}
}
else {
for (int m = j - 2; m >= k; m--) {
arr[j - 1][m] = num++;
}
for (int m = j - 2; m >= k + 1; m--) {
arr[m][k] = num++;
}
}
}
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++)
printf("%3d ", arr[i][j]);
printf("\n");
}
return 0;
}
출력 결과
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
아직도 코드를 참 지저분하게 짜는 것 같다. 전에 어셈블리어 강의를 들을 때 어셈블리어로 비슷한 문제를 풀었었는데, 그 때 고생했던 기억이 났다. 하지만 그 때의 풀이가 기억나지 않았고 오히려 더 퇴화한 것 같은 기분이다. 더 열심히 해야겠다.
int rand(void)를 이용하여 0부터 99까지의 난수 5개 출력
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("난수의 범위 : 0부터 99까지\n");
for (int i = 0; i < 5; i++)
printf("난수 출력 : %d\n", rand() % 100);
return 0;
}
출력 결과
난수의 범위 : 0부터 99까지
난수 출력 : 41
난수 출력 : 67
난수 출력 : 34
난수 출력 : 0
난수 출력 : 69
문제 3에서, 프로그램 실행 시 몇 번을 다시 실행해도 처음 생성된 난수로 고정되어있다. 이렇게 되면 계속해서 난수가 나오는 것이 아니므로 문제가 된다. 이렇듯 rand()가 반환한 예측 가능한 난수를 pseudo-random number라 한다. 이는 가짜 난수라는 의미이다. 따라서 ANSI표준에서 srand라는 함수를 제공한다. 함수의 인자인 seed값에 따라 함수가 반환하는 난수가 달라진다.
void srand(usigned int seed);
다음 예시를 보자.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int seed;
printf("씨드값 입력 : ");
scanf("%d", &seed);
srand(seed); //씨앗 심기
for (int i = 0; i < 5; i++)
printf("난수 출력 : %d\n", rand());
return 0;
}
씨드값 입력 : 15
난수 출력 : 87
난수 출력 : 5105
난수 출력 : 27056
난수 출력 : 2938
난수 출력 : 32501
씨드값 입력 : 7
난수 출력 : 61
난수 출력 : 17422
난수 출력 : 15215
난수 출력 : 7040
난수 출력 : 15521
씨드값 입력 : 15
난수 출력 : 87
난수 출력 : 5105
난수 출력 : 27056
난수 출력 : 2938
난수 출력 : 32501
하지만 매번 씨드를 입력받을 수도 없고, 입력받은 씨드값이 다르다는 가정을 세우기에는 무리가 있다. 위의 예시를 보면 알 수 있듯이 씨드값이 같으면 동일한 결과를 얻는다.
그래서 사용하는 방법이 컴퓨터의 시간을 이용하는 것이다. 컴퓨터 시간은 계속 바뀌므로 다른 씨드값을 넣을 수 있다.
컴퓨터의 현재 시간을 얻으려면 헤더파일 time.h에 선언되어있는 time함수를 이용하면 된다. 이 함수는 컴퓨터의 현재 시간과 1970년 1월 1일 이후의 시간적 차를 초 단위로 계산하여 반환한다. 따라서 time 함수는 매 초마다 다른 정수를 반환하고, 이는 매번 달라지는 씨드값으로 전달하기에 적합하다.
다음과 같이 활용하면 된다.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
srand((int)time(NULL));
for (int i = 0; i < 5; i++)
printf("난수 출력 : %d\n", rand());
return 0;
}
난수 출력 : 5252
난수 출력 : 13805
난수 출력 : 1332
난수 출력 : 23948
난수 출력 : 8170
난수 출력 : 5327
난수 출력 : 31642
난수 출력 : 18992
난수 출력 : 20348
난수 출력 : 16029
매번 달라지는 난수를 얻을 수 있다.
이때, 두 개의 주사위를 던졌을 때의 결과를 출력하는 프로그램을 작성하라. 결과는 예측 불가해야 한다.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand((int)time(NULL));
for (int i = 0; i < 2; i++)
printf("주사위%d의 결과 : %d\n", i + 1, rand()%6 + 1);
return 0;
}
주사위1의 결과 : 5
주사위2의 결과 : 3
주사위1의 결과 : 6
주사위2의 결과 : 3
컴퓨터와의 가위바위보 게임을 만들어보자. 사용자는 가위, 바위, 보 중 하나를 입력하고, 컴퓨터는 난수 생성을 통해 가위바위보 중 하나를 선택하게 된다. 게임은 사용자가 질 때까지 반복되며, 종료 후 결과를 출력한다.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int user, computer;
int win = 0, draw = 0;
char* str[3] = { "바위", "가위", "보" };
srand((int)time(NULL));
do{
printf("바위1 가위2 보3 :");
scanf("%d", &user);
computer = rand()%3 + 1;
printf("당신은 %s 선택, 컴퓨터는 %s 선택, ", str[user - 1], str[computer - 1]);
switch (user - computer)
{
case -1:
case 2:
printf("당신이 이겼습니다!");
win++;
break;
case 0:
printf("비겼습니다!");
draw++;
break;
case -2:
case 1:
printf("당신이 졌습니다!");
break;
}
printf("\n");
} while (user - computer != -2 && user - computer != 1);
printf("게임의 결과 : %d승, %d무", win, draw);
return 0;
}
출력 결과
바위1 가위2 보3 :1
당신은 바위 선택, 컴퓨터는 가위 선택, 당신이 이겼습니다!
바위1 가위2 보3 :3
당신은 보 선택, 컴퓨터는 보 선택, 비겼습니다!
바위1 가위2 보3 :2
당신은 가위 선택, 컴퓨터는 바위 선택, 당신이 졌습니다!
게임의 결과 : 1승, 1무
바위1 가위2 보3 :1
당신은 바위 선택, 컴퓨터는 바위 선택, 비겼습니다!
바위1 가위2 보3 :1
당신은 바위 선택, 컴퓨터는 가위 선택, 당신이 이겼습니다!
바위1 가위2 보3 :1
당신은 바위 선택, 컴퓨터는 가위 선택, 당신이 이겼습니다!
바위1 가위2 보3 :1
당신은 바위 선택, 컴퓨터는 보 선택, 당신이 졌습니다!
게임의 결과 : 2승, 1무
문제만 봤을 때에는 쉬워보였는데, 해결하는 데에 매우 오래 걸렸다. 숫자와 문자열을 대응하는 방식이 생각나지 않아 조건문으로 일일히 대응하는 수밖에 없어 구글링을 통해 힌트를 얻었다. 배열을 이용하는 방법은 까먹지 말고 앞으로도 잘 활용해야겠다.
컴퓨터와 숫자 야구 게임을 하는 프로그램을 작성하라.
컴퓨터가 0부터 9까지의 숫자 중 서로 다른 세 개의 숫자를 고르고, 이를 순서와 숫자 모두 맞춰야 한다.
이 때, 컴퓨터는 사용자가 고른 숫자가 얼마나 맞는지 알려줘야 하는데, 숫자와 위치가 모두 일치하면 strike, 숫자만 맞고 자리가 일치하지 않으면 ball이다.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int correct_answer[3], answer, strike = 0, ball = 0, trial = 0, num;
srand((int)time(NULL));
do{
for (int i = 0; i < 3; i++) {
correct_answer[i] = rand() % 10;
}
} while ((correct_answer[0] == correct_answer[1]) || (correct_answer[1] == correct_answer[2]) || (correct_answer[2] == correct_answer[0]));
printf("Start Game!\n");
do {
strike = 0, ball = 0;
printf("3개의 숫자 선택 : ");
for (int i = 0; i < 3; i++) {
scanf("%d", &answer);
for (int j = 0; j < 3; j++){
if (answer == correct_answer[j]) {
if (i == j)
strike++;
else
ball++;
}
}
}
trial++;
printf("%d번째 도전 결과 : %dstrike, %dball\n", trial, strike, ball);
} while (strike < 3);
printf("\nGame Over!");
return 0;
}
출력 결과
Start Game!
3개의 숫자 선택 : 1 2 3
1번째 도전 결과 : 0strike, 0ball
3개의 숫자 선택 : 4 5 6
2번째 도전 결과 : 0strike, 1ball
3개의 숫자 선택 : 6 7 8
3번째 도전 결과 : 0strike, 1ball
3개의 숫자 선택 : 4 5 8
4번째 도전 결과 : 0strike, 0ball
3개의 숫자 선택 : 0 6 9
5번째 도전 결과 : 1strike, 2ball
3개의 숫자 선택 : 9 6 0
6번째 도전 결과 : 3strike, 0ball
Game Over!
Start Game!
3개의 숫자 선택 : 3 2 1
1번째 도전 결과 : 0strike, 0ball
3개의 숫자 선택 : 0 4 5
2번째 도전 결과 : 0strike, 1ball
3개의 숫자 선택 : 5 6 7
3번째 도전 결과 : 1strike, 0ball
3개의 숫자 선택 : 5 8 9
4번째 도전 결과 : 0strike, 1ball
3개의 숫자 선택 : 8 6 9
5번째 도전 결과 : 2strike, 0ball
3개의 숫자 선택 : 8 6 4
6번째 도전 결과 : 3strike, 0ball
Game Over!
'서로 다른' 세 숫자라는 것을 까먹어서 완성한 줄 알고 테스트 했을 때 낭패를 봤다. 서로 다른 세 수를 받도록 하는 부분이 어려웠고, 작성할 때 너무 길어지고 복잡해져서, 그냥 조건을 만족하지 못하면 세 숫자를 전부 다시 받는 형태로 do~while문을 사용해 작성했다. 이 편이 코드를 더 간단하게 만드는 것 같아서이다. 하지만 다른 방법으로 중복되는 수만 다시 받는 방법을 생각해보는 것도 좋을 것 같다.
그리고 6번 문제를 풀면서 너무 많은 중첩문이 발생해 스스로 굉장히 아쉬웠다. 코드를 잘 짜는 사람들은 이렇게 지저분하게 짜지는 않을 것이다. 문제를 많이 풀어보면서 발전하고 싶다.
+숫자 야구 너무 재밌어서 못 끊겠다...ㅎㅎ