2013-12-18 2 views
1

게임 프로그래밍에 대한 책에서 다음 연습을합니다.추측 동수 번호

사용자는 숫자를 생각한 다음 사용자가 피드백을 제공하면서 프로그램이 추측을 시도합니다.

이 바로 CPU가 높고 낮은 사이의 임의의 숫자를 선택할 수있게됩니다 해결하기 나의 방법 대신 번호를 찾을 수있는 빠른 방법의 (이전의 추측을 기반으로)

(사이 중간 숫자를 추측 높고 낮은). 따라서 작동하지만 CPU가 동일한 숫자를 여러 번 추측한다는 오류가 있습니다. 어디서 잘못 되었습니까? 어떻게 수정합니까?

enum statuses {NEUTRAL, HIGH, LOW}; 
      int status = NEUTRAL; 
      int cpuguess, high = 100, low = 1; 
      char winner, highorlow, playAgain; 

      do { 

       cout << "Guess My Number" << endl << endl; 

       cout << "Press Enter to Play !" << endl; 
       cin.ignore(); 
       cin.get(); 

       do { 
        cpuguess = getGuess(status, high, low); 

        cout << "Is your guess " << cpuguess << " ?" << endl; 
        cout << "(y/n)"; 
        cin >> winner; 
        winner = toupper(winner); 

        if(winner == 'N') 
        { 
        WrongInputHL: 
         cout << "Too HIGH or Too LOW ? O_O" << endl; 
         cout << "(h/l)"; 
         cin >> highorlow; 
         highorlow = toupper(highorlow); 
         if(highorlow == 'H') 
         { 
          status = HIGH; 
          high = cpuguess; 
         } 
         else if(highorlow == 'L') 
         { 
          status = LOW; 
          low = cpuguess; 
         } 
         else 
         { 
          goto WrongInputHL; 
         } 
        } 
       } while (winner == 'N'); 

       cout << "I won ! :D" << endl << endl; 

       cout << "Do you want to play again ?" << endl; 
       cout << "(y/n)" << endl; 
       cin >> playAgain; 
       playAgain = toupper(playAgain); 
      }while(playAgain == 'Y'); 

개선 할 다른 모든 조언도 환영합니다.

+6

우리는 추측 할 필요가 없도록'getGuess' 함수를 포함해야합니다. – Matt

+1

Re : '개선 할 수있는 다른 조언은 너무 환영합니다.': 더 많은 전문 지식을 얻을 때까지 goto를 사용하지 말라는 조언을드립니다. (그들은 일반적으로 눈살을 찌푸리고 많은 사람들이 전혀 사용하지 마십시오.) 그들은 종종 프로그램을 제대로 구성하지 않았고 논리가보다 명확하고 명확한 방법으로 윤곽을 잡을 수 있다는 지표를 사용합니다. – Warty

+0

omg gotos .... burn it –

답변

1

문제는 당신이 높고 낮은 끝을 설정하는 방법을 발견하지만,이 섹션 그것은 당신의 알고리즘의 기초처럼 보인다

   { 
       WrongInputHL: 
        cout << "Too HIGH or Too LOW ? O_O" << endl; 
        cout << "(h/l)"; 
        cin >> highorlow; 
        highorlow = toupper(highorlow); 
        if(highorlow == 'H') 
        { 
         status = HIGH; 
         high = cpuguess; 
        } 
        else if(highorlow == 'L') 
        { 
         status = LOW; 
         low = cpuguess; 
        } 

이진 검색이 될 것으로 보인다. 하이 엔드는 잠재적으로 선택할 수 있기 때문에 반복 될 수 있습니다.

이 시도 :

   WrongInputHL: 
        cout << "Too HIGH or Too LOW ? O_O" << endl; 
        cout << "(h/l)"; 
        cin >> highorlow; 
        highorlow = toupper(highorlow); 
        if(highorlow == 'H') 
        { 
         status = HIGH; 
         high = cpuguess-1; 
        } 
        else if(highorlow == 'L') 
        { 
         status = LOW; 
         low = cpuguess+1; 
        } 

이 방법을 수가 너무 높은 경우, 새로운 범위는 (저, cpuguess-1) 되고있는 동안 그것이 될 너무 낮은 있다면 (cpuguess + 1, 고) 컴퓨터가 이전에 선택한 번호는 무시됩니다.

희망이 있습니다. :)

0

다른 사람들이 프로그램의 논리에 도움이 될 것이라고 판단하므로 구조를 도와 드리겠습니다. 즉, 어떻게 프로그램을 논리적으로 설명했는지 그리고 어떻게하면 더 잘할 수 있을지 생각해보십시오. 실제로 여기서 코드를 실행하지는 않았습니다. 지금은 그렇게 할 수있는 환경이 없습니다.

코드를 자동 포맷하고 do-while 루프에서 간단한 while 루프로 마이그레이션하는 것으로 시작했습니다. 또한 변수 선언을 사용하는 곳으로 옮겼습니다. 실제 세계에서 일부 코딩 표준은 마지막 단계를 금지하지만, 프로그램의 가독성을 향상시키고 내 논리를 이해하는 데 도움이된다고 생각합니다.

enum statuses { NEUTRAL, HIGH, LOW }; 
int status = NEUTRAL; 
char input; 
int cpuguess, high = 100, low = 1; 
bool playing = true; // use booleans to represent true/false state, rather than characters 
while (playing) { // "playing" closer to declaration = arguably easier to read & find purpose 
    cout << "Guess My Number" << endl << endl; 
    cout << "Press Enter to Play !" << endl; 
    cin.ignore(); 
    cin.get(); 

    bool gameWon = false; 
    while (!gameWon) { 
     cpuguess = getGuess(status, high, low); 

     cout << "Is your guess " << cpuguess << " ?" << endl; 
     cout << "(y/n)"; 
     cin >> input; 
     gameWon = toupper(input) == 'Y'; 

     if (!gameWon) 
     { 
     status = NEUTRAL; 
     while (status == NEUTRAL) { 
      cout << "Too HIGH or Too LOW ? O_O" << endl; 
      cout << "(h/l)"; 
      cin >> input; 
      input = toupper(input); 
      if (input == 'H') { 
       status = HIGH; 
       high = cpuguess; 
      } else if (input == 'L') { 
       status = LOW; 
       low = cpuguess; 
      } 
     } 
     } 
    } 

    cout << "I won ! :D" << endl << endl; 
    cout << "Do you want to play again ?" << endl; 
    cout << "(y/n)" << endl; 
    cin >> input; 
    playing = toupper(input) == 'Y'; 
} 

- 프로그램에서

, 당신은 종종 사용자가 두 개의 답 중 하나를주고 싶다. 사실

과 비슷한 코드가 표시됩니다.
cout << "Is your guess " << cpuguess << " ?" << endl; 
cout << "(y/n)"; 
cin >> input; 
gameWon = toupper(input) == 'Y'; 

3 번! 아마도 getAnswer라는 새로운 함수를 도입하여 질문과 두 가지 가능한 답변 (예 : 'y'및 'n')을 얻고 사용자의 대답을 반환 할 수 있습니다. 또한 대문자 Y/N 옵션을 일관되게 인쇄하도록 선택했으며 '\ 0'을 사용자가 입력하지 않을 값으로 간주했습니다. 따라서 option1 또는 option2가 소문자이면 프로그램이 더 이상 제대로 작동하지 않습니다. getAnswer 함수의 시작 부분에 option1과 option2 isupper (c)를 확인하는 것과 같은 여러 가지 방법으로 처리 할 수 ​​있습니다. 여기서는 그렇게하지 않았습니다.

char getAnswer(const char * question, const char option1, const char option2); 

void main() { // or whatever entry-point signature you've used 
    enum statuses { NEUTRAL, HIGH, LOW }; 
    int status = NEUTRAL; 
    char input; 
    int cpuguess, high = 100, low = 1; 
    bool playing = true; // use booleans to represent true/false state, rather than characters 
    while (playing) { // "playing" closer to declaration = arguably easier to read & find purpose 
     cout << "Guess My Number" << endl << endl; 
     cout << "Press Enter to Play !" << endl; 
     cin.ignore(); 
     cin.get(); 

     bool gameWon = false; 
     while (!gameWon) { 
     cpuguess = getGuess(status, high, low); 

     stringstream ss; 
     ss << "Is your guess " << cpuguess << " ?"; 
     gameWon = getAnswer(ss.c_str(), 'Y', 'N') == 'Y'; 

     if (!gameWon) { 
      status = getAnswer("Too HIGH or Too LOW ? O_O", 'H', 'L') == 'H' ? HIGH : LOW; 
      if (status == HIGH) 
       high = cpuguess; 
      else 
       low = cpuguess; 
     } 
     } 

     cout << "I won ! :D" << endl << endl; 
     playing = getAnswer("Do you want to play again?", 'Y', 'N') == 'Y'; 
    } 
} 

char getAnswer(const char * question, const char option1, const char option2) { 
    char response = '\0'; 
    while (response != option1 && response != option2) { 
     cout << question << endl; 
     cout << "(" << option1 << "/" << option2 << ")" << endl; 
     cin >> response; 
     response = toupper(response); 
    } 
    return response; 
} 

신난다, 우리의 코드는 단지에서 많은 청소기를 보이지만, 우리는 여전히 논리적 조각으로 우리의 코드를 파손, 그래서 그 일을 시도 할 수 없다. 내가 당신의 콘솔 아웃풋을 외부 while 루프 밖으로 옮기고 '당신의 숫자'라고 '당신의 추측이다'라고 바꿨습니다. 이전에, 사용자가 다시 놀고 싶다고 말하면, 짜증나는 그 후에 enter를 눌러야했습니다!

enum class GuessStatus { NEUTRAL, HIGH, LOW }; // I elected to use c++11's 'enum class' 

// these are called forward declarations 
void runIntroduction(); 
void playGame(); 

// I elected to use const char * and const char here. They weren't necessary, though. 
char getAnswer(const char * question, const char option1, const char option2); 

void main() { // or whatever entry-point signature you've used 
    runIntroduction(); 

    bool playing = true; // use booleans to represent true/false state, rather than characters 
    while (playing) { // "playing" closer to declaration = arguably easier to read & find purpose 
     playGame(); 
     playing = getAnswer("Do you want to play again?", 'Y', 'N') == 'Y'; 
    } 
} 

void runIntroduction() { 
    cout << "Guess My Number" << endl << endl; 
    cout << "Press Enter to Play !" << endl; 
    cin.ignore(); 
    cin.get(); 
} 

void playGame() { 
    int guessHigh = 100, guessLow = 1; 
    GuessStatus status = GuessStatus::NEUTRAL; // I'd suggest having GuessState::INITIAL = NEUTRAL to improve readability. Either that, or throwing in a comment to describe why you use NEUTRAL. 
    bool gameWon = false; 
    while (!gameWon) { 
     int cpuguess = getGuess(status, high, low); 

     stringstream ss; 
     ss << "Is your number " << cpuguess << " ?"; 
     gameWon = getAnswer(ss.c_str(), 'Y', 'N') == 'Y'; 

     if (!gameWon) { 
     status = getAnswer("Too HIGH or Too LOW ? O_O", 'H', 'L') == 'H' ? GameStatus::HIGH : GameStatus::LOW; 
     if (status == GameStatus::HIGH) 
      high = cpuguess; 
     else // status == GameStatus::LOW 
      low = cpuguess; 
     } 
    } 
    cout << "I won ! :D" << endl << endl; 
} 

char getAnswer(const char * question, const char option1, const char option2) { 
    char response = '\0'; 
    while (response != option1 && response != option2) { 
     cout << question << endl; 
     cout << "(" << option1 << "/" << option2 << ")" << endl; 
     cin >> response; 
     response = toupper(response); 
    } 
    return response; 
} 

그게 전부입니다. 혼란스러운 점이 있다면 질문하십시오.

+0

마지막으로 전역 네임 스페이스를 오염시킬 때'using namespace std; '를 사용하는 것은 나쁜 습관으로 간주된다는 점에 유의해야합니다 (충돌하는 메소드 서명이있을 확률이 높아짐). 많은 개발자들은 대신 "std :: cout", "std :: endl"및 "std :: cin"을 입력합니다. – Warty

+0

나는 std :: cout을 입력했지만 C++로 첫 수업을 듣고 나서 사용하지 말라고했다. 그러나 저는 그렇게하는 것이 더 나은 실천이라고 읽는 것이 어딘가에 있다고 믿습니다. 답장을 보내 주셔서 감사합니다. 정말 깨끗한 일을했습니다. playing = getAnswer ("다시 재생 하시겠습니까?", 'Y', 'N') == 'Y'; 함수가 bool 값인 경우 함수가 char 만 반환하면 루프를 끝내는 방법을 알 수 있습니까? 죄송합니다.이 사이트에서 아직 텍스트 편집 방법을 모르겠습니다. lol – ericjets

+0

'=='부분을 확인하십시오. 이 함수는 응답을 얻고 응답이 "Y"와 같은지 여부에 "재생"을 설정합니다. 대답이''Y ''이면, 재생은 참으로 설정됩니다 (''Y '=='Y ''). 그렇지 않으면, 재생은 false로 설정됩니다 (''Y '! ='N''). while 루프의 맨 아래에 도달하면 프로그램은 while (condition)에서 조건을 검사하여 다른 본문 반복을 실행할지를 결정합니다. – Warty