강께르의 개발일지
[C++] 빙고 게임_미완성 본문
1. 이것은 무엇인가?
- 컴퓨터가 무작위로 중복되지 않은 일정 범위의 숫자를 5x5 게임판에 배열하고 플레이어는 특정 숫자를 지정하여 체크한 후, 가로나 세로 혹은 대각선이든 숫자 5개를 연속하여 1줄을 완성한다면 1 빙고로 인정하고 이 빙고를 3개 달성하는 것이 목표인 빙고 게임이다.
- 사실 구조체화한 일대일 턴제 게임보다 더 먼저 만들었으나 시간이 지난 뒤, 수정하려 했으나 일정상 어려움과 시간이 얼마 지나지 않았음에도 내 코드를 내가 다시 익히기 위해 읽어야하는 불상사가 발생하여 일단은 코드만 올리려고 한다.
2. 주요 게임 동작 설명
2-1. 게임 시작 전 숫자 섞기
- 컴퓨터는 2차원 배열 5x5의 첫번째 인덱스에 1부터 25까지의 숫자 중 무작위로 하나를 넣는다. 그리고 그 다음 두번째 인덱스부터 무작위 숫자를 하나 다시 넣고 그 이전의 모든 인덱스의 숫자와 비교를 하여 중복되었는지 검사한다. 이를 25번 반복해 무작위로 숫자를 채운다.
2-2. 플레이어가 선택한 숫자를 게임판에서 찾기
- 플레이어로부터 숫자 하나를 입력받고 입력한 숫자가 2차원 배열에 있는지 첫번째 인덱스부터 순서대로 확인한다.
2-3. 빙고인지 확인하기
- 체크되는 숫자가 확인될 때마다 빙고가 달성되어 있는지 확인한다. 특정 배열이 모두 체크인지 and 연산자로 조건이 부합하면 빙고 카운트를 따로 하나 추가한다. 이 빙고 카운트는 체크되는 숫자가 있을 때마다 0으로 초기화하고 조건이 부합하는 배열 모음이 있을 때마다 카운트를 증가시킨다.
3. 새로 알게 된 점
- inline 키워드를 사용해 많이 호출하는 함수를 인라인화해봤다. 함수 호출하는 비용을 없애고 컴파일 단계에서 코드를 옮겨놓은 효과라고 해서 썼다. 프로그래밍한 내 입장해선 엄청난 차이가 있는지 체감할 수는 없지만 이렇게 사용하는 방법을 익혀두는 것도 좋을 것 같다.
- 개발을 대강 마치고 나서 다른 거 개발하러 갔다가 오니 다시 시작하기 너무 어려웠다. 포스팅하기 위해 대강 정리하고 다시 파악하는 수고를 들였는데 이래서 처음부터 짜임새 있는 코드를 짜라고 하는 것을 느꼈다.
4. 코드
4-1. header.h
#ifndef __BINGO_H__
#define __BINGO_H__
#include<iostream>
#include<Windows.h>
#include<ctime>
using namespace std;
enum class MENU
{
SINGLE = 1,
COMPUTER
};
struct Bingo
{
int m_table[5][5] = { 0, };
bool m_isCheck[5][5] = { false, };
int m_bingoCnt = 0;
bool m_bingoShow[3] = { true, true, true };
};
void Gotoxy(int, int);
void SetConsoleView(void);
void ShowReadyGameTable(void);
void ShowEmptyArr(void);
void ShowEmptyBottom(void);
void ShowMenu(void);
MENU GetInput(void);
void ShowWrongMenu(void);
void RandomChooseNum(int(*)[5]);
bool CheckOverlap(int(*)[5], int, int);
int ShowPressNum(void);
bool CheckNumInArr(Bingo&, int);
void DrawGameTable(Bingo);
inline void DrawNumOrChar(Bingo, int, int);
void ShowCheckNum(int);
int CheckBingoLine(const Bingo);
void ShowBingoCnt(int);
void ShowNotCheckNum(int);
void ShowGameover(void);
const int horizon = 5;
const int vertical = 5;
#endif
4-2. function.cpp
#include "header.h"
void Gotoxy(int x, int y)
{
COORD position;
position.X = 2 * x;
position.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
}
void SetConsoleView(void)
{
system("mode con:cols=55 lines=25");
}
void ShowReadyGameTable(void)
{
ShowEmptyArr();
ShowEmptyBottom();
system("cls");
ShowEmptyArr();
cout << " 메세지\t|\t엔터를 눌러주세요.\t\t|" << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
Gotoxy(5, 17);
cin.get();
system("cls");
ShowEmptyArr();
ShowMenu();
}
void ShowEmptyArr(void)
{
cout << "======================================================" << endl;
cout << "=====B===I===N===G===O==============G===A===M===E=====" << endl;
cout << "======================================================" << endl;
cout << "\t| [1]\t| [2]\t| [3]\t| [4]\t| [5]\t|" << endl;
cout << "--------+-------+-------+-------+-------+-------+-----" << endl;
cout << " [1]\t|\t|\t|\t|\t|\t|" << endl;
cout << "--------+-------+-------+-------+-------+-------|" << endl;
cout << " [2]\t|\t|\t|\t|\t|\t|" << endl;
cout << "--------+-------+-------+-------+-------+-------|" << endl;
cout << " [3]\t|\t|\t|\t|\t|\t|" << endl;
cout << "--------+-------+-------+-------+-------+-------|" << endl;
cout << " [4]\t|\t|\t|\t|\t|\t|" << endl;
cout << "--------+-------+-------+-------+-------+-------|" << endl;
cout << " [5]\t|\t|\t|\t|\t|\t|" << endl;
cout << "--------+---------------------------------------+-----" << endl;
}
void ShowEmptyBottom(void)
{
cout << " 메세지\t|\t\t\t\t\t|" << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
Sleep(1000);
}
void ShowMenu(void)
{
cout << " 메세지\t|1. 혼자 빙고\t\t2.컴퓨터와 빙고\t|" << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
}
MENU GetInput(void)
{
int inputNum;
Gotoxy(5, 17);
cin >> inputNum;
while (((MENU)inputNum < MENU::SINGLE) || ((MENU)inputNum > MENU::COMPUTER))
{
system("cls");
ShowWrongMenu();
Gotoxy(5, 17);
cin >> inputNum;
}
return (MENU)inputNum;
}
void ShowWrongMenu(void)
{
ShowEmptyArr();
cout << " 메세지\t|\t다시 입력해주세요.\t\t|" << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
Gotoxy(5, 17);
cin.get();
cin.get();
system("cls");
ShowEmptyArr();
ShowMenu();
}
void RandomChooseNum(int(*arr)[5])
{
bool isOverlap = false;
srand((unsigned int)time(NULL));
for (int i = 0; i < horizon; i++)
{
for (int j = 0; j < vertical; j++)
{
arr[i][j] = (rand() % 25) + 1;
// 컴퓨터가 비교 연산하는 모습 보고 싶으면 주석처리 풀기
/*system("cls");
DrawGameTable(arr);*/
if ((i == 0) && (j == 0))
{
continue;
}
else
{
isOverlap = CheckOverlap(arr, i, j);
if (isOverlap)
{
if (j == 0)
{
i--;
j = vertical - 1;
}
else
j = j - 1;
}
}
}
}
}
bool CheckOverlap(int(*arr)[5], int horizonIdx, int verticalIdx)
{
bool result = false;
int vertIdx = vertical;
for (int i = 0; i <= horizonIdx; i++)
{
if (i == horizonIdx)
vertIdx = verticalIdx;
for (int j = 0; j < vertIdx; j++)
{
if (arr[horizonIdx][verticalIdx] == arr[i][j])
{
result = true;
break;
}
}
if (result == true)
break;
}
return result;
}
int ShowPressNum(void)
{
int input;
cout << " 메세지\t|\t체크할 숫자를 입력하세요.\t|" << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
Gotoxy(5, 17);
cin >> input;
return input;
}
bool CheckNumInArr(Bingo& bingo, int checkNum)
{
bool isFind = false;
int i, j;
for (i = 0; i < horizon; i++)
{
for (j = 0; j < vertical; j++)
{
if (bingo.m_table[i][j] == checkNum)
{
isFind = true;
bingo.m_isCheck[i][j] = isFind;
i = horizon;
break;
}
}
}
return isFind;
}
void DrawGameTable(Bingo bingo)
{
cout << "======================================================" << endl;
cout << "=====B===I===N===G===O==============G===A===M===E=====" << endl;
cout << "======================================================" << endl;
cout << "\t| [1]\t| [2]\t| [3]\t| [4]\t| [5]\t|" << endl;
cout << "--------+-------+-------+-------+-------+-------+-----" << endl;
cout << " [1]\t| "; DrawNumOrChar(bingo, 0, 0); cout << "\t| ";
DrawNumOrChar(bingo, 0, 1); cout << "\t| ";
DrawNumOrChar(bingo, 0, 2); cout << "\t| ";
DrawNumOrChar(bingo, 0, 3); cout << "\t| ";
DrawNumOrChar(bingo, 0, 4); cout << "\t| ";
cout << endl;
cout << "--------+-------+-------+-------+-------+-------|" << endl;
cout << " [2]\t| "; DrawNumOrChar(bingo, 1, 0); cout << "\t| ";
DrawNumOrChar(bingo, 1, 1); cout << "\t| ";
DrawNumOrChar(bingo, 1, 2); cout << "\t| ";
DrawNumOrChar(bingo, 1, 3); cout << "\t| ";
DrawNumOrChar(bingo, 1, 4); cout << "\t| ";
cout << endl;
cout << "--------+-------+-------+-------+-------+-------|" << endl;
cout << " [3]\t| "; DrawNumOrChar(bingo, 2, 0); cout << "\t| ";
DrawNumOrChar(bingo, 2, 1); cout << "\t| ";
DrawNumOrChar(bingo, 2, 2); cout << "\t| ";
DrawNumOrChar(bingo, 2, 3); cout << "\t| ";
DrawNumOrChar(bingo, 2, 4); cout << "\t| ";
cout << endl;
cout << "--------+-------+-------+-------+-------+-------|" << endl;
cout << " [4]\t| "; DrawNumOrChar(bingo, 3, 0); cout << "\t| ";
DrawNumOrChar(bingo, 3, 1); cout << "\t| ";
DrawNumOrChar(bingo, 3, 2); cout << "\t| ";
DrawNumOrChar(bingo, 3, 3); cout << "\t| ";
DrawNumOrChar(bingo, 3, 4); cout << "\t| ";
cout << endl;
cout << "--------+-------+-------+-------+-------+-------|" << endl;
cout << " [5]\t| "; DrawNumOrChar(bingo, 4, 0); cout << "\t| ";
DrawNumOrChar(bingo, 4, 1); cout << "\t| ";
DrawNumOrChar(bingo, 4, 2); cout << "\t| ";
DrawNumOrChar(bingo, 4, 3); cout << "\t| ";
DrawNumOrChar(bingo, 4, 4); cout << "\t| ";
cout << endl;
cout << "--------+---------------------------------------+-----" << endl;
}
inline void DrawNumOrChar(Bingo bingo, int horiz, int verti)
{
if (bingo.m_isCheck[horiz][verti] == false)
cout << bingo.m_table[horiz][verti];
else
cout << "*";
}
void ShowCheckNum(int CheckNum)
{
cout << " 메세지\t|\t" << CheckNum << "이/가 체크됐습니다.\t\t| " << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
Sleep(1000);
}
int CheckBingoLine(const Bingo bingo)
{
int cnt = 0;
for (int horiz = 0; horiz < horizon; horiz++)
{
if (bingo.m_isCheck[horiz][0] && bingo.m_isCheck[horiz][1] && bingo.m_isCheck[horiz][2] && bingo.m_isCheck[horiz][3] && bingo.m_isCheck[horiz][4])
cnt++;
}
for (int verti = 0; verti < vertical; verti++)
{
if (bingo.m_isCheck[0][verti] && bingo.m_isCheck[1][verti] && bingo.m_isCheck[2][verti] && bingo.m_isCheck[3][verti] && bingo.m_isCheck[4][verti])
cnt++;
}
if (bingo.m_isCheck[0][0] && bingo.m_isCheck[1][1] && bingo.m_isCheck[2][2] && bingo.m_isCheck[3][3] && bingo.m_isCheck[4][4])
cnt++;
if (bingo.m_isCheck[0][4] && bingo.m_isCheck[1][3] && bingo.m_isCheck[2][2] && bingo.m_isCheck[3][1] && bingo.m_isCheck[4][0])
cnt++;
return cnt;
}
void ShowBingoCnt(int bingoCnt)
{
cout << " 메세지\t|\t" << bingoCnt << " BINGO!\t\t\t| " << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
Sleep(1000);
}
void ShowNotCheckNum(int notCheckNum)
{
cout << " 메세지\t|\t" << notCheckNum << "은/는 없습니다.\t\t| " << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
Sleep(1000);
}
void ShowGameover(void)
{
cout << " 메세지\t|\t게임을 종료합니다.\t\t|" << endl;
cout << "======================================================" << endl;
cout << " 입력\t|" << endl;
cout << "======================================================" << endl;
Sleep(1000);
}
4-3. main.cpp
#include"header.h"
int main(void)
{
Bingo bingo;
MENU menu;
int inputNum;
bool isCheck;
SetConsoleView();
ShowReadyGameTable();
menu = GetInput();
system("cls");
switch (menu)
{
case MENU::SINGLE:
RandomChooseNum(bingo.m_table);
while (bingo.m_bingoCnt < 3)
{
DrawGameTable(bingo);
inputNum = ShowPressNum();
isCheck = CheckNumInArr(bingo, inputNum);
system("cls");
switch (isCheck)
{
case true:
DrawGameTable(bingo);
ShowCheckNum(inputNum);
system("cls");
DrawGameTable(bingo);
bingo.m_bingoCnt = CheckBingoLine(bingo);
if ((bingo.m_bingoCnt > 0) && (bingo.m_bingoShow[bingo.m_bingoCnt - 1]))
{
ShowBingoCnt(bingo.m_bingoCnt);
bingo.m_bingoShow[bingo.m_bingoCnt - 1] = false;
}
break;
case false:
DrawGameTable(bingo);
ShowNotCheckNum(inputNum);
break;
}
system("cls");
}
break;
case MENU::COMPUTER:
ShowEmptyArr();
ShowEmptyBottom();
Gotoxy(5, 17);
cout << "구현되지 않았습니다.";
Sleep(3000);
Gotoxy(5, 19);
break;
}
ShowEmptyArr();
ShowGameover();
return 0;
}
5. 결과
- 미구현된 컴퓨터와의 대전과 배우고 있는 데이터를 클래스화하는 것을 하러 다시 오겠다..!
'연습' 카테고리의 다른 글
[C++] 몬스터와 1대3 턴제 전투 게임 (0) | 2021.06.14 |
---|---|
[C++] 슬라이드 퍼즐 게임 (0) | 2021.06.14 |
[C++] 몬스터와 일대일 턴제 전투 게임_구조체로 수정 (0) | 2021.06.12 |
[C++] 숫자야구 게임 (0) | 2021.06.08 |
[C++] 몬스터와 일대일 턴제 전투 게임 (0) | 2021.06.08 |