스택(Stack)과 큐(Queue)를 이용한 지렁이 게임


스택(Stack)과 큐(Queue)를 이용한 지렁이 게임


이번에는 스택(Stack)과 큐(Queue)를 이용한 지렁이 게임을 만들어 보겠다.
스택은 LIFO (Last In First Out) 나중에 들어온 것이 제일 먼저 나간다라는 뜻이다.
스택을 이용한 계산기도 있으니 이 게시물을 통해서 스택의 구조를 먼저 익히고 오기를 바란다.

그리고 큐는 FIFO (First In First Out) 먼저들어온게 먼저 나간다라는 뜻이다.

큐를 이용한 계산기가 마찬가지로 있으니 이 게시물을 통해서 큐의 구조를 먼저 익히고 오기를 바란다.


[프로그래밍/C] - 큐(Queue)를 이용한 계산기 프로그램


이 두개를 알아보았으니 스택과 큐를 이용해서 지렁이 게임을 만들어보자.

지렁이 게임 만들거는 대략 이런 것이다.




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
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80
#define MAP_X 38
#define MAP_Y 23
#define ESC 27
#define SEE_UP 1
#define SEE_DOWN 2
#define SEE_LEFT 3
#define SEE_RIGHT 4
typedef struct xy {
    int x;
    int y;
}XY;
 
typedef struct NODE {
    int t;
    int x;
    int y;
    struct NODE *tail;
}Node;
void gotoxy(int x, int y);
void insertNode(Node **head, int x, int y);
void insertObs(Node **Obs, int x, int y);
void createTail(XY *tails, Node *obs);
void createObs(Node *Head, Node **obs, XY *tails);
void init_Game(Node ** HEAD, XY *tails);
void end_Game();
void checkWall(Node *HEAD);
void checkObject(Node **HEAD, XY *tails, Node **obs);
void moveSnake(Node *HEAD, int s);
void start_Game(Node **HEAD, XY *tails);
cs


일단 main.h파일이다.

헤더파일에는 함수의 원형과 구조체, define으로 설정해준것을 넣어줬다.


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
#include "main.h"
void start_Game(Node **HEAD, XY *tails) // 게임 시작
{
    Node *obs = NULL;
    char ip = '\0';
    int s_see = SEE_LEFT, count = 0;
    int gameSpd = 250, score = 0;
    short ctime = (short)time(0);
    short mtime;
    while (1)
    {
        if (_kbhit())
        {
            ip = _getch();
            switch (ip)
            {
            case LEFT:
                s_see = SEE_LEFT;
                break;
            case RIGHT:
                s_see = SEE_RIGHT;
                break;
            case UP:
                s_see = SEE_UP;
                break;
            case DOWN:
                s_see = SEE_DOWN;
                break;
            case ESC:
                exit(1);
                break;
            }
            ip = '\0';
        }
        else { // 키 입력이 없을 때
            moveSnake(*HEAD, s_see);
            checkObject(HEAD, tails, &obs);
            gotoxy(tails->* 2, tails->y);
            printf("⊙");
            if (obs != NULL)
            {
                gotoxy(obs->* 2, obs->y);
                printf("▩");
            }
            Sleep(gameSpd);
        }
        mtime = (short)time(0);
        if (mtime - ctime >= 1// 게임 속도 조절
        {
            ctime = mtime;
            count++;
            if (count == 10)
            {
                count = 0;
                if (gameSpd - (*HEAD)->* 2 > 40)
                    gameSpd -= (*HEAD)->* 2;
            }
            score += ((*HEAD)->* (*HEAD)->t) * 10 + (*HEAD)->t; // 점수 계산
            gotoxy(0, MAP_Y + 1); // 점수 출력
            printf("YOUR SCORE [ %d ] / TAILS [ %d ] / GAME SPEED [ %d ]", score, (*HEAD)->t, gameSpd);
        }
    }
}
void end_Game()
{
    gotoxy(0, MAP_Y / 2);
    printf("[ 게임 오버 ][ 게임 오버 ][ 게임 오버 ][ 게임 오버 ][ 게임 오버 ][ 게임 오버 ]");
    _getch();
    exit(1);
}
main()
{
    Node *HEAD = NULL;
    XY tails = { 0,0 };
    srand((unsigned)time(NULL));
    printf("┏━━━━━━━━━━┓\n");
    printf("┃                    ┃\n");
    printf("┃ 지렁이게임         ┃\n");
    printf("┃  (스택,큐 연습)    ┃\n");
    printf("┃                    ┃\n");
    printf("┗━━━━━━━━━━┛\n\n");
    printf("> 게임키 : 방향키 좌( ← ), 우( → ), 위( ↑ ), 아래( ↓ )\n");
    printf("         - 게임종료 ESC\n\n");
    printf("> 게임을 시작하시려면 아무키나 눌러주세요 <");
    _getch();
    system("cls");
    init_Game(&HEAD, &tails);
    start_Game(&HEAD, &tails);
}
cs

main.c 파일이다.
73~74행에서 Node 포인터 변수와 XY 구조체를 0으로 초기화 해준다. (main.h파일을 보면 알수있다.)
75행에서 시간을 초기화 해준다.
87행에서 게임 초기화를 해준다. 맵을 만들어주는 것이다.
88행에서 게임을 시작한다.
나머지는 다 코드를 분석해보면 안다.



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
#include "main.h"
void init_Game(Node ** HEAD, XY *tails) // 게임 초기화
{
    int i = 0, k = 0;
    for (i = 0; i <= MAP_Y; i++// 맵 테두리 만들기
    {
        for (k = 0; k <= MAP_X; k++)
        {
            if (i == 0 || i == MAP_Y || k == 0)
            {
                printf("▩");
            }
            if (k == MAP_X)
            {
                gotoxy((MAP_X) * 2, i);
                printf("▩");
            }
        }
        printf("\n");
    }
    insertNode(&(*HEAD), MAP_X - 2, MAP_Y / 2);
    createTail(tails, NULL);
}
void checkWall(Node *HEAD)
{
    if (HEAD->< 1 || HEAD->>= MAP_X || HEAD->< 1 || HEAD->>= MAP_Y)
        end_Game();
}
cs

map.c 파일이다.

5행에서 MAP_Y는 23으로 지정되어 있다.
7행에서 MAP_Y는 38으로 지정되어 있다.
9행에서 i가 0이거나 MAP_Y 이거나 k가 0이면 ▩를 출력해준다.
13행에서 k가 MAP_X면 MAP_X * 2, i 좌표로 이동해서 ▩를 출력해준다.
21행에서 큐에다가 삽입을 해준다.

코드 분석을 내가 일일이 해주니 너무 시간이 오래걸린다. 그러므로 직접 코드를 분석해보기를 바란다.
모르는 곳이 있으면 책을 찾아보든 물어보든가 하자. 그래야 실력이 오른다.

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
#include "main.h"
void checkObject(Node **HEAD, XY *tails, Node **obs)
{
    Node *tmp = (*HEAD)->tail;
 
    checkWall(*HEAD); // 벽
 
 
    while (tmp != NULL// 자기 꼬리
    {
        if (tmp->== (*HEAD)->&& tmp->== (*HEAD)->y)
            end_Game();
        tmp = tmp->tail;
    }
 
    if ((tails->== (*HEAD)->x) && (tails->== (*HEAD)->y)) // 꼬리
    {
        insertNode(&(*HEAD), (*HEAD)->x, (*HEAD)->y);
        (*HEAD)->t++;
        createTail(tails, *obs);
        createObs(*HEAD, &(*obs), tails);
        createObs(*HEAD, &(*obs), tails);
    }
 
    while (*obs != NULL// 장애물
    {
        if ((*obs)->== (*HEAD)->&& (*obs)->== (*HEAD)->y)
            end_Game();
        obs = &(*obs)->tail;
    }
}
void moveSnake(Node *HEAD, int s) // 뱀의 이동
{
    Node *tmp = HEAD;
    XY tmp1 = { HEAD->x,HEAD->y };
    XY tmp2 = tmp1;
    if (s == SEE_LEFT) // 바라보는 방향으로 이동
        HEAD->-= 1;
    else if (s == SEE_RIGHT)
        HEAD->+= 1;
    else if (s == SEE_UP)
        HEAD->-= 1;
    else
        HEAD->+= 1;
    HEAD = HEAD->tail;
    while (HEAD != NULL// 꼬리들 좌표 전달
    {
        tmp2.x = HEAD->x;
        tmp2.y = HEAD->y;
        HEAD->= tmp1.x;
        HEAD->= tmp1.y;
        tmp1.x = tmp2.x;
        tmp1.y = tmp2.y;
        HEAD = HEAD->tail;
    }
    gotoxy(tmp2.x * 2, tmp2.y); // 맨 뒤 꼬리 지우기
    printf("  ");
    gotoxy(tmp->* 2, tmp->y); // 머리 출력
    printf("◎");
    if (tmp->tail != NULL// 전 머리부분 몸통 출력
    {
        gotoxy(tmp->tail->* 2, tmp->tail->y);
        printf("⊙");
    }
}
void createTail(XY *tails, Node *obs) // 보너스 꼬리 아이템 생성
{
    int flag = 1;
    while (flag)
    {
        flag = 0;
        tails->= rand() % (MAP_X - 1+ 1;
        tails->= rand() % (MAP_Y - 1+ 1;
        while (obs != NULL// 장애물하고 위치 중복 체크
        {
            if (obs->== tails->&& obs->== tails->y)
            {
                flag = 1;
                break;
            }
            obs = obs->tail;
        }
    }
    gotoxy(tails->* 2, tails->y);
    printf("⊙");
}
void createObs(Node *Head, Node **obs, XY *tails) // 장애물 생성
{
    Node *tmp = *obs;
    int flag = 1;
    XY oxy = { 0,0 };
    while (flag) {
        flag = 0;
        oxy.x = rand() % (MAP_X - 1+ 1;
        oxy.y = rand() % (MAP_Y - 1+ 1;
        if ((oxy.x == tails->&& oxy.y == tails->y) || // 뱀의 머리, 보너스 꼬리 아이템하고 위치 중복 체크
            (oxy.x == Head->&& oxy.x == Head->y))
        {
            flag = 1;
            continue;
        }
        while (tmp != NULL// 이전에 생성된 장애물들과 위치 중복 체크
        {
            if (tmp->== oxy.x && tmp->== oxy.y)
            {
                flag = 1;
                break;
            }
            tmp = tmp->tail;
        }
    }
    insertObs(&(*obs), oxy.x, oxy.y); // 장애물 추가
    gotoxy(oxy.x * 2, oxy.y);
    printf("▩");
}
cs

snake.c 파일이다.

뱀의 부분에 해당하는 부분이다.

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
#include "main.h"
void gotoxy(int x, int y)
{
    COORD pos = { x, y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
Node* getNode() // 노드 생성
{
    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->tail = NULL;
    return newNode;
}
void insertNode(Node **head, int x, int y) // 큐
{
    if (*head == NULL)
    {
        *head = getNode();
        (*head)->= x;
        (*head)->= y;
        (*head)->= 0;
    }
    else
        insertNode(&(*head)->tail, x, y);
}
void insertObs(Node **Obs, int x, int y) // 스택
{
    Node *tmp = *Obs;
    *Obs = getNode();
    (*Obs)->= x;
    (*Obs)->= y;
    if (*Obs != NULL)
        (*Obs)->tail = tmp;
}
cs

StackQueue.c 파일이다.

스택과 큐 부분에 있는 소스파일이다.

이렇게 스택과 큐를 이용해 지렁이 게임을 만들어보았다.
모르는 부분은 댓글로 물어보기를 바란다.
실시간으로 답을 해줄것이다.



댓글

Designed by JB FACTORY