C: 도전프로그래밍3

aiden·2023년 4월 13일
0

C

목록 보기
20/28

#2

#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


아직도 코드를 참 지저분하게 짜는 것 같다. 전에 어셈블리어 강의를 들을 때 어셈블리어로 비슷한 문제를 풀었었는데, 그 때 고생했던 기억이 났다. 하지만 그 때의 풀이가 기억나지 않았고 오히려 더 퇴화한 것 같은 기분이다. 더 열심히 해야겠다.

#3

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

#4

문제 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

#5

컴퓨터와의 가위바위보 게임을 만들어보자. 사용자는 가위, 바위, 보 중 하나를 입력하고, 컴퓨터는 난수 생성을 통해 가위바위보 중 하나를 선택하게 된다. 게임은 사용자가 질 때까지 반복되며, 종료 후 결과를 출력한다.

#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무


문제만 봤을 때에는 쉬워보였는데, 해결하는 데에 매우 오래 걸렸다. 숫자와 문자열을 대응하는 방식이 생각나지 않아 조건문으로 일일히 대응하는 수밖에 없어 구글링을 통해 힌트를 얻었다. 배열을 이용하는 방법은 까먹지 말고 앞으로도 잘 활용해야겠다.

#6

컴퓨터와 숫자 야구 게임을 하는 프로그램을 작성하라.
컴퓨터가 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번 문제를 풀면서 너무 많은 중첩문이 발생해 스스로 굉장히 아쉬웠다. 코드를 잘 짜는 사람들은 이렇게 지저분하게 짜지는 않을 것이다. 문제를 많이 풀어보면서 발전하고 싶다.

+숫자 야구 너무 재밌어서 못 끊겠다...ㅎㅎ

profile
파인애플 좋아하세요?

0개의 댓글