C

[C] #3 미로찾기 게임

Rix 2021. 9. 30. 00:21
conio 헤더파일

conio.h 헤더파일은 콘솔 입출력 함수를 제공한다.

C언어 표준이 아니기 때문에 Visual Studio 에서만 사용이 가능하다.

 

_kbhit 함수

_kbhit() 함수는 현재 키보드가 입력된 상태인지 조사하는 함수이다.

키 입력이 있을 때는 1, 없을 때는 0을 리턴한다.

 

 _getch 함수

_getch() 함수는 키보드의 입력을 받는 함수이다.

입력된 키의 아스키 코드 값을 리턴한다.

* 아스키 코드 : 문자를 컴퓨터가 이해할 수 있도록 숫자로 변환시킨 값이다.

 

방향키 코드값

#include <stdio.h>
#include <conio.h>

int main(void)
{

    int nkey;
    while (1)
    {
        if (_kbhit())
        {
            nkey = _getch();
            printf("%d\n", nkey);
        }
    }
}
// 실행결과 : 입력한 키의 아스키 코드 값
224
72
224
80
224
77
224
75

위에서부터 2개씩 위, 아래, 오른쪽, 왼쪽 방향키의 값이다.

값이 2개씩 나오는 이유는, 방향키는 1바이트의 값을 가지는 다른 문자들과 달리 2바이트 크기의 값을 가지는 확장키이기 때문이다.

--> 이러한 확장키는 아스키 코드 값을 어떻게 리턴 받을까?

_getch 함수를 2번 호출하면 된다. 위의 코드에서는 무한반복문을 통해 계속해서 함수가 호출되었기 때문에 출력이 2번 나온 것이다.

 

키 입력을 받는 함수, MoveMaze 틀 만들기

보통 함수를 만들 때 필요한 기능을 먼저 파악한 뒤, 함수를 만들지만 MoveMaze 함수는 틀을 먼저 생성한 후에 필요한 기능을 파악하려고 한다.

 

즉, 다음과 같은 과정을 통해 만들 것이다.

1. 함수의 틀 갖추기
2. 해당 함수가 필요로 하는 기능과 함수를 표현 (의사코드로)
3. 2번의 기능을 구현
4. 함수 완성

 

MoveMaze 함수의 틀

#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80
#define ARROW 224

void MoveMaze()
{
    int nkey;

    if (_kbhit())
    {
        nkey = _getch();

        if (nkey == ARROW)
        {
            nkey = _getch();
            switch (nkey)
            {
            case UP:
								printf("위 ");
                break;

            case DOWN:
								printf("아래 ");
                break;

            case LEFT:
								printf("왼쪽 ");
                break;

            case RIGHT:
								printf("오른쪽 ");
                break;
            }
        }

    }

}
#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80
#define ARROW 224

방향키는 224, XX의 값을 갖는 확장키라고 했다.

즉, XX에 해당하는 값을 해당 화살표의 방향으로, 224는 화살표 그 자체로 설정했다.

 

void MoveMaze()
{
    int nkey;

    if (_kbhit())
    {
        nkey = _getch();

        if (nkey == ARROW) // ARROW -> 224!
        {
						//...
        }

    }

}

nkey라는 int형 변수를 선언한다.

키 입력을 받을 때 해당 변수에 입력된 키의 아스키 코드 값을 집어넣는다.

그 후, 아스키 코드가 224, 즉 방향키라는 것이 판정나면 내부 코드로 들어가는 형태이다.

 

의사코드 작성

의사코드란 알고리즘을 표현하는 방법 중 하나이다. 우리가 사용하는 자연어로 만든 문장을 프로그래밍 언어와 유사하게 배치한 코드를 의미한다.

 

위에서 만들었던 함수의 틀을 가져와서 의사코드로 작성을 하면 다음과 같다.

void MoveMaze(현재 플레이어의 위치좌표 (x), (y) 포인터 )
{
    int nkey;

    if (_kbhit())
    {
        nkey = _getch();

        if (nkey == ARROW)
        {
            nkey = _getch();
            switch (nkey)
            {
            case UP:
                if (위쪽이 막히지 않았다면)
								{
									미로의 *(x), *(y)를 길로 변경;
									미로의 *(x), *(y)-1을 플레이어로 변경;
								  *(y)를 *(y)-1 로 변경
								}
								else if (위쪽이 도착지라면)
								{
									미로의 *(x), *(y)를 길로 변경;
									미로의 *(x), *(y)-1을 플레이어로 변경;
									프로그램 종료;
								}	
                break;

            case DOWN:
                if (아래쪽이 막히지 않았다면)
								{
									미로의 *(x), *(y)를 길로 변경;
									미로의 *(x), *(y)+1을 플레이어로 변경;
								  *(y)를 *(y)+1 로 변경
								}
								else if (아래쪽이 도착지라면)
								{
									미로의 *(x), *(y)를 길로 변경;
									미로의 *(x), *(y)-1을 플레이어로 변경;
									프로그램 종료;
								}	
                break;

            case LEFT:
								if (왼쪽이 막히지 않았다면)
								{
									미로의 *(x), *(y)를 길로 변경;
									미로의 *(x)-1, *(y)을 플레이어로 변경;
								  *(x)를 *(x)-1 로 변경
								}
								else if (왼쪽이 도착지라면)
								{
									미로의 *(x), *(y)를 길로 변경;
									미로의 *(x), *(y)-1을 플레이어로 변경;
									프로그램 종료;
								}	
                break;

            case RIGHT:
                if (오른쪽이 막히지 않았다면)
								{
									미로의 *(x), *(y)를 길로 변경;
									미로의 *(x)+1, *(y)을 플레이어로 변경;
								  *(x)를 *(x)+1 로 변경
								}
								else if (오른쪽이 도착지라면)
								{
									미로의 *(x), *(y)를 길로 변경;
									미로의 *(x), *(y)-1을 플레이어로 변경;
									프로그램 종료;
								}	
                break;
            }
        }

    }

}

함수 내부에서 함수 외부에 선언되어 있는 변수의 값에 접근하기 위해 해당 함수의 포인터를 매개변수로 받는 것이다.