1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#include<stdbool.h>
#include<time.h>
#define DINO_BOTTOM_Y 12
#define TREE_BOTTOM_Y 20
#define TREE_BOTTOM_X 45
 
//콘솔 창의 크기와 제목을 지정하는 
void SetConsoleView() {
    system("mode con:cons=100 lines=25");
    system("title Google Dinosaurs. By BlockMask");
}
 
//커서의 위치를 x,y로 이동하는 함수
void GotoXY(int x, int y) {
    COORD Pos;
    Pos.X = 2 * x;
    Pos.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}
 
//키보드의 입력을 받고, 입력된 키의 값을 반환하는 함수
int GetKeyDown() {
    if (_kbhit() != 0) {
        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("          $$     \n");
        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(" $$ ");
}
 
void DrawGameOver(const int score) {
    system("cls");
    int x = 22;
    int y = 10;
    GotoXY(x, y);
    printf("==============================");
    GotoXY(x, y+1);
    printf("========G A M E O V E R=======");
    GotoXY(x, y+2);
    printf("==============================");
    GotoXY(x, y+5);
    printf("SCORE : %d", score);
 
    printf("\n\n\n\n\n");
    system("pause");
}
//충돌 했으면 true , 아니면 false
bool isCollision(const int treeX, const int dinoY) {
    //트리의 x가 공룡의 몸체쪽에 있을때
    //공룡의 높이가 충분하지 않다면 충돌
    GotoXY(00);
    printf("treeX : %d,dinoY : %d", treeX, dinoY);
    if (treeX <= 8 && treeX >= 4 && dinoY > 8) {
        return true;
    }
    return false;
}
 
 
int main(void) {
    SetConsoleView();
    while (true) {//게임 루프
 
        bool isJumping = false;
        bool isBottom = true;
        const int gravity = 3;
 
        int dinoY = DINO_BOTTOM_Y;
        int treeX = TREE_BOTTOM_X;
 
        int score = 0;
        clock_t start, curr;
        start = clock();
 
        while (true) { //한 판에 대한 루프
            if (isCollision(treeX, dinoY))
                break;
 
 
            //z가 눌렸고, 바닥이 아닐때만 점프가능
            if (GetKeyDown() == 'z' && isBottom) {
                isJumping = true;
                isBottom = false;
            }
 
            //점프중 = y감소
            //점프끝 = y증가
            if (isJumping) {
                dinoY -= gravity;
            }
            else {
                dinoY += gravity;
            }
            //Y가 계속해서 증가하는걸 막기 위해 바닥을 지정
            //Y가 증가한다는 것은 공룡이 아래로 내려온다는 뜻
            if (dinoY >= DINO_BOTTOM_Y) {
                dinoY = DINO_BOTTOM_Y;
                isBottom = true;
            }
            //점프의 맨위를 찍으면 점프가 끝난 상황
            if (dinoY <= 3) {
                isJumping = false;
            }
 
            //나무가 왼쪽으로 가도록 하고(x의 음수방향)
            //나무의 위치가 왼쪽 끝으로 가면 다시 초기 위치로 소환
            treeX -= 2//x축을 줄여서 왼쪽으로 가도록
            if (treeX <= 0) { // 0 이되면 (왼벽에 닿으면) 
                treeX = TREE_BOTTOM_X; //다시 45값을 입력
            }
 
            DrawDino(dinoY);
            DrawTree(treeX);
 
            curr = clock(); //현재시간 받아오기
            if (((curr - start) / CLOCKS_PER_SEC) >= 1) {
                score++//스코어 up
                start = clock(); // 시간 시간 초기화
            }
            Sleep(60);
            system("cls"); //clear
 
            //점수출력을 항상출력 해주면서 1초마다 ++
 
            GotoXY(220);
            printf("Score : %d", score);            
        }
 
        //게임 오버
        DrawGameOver(score);
 
    }
    return 0;
}
 
 
cs

 

 

#include <windows.h>

system 함수를 사용할 수 있다

Sleep(ms) : ms단위로 시스템을 잠시 멈춘다 (1000ms = 1s)

system("cls") : 콘솔창을 깨끗이 지운다

등등

#include <conio.h>

console and port I/O 의 약자 

대표적인 함수로는

int kbhhit : 버퍼에 값이 있으면 1, 없으면 0

(입력이 있었는지 없었는 지 판단하는 함수)

 

int getch() : 버퍼에 있는 값을 꺼내오는 함수

COORD structure

x,y위치를 가지고 있는 구조체

이 구조체 변수를 만들어서 x,y를 채워 넣어줍니다

2*x 를 넣어주는 이유는 2씩 이동하는게 자연스럽기 때문입니다

const int

상수(constant), const 로 지정하면 그 값을 절대로 바꿀수 없다

(변수와 반대)

#include <time.h>

시간과 날짜에 대한 함수를 가지고 있습니다

clock() : 프로세서가 소비된 시간을 반환하는 함수(프로그램 실행 시간)

clock_t : clock ticks 의 자료를 담고 있는 자료형으로 clock()의 반환형

clocks_per_sec : 마아크로 초(ms)단위를 초(s)로 나타내려면 clocks_per_sec 으로 나누면 됩니다

 

 

*코드출처*

BlockDMask 님

깃허브: 

github.com/BlockDMask/Google_Dino

 

블로그:

https://blockdmask.tistory.com/344

 

[C언어 게임] 구글 공룡 게임 만들기 (충돌처리 추가)

안녕하세요. BlockDMask 입니다. C언어나 C++을 책만보고 공부만하면 재미가 없잖아요. 그래서 제가 간단한 게임을 만들어서 소개해보려 합니다. 제가 만든 게임이 게임성이 없는 프로그램 일 수 있

blockdmask.tistory.com

 

 

'C > game' 카테고리의 다른 글

C언어 Up&Down 게임  (0) 2021.02.26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//up&down game
//1.컴퓨터는 임의 숫자를 결정
//2.플레이어가 숫자 입력
//3.낮으면 Low , 높으면 High 출력
//4.같으면 정답 출력
//5.이때 숫자를 몇번에 맞췄는지 출력
 
int main(void) {
    int number;
    int input;
    int count = 0;
    srand((unsigned int)time(NULL));
    number = rand() % 100 + 1;
    while (1) {
        scanf("%d"&input);
        if (number < input) {
            printf("Low\n");
            count++;
        }
        else if (number > input) {
            printf("High\n");
            count++;
        }
        else if (number == input) {
            printf("정답\n");
            printf("%d", count);
            break;
        }
    }
    return 0;
}
cs

1.컴퓨터는 임의 숫자를 결정

임의의 숫자를 결정해야하기 때문에

1
2
3
int number;
srand((unsigned int)time(NULL));
number = rand() % 100 + 1;
cs

srand 를 활용해 난수를 만들고 매번 다른 값을 나오게 하기위해 time(NULL)을 사용합니다

필요한 숫자는 1~100까지이기 때문에 나머지 값을 활용합니다

어떤수가 나와도 100으로 나눴을때의 나머지 값은 0~99이기 때문에 +1을 하면

우리가 원하는 1~100을 얻을 수 있습니다

 

2.플레이어가 숫자 입력

 

1
2
3
4
5
#define _CRT_SECURE_NO_WARNINGS
 
int input;
scanf("%d"&input);
 
cs

 

비주얼 스튜디오를 사용한다면 scanf()를 사용할 때 #define _CRT_SECURE_NO_WARNINGS 을 꼭 사용해야합니다

int input을 선언하고 scanf("%d"&input); 에 정수를 입력받습니다

 

3.낮으면 Low, 높으면 High 출력

1
2
3
4
5
6
7
8
if (number < input) {
    printf("Low\n");
    count++;
}        
else if (number > input) {
    printf("High\n");
    count++;
}
cs

if 문을 활용해 number값과 input값을 비교하고

낮으면 Low 높으면 High을 출력하고

count++; 을 해서 횟수를 기록합니다

4.같으면 정답 출력

1
2
3
4
5
else if (number == input) {
    printf("정답\n");
    printf("%d", count);
    break;
}
cs

정답 처리도 else if 를 활용해 정답을 출력하고

break;로 if 문을 탈출합니다

 

3.4번을 반복하기 위해

while 문으로 전체를 감싸줍니다

 

5.이때 숫자를 몇번에 맞췄는지 출력

printf("%d", count);

 

이렇게 조건문를 활용해 간단한 Up&Down 게임을 만들 수 있습니다

'C > game' 카테고리의 다른 글

C언어 구글 공룡 게임  (0) 2021.02.28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
int nCr(int n, int r) {
    if (r == 0 || r == n) {
        return 1;
    }
    else {
        return nCr(n - 1, r - 1+ nCr(n - 1, r);
    }
}
 
int main(void) {
    int n, r;
    scanf("%d %d"&n, &r);
    printf("%d", nCr(n, r));   
    return 0;
}
cs

nCr은 r이 0이거나 n이라면 1이고, nCr(n-1,r-1)+nCr(n-1,r)와 같다

 

'C' 카테고리의 다른 글

전처리기  (0) 2021.02.14
파일 입출력  (0) 2021.02.13
구조체  (0) 2021.02.13
함수 포인터  (0) 2021.02.13
동적 메모리 할당  (0) 2021.02.10

전처리기 구문은 다른 프로그램 영역과 독립적으로 처리됩니다

#include 는 전처리기에서 가장 많이 사용되는 문법입니다

 

#include<파일 이름> 

이와 같이 선언하면 시스템 디렉토리에서 파일을 검색합니다

운영체제마다 시스템 디렉토리가 존재하는 경로가 다를 수 있습니다

대표적으로 stdio.h와 같은 헤더 파일 등이 시스템 디렉토리에 존재합니다

 

#include"파일 이름"

이와 같이 선언하면 현재 폴더에서 파일을 먼저 검색합니다

만약 현재 폴더에 파일이 없다면 시스템 디렉토리에서 파일을 검색합니다

 

 

매크로 전처리기

프로그램 내에서 사용되는 상수나 함수를 매크로 형태로 저장하기 위해 사용합니다

#define 문법을 사용해 정의할 수 있습니다

 

매크로 전처리기를 사용해 원의 둘레를 구하는 예시

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#define PI 3.1415926535
 
int main(void) {
    int r = 10;
    printf("원의 둘레: %.2f\n"2 * PI * r);
 
    return 0;
}
 
cs

 

 

인자를 가지는 매크로 전처리기 예시(POW)

1
2
3
4
5
6
7
8
9
10
11
12
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define POW(x) (x * x)
 
int main(void) {
    int x;
    scanf("%d"&x);
    printf("x의 제곱: %d\n", POW(x));
 
    return 0;
}
 
cs

 

인자를 가지는 매크로 전처리기 예시(long long , long double)

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#define ll long long
#define ld long double
 
int main(void) {
    ll a = 987654321000;
    ld b = 100.5054;
    printf("%.1f\n", a * b);
    return 0;
}
 
cs

 

 

조건부 컴파일

조건부 컴파일은 컴파일이 이루어지는 영역을 지정하는 기법입니다

일반적으로 디버깅과 소스코드 이식을 목적으로 하여 작성됩니다

C언어로 시스템 프로그램을 작성할 때에는 운영체제에 따라서 소스코드가 달라질 수 있습니다

 

 

전처리기 사용은 필수는 아니지만 때에 일반적으로 소스코드를 획기적으로 줄일 수 있습니다

'C' 카테고리의 다른 글

재귀함수를 활용한 조합 공식  (0) 2021.02.23
파일 입출력  (0) 2021.02.13
구조체  (0) 2021.02.13
함수 포인터  (0) 2021.02.13
동적 메모리 할당  (0) 2021.02.10

파일 입출력의 필요성

프로그램이 꺼진 이후에도 데이터를 저장하기 위해서는 파일 입출력이 필요합니다

 

파일 입출력 변수는 FILE 형식의 포인터 변수로 선언합니다

파일을 열때는 fopen() 함수를 이용하고 닫을때는 fclose() 함수를 이용합니다

 

fopen() 함수에는 파일 경로와 접근 방식을 설정할 수 있습니다

기본 경로는 현재 프로그램의 경로입니다

접근 방식

  • r   파일에 접근하여 데이터를 읽습니다
  • w   파일에 접근하여 데이터를 기록합니다(파일이 이미 존재하면 덮어쓰기)
  • a   파일에 접근하여 데이터를 뒤에서부터 기록합니다

파일 입출력을 위해서 fprintf()fsanf() 가 사용됩니다

fprintf(파일 포인터 , 서식 , 형식지정자);

fscanf(파일 포인터, 서식 , 형식지정자);

 

파일을 처리 한 이후에 닫아주지 않으면 메모리 누수가 발생하기 때문에

열고 , 읽고/쓰고, 닫기의 과정을 철저히 따라야 합니다

 

텍스트 파일 읽는 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
int main(void) {
 
    FILE* fp = NULL;
    int c;
 
    fp = fopen("input.txt""r");
 
    if (fp == NULL) {
        printf("파일 열기에 실패했습니다\n");
    }
    else {
        printf("파일 열기에 성공했습니다\n");
    }
    while ((c = fgetc(fp)) != EOF) {
        putchar(c);
    }
    fclose(fp);
    return 0;
}
cs

 

텍스트 파일 분석 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define _CRT_SECURE_NO_WARNINGS
 
#include <stdio.h>
#include <string.h>
 
int main(void) {
    FILE* fp;
    char fname[256];
    char buffer[256];
    char word[256];
    int line = 0;
 
    printf("파일 이름을 입력하세요 : ");
    scanf("%s", fname);
 
    printf("탐색할 단어를 입려하세요 : ");
    scanf("%s", word);
 
    if ((fp = fopen(fname, "r")) == NULL) {
        fprintf(stderr, "파일 %s을 열수 없습니다\n", fname);
        return 0;
    }
    while (fgets(buffer, 256, fp)) {
        line++;
        if (strstr(buffer, word)) {
            printf("라인 %d : 단어 %s이(가) 발견되었습니다\n", line, word);
        }
    }
    fclose(fp);
 
    return 0;
}
cs

 

 

 

 

파일 입출력을 활용해 간단한 학생 정보 시스템 만들기 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
 
typedef struct {
    char name[20];
    int score;
} student;
 
int main(void) {
    int n, sum = 0;
    FILE* fp;
    fp = fopen("input.txt""r");
    fscanf(fp, "%d"&n);
    student *students = (student*)malloc(sizeof(student) * n);
    if (students == NULLreturn -1;
        for (int i = 0; i < n; i++) {
            fscanf(fp, "%s %d"&((students + i)->name), &((students + i)->score));
            printf("이름: %s , 성적: %d\n", (students + i)->name, (students + i)->score);
        }
    system("pause");
    return 0;
}
 
cs

위의 코드를 작성하기전에 먼저 프로젝트가 저장되어있는 Debug 폴더에 input.txt 파일을 만들고

학생수

이름 점수  를 작성해야합니다

ex)

5
장병학 90
김찬호 91
유민호 92
박민규 93
홍준휘 94

 

파일 입출력을 활용해 간단한 학생 정보 시스템 만들기 예시2 (성적 평균 구하고 메모리 할당 해제하기)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
 
typedef struct {
    char name[20];
    int score;
} student;
 
int main(void) {
    int n, sum = 0;
    FILE* fp;
    fp = fopen("input.txt""r");
    fscanf(fp, "%d"&n);
    student *students = (student*)malloc(sizeof(student) * n);
    if (students == NULLreturn -1;
        for (int i = 0; i < n; i++) {
            fscanf(fp, "%s %d"&((students + i)->name), &((students + i)->score));
        }
        for (int i = 0; i < n; i++) {
            sum += (students + i)->score;
        }
    free(students);
    fclose(fp);
    printf("점수 평균: %.2f\n", (double)sum / n);
    system("pause");
    return 0;
}
 
cs

 

위와 같이 파일 입출력이 끝난 이후에는 반드시 객체를 메모리에서 할당 해제해주어야 합니다

'C' 카테고리의 다른 글

재귀함수를 활용한 조합 공식  (0) 2021.02.23
전처리기  (0) 2021.02.14
구조체  (0) 2021.02.13
함수 포인터  (0) 2021.02.13
동적 메모리 할당  (0) 2021.02.10

+ Recent posts