강께르의 개발일지
[C++] 숫자야구 게임 본문
1. 이것은 무엇인가?
컴퓨터가 무작위로 고른 4자리의 숫자를 맞추는 게임이다. 자릿수와 숫자가 맞은 것 하나당 스트라이크 하나로 인정하고, 자릿수는 다르지만 숫자가 맞은 것은 볼 하나로 인정한다. 이렇게 해서 스트라이크 4개 즉, 모든 숫자와 자릿수를 알아 맞히면 홈런이라고 하여 정답 처리를 하고 게임을 끝낸다.
숫자야구 진행 순서는 "시작 출력문 - 난이도 설정 - (플레이어 입력 - 입력한 값에서 정답 판단 처리 - 그에 대한 결과 출력) - 게임 종료 출력문"으로 이루어져있다.
2. 새로 알게 된 점
- int형배열을 4개의 요소로 하나 정의하고 그곳에 입력을 받으려고 시험삼아 1234를 입력했는데 아뿔싸, 첫번째 배열요소에 1234라고 때려박는 걸 발견했다.
- 이에 대한 고민으로 문자열은 숫자를 하나 하나 단일문자로 배열요소에 저장한다는 것을 알게 되어 문자 배열로 플레이어의 입력을 받고 정답 판단을 하려고 했다.
- 그런데 컴퓨터는 무작위로 설정하는 숫자는 int형이어서 플레이어 입력과 자료형이 달라 비교할 수 없던 것이다.
- 그래서 알아보니 단일 문자를 int형으로 캐스팅하면 아스키코드 값이 나오는데 그 아스키코드 값에 48을 빼면 정수값을 얻을 수 있다는 것이다.
3. 코드
#include<iostream>
#include<Windows.h>
#include<ctime>
using namespace std;
enum DIFF
{
EASY = 1,
NORMAL,
HARD
};
enum COUNT
{
STRIKE,
BALL,
OUTGAME
};
void SetConsoleView(void);
void ShowTitle(void);
void RandomChooseNum(int*);
void CountStkBall(int*, int*, int*);
bool IsGameover(int&, int);
bool ShowCntRes(int*);
int SetDifficulty(int*);
int ConvertCharInt(char);
const int arrLength = 4;
int main(void)
{
int difficulty[3] = { 20, 15, 10 };
int gameCount = 20;
int countArr[3] = { 0, };
bool isNotGameover = true;
int computerChooseNum[arrLength] = { 0, };
int playerChooseNum[arrLength] = { 0, }; // 아스키 코드값을 빼서 플레이어 선택한 진짜 정수를 저장
char playerinputNum[arrLength] = { 0, }; // 플레이어의 입력을 받을 배열
// 문자열로 입력 시의 캐스팅할 필요 없이 손쉽게 저장
RandomChooseNum(computerChooseNum);
SetConsoleView();
ShowTitle();
gameCount = SetDifficulty(difficulty);
cout << "===============================================================" << endl;
Sleep(2000);
while (isNotGameover)
{
cout << "당신에게 " << gameCount << "번의 기회가 있습니다. " << endl;
cout << "컴퓨터가 생각하는 네 자리의 수를 입력 : ";
for (int i = 0; i < arrLength; i++)
cin >> playerinputNum[i];
cout << "===============================================================" << endl;
cout << "플레이어가 선택한 숫자 : ";
for (int i = 0; i < arrLength; i++)
{
playerChooseNum[i] = ConvertCharInt(playerinputNum[i]);
cout << playerChooseNum[i];
}
cout << endl;
CountStkBall(computerChooseNum, playerChooseNum, countArr);
if (ShowCntRes(countArr) == true)
{
cout << "HOME RUN!" << endl;
Sleep(1000);
cout << "컴퓨터가 생각한 숫자를 " << gameCount << "회 남겨놓고 모두 맞췄습니다!" << endl;
Sleep(1000);
cout << "컴퓨터가 생각한 숫자 : ";
for (int i = 0; i < arrLength; i++)
cout << computerChooseNum[i] << " ";
cout << endl;
cout << "===============================================================" << endl;
break;
}
Sleep(2000);
isNotGameover = !(IsGameover(gameCount, countArr[COUNT::OUTGAME]));
}
}
// 게임오버 체크 함수
bool IsGameover(int& gameCnt, int outCnt)
{
bool result = false;
gameCnt--;
if ((gameCnt < 1) || (outCnt > 3))
result = true;
return result;
}
void SetConsoleView(void)
{
system("mode con:cols=64 lines=100");
system("title 숫자야구");
}
void ShowTitle(void)
{
cout << "===============================================================" << endl;
cout << "===============================================================" << endl;
cout << "============숫========자==========야=========구================" << endl;
cout << "===============================================================" << endl;
cout << "===============================================================" << endl;
}
// 게임 시작 시 컴퓨터의 숫자를 미리 정해놓는 함수
void RandomChooseNum(int* arr)
{
srand((unsigned int)time(NULL));
for (int i = 0; i < arrLength; i++)
{
arr[i] = rand() % 10;
if (i > 0)
{
for (int j = 0; j < i; j++)
{
if (arr[i] == arr[j]) // 지금 선택한 숫자가 이전에 있었냐?
{
i--;
break;
}
}
}
}
}
// 플레이어가 입력한 수와 컴퓨터의 수를 비교해 스트라이크와 볼을 세는 함수
void CountStkBall(int* comArr, int* plyArr, int* cntArr)
{
for (int comIdxCnt = 0; comIdxCnt < arrLength; comIdxCnt++) // 컴퓨터 인덱스
{
for (int plyIdxCnt = 0; plyIdxCnt < arrLength; plyIdxCnt++) // 플레이어 인덱스
{
if (comArr[comIdxCnt] == plyArr[plyIdxCnt]) // 숫자가 맞으면
{
if (comIdxCnt == plyIdxCnt) // 자릿수까지 맞으면 스트라이크
cntArr[COUNT::STRIKE]++;
else if (comIdxCnt != plyIdxCnt) // 자릿수가 다르면 볼
cntArr[COUNT::BALL]++;
}
}
}
}
// 스트라이크와 볼 갯수를 알려주는 함수, 홈런일 경우 true를 반환
bool ShowCntRes(int* cntArr)
{
bool result = false;
if ((cntArr[COUNT::STRIKE] == 0) && (cntArr[COUNT::BALL] == 0)) // 0 스트라이크 0 볼일때
{
cntArr[COUNT::OUTGAME]++;
cout << "맞는 숫자가 없습니다!" << endl << endl;
cout << cntArr[COUNT::OUTGAME] << "OUT!!" << endl;
}
else
{
cout << "맞는 숫자가 있습니다!" << endl << endl;;
Sleep(2000);
if (cntArr[COUNT::STRIKE] == arrLength)
result = true;
else if (cntArr[COUNT::STRIKE] > 0)
cout << cntArr[COUNT::STRIKE] << "STRIKE ";
if (cntArr[COUNT::BALL] > 0)
cout << cntArr[COUNT::BALL] << "BALL";
cntArr[COUNT::STRIKE] = 0;
cntArr[COUNT::BALL] = 0;
Sleep(1000);
cout << endl;
cout << "===============================================================" << endl;
}
return result;
}
// 난이도 설정으로 게임 횟수를 정함
int SetDifficulty(int* diffArr)
{
int diff;
int gameCnt = 0;
cout << "난이도를 선택해주세요." << endl;
cout << "맞출 수 있는 기회가 달라집니다." << endl;
cout << "1. 20회(응애 난이도)\t\t2. 15회(보통 난이도)" << endl << "3. 10회(어려움 난이도)" << endl;
cout << "선택 : ";
cin >> diff;
cout << "===============================================================" << endl;
switch (diff)
{
case DIFF::EASY:
gameCnt = diffArr[DIFF::EASY - 1];
cout << "플레이어는 응애 난이도를 선택했습니다." << endl;
break;
case DIFF::NORMAL:
gameCnt = diffArr[DIFF::NORMAL - 1];
cout << "플레이어는 보통 난이도를 선택했습니다." << endl;
break;
case DIFF::HARD:
gameCnt = diffArr[DIFF::HARD - 1];
cout << "플레이어는 어려움 난이도를 선택했습니다." << endl;
break;
}
cout << "플레이어에게 " << gameCnt << "번의 기회가 주어졌습니다." << endl;
return gameCnt;
}
// 단일 문자를 아스키코드로 변환하여 아스키코드값만큼 빼서 정수로 변환
int ConvertCharInt(char chr)
{
return (int)chr - 48;
}
4. 결과
'연습' 카테고리의 다른 글
[C++] 빙고 게임_미완성 (0) | 2021.06.13 |
---|---|
[C++] 몬스터와 일대일 턴제 전투 게임_구조체로 수정 (0) | 2021.06.12 |
[C++] 몬스터와 일대일 턴제 전투 게임 (0) | 2021.06.08 |
[C++] 숫자 맞추기 게임 (0) | 2021.06.04 |
[C++] 가위바위보 게임 (0) | 2021.06.03 |