본문 바로가기
C언어 프로젝트

[C언어] 타자게임 - 2 (clock함수 추가, 오류수정)

by davidlee_ 2021. 5. 19.
반응형

저번에 작성한 코드에 clock 함수를 이용하여 난이도를 조절해 주었다.(임시)
또한 팀원들의 코드를 내 코드와 병합하는 과정에서 생긴 오류들을 수정해 주었다.


1. clock함수를 사용하여 게임 난이도 조절하기

플레이어가 단어를 보고 입력하는데 걸리는 시간이 일정한 시간을 초과하면 경과한 시간만큼 비례하여 점수에서 마이너스 되도록 하여 난이도를 조절하였다.

일단 clock 함수는 <time.h>에 있는 함수이므로 사용하기 전 명시해 주어야 한다.
사용하기 위해선 clock_t로 시간 측정 시작점과 끝 지점 변수를 선언해 주고, 실행 시간을 측정할 코드 시작과 끝에 clock()을 사용하여 리턴값을 받아준다.

clock_t start, end;
start = clock(); //시간측정 시작
gotoxy(COLS / 2 - 5, 5); //커서 위치이동
scanf("%s", input); //사용자 입력 문자열 받아오기
end = clock(); //시간측정 정지


clock 함수는 ms(밀리세컨드)가 기본단위이므로 s(초)로 값을 받아오기 위해선 time.h에서 정의되어 있는 상수 CLOCKS_PER_SEC을 사용하여 계산해 주면 된다.

result = (double)(end - start) / CLOCKS_PER_SEC; //시간 측정값 (end - start) / 1000


이제 입력까지 걸린 시간을 받아왔으면 이 값을 이용하여 난이도를 조절하면 된다.
if문을 사용하여 시간 초과 여부를 판별하고, 초과했다면 경과한 시간에 비례하여 점수를 차감한다.
또한 목숨도 같이 차감되게끔 설정해 주었다.

if ((int)result >= 3) //난이도 조절 부분
{
    score = score - (int)(result*5); //경과한 시간에 비례하여 점수 차감
    heart = heart - 1; //목숨도 같이 차감
}


또한 테스트를 위해 경과한 시간을 볼 수 있게끔 해 주었다.

printf("경과한 시간: %f\n", result); 
Sleep(1000); //시간 보기 위해서 임시로 걸어놓은 딜레이



2. 코드 병합 과정에서 생긴 오류 해결

팀원이 csv 파일에서 단어들을 가져와 배열에 저장해 주고 랜덤한 값으로 배열에 저장되어 있는 값을 가져올 수 있도록 함수를 만들어주었다.
저번에 나는 임의의 배열을 생성하여 값을 가져왔었는데 이제는 csv 파일에서 단어들을 가져올 수 있게 되었다.
하지만 코드를 병합하고 빌드 하는 데에는 문제가 없었지만 게임 실행에 문제가 발생하였다.

주어진 단어의 문자열에 맞게 입력했는데 check값(문자열 비교 반환값)이 이상하게 나오는 문제
-> 이는 곧 score와 heart값에 영향을 주었고, 맞게 입력을 했는데도 목숨이 깎이거나 틀리게 입력했는데 맞는 등의 문제를 발생시켰다.

문제점을 해결하기 위해 코드를 다시 살피던 중 첫 번째 문제점을 발견했다.

printf("%s\n", wordBase[get_random_word()]); //배열에서 랜덤 추출된 단어 출력
check = strcmp(input, wordBase[get_random_word()]); //문자열 비교
//wordBase는 csv파일에서 받아온 단어를 담은 2차원 배열이다.

여기서 get_random_word 함수는 랜덤한 인덱스값을 반환해 주는 함수이다.
위 코드를 보면 알다시피 get_random_word 함수를 두 번 호출해 줬다.
이렇게 되면 printf 속 배열 인덱스값과 strcmp 함수 속 배열의 인덱스 값이 달라질 수 있다.

따라서 나는 get_random_word 함수를 한 번만 호출하여 그 값을 변수에 저장한 후 사용하는 방식으로 변경해주었다.

a = get_random_word(); printf("%s\n", wordBase[a]); //배열에서 랜덤 추출된 단어 출력 
check = strcmp(input, wordBase[a]); //문자열 비교


하지만 오류는 계속 발생하였다.
혹시 입력값에 공백이 포함되어 저장되는지, 아니면 배열 속 단어를 가져올 때 다른 문자가 포함되어 가져와지는지 확인해보기 위해 디버그를 해보았다.

디버깅을 해보았더니 배열에서 값을 가져올 때 \n이 포함되어 가져와지고 있었다.
이를 해결하기 위해 for문과 if문을 사용하여 '\n'을 만나면 null값으로 변경되게 처리해 주었다.

for (int i = 0; wordBase[a][i] !=0 ; i++) //배열값 마지막에 붙어있는 \n 제거
{
    if (wordBase[a][i] == '\n')
    {
        wordBase[a][i] = 0; break;
    }
}


실행시켜보면 문제없이 값이 나오는 것을 알 수 있다.




위 두 문제를 해결하니 게임 실행에 문제가 없었다.
팀원들이 스토리와 디자인을 다룬 함수를 만들어 주었는데, 이번 주는 이것을 오류 없이 게임코드에 녹여내는 작업을 해야 할 것 같다.
또한 콤보 기능, 난이도 조절 알고리즘(임시가 아닌)을 추가하거나 윤곽을 잡아야 할 것 같다.



전체코드( csv 파일 불러오는 함수 제외)

int game_run()
{
    char input[20]; //입력받을 단어 배열
    int a; //랜덤 숫자 받을 변수
    int check; //문자열 비교한 값 담는 변수
    int score = 0; //점수 변수
    int heart = 5; //남은 목숨 변수
    clock_t start, end;
    double result; //시간값을 저장하기 위한 변수
    //system("mode con cols=120 lines=45"); //콘솔창 크기
    system("cls"); // 콘솔창 초기화
    //srand(time(NULL));
    gotoxy(110, 0);
    printf("■■■■■\n"); //체력바 테스트
    while (1)
    {
        gotoxy(5, 5);
        printf("%d", score);
        a = get_random_word(); //배열에서 단어 추출하기 위한 랜덤 인덱스 값
        gotoxy(COLS/2-5, 3);
        printf("%s\n", wordBase[a]); //배열에서 랜덤 추출된 단어 출력
        start = clock(); //시간측정 시작
        gotoxy(COLS / 2 - 5, 5);
        scanf("%s", input); //사용자 입력 문자열 받아오기
        //gets_s(input, 20);
        end = clock(); //시간 측정 정지
        result = (double)(end - start) / CLOCKS_PER_SEC; //시간 측정값
        printf("경과한 시간: %f\n", result);
        Sleep(1000); //시간 보기 위해서 임시로 걸어놓은 딜레이
        if ((int)result >= 1) //난이도 조절 부분
        {
            score = score - (int)(result*5); //경과한 시간에 비례하여 점수 차감
            heart = heart - 1; //목숨도 같이 차감
        }
        system("cls"); // 콘솔창 초기화
        for (int i = 0; wordBase[a][i] !=0 ; i++) //배열값 마지막에 붙어있는 \n 제거
        {
            if (wordBase[a][i] == '\n')
            {
                wordBase[a][i] = 0;
                break;
                
            }
        }
        check = strcmp(input, wordBase[a]); //문자열 비교
        switch (check) // 문자열 비교값에 따른 출력
        {
            case 0:
                gotoxy(COLS / 2 - 5, 10);
                printf("맞았습니다!\n");
                score = score + 10;
                break;
            case 1:
                gotoxy(COLS / 2 - 5, 10);
                printf("틀렸습니다!\n");
                heart = heart - 1;
                break;
            case -1:
                gotoxy(COLS / 2 - 5, 10);
                printf("틀렸습니다!\n");
                heart = heart - 1;
                break;
                
        }
        switch (heart) // 목숨값에 따른 체력바
        {
            case 0:
                gotoxy(110, 0);
                printf("□□□□□\n");
                break;
                case 1:
                gotoxy(110, 0);
                printf("□□□□■\n");
            break;
                case 2:
                gotoxy(110, 0);
                printf("□□□■■\n");
                break;
            case 3:
                gotoxy(110, 0);
                printf("□□■■■\n");
                break;
            case 4:
                gotoxy(110, 0);
                printf("□■■■■\n");
                break;
            case 5:
                gotoxy(110, 0);
                printf("■■■■■\n");
                break;
                
        }
        if (score>=50) // 점수에 따른 동작
        {
            system("cls"); // 콘솔창 초기화
            gotoxy(COLS / 2 - 10, LINES / 2);
            printf("1단계를 클리어 하셨습니다!"); Sleep(2000); //2초 딜레이
            return 1;
            break;
        }
        else if (heart==0) //목숨이 0이 되었을때의 동작
        {
            system("cls"); // 콘솔창 초기화
            gotoxy(COLS / 2 - 10, LINES / 2);
            printf("당신의 점수: %d", score);
            Sleep(1000); //1초 딜레이
            system("cls"); // 콘솔창 초기화
            gotoxy(COLS / 2 - 10, LINES / 2);
            printf("게임오버");
            Sleep(1000);//1초 딜레이
            return 0;
            break;
        }
    }
}
반응형

댓글