본문 바로가기
쿤즈 Dev/C

[C언어 문제] 랜덤(random)함수를 이용한 Up & Down 게임 만들기

by :)Koon 2021. 5. 12.

이번에 만들어볼 문제는 업 다운 게임입니다. 0에서 100까지의 숫자 중에서 하나의 숫자를 정하면 그 숫자를 업다운으로 해서 맞추는 게임입니다. 비교적 간단한 게임입니다.

 

 

이번 포스팅에서는 기본 헤더인 stdio.h 외에 추가적인 헤더를 사용해서 랜던 함수를 이용해 보도록 하겠습니다.


C언어 문제. 랜덤(random) 함수를 이용한 Up & Down 게임 만들기

화면에 다음과 같이 출력되도록 프로그래밍하시오.

숫자를 입력하세요 ( 0 ~ 100 ) :  105
범위에 벗어난 숫자입니다.
숫자를 입력하세요 ( 0 ~ 100 ) : 30
Down
숫자를 입력하세요 ( 0 ~ 100 ) : 20
Up
숫자를 입력하세요 ( 0 ~ 100 ) : 25
정답입니다.

조건 1. rand() 함수를 사용하기(rand() 함수만을 사용했을 때 문제점 파악하기)

조건 2. 반복문 사용하기

조건 3. 조건문 사용하기

 

*프로그래밍 의도

헤더를 추가하고 이용할 수 있는가?

반복문을 사용할 수 있는가?

조건문을 사용할 수 있는가?

 

*문제 해결을 위한 글

2020.08.10 - [쿤즈 Dev/C] - [C언어] 조건문을 사용해서 분기시켜보자(1) - if 조건문!

2020.08.25 - [쿤즈 Dev/C] - [C언어] 반복문의 시작! - for 구문

2020.09.14 - [쿤즈 Dev/C] - [C언어] 반복문 두 번째 - while 구문

2020.09.15 - [쿤즈 Dev/C] - [C언어] 반복문 세 번째 - do while

 


C언어 문제 풀이

작성된 프로그래밍은 정답이 아닙니다. 프로그래밍 소스에 대해 정답은 없습니다. 다양한 방법으로 프로그래밍이 가능하며 한 가지 예일뿐입니다.

소스코드 1. updown_game.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
	int rand_num; // 랜덤값 저장하는 변수
	int input;

	srand((unsigned int)time(NULL));
	// #define RAND_MAX 0x7fff
	// 0x7fff를 10진수로 바꾸면 32,767
	rand_num = rand() % 101;

	while (1) {
		printf("숫자를 입력하세요(0~100): ");
		scanf_s("%d", &input);

		if (input < 0 || input > 100) {
			printf("범위에 벗어난 숫자입니다.\n");
			continue;
		}

		if (input == rand_num) {
			printf("정답입니다.\n");
			break;
		}
		else if (input > rand_num) {
			printf("Down\n");
		}
		else {
			printf("Up\n");
		}
	}

	return 0;
}

 

* 프로그래밍 의도 파악

헤더를 추가하고 이용할 수 있는가?

C언어의 기초를 공부할 때에는 대부분 사용하는 헤더는 stdio.h입니다. 헤더를 어떤 것을 사용하느냐에 따라서 여러 가지 함수를 추가적으로 사용할 수 있습니다. 

 

우선 랜덤(random) 값을 가져오기 위한 함수가 필요합니다. 검색해보시면 random을 만들어주는 함수가 어떤 것인지 찾을 수 있습니다. 그리고 이 함수를 사용하기 위한 헤더가 필요합니다.

 

저는 rand(), srand(), time() 함수를 사용하기 위해서 stdlib.h 헤더와 time.h 헤더를 사용했습니다.

 

먼저 랜덤 값을 가져오는 함수는 rand() 함수입니다. 이 값의 정의를 확인해보시면 아래와 같이 작성되어 있습니다.

// Maximum value that can be returned by the rand function:
#define RAND_MAX 0x7fff

_ACRTIMP void __cdecl srand(_In_ unsigned int _Seed);

_Check_return_ _ACRTIMP int __cdecl rand(void);

우선 랜덤 값의 MAX(가장 큰 수)는 헥사로 0x7fff입니다. 이를 10진수로 변환하면 32,767입니다. 즉, 랜덤 하게 0에서 32,767까지의 숫자가 나타난다는 것입니다.

 

하지만 문제가 하나 있습니다. 아래와 같이 프로그래밍을 해보세요.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
	int rand_num;
	int i;

	for (i = 0; i < 10; i++) {
		rand_num = rand();
		printf("rand_num: %d\n", rand_num);
	}
	return 0;
}

실행해보면 아래와 같이 결과가 만족스럽게 나타납니다.

rand_num: 41
rand_num: 18467
rand_num: 6334
rand_num: 26500
rand_num: 19169
...

그렇다면 문제가 무엇일까요? 결과를 닫고 다시 한번 더 실행합니다. 이때 결과는 전과 동일한 결과가 나타납니다. 즉, rand() 함수는 랜덤 값을 return 해주는 함수가 맞지만 동일한 결과를 출력해줍니다. 사실 랜덤이 아닌 것이죠. 고정된 값입니다. 그래서 필요한 함수가 srand() 함수와 time() 함수입니다.


랜던 값을 정말 랜덤으로 만들어 주기 위해서는 seed라는 것이 필요합니다. 말 그대로 씨앗이 되는 초기값을 의미합니다. 이런 초기값을 세팅해주는 함수가 바로 srand() 함수입니다. 위에서 원형을 잠시 보여드렸죠?

_ACRTIMP void __cdecl srand(_In_ unsigned int _Seed);

srand() 함수는 parameter로 unsigned int 값을 받고 return 값은 없습니다. 이 값에 따라서 rand()의 결과가 달라집니다. 그렇다면 seed가 되는 값이 고정이 된다면 어떻게 될까요? 아래와 같이 바꿔보겠습니다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
	int rand_num;
	int i;
	
	srand(20);

	for (i = 0; i < 10; i++) {
		rand_num = rand();
		printf("rand_num: %d\n", rand_num);
	}
	return 0;
}

결과는 달라집니다. 하지만 다른 결과가 반복해서 동일하게 나타납니다. 즉 srand()의 parameter로 들어가는 값이 변해야 한다는 것입니다. 그래서 이때 사용하는 함수가 바로 time() 함수입니다.

 

time() 함수는 시간 값을 return 값으로 가지는 함수입니다. 다만 이 값의 원형을 따라가다 보면 __int64로 정의되어 있습니다. 이는 long long 자료형과 동일한 타입입니다. 이렇게 변화하는 시간 값을 seed로 사용해보았습니다. 정확한 시간이 아닌 변하는 값이 필요하기 때문입니다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
	int rand_num;
	int i;
	
	srand((unsigned int) time(NULL));

	for (i = 0; i < 10; i++) {
		rand_num = rand();
		printf("rand_num: %d\n", rand_num);
	}
	return 0;
}

결과는 매번 달라집니다. 물론 이 부분도 완벽하게 안전하지 않습니다. 시간이라는 것은 규칙적인 값이기 때문입니다. 하지만 이 프로그램에서는 시간이 중요한 것이 아닌 변하는 값이 필요하기 때문에 사용했습니다.

 

이렇게 가져온 rand() 값을 101로 나눈 나머지를 사용합니다. 이유는 간단합니다.

어떤 수를 2로 나눈 나머지가 되는 값은 0, 1입니다.

어떤 수를 20으로 나눈 나머지가 되는 값은 0, 1, 2, ..., 18, 19입니다.

따라서 어떤 수를 101로 나눈 나머지가 되는 값은 0, 1, 2, ..., 99, 100입니다.

 

 

반복문을 사용할 수 있는가?

반복문은 while을 선택했습니다. 정답을 맞힐 때까지 계속적으로 반복하기 위함입니다. 따라서 반복문은 무한반복이 될 수 있도록 while(1)을 사용합니다.

 

 

조건문을 사용할 수 있는가?

먼저 범위에 맞는 숫자인지를 파악하기 위해서 조건문을 사용합니다. 범위는 0보다 크거나 같고 100보다 작거나 같은 수를 파악하기 위해서 조건을 만들어 줍니다.

 

그리고 이 조건에 맞지 않으면 continue를 이용해서 처음부터 다시 숫자를 입력받도록 합니다.

만약 조건에 맞다면 이 값과 랜덤으로 만든 값을 비교합니다. 그래서 일치하면 break를 이용해서 반복문을 종료하고 일치하지 않으면 계속 진행하여 반복하게 만들어 줍니다.


이번 포스팅에서는 rand() 함수와 srand(), time() 함수를 이용하는 방법을 알아보았습니다. 문제는 랜덤 값을 어떻게 생성하고 이를 이용해서 게임을 만드는 것입니다. 하지만 문제에 포함돼서 알아야 할 부분은 stdlib.h, time.h 헤더를 찾고 포함시킨 후에 함수를 어떻게 사용하는가입니다.

 

C언어에는 무수히 많은 헤더들이 존재하고 또 사용할 수 있습니다. 앞으로는 이러한 문제들을 조금씩 더 다뤄보도록 하겠습니다. 도움이 되셨으면 합니다. 이상입니다.

댓글