c++

20210713 과제 풀이 ~ 난수

TIN9 2021. 7. 13.
반응형

안녕하세요 틴구입니다.

오늘도 배운 내용에 대해 코드 분석하고 글을 써 보려고 합니다.

먼저 어제 과제에서 헷갈렸던 다이아몬드 별짓기부터 코드 분석하고 가볼게요.

 

저가 블로그를 보다 보니깐 주석이랑 코드 구성이랑 보기 헷갈리더라고요.

그래서 visual studio처럼 주석은 초록색 굵게 표현하겠습니다.

 

#include <iostream>

int main()
{

    /*

       *

      ***

     *****

    *******

     *****

      ***

       *

    */

    // int Line으로 총 7 줄이란 것을 표현해주고

    // 줄마다의 값을 변화주기 위해서 LineNmber란 변수를 사용한다.

    // 다이아몬드 공백 : 3, 2, 1, 0, 1, 2, 3
    // 별 : 1, 3, 5, 7, 5, 3, 1

    int Line = 7;
    int LineNumber = 0;
    // Line 값에 7을 넣어주어 총 7줄의 값을 설정한다. false가 될 경우 for문을 빠져나오게 된다.
    for (int i = 0; i < Line; ++i)
     // 별 모양을 보면 4줄까지는 공백의 개수가 하나씩 줄고 별의 개수가 2개씩 커지는데

        // 5줄부터는 반대로 공백이 한 개씩 생기고 별의 개수가 2개씩 줄기 때문에

        // if문을 활용하여 i <= 3이라는 값을 조건으로 부여한다.

        // i 가 0, 1, 2, 3일 때는 LineNumber = i;란 값을 주고
        if (i <= 3)
            LineNumber = i;
        // else일 때는 LineNumber = 6 - i; 라는 값을 주어 줄 순서가 4일 때부터 6 - i를 하여

        // 2, 1, 0의 값이 나오게 만들어 이중포문에서 공백, 별 개수를 조절한다.

        else
            LineNumber = 6 - i;
        // j = LineNumber; 이라는 초기값을 주어 i가 0, 1, 2, 3일 때는 if 조건식에 의해 LineNumber = i;이기 때문에

        // 첫 줄부터 순서대로 공백의 개수가 3, 2, 1이 되고 

        // 4가 넘어가는 순간 if 조건식의 false가 되어 else 구문으로 넘어가 LineNumber = 6 - i;로 바뀐다

        // 결국 5번째 줄(4)부터는 6 - i 의 값으로 바뀌어 공백이 1, 2, 3개 순으로 늘어난다.
        for (int j = LineNumber; j < 3; ++j)
        {
            std::cout << " ";
        }
        // 여기도 마찬가지로 if 구문에 의해 i <=3 일 때 LineNumber * 2 + 1; 의 값은

        // 1, 3, 5, 7이 나와 별의 개수를 나타내고

        // i가 4가 되면 else구문으로 넘어와 2, 1, 0을 대입하게 되면 별의 개수가 5, 3, 1이 나오게 된다.
        for (int j = 0; j < LineNumber * 2 + 1; ++j)
        {
            std::cout << "*";
        }
    // 각각의 줄 구분을 위해 std::endl;을 이중포문 밖에다가 구성
    std::cout << std::endl;

}

return 0;
}

 

이렇게 코드를 구성해주셨습니다!!

진짜 코드는 짜기 나름인 거 같아요 똑같은 문제를 풀어도 사람마다 코드 구성이 다른 거 보면

강사님께서 구성해주신 코드는 진짜 간결한 거 같아요 코드 분석의 주석 때문에 엄청 긴 거 같은데 주석 빼면 진짜 간결하답니다...

int Line = 7;
    int LineNumber = 0;

    for (int i = 0; i < 7; ++i)
    {
        if (i <= 3)
            LineNumber = i;

        else
            LineNumber = 6 - i;

        for (int j = LineNumber; j < 3; ++j)
        {
            std::cout << " ";
        }

        for (int j = 0; j < LineNumber * 2 + 1; ++j)
        {
            std::cout << "*";
        }

        std::cout << std::endl;
    }

이렇게 말이죠...

난수

그리고 오늘은 난수란 것을 배웠어요.

먼저 srand()란 난수를 사용하기 위해서는 헤더값을 불러와야 한답니다

저번에 배웠던 전처리기 기능으로 #include <time.h>를 가져옵니다!!

 

time.h를 갖고 오게되면 time(0)이란 코드를 사용할 수 있는데 요것은 시간을 얻어올 수 있는 기능입니다.

1초가 지나면 1이 증가되는 값을 갖고오게 됩니다.

이 time(0)은 1970년도에 만들어졌다고 해요... 엄청 오래됐죠??

rand() 란 랜덤 한 값을 얻어올수 있습니다. 0 ~ 32767 사이의 수를 얻어오게 됩니다.

rand()를 이용해서 랜덤 한 값을 얻어올때 내부적으로 랜덤한 값이 들어가 있는 표를 이용해서 얻어온다고 합니다.

그런데

std::cout << rand() << std::endl;
std::cout << rand() << std::endl;
std::cout << rand() << std::endl;

이렇게 코드를 구성해서 돌려보면

41
18467
6334

이라는 숫자가 고정적으로 나오게 됩니다.

이 이유는 어떤 표를 사용할 것이다 라고 지정한 게 아닌 고정된 표에서 랜덤 한 값을 얻어와서 계속 같은 값이 나오게 되는 것입니다.

그래서 랜덤한 값을 사용하기 위해서는 표를 실행할 때마다 다른 표를 가져올 수 있게 만들어야 합니다.

srand(time(0));

이런 식으로 말이죠

time();라는 코드 자체가 1초마다 숫자가 1씩 증가되어 계속적으로 srand값이 바뀌는 원리를 이용한 겁니다.

 

또 나머지 연산자를 통해서 ? ~ ? 의 값 사이의 난수를 얻어올 수도 있습니다.

std::cout << rand() % 101 << std::endl;

을 하게 되면 1~100 사이의 난수를 얻어올 수 있게 됩니다.

만약에 여기서 1~200의 난수 코드를 작성하게 되면

std::cout << rand() % 101 + 100 << std::endl;

의 구성이 되게 됩니다.

 

또 이것을 활용해 1 ~ ???이 아니라

100 ~ 500을 같이 만들려면

난수 % (최대 - 최소 + 1) + 최소의 구성으로

std::cout << rand() % (500 - 100 + 1) + 100 << std::endl;

이 되게 됩니다.

 

선생님께서 난수를 활용한 가위바위보 게임을 만드셨는데 오늘 내용 마지막으로 이 코드를 분석해봅시다!

 

#include <iostream> // 입출력 헤더 파일을 갖고 오기 위한 전처리기

#include <time.h> // 난수 사용을 위해 갖고 온 타임 헤더 파일

 

// enum문을 활용해 가위 바위 보를 구성
enum class SRP
{
S = 1,  // 가위
R,  // 바위
P   // 보
};

int main()
{

    // srand를 활용하여 난수 테이블 생성
    srand(time(0));
    // 첫 난수는 랜덤 한 수가 아닌 계속적으로 상승하는 버그? 가 있어서 rand();값을 한번 작성한다.
    rand();
    // 플레이어가 가위, 바위, 보, 종료를 선택하기 위한 변수를 생성
    int Player = 0;
    // while문을 이용하여 게임이 나가지지 않고 반복되게 설정
    while (true)
    {
        // cls 콘솔 명령을 입력해주어서 콘솔 창의 내용을 모두 지워준다.
        system("cls");

        // 선택하기 위한 내용 설명
        std::cout << "1. 가위" << std::endl;
        std::cout << "2. 바위" << std::endl;
        std::cout << "3. 보" << std::endl;
        std::cout << "4. 종료" << std::endl;
        std::cout << "선택하세요 : ";

        // cin을 활용해 플레이어가 선택할 수 있게 만듦
        std::cin >> Player;
        // if문을 활용해 플레이어가 4번을 누르면 break;되어 게임을 종료하게 만듦
        if (Player == 4)
            break;

        // 인공지능은 랜덤 하게 셋 중 하나를 선택한다.
        int AI = rand() % 3 + 1;

        // 스위치문에 인공지능이 선택한것을 enum class 의 열거체 타입만의 변수를 만듬으로써 스위치문에 넣기 위함
        SRP AISRP = (SRP)AI;

        switch (AISRP)
        {
        case SRP::S:
            std::cout << "AI : 가위" << std::endl;
            break;
        case SRP::R:
            std::cout << "AI : 바위" << std::endl;
            break;
        case SRP::P:
            std::cout << "AI : 보" << std::endl;
            break;
        }
        // enum문 구성을 보면 가위 = 1, 바위 = 2, 보 = 3의 구성이므로

        // 승리의 조건은 Player - AI가 1 or -2가 나와야 한다
        int Result = Player - AI;
        // if문을 활용한 승리 조건
        if (Result == 1 || Result == -2)
            std::cout << "Player 승리" << std::endl;
        // else if를 활용해 비긴 조건
        else if (Result == 0)
            std::cout << "비겼다" << std::endl;
        // else를 활용한 진 조건
        else
            std::cout << "졌다..ㅠㅠ" << std::endl;

        // 콘솔 창을 일시정지시켜준다. 아무 키나 누르면 다시 시작된다.
        system("pause");
    }

return 0;
}

 

이렇게 분석을 해볼 수 있다!!

내일 또 새로운 내용을 들고 올게요!! 오늘은 코드 분석 위주로 한 거 같아요

그럼 Bye Bye!~

 

반응형

댓글