Essential C++ 第一章,猜数代码分析ch1.cpp

来源:互联网 发布:centos 7中文 编辑:程序博客网 时间:2024/06/14 18:03
 d
  1. /**************************************************
  2.  * Essential C++ -- Stanley Lippman
  3.  * Addison-Wesley 
  4.  * ISBN 0-201-48518-4
  5.  * homepage: www.objectwrite.com
  6.  * email: slippman@objectwrite.com
  7.  *************************************************/
  8. #include "ch1.h"
  9. pvec Fibonacci_gen_elems( int pos ) 
  10.     static vector<unsigned int> _elems;
  11.     if ( ! check_integrity( pos ))
  12.          return 0;
  13.     if ( _elems.empty() )
  14.        { _elems.push_back( 1 ); _elems.push_back( 1 ); }
  15.     if ( _elems.size() < pos )
  16.     {
  17.             int ix = _elems.size();
  18.             int n_2 = _elems[ ix-2 ], 
  19.                 n_1 = _elems[ ix-1 ];
  20.             int elem;
  21.             for ( ; ix < pos; ++ix ){
  22.                     elem = n_2 + n_1; 
  23.                     _elems.push_back( elem );
  24.                     n_2 = n_1; n_1 = elem;
  25.             }
  26.      }
  27.      return &_elems;
  28. }  
  29.    
  30. pvec Pell_gen_elems( int pos )    
  31.     static vector< unsigned int> _elems;
  32.     if ( ! check_integrity( pos ))
  33.          return 0;
  34.     if ( _elems.empty() )
  35.        {  _elems.push_back( 1 ); _elems.push_back( 2 ); }
  36.     if ( _elems.size() < pos )
  37.     {
  38.             int ix = _elems.size();
  39.             int n_2 = _elems[ ix-2 ], 
  40.                 n_1 = _elems[ ix-1 ];
  41.             int elem;
  42.             for ( ; ix < pos; ++ix ){
  43.                     elem = n_2 + 2 * n_1; 
  44.                     _elems.push_back( elem );
  45.                     n_2 = n_1; n_1 = elem;
  46.             }
  47.      }
  48.      return &_elems;
  49. }
  50.    
  51. pvec Lucas_gen_elems( int pos ) 
  52. {    
  53.     static vector<unsigned int> _elems;
  54.     if ( ! check_integrity( pos ))
  55.          return 0;
  56.     if ( _elems.empty() )
  57.        {  _elems.push_back( 1 ); _elems.push_back( 3 ); }
  58.     if ( _elems.size() < pos )
  59.     {
  60.             int ix = _elems.size();
  61.             int n_2 = _elems[ ix-2 ], 
  62.                 n_1 = _elems[ ix-1 ];
  63.             int elem;
  64.             for ( ; ix < pos; ++ix ){
  65.                     elem = n_2 +  n_1; 
  66.                     _elems.push_back( elem );
  67.                     n_2 = n_1; n_1 = elem;
  68.             }
  69.      }
  70.      return &_elems;
  71. }    
  72.    
  73. pvec Triangular_gen_elems( int pos ) 
  74. {
  75.     static vector<unsigned int> _elems;
  76.     if ( ! check_integrity( pos ))
  77.          return 0;
  78.     if ( _elems.size() < pos )
  79.     {
  80.         int ix = _elems.size() ? _elems.size()+1 : 1;
  81.         for ( ; ix <= pos; ++ix )
  82.               _elems.push_back( ix*(ix+1)/2 );
  83.     }
  84.     return &_elems;
  85. }
  86. pvec Square_gen_elems( int pos ) 
  87. {
  88.     static vector<unsigned int> _elems;
  89.     if ( ! check_integrity( pos ))
  90.          return 0;
  91.     if ( _elems.size() < pos )
  92.     {
  93.         int ix = _elems.size() ? _elems.size()+1 : 1;
  94.         for ( ; ix <= pos; ++ix )
  95.               _elems.push_back( ix*ix );
  96.     }
  97.     return &_elems;
  98. }   
  99.     
  100. pvec Pentagonal_gen_elems( int pos ) 
  101. {
  102.     static vector<unsigned int> _elems;
  103.     if ( ! check_integrity( pos ))
  104.          return 0;
  105.     if ( _elems.size() < pos )
  106.     {
  107.         int ix = _elems.size() ? _elems.size()+1 : 1;
  108.         for ( ; ix <= pos; ++ix )
  109.               _elems.push_back( ix*(3*ix-1)/2 );
  110.     }
  111.     return &_elems;
  112. }
  113. pfunc gen_elems[] = 
  114. { 0,
  115.   Fibonacci_gen_elems,
  116.   Pell_gen_elems,
  117.   Lucas_gen_elems,
  118.   Triangular_gen_elems,
  119.   Square_gen_elems,
  120.   Pentagonal_gen_elems
  121. };
  122. const char *name_seq[] = { "Invalid Sequence",
  123.    "Fibonacci""Pell""Lucas",
  124.    "Triangular""Square""Pentagonal"
  125. };
  126. int level_size[] = { 8, 8, 32, 128, 512 };
  127. const char* wrong_msg[] = {
  128.  "Oops! Nice guess but not quite it.",
  129.  "Hmm. Sorry. Wrong again.",
  130.  "Ah, this is harder than it looks, isn't it?",
  131.  "It must be getting pretty frustrating by now!"
  132. };
  133. void display_statistics( user_profile *puser )
  134. {
  135.     cout << "Game Statistics for " << puser->name << "/n/t"
  136.          << "# guesses: " << puser->guesses << "/n/t"
  137.          << "# correct: " << puser->correct << "/n/t"
  138.          << "% correct: " 
  139.          << (static_cast<float>( puser->correct ) / static_cast<float>( puser->guesses )) * 100 << endl;
  140. }
  141. bool greet_user( user_profile *puser )
  142. {
  143.       cout << "Hi. What's your name? ";
  144.       string nm;
  145.       cin >> nm;
  146.       if ( nm.empty() || nm[ 0 ] == ' ' ){
  147.            cout << "ok. I guess you don't want to play. See ya!/n";
  148.            return false;
  149.       }
  150.       cout << "Hi, " << nm
  151.            << " Would you like to play Guess the Sequence? (y/n) ";
  152.       char ch;
  153.       cin >> ch;
  154.       if ( ch != 'y' && ch != 'Y' ){
  155.            cout << "ok. I'm sorry you don't want to play./n";
  156.            return false;
  157.       }
  158.       cout << "/n/n" << "Hey, that's great, " << nm << "./n"
  159.            << "We'll start in just a moment./nIt/'s simple, really!/n"
  160.            << "I will print out two elements of a sequence/n"
  161.            << "You just answer with the element value that comes next!/n/n";
  162.       cout << "Oh, by the way, do you consider yourself a/n/t"
  163.            << "beginner     -- enter 1/n/t"
  164.            << "intermediate -- enter 2/n/t"
  165.            << "advanced     -- enter 3/n/t"
  166.            << "guru         -- enter 4/n/t" << endl;
  167.       int level;
  168.       cin >> level;
  169.       if ( level < 1 || level > 4) level = 4;
  170.       init_user( puser, nm, level );
  171.       return true;
  172. }
  173. void print_seq( user_profile *puser )
  174. {
  175.     for ( int i = 0; i < puser->cur_seq_vec->size(); ++i )
  176.           cout << (*puser->cur_seq_vec)[i] << ' ';
  177.     cout << endl;
  178. }
  179. void display_seq( user_profile *puser )
  180. {
  181.     pvec p = seq_vec( puser ); 
  182.     cout << "The first two elements of the series are: "
  183.          << (*p)[ puser->pos-3 ] << ", " << (*p)[ puser->pos-2 ] 
  184.          << "/nWhat is the next element? ";
  185. }
  186. void set_up_index( user_profile *puser )
  187. {
  188.     static string wherefrom( "set_up_index" );
  189.     // randomly pick a position within the sequence
  190.     puser->pos = rand() % ( level_size[ puser->level ] );
  191.     // position represents 
  192.     if ( puser->pos < 3 ) puser->pos += 3;
  193.     
  194.     set_seq_vec( puser, (*gen_elems[ puser->cur_seq ])( puser->pos ));
  195.     trace( wherefrom, "new position: ", puser->pos );
  196. }
  197. void reset_seq( user_profile *puser )
  198. {
  199.     static string wherefrom( "reset_seq" );
  200.     int new_seq = gen_seq_id( reinterpret_cast<unsigned int>( puser ));
  201.     if ( new_seq == puser->cur_seq )
  202.          new_seq = new_seq < ns_cnt ? new_seq+1 : 1;
  203.     puser->cur_seq = static_cast<num_sequence>( new_seq );
  204.     set_up_index( puser );
  205.     print_seq( puser );
  206.     trace( wherefrom, "new sequence: ", name_seq[ puser->cur_seq ]);
  207. }
  208. void init_user( user_profile *puser, const string& nm, int level )
  209. {
  210.     static string wherefrom( "init_user" );
  211.     puser->name = nm;
  212.     puser->guesses = 0;
  213.     puser->correct = 0;
  214.     puser->level = level;
  215.     reset_seq( puser );
  216.     trace( wherefrom, nm, puser->cur_seq, level );
  217. }   
  218. bool correct_guess( user_profile *puser, int guess )
  219. {
  220.     pvec p = seq_vec( puser ); 
  221.     if ( guess == (*p)[ puser->pos-1 ] )
  222.          return true;
  223.     return false;
  224. }
  225. void play_game( user_profile *puser )
  226. {
  227.     bool next_seq  = true;      // show next sequence?
  228.     bool go_for_it = true;      // user wants to guess?
  229.     bool got_it    = false;     // user guessed correctly?
  230.     int  num_tries;             // number of tries per sequence
  231.     while ( next_seq == true )
  232.     {
  233.         num_tries = 0;
  234.         display_seq( puser );
  235.         while (( got_it == false ) &&
  236.                ( go_for_it == true ))
  237.         {
  238.              unsigned int usr_guess;
  239.              cin >> usr_guess;
  240.               if ( correct_guess( puser, usr_guess ))
  241.               {
  242.                   bump_correct( puser );
  243.                   got_it = true;
  244.                   cout << "Hey, most excellent! /n/t"
  245.                        << usr_guess << " is element # "
  246.                        << puser->pos << " of the " 
  247.                        << name_seq[ puser->cur_seq ] << " sequence./n";
  248.               }
  249.               else 
  250.               {
  251.                   bump_guess( puser );
  252.                   cout << wrong_msg[ num_tries < ns_wrong_msg ? num_tries : ns_wrong_msg-1 ]
  253.                        << " Would you like to try again? (y/n) ";
  254.                   char usr_rsp;
  255.                   cin >> usr_rsp;
  256.  
  257.                   if ( usr_rsp == 'N' || usr_rsp == 'n' )
  258.                        go_for_it = false;
  259.                   else { ++num_tries; cout << "Your next guess? "; }
  260.               }
  261.         } 
  262.         cout << "Want to try another sequence? (y/n) ";
  263.         char try_again;
  264.         cin >> try_again;
  265.         if ( try_again == 'N' || try_again == 'n' )
  266.              next_seq = false;
  267.         else { got_it = false; reset_seq( puser ); }
  268.     }