본문 바로가기

교육 노트/C++ 기초강의

[C++ 때려 잡기] C++ 기초강의 2-advanced-1 랜덤

2018/08/24 - [교육 노트/C++ 기초강의] - [C++ 때려 잡기] C++ 기초강의 2-1 함수의 선언과 정의

2018/08/25 - [교육 노트/C++ 기초강의] - [C++ 때려 잡기] C++ 기초강의 2-2 함수 오버로딩

2018/08/25 - [교육 노트/C++ 기초강의] - [C++ 때려 잡기] C++ 기초강의 2-3 call by value / call by reference

2018/08/26 - [교육 노트/C++ 기초강의] - [C++ 때려 잡기] C++ 기초강의 2-4 재귀함수

주사위 게임, 로또등

실생활은 확률과 랜덤으로 가득 차있다.


C++에서는 이러한 랜덤 상황을 어떻게 표현하는가?


1. 랜덤

랜덤을 표현하는 방법
rand() 함수 사용
: 0 ~ RAND_MAX까지의 난수를 발생


rand()함수를 사용하면 미리 표준으로 정해진 RAND_MAX 의 값까지 랜덤한 숫자를 나타낸다.


#include <iostream>
using namespace std;

int main()
{
  cout << rand() << endl;
  cout << rand() << endl;
  cout << rand() << endl;
  return 0;
}



ps. rand함수가 없다면 #include <cmath> 를 추가해보자




2. 랜덤 범위지정


rand함수를 통하여 랜덤한 숫자를 표현할수있다.


그러면 0~100까지의 랜덤한 수만 필요하면 해당 함수를 어떻게 사용해야할까


#include <iostream>
using namespace std;

int main()
{
  cout << rand()%101 << endl;
  cout << rand()%101 << endl;
  cout << rand()%101 << endl;
  return 0;
}



다음과 같이 101으로 나눈 나머지로 해버리면 최대 100까지 숫자가 나올것이다.


그러면 100~200으로 범위를 지정하고 싶다면 어떻게 할까


#include <iostream>
using namespace std;

int main()
{
  cout << rand() % 101 + 100 << endl;
  cout << rand() % 101 + 100 << endl;
  cout << rand() % 101 + 100 << endl;
  return 0;
}





3. srand 함수


위 결과를 통하여 범위까지 지정하는 방법을 알아냈으나

눈치 빠른 사람들은 결과를 보고 알아차린것이 있을것이다.


맨처음 나오는 rand함수의 결과는 41이었고 다음코드도 41이었고 그다음코드는 41에 100을 더한 141이다.

두번째도 결과도 18467 이고 다음코드는 18467%101 이고 그 다음 코드에서는 18467%101 에 100을 더한 185이다.


즉 rand함수를 썻지만 나오는 랜덤한 숫자는 순서까지 완전 동일하다는 것이다.


이 이유는 rand 함수가 의사 난수를 사용하기 때문이다

의사에서 의사는 가짜를 의미한다 (pseudo,슈도)

즉 rand는 난수이지만 가짜 난수이다. 이게 무슨의미냐 하면


컴퓨터에 이미

다음과 같은 난수 순서가 이미 저장되어있다.

그래서 rand를 쓸때마다 다음으로넘어가 거기에 있는 숫자를 가져오는것이다.


즉 이걸로 주사위 게임을 만들면 게임을 할때마다 똑같은 상황이 반복된다는 것이다.


해당 문제를 해결하기위해서

C++ 에서는 srand()라는 함수를 제공한다.

srand함수는 rand함수가 값을 가져올 위치를 지정해줄수있고 해당 값을 seed하고 한다.


예를 들어

Seed1 일때 순서 : 41 18467 6334 ...

Seed2 일때 순서 : 58 8776 5746 ...

와 같이 동작하게 된다.


srand함수는 다음과 같이 사용하게 된다.

#include <iostream>
using namespace std;

int main()
{
  srand(700);
  cout << rand() << endl;
  cout << rand() << endl;
  cout << rand() << endl;
  cout << rand() << endl;

  return 0;
}


srand 함수안에 seed값을 집어넣으면된다.


그러나 해당 seed값을 변경하면 난수 변경 순서를 변경할수있지만

결국 같은 프로그램이라면 전부 700시드를 사용하는 난수일테니

결과적으로 같은 프로그램이라면 같은 상황이 반복 될것이다.


그래서 seed의 값도 프로그램마다 다르도록 해야할것이다.


그러면 seed도 난수로 해야되고..

그 난수의 seed도 난수로..

그 난수의 seed도 난수로..



즉 이런식으로는 랜덤을 만들수없다는것이다.


그럼 seed의 값을 어떻게 설정해야 실행할때마다 다른 난수를 생성 할 수 있을까



3. time

C++ 에서는 time이라는 함수를 제공한다

time함수는 UTC 시간 기준  1970년 1월 1일을 기준으로 지금까지 지난 시간을 반환한다.

즉 해당 값을 Seed로 집어 넣으면 프로그램을 실행할때마다 지난 시간이 달라지므로 seed가 달라지게 된다.

time함수는 ctime이라는 헤더 안에존재하므로

#include <ctime> 을 해주자


#include <iostream>
#include <ctime>
using namespace std;

int main()
{
  srand(time(0));
  cout << rand() << endl;
  cout << rand() << endl;
  cout << rand() << endl;
  cout << rand() << endl;

  return 0;
}


다음과 같다.

time함수는 파라미터를 받는데

무시하고 0을 넣어주거나 NULL (모두대문자) 값을 넣어주자




실습

1. 행맨 게임에서 문제가 랜덤하게  나오도록한다.

2. 업엔다운 게임을 제작한다 (프로그램 참고)

728x90