<토이프로젝트>/[C++ 게임]

[C++ 게임] 행맨 게임 프로그래밍

사용자 BlockDMask 2019. 11. 27. 21:35
반응형

안녕하세요. BlockDMask 입니다.

이전에 제가 심심해서 따로 만든 C++ 게임들을.. 올려보려고합니다.

하나하나 주석을 좀 달고 하느라 올리는데 시간이 좀 걸릴 것 같습니다.

오늘 포스팅할 게임은 C++ 행맨 게임 입니다.

간단한 게임이고, 게임성이 없는 프로그램 이라 생각할 수 있습니다.

예제, 연습, 취미로 만든 게임이니 "아 C++을 이용해서 게임을 이런식으로 만들 수 있구나" 하고 봐주시면 감사하겠습니다.


<목차>

1. 게임 이름 및 설명

2. 게임 플레이 영상

3. 게임 소스 코드


1. 게임 이름 및 설명


▶ 게임 이름

C++ 프로그램 예제 행맨게임.

C++ 행맨 게임 프로그램.


▶ 게임 설명

1. words.txt 파일에 있는 단어들을 읽어와서 단어장을 만듭니다.

2. 프로그램을 맨 처음 실행하게 된다면 단어장이 없기 때문에 words.txt 라는 메모장을 만들고, 예제 단어들을 넣어 단어장을 만들어줍니다.

3. 단어를 _ _ _ _  이와같이 언더바(_)로 몇글자인지 추측하게 만들고, 사용자의 입력을 받아서 맞는 알파벳을 출력해 줍니다.

4. 사용자가 알파벳을 추측해서 단어를 맞추게 되면 점수(score)가 오르고 다음 문제(단어)를 냅니다.

5. 사용자가 입력할때마다 생명력(life)가 깎이게 되고 life가 0이되면 점수(score)가 깎이고 다음 문제(단어)로 넘어갑니다.

6. 각 탄의 생명력은 "단어의 길이+2"

7. 사용자는 자신이 words.txt 를 이용해서 단어들을 추가하거나 삭제할 수 있습니다.


▶ 행맨 게임에 사용된 C++ 지식, 함수들

1. C++ vector 에 관한 지식이 필요합니다. [바로가기]

- 문자열 배열(단어장)을 다루기 위해서 vector<string>을 사용했습니다.


2. C언어/C++ 에서 사용하는 랜덤 함수(난수생성)에 대한 지식이 필요합니다. [바로가기]

- vector에 넣은 단어들중 랜덤한 단어를 가지고 오기 위해서 사용했습니다.


3. C++ 파일입출력에 대한 지식이 필요합니다. [바로가기]

- 단어장을 저장하거나 불러올때 파일에 읽고 쓰는 작업이 필요하기 때문에 사용했습니다.


2. 게임 플레이 영상

▶ 게임 영상 바로가기 : https://youtu.be/xWYOIZOlKp8



3. 게임 소스 코드


▶ 프로그램 소스코드 

행맨 게임 소스 코드에 주석을 단다고 달았는데, 이해가 어려울 수 있습니다.

최대한 분석 해보시고 이해가 안간다면 질문 달아주세요.

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
//[C++ 예제 프로젝트. 행맨 게임] by. BlockDMask
#include<iostream>
#include<string>
#include<ctime>
#include<cstdlib>
#include<conio.h>
#include<Windows.h>
#include<vector>    // C++ vectror   : https://blockdmask.tistory.com/70
#include<fstream>    // C++ 파일입출력 : https://blockdmask.tistory.com/322
using namespace std;
 
//콘솔 내부의 특정 위치로 커서를 이동시키는 함수 입니다.
void gotoxy(int x, int y)
{
    COORD Pos;
    Pos.X = 2 * x;
    Pos.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}
 
//keyboard 입력
int GetKeyDown()
{
    if (_kbhit() != 0)        //키보드에 뭔가 입력이 오면
    {
        return _getch();    //입력된 키값을 반환.
    }
    return 0;
}
 
//콘솔 세팅
void SetConsoleView()
{
    system("mode con:cols=50 lines=20");        //화면크기
    system("title [HangManGame] by.BlockDMask");    //게임이름
}
 
//시작화면 draw
void DrawReadyGame()
{
    system("cls");
    gotoxy(52);
    cout << "==============================";
    gotoxy(53);
    cout << "======= HANG MAN GAME ========";
    gotoxy(54);
    cout << "==============================";
    gotoxy(66);
    cout << "시작하려면 's'를 눌러주세요";
    gotoxy(67);
    cout << "종료하려면 'q'를 눌러주세요";
    gotoxy(914);
    cout << "by. BlockDMask" << endl;
}
 
//게임화면 draw
void DrawStartGame(int life, int score, vector<string>& pastWord)
{
    system("cls");
    gotoxy(51);
    cout << "life = " << life;
    gotoxy(52);
    cout << "score = " << score;
    gotoxy(58);
    cout << "past = ";
    for (int i = 0; i < static_cast<int>(pastWord.size()); ++i)
    {
        cout << pastWord[i] << " ";
    }
 
    gotoxy(512);
    cout << "input = ";
    gotoxy(1314);
    cout << "메인화면 'qq'" << endl;
}
 
//사전을 세팅하는 함수 입니다.
//[C++] 파일입출력 포스팅 : https://blockdmask.tistory.com/322
void SetDictionary(vector<string>& strArr)
{
    static const int INIT_NUM = 4;
    static const string str[INIT_NUM] = { "apple""banana""code""program" };    //샘플 단어들
    ifstream readFromFile("words.txt");        //words.txt 파일을 읽기 전용으로 오픈
    if (!readFromFile.is_open())            //is_open이 되지 않는다는것은 파일이 존재하지 않다는 뜻.
    {
        ofstream writeToFile("words.txt");    //쓰기 전용으로 words.txt 파일을 오픈 (파일이 없으면 자동 생성됨)
        for (int i = 0; i < INIT_NUM; ++i)    //샘플 단어들을 format에 맞게 words.txt 파일에 입력
        {
            string tmp = str[i];
            if (i != INIT_NUM - 1)
            {
                tmp += "\n";
            }
            writeToFile.write(tmp.c_str(), tmp.size());    //파일에 쓰는 함수
            strArr.push_back(str[i]); //단어장(strArr)에 단어를 집어넣습니다.
        }
        writeToFile.close();    //쓰기전용파일 닫기
        return;                    //함수끝
    }
 
    //여기로 왔다는것은 읽기전용으로 파일오픈 되었다는뜻.
    while (!readFromFile.eof())    //파일 끝까지
    {
        string tmp;
        getline(readFromFile, tmp);    //한줄씩 읽어서
        strArr.push_back(tmp);        //단어장(strArr)에 단어 넣기
    }
    readFromFile.close();        //읽기전용파일 닫기
    return;
}
cs

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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
//시작화면 기능
bool ReadyGame()
{
    DrawReadyGame();    //시작화면 그리기
    while (true)
    {
        int key = GetKeyDown();                //키가 들어오면
        if (key == 's' || key == 'S')        //s는 스타트
        {
            return true;
        }
        else if (key == 'q' || key == 'Q')    //q는 끝
        {
            break;
        }
    }
    return false;
}
 
//게임 시작 함수.
void StartGame()
{
    int score = 0;
    vector<string> pastWord;    //입력한 영단어 저장
    vector<string> strArr;        //맞출 단어장
    SetDictionary(strArr);        //read from file
 
    while (true)    //하나의 탄을 표현하는 루프
    {
        //1 play
        int num = 0;
        srand((unsigned int)time(NULL));    //랜덤함수 : https://blockdmask.tistory.com/308
        num = rand() % static_cast<int>(strArr.size());    //단어장 내에 랜덤한 단어 선택
 
        string strQuestion;                        // _ _ _ _ _ 로 표현할 변수
        const string strOriginal = strArr[num];    //단어가 맞는지 정답확인용으로 저장
        const int originLen = static_cast<int>(strOriginal.length());
 
        //init
        for (int i = 0; i < originLen; ++i)
        {
            strQuestion += "_";    //정답 길이만큼 "_"
        }
 
        int life = originLen + 2;    //생명력은 정답 단어 길이 + 2
 
        //1 question
        while (true)    //하나의 단어를 맞추는 루프
        {
            DrawStartGame(life, score, pastWord);    //사용단어, 생명력, 점수표기
 
            //draw question
            gotoxy(55);
            for (int i = 0; i < originLen; ++i)
            {
                cout << strQuestion[i] << " ";    // _ _ _ _ 표기
            }
            cout << endl;
 
            //input
            gotoxy(912);
            string strInput;
            cin >> strInput;    //입력 받기.
            if (strInput == "qq")
            {
                return;
            }
            pastWord.push_back(strInput);    //한번 입력한 단어는 pastword에서 표기
 
            if (strInput.length() == 1)        //입력받은 스트링의 길이가 1인경우
            {
                //alphabet
                for (int i = 0; i < originLen; ++i)
                {
                    if (strOriginal[i] == strInput[0])    //오리지널 단어에 입력한 알파벳이 있는경우
                    {
                        strQuestion[i] = strInput[0];    // 해당 위치의 "_" 를 알파벳으로 바꿔줌 
                    }
                }
            }
            else if (strInput.length() > 1)    //입력받은 스트링의 길이가 1보다 큰 경우
            {
                //word
                if (strOriginal == strInput) //오리지널 단어랑 입력 단어가 같을때 (정답)
                {
                    //score up !!
                    score += 5;
                    pastWord.clear();
                    break;    //하나의 단어를 맞추는 루프를 나가게되고 다음 탄으로 넘어가게 됩니다.
                }
            }
 
            //틀리거나, 맞거나 어쨋든 입력이 되면 라이프가 무조건 1개씩 깎입니다.
            life -= 1;
            if (life < 0)
            {
                score -= 5;
                if (score < 0)
                {
                    score = 0;
                }
                pastWord.clear();
                break;
            }
        }
    }
}
 
//메인함수
int main(void)
{
    SetConsoleView();
    bool isStart = false;
    while (true)
    {
        isStart = ReadyGame();    //readgame함수가 true면
        if (isStart)
        {
            StartGame();        //게임시작
        }
        else
        {
            break;
        }
    }
    return 0;
}
cs


이상으로, "C++ 행맨 게임 만들기" 포스팅을 마치겠습니다.

블로그에서 소스코드 분석하기가 불편하다면, 댓글로 이메일 주소 남겨주시면 보내드리겠습니다.

더 많은 C++ 게임, 컴퓨터 지식으로 기다리겠습니다. 또 방문해주세요! 감사합니다.

소스코드 : https://github.com/BlockDMask/Hangman_Game

반응형