본문 바로가기
  • 부자가 될 남자
프로그래밍/C

2022-05-04 동아리, 공룡 점프 코드 분석하기

by ㅍ우주 2022. 5. 4.
#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#define DINO_BOTTOM_Y 12
#define TREE_BOTTOM_Y 20
#define TREE_BOTTOM_X 45

//콘솔 창의 크기와 제목을 지정하는 함수
void SetConsoleView()
{
    /*
    system()함수는 우리가 윈도우 창에서 콘솔창을 띄워 cmd 명령을 내리는 과정을 다이렉트로 실행시키는 함수.
    */
    system("mode con:cols=100 lines=25");
    system("title Google Dinosaurs. By BlockDMask");
}

//커서의 위치를 x, y로 이동하는 함수
void GotoXY(int x, int y) // 콘솔 창의 커서를 특정 위치로 이동시키기 위한 함수
{
    /*
    구조체란?
    '구조체'란 여러 자료형을 가진 변수들을 하나로 묶어 자료형으로 사용할 수 있도록 정의하는 것
     // COORD : 커서의 위치를 저장하는 구조체
     coords의 특성 : 언제자 왼쪽 위 모서리의 좌표가 (0,0)이 된다.
    */
    COORD Pos;
   \
    Pos.X = 2 * x;
    Pos.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos); // SetConsoleCursorPosition : 커서의 위치를 이동시키는 함수
    /*
    콘솔 화면의 특정위치에 출력을 하기 위해 print("\n")으로 이동한다면, 화면이 밀릴 수 있음.
    때문에 특정위치에 출력을 할때는 커서를 해당 좌표로 이동 시킨 뒤 확실히 출력하는 방법을 써야함.
    */ 

}

//키보드의 입력을 받고, 입력된 키의 값을 반환하는 함수
int GetKeyDown()
{
    if (_kbhit() != 0)
        /*
        _kbhit() : 현재 키보드가 입력된 상태인지를 조사함.
        비슷한 함수인 getch() 함수와의 차이점은 getch는 키가 눌려있지 않을때는 모든 코드가 무한 대기상태에 빠져버리지만,
        _kbhit은 키의 입력이 없다면 그냥 지나쳐버린다. -> 원래 하던걸 하면서 계속 키의 입력을 조사.
        */
    {
        return _getch();
    }
    return 0;
}

// 입력과 출력 함수

void DrawDino(int dinoY)
{
    GotoXY(0, dinoY);
    static bool legFlag = true;
    printf("        $$$$$$$ \n");
    printf("       $$ $$$$$$\n");
    printf("       $$$$$$$$$\n");
    printf("$      $$$      \n");
    printf("$$     $$$$$$$  \n");
    printf("$$$   $$$$$     \n");
    printf(" $$  $$$$$$$$$$ \n");
    printf(" $$$$$$$$$$$    \n");
    printf("  $$$$$$$$$$    \n");
    printf("    $$$$$$$$    \n");
    printf("     $$$$$$     \n");
    if (legFlag)
    {
        printf("     $    $$$    \n");
        printf("     $$          ");
        legFlag = false;
    }
    else
    {
        printf("     $$$  $     \n");
        printf("          $$    ");
        legFlag = true;
    }
}

void DrawTree(int treeX)
{
    GotoXY(treeX, TREE_BOTTOM_Y);
    printf("$$$$");
    GotoXY(treeX, TREE_BOTTOM_Y + 1);
    printf(" $$ ");
    GotoXY(treeX, TREE_BOTTOM_Y + 2);
    printf(" $$ ");
    GotoXY(treeX, TREE_BOTTOM_Y + 3);
    printf(" $$ ");
    GotoXY(treeX, TREE_BOTTOM_Y + 4);
    printf(" $$ ");
}

int main(void)
{
    SetConsoleView();

    bool isJumping = false; 
    bool isBottom = true;
    const int gravity = 3; // 변하지 않는 값, 중력 = 3

    int dinoY = DINO_BOTTOM_Y;   //20
    int treeX = TREE_BOTTOM_X;   //45

    while (true)
    {
        //z키가 눌렸고, 바닥이 아닐때만 점프가능.
        if (GetKeyDown() == 'z' && isBottom)
        {
            isJumping = true; 
            isBottom = false;
        }

        //점프중 = y감소
        //점프끝 = y증가
        if (isJumping)
        {
            dinoY -= gravity; // dinoY - gravity = dinoY
        }
        else
        {
            dinoY += gravity; // dinoY = dinoY + gravity
        }

        //Y가 계속해서 증가하는걸 막기위해 바닥을 지정.
        //Y가 증가한다는 것은 공룡이 아래로 내려온다는 뜻.
        if (dinoY >= DINO_BOTTOM_Y) // 만약 DinoY (공룡의 Y축)가 바닥의 Y좌표 20보다 크거나 같다면
        {
            dinoY = DINO_BOTTOM_Y; // 공룡의 위치를 바닥 값으로 변경.
            isBottom = true; // 공룡의 위치가 바닥이므로, IsBottom = true.
        }

        //점프의 맨 위를 찍으면 점프가 끝난 상황
        if (dinoY <= 3) // dinoY의 위치가 최대 즉, 천장의 높이가 3이라고 생각.
        {
            isJumping = false; // dinoY의 값은 다시 증가함.
        }

        //나무가 왼쪽으로 가도록 하고(x의 음수방향)
        //나무의 위치가 왼쪽 끝으로가면 다시 초기 위치로 소환
        treeX -= 2;
        if (treeX <= 0)
        {
            treeX = TREE_BOTTOM_X;
        }

        DrawDino(dinoY);    //draw dino
        DrawTree(treeX);    //draw tree
        Sleep(80);
        system("cls");    //clear
    }
    system("pause");
    return 0;
}