실전 프로젝트 2 : 숫자야구 숫자 야구를 구현해보자
이 장에서 다룰 내용 게임 개요 1 2 게임 구현 3 실행 결과
숫자 야구 01_게임 개요 2명의 player ( 1 유저, 1 컴퓨터) 로 구성 숫자를 정확하게 먼저 맞추는 사람이 이김 숫자가 맞고 위치까지 정확하면 S(스트라이크) 숫자는 맞고 위치가 틀린다면 B(볼) ‘O S O B’의 힌트를 상대방에게 제공하고, 서로의 숫자를 맞추는 게임.
고려 사항 02_게임 구현 Console로(텍스트 화면으로) 입출력을 표현한다. 매 턴마다 사용자로부터 정답을 입력 받는다. 정답의 구분은‘,’문자로 하면 될 것이다. 사용자와 Bot이 서로 번갈아 가며, 게임을 진행한다. 입력 받으면 즉시 결과를 화면으로 출력한다. 정확히 정답을 맞추면 메시지를 출력하고 게임을 종료한다.
[소스 설명 17-1] main함수 358 void main() 359 { 360 cout << "======================" << endl; 361 cout << "The game is setting..." << endl; 362 cout << "======================" << endl; 363 364 BaseBallGame* bbgame = new BaseBallGame(); 365 bbgame->setGame(); 366 bbgame->start(); 367 } 게임 셋팅 로고를 출력한다. 게임 자체를 의미하는 BaseBallGame 객체를 생성하고, 각자 정답을 입력하도록 setGame() 함수를 호출한 후, 정답이 입력되면 start() 함수를 호출해서 게임을 시작한다.
[소스 설명 17-2] 야구 게임 클래스 284 class BaseBallGame 285 { 286 287 private: 288 BallCount* ballcount; 289 Player* players[2]; 290 291 public: 292 BaseBallGame() 293 { 294 players[0] = new Human(); 295 players[1] = new Bot(); 296 ballcount = new BallCount(); 297 } 298 299 void setGame() 300 { 301 players[0]->setAnswer(); 302 players[1]->setAnswer(); 303 } 307 void start() 308 { … 생성자에서는 2명의 플레이어를 생성하는데, 하나는 사람이고, 다른 하나는 봇으로 생성을 한다. setGame 함수에서는 각 player에게 정답을 셋팅할 것을 지시한다. start 함수는 실제 게임을 진행하는 함수로서, 310행~312행에 게임의 진행을 알리고, 정답이 나올 때까지 각각의 플레이어에게 정답이라고 생각되는 답을 입력할 것을 요청하고(320행, 334행), 이를 실제 상대방의 정답과 비교함으로써(321행, 340행) 게임을 진행한다.
[소스 설명 17-3] 정답 클래스 addAnswer 함수는 플레이어들로부터 받은 031 class Answer 032 { 033 034 private: 035 Ball* mBalls; 036 int mIndex; 037 038 public: 039 Answer() 040 :mIndex(0) 041 { 042 mBalls = new Ball[MAX_BALL]; 043 } 044 045 bool addAnswer(int agAns) 046 { 047 for(int i = 0; i < mIndex; i++) 048 { 049 if (mBalls[i].getNumber() == agAns) return false; 050 } 051 052 if (mIndex < MAX_BALL) 053 { 054 mBalls[mIndex].setNumber(agAns); 055 mIndex++; 056 } 057 return true; 058 } 059 060 Ball* getAnswer() 061 { 062 return mBalls; 063 } 064 065 int getNumberofBalls() 066 { 067 return mIndex; 068 } 069 }; addAnswer 함수는 플레이어들로부터 받은 숫자를 우리의 정답, 즉 Ball로 하나씩 저장하 는 부분이다. 게임의 룰에 따라서 겹치는 숫자는 정답이 될 수 없기 때문에 그것을 체크하는 부분이다.
[소스 설명 17-4] 볼 클래스 009 class Ball 010 { 011 012 private: 013 int mNumber; 014 015 public: 016 Ball() 017 : mNumber(0) {}; 018 019 public: 020 int getNumber() 021 { 022 return mNumber; 023 } 024 void setNumber(int agNumber) 025 { 026 mNumber = agNumber; 027 } 028 029 }; 030
[소스 설명 17-5] 볼 카운트 클래스 - 1 126 class BallCount 127 { 128 129 private: 130 int mCountofStrike; 131 int mCountofBall; 132 133 public: 134 BallCount() 135 { 136 clear(); 137 } 138 139 bool is3Out() 140 { 141 return ( mCountofStrike == MAX_BALL ); 142 } 143 144 void clear() 145 { 146 mCountofBall = 0; 147 mCountofStrike = 0; 148 } i3Out 함수는 점수를 계산했을 때, 3 스트라이크인지를 검사하는 루틴이다.
[소스 설명 17-5] 볼 카운트 클래스 - 2 149 150 void checkResult(Player* agPlayer, Answer* agAttacker, Answer* agDefender) 151 { 152 clear(); 153 for(int i = 0; i < MAX_BALL; i++) 154 { 155 if (agAttacker->getAnswer()[i].getNumber() == agDefender-> getAnswer()[i].getNumber()) 156 mCountofStrike++; 157 else 158 { 159 for(int j = 0; j < MAX_BALL; j++) 160 { 161 162 if (j != i && agAttacker->getAnswer()[i].getNumber() == agDefender-> getAnswer()[j].getNumber()) 163 mCountofBall++; 164 } 165 } 166 } 167 } 168 i3Out checkResult 함수가 바로 예비 정답과 실제 정답들을 비교해서 Strike가 몇 개고, Ball이몇 개인지를 계산해 주는 함수다.
[소스 설명 17-6] 사용자 클래스 - 1 237 class Human : public Player 238 { 239 242 : Player("Human") 243 {} 244 245 void setAnswer() 246 { 247 Player::setAnswer(getGuessAnswer()); 248 } 249 250 Answer* getGuessAnswer() 251 { 252 253 char oneline[50]; 254 string oneNumber; 255 char* token; 256 char seps[] = ", "; 257 Answer* answer = new Answer(); 258 setAnser 함수는 사용자에게서 답을 입력받아, 플레이어 클래스의 검증을 거쳐 플레이어 클래스에 답을 저장하는 루틴이다. getGuessAnswer 함수는 필수 함수로서, 사용자에게서 직접 입력을 받아 입력받은 숫자들로 답(answer)을 구성하는 역할을 한다.
[소스 설명 17-6] 사용자 클래스 - 2 259 cout << "Insert the answer.. (ex. 1,3,5)" << endl; 260 cin >> oneline; 261 262 if ( strcmp(oneline, "cheat") == 0 ) 263 { 264 Bot::CheatOn(); 265 cout << "CHEAT MODE ON " << endl; 266 267 cout << "Insert the answer.. (ex. 1,3,5)" << endl; 268 cin >> oneline; 269 } 270 271 272 token = strtok(oneline, seps); 273 while(token != NULL) 274 { 275 answer->addAnswer(atoi(token)); 276 token = strtok(NULL, seps); 277 } 278 279 return answer; 280 } 281 }; 282 283 사용자 입력 때,‘cheat’을 입력하면, bot이 정한 답을 볼 수 있도록 bot 클래스에 CHEAT_MODE를ON 할 수 있게 한다. “1,3,5”식으로 입력 받은 사용자 입력을‘,’를 기준으로 하나의 숫자로 쪼개어 각각을 답 으로 만드는 부분이다.
[소스 설명 17-7] 봇 클래스 190 class Bot : public Player 191 { 192 private: 193 static bool isCheatMode; 194 195 public: 196 Bot() 197 :Player("Bot") 198 {} 199 200 void setAnswer() 201 { 202 Player::setAnswer(getGuessAnswer()); 203 } 204 205 Answer* getGuessAnswer() 206 { 207 Answer* answer = new Answer(); 208 209 srand((unsigned)time(NULL)); 210 211 for (int i = 0; i < 3; i++) 212 { 213 int temp = rand() % 10; 214 215 while(!(answer->addAnswer(temp))) 216 { 217 temp = rand() % 10; 218 } 219 220 if (isCheatMode) 사용자 입력 때,‘cheat’을 입력하면, bot이 정한 답을 볼 수 있도록 bot 클래스에 CHEAT_MODE를ON 할 수 있게 한다. getGuessAnswer 함수는 사용자처럼 입력을 직접 받을 수가 없으므로, 랜덤하게 값을 생성하여 답을 만드는 역할을 한다. 지금은 단순히 랜덤값을 만들지만, 혹시 지능을 좀더 높이 고 싶다면 이 함수를 수정하면 된다.
03_실행 결과 실행 결과
IT CookBook for Beginner, C++ 기초 17장 끝 www.themegallery.com Thank You ! IT CookBook for Beginner, C++ 기초 17장 끝