劣质代码评析——《写给大家看的C语言书(第2版)》》附录B之21点程序(七)

劣质代码评析——《写给大家看的C语言书(第2版)》》附录B之21点程序(七)
0. #include <stdio.h>

1. #include <time.h>

2. #include <ctype.h>

3. #include <stdlib.h>

4. 5. #define BELL '\a'

6. #define DEALER 0

7. #define PLAYER 1

8. 9. #define ACELOW 0

10. #define ACEHIGH 1

11. 12. int askedForName = 0; 13. 14. void dispTitle(void); 15. void initCardsScreen(int cards[52],int playerPoints[2], 16. int dealerPoints[2], int total[2], 17. int *numCards); 18. int dealCard(int * numCards,int cards[52]); 19. void dispCard(int cardDrawn,int points[2]); 20. void totalIt(int points[2],int tatal[2],int who); 21. void dealerGetsCard(int *numCards,int cards[52], 22. int dealerPoints[2]); 23. void playerGetsCard(int *numCards,int cards[52], 24. int playerPoints[2]); 25. char getAns(char mesg[]); 26. void findWinner(int total[2]); 27. 28. main() 29. { 30.    int numCards; 31.    int cards[52],playerPoints[2],dealerPoints[2],total[2]; 32.    char ans; 33. 34.    do 

35. { 36.       initCardsScreen(cards,playerPoints,dealerPoints,total, &numCards); 37.       dealerGetsCard(&numCards,cards, dealerPoints); 38.       printf("\n"); 39.       playerGetsCard(&numCards,cards,playerPoints); 40.       playerGetsCard(&numCards,cards,playerPoints); 41.       do

42. { 43.          ans = getAns("Hit or stand (H/S)?"); 44.          if ( ans == 'H' ) 45. { 46.             playerGetsCard(&numCards,cards,playerPoints); 47. } 48. } 49.       while( ans != 'S' ); 50. 51. totalIt(playerPoints,total,PLAYER); 52.       do

53. { 54.          dealerGetsCard(&numCards,cards,dealerPoints); 55. } 56.       while (dealerPoints[ACEHIGH] < 17 ); 57. 58. totalIt(dealerPoints,total,DEALER); 59. findWinner(total); 60. 61.       ans = getAns("\nPlay again(Y/N)?"); 62. } 63.    while(ans=='Y'); 64. 65.    return ; 66. 67. } 68. 69. void initCardsScreen( int cards[52],int playerPoints[2], 70.                       int dealerPoints[2], int total[2], 71.                       int *numCards ) 72. { 73.    int sub,val = 1 ; 74.    char firstName[15]; 75.    *numCards=52; 76. 77.    for(sub=0;sub<=51;sub++) 78. { 79.       val = (val == 14) ? 1 : val; 80.       cards[sub] = val; 81.       val++; 82. } 83. 84.    for(sub=0;sub<=1;sub++) 85. { 86.       playerPoints[sub]=dealerPoints[sub]=total[sub]=0; 87. } 88. dispTitle(); 89. 90.    if (askedForName==0) 91. { 92.       printf("What is your first name?"); 93.       scanf(" %s",firstName); 94.       askedForName=1; 95.       printf("Ok, %s,get ready for casino action!\n\n",firstName); 96. getchar(); 97. } 98.    return; 99. } 100. 101. void playerGetsCard(int *numCards,int cards[52],int playerPoints[2]) 102. { 103.    int newCard; 104.    newCard = dealCard(numCards, cards); 105.    printf("You draw:"); 106. dispCard(newCard,playerPoints); 107. } 108. 109. 110. void dealerGetsCard(int *numCards,int cards[52],int dealerPoints[2]) 111. { 112.    int newCard; 113.    newCard = dealCard(numCards,cards); 114.    printf("The dealer draws:"); 115. dispCard(newCard,dealerPoints); 116. } 117. 118. int dealCard(int * numCards,int cards[52]) 119. { 120.    int cardDrawn,subDraw; 121. time_t t; 122.    srand(time(&t)); 123.    subDraw = (rand()%(*numCards)); 124.    cardDrawn = cards[subDraw]; 125.    cards[subDraw] = cards[*numCards -1]; 126.    (*numCards)-; 127.    return cardDrawn; 128. } 129. 130. void dispCard(int cardDrawn, int points[2]) 131. { 132.    switch(cardDrawn) 133. { 134.       case(11): printf("%s\n","Jack"); 135.                 points[ACELOW] += 10; 136.                 points[ACEHIGH] += 10; 137.                 break; 138.       case(12): printf("%s\n","Queen"); 139.                 points[ACELOW] += 10; 140.                 points[ACEHIGH] += 10; 141.                 break; 142.       case(13): printf("%s\n","King"); 143.                 points[ACELOW] += 10; 144.                 points[ACEHIGH] += 10; 145.                 break; 146.       default : points[ACELOW] += cardDrawn; 147.                 if(cardDrawn==1) 148. { 149.                    printf("%s\n","Ace"); 150.                    points[ACEHIGH]+= 11; 151. } 152.                 else

153. { 154.                   points[ACEHIGH]+=cardDrawn; 155.                   printf("%d\n",cardDrawn); 156. } 157. } 158.    return ; 159. } 160. 161. void totalIt(int points[2],int total[2],int who) 162. { 163.    if ( (points[ACELOW] == points[ACEHIGH]) 164.       ||(points[ACEHIGH] > 21 )) 165. { 166.      total[who] = points[ACELOW]; 167. } 168.    else

169. { 170.        total[who] = points[ACEHIGH]; 171. } 172. 173.    if (who == PLAYER ) 174. { 175.       printf("You have a total of %d\n\n", total[PLAYER]); 176. } 177.    else

178. { 179.        printf("The house stands with a total of %d\n\n", 180. total[DEALER]); 181. } 182.    return; 183. } 184. 185. void findWinner(int total[2]) 186. { 187.    if ( total[DEALER] ==  21 ) 188. { 189.        printf("The house wins.\n"); 190.        return ; 191. } 192.    if ( (total[DEALER] > 21) && (total[PLAYER] > 21) ) 193. { 194.       printf("%s", "Nobody wins.\n"); 195.       return ; 196. } 197.    if ((total[DEALER] >= total[PLAYER])&& (total[DEALER] < 21)) 198. { 199.       printf("The house wins.\n"); 200.       return ; 201. } 202.    if ((total[PLAYER] > 21)&& (total[DEALER] < 21)) 203. { 204.       printf("The house wins.\n"); 205.       return ; 206. } 207.    printf("%s%c","You win!\n",BELL); 208.    return; 209. } 210. 211. char getAns(char mesg[]) 212. { 213.    char ans; 214.    printf("%s", mesg); 215.    ans = getchar(); 216. getchar(); 217.    return toupper(ans); 218. } 219. 220. void dispTitle(void) 221. { 222.    int i = 0 ; 223.    while(i<25) 224. { 225.         printf("\n"); 226.         i++; 227. } 228.    printf("\n\n*Step right up to the Blackjack tables*\n\n"); 229.    return ; 230. }
View Code

  庄家抽牌结束后,就到了宣布胜负的时候。

26. void findWinner(int total[2]); 185. void findWinner(int total[2]) 186. { 187.    if ( total[DEALER] ==  21 ) 188. { 189.        printf("The house wins.\n"); 190.        return ; 191. } 192.    if ( (total[DEALER] > 21) && (total[PLAYER] > 21) ) 193. { 194.       printf("%s", "Nobody wins.\n"); 195.       return ; 196. } 197.    if ((total[DEALER] >= total[PLAYER])&& (total[DEALER] < 21)) 198. { 199.       printf("The house wins.\n"); 200.       return ; 201. } 202.    if ((total[PLAYER] > 21)&& (total[DEALER] < 21)) 203. { 204.       printf("The house wins.\n"); 205.       return ; 206. } 207.    printf("%s%c","You win!\n",BELL); 208.    return; 209. }

  这个函数写得比较乱,缺乏条理。改成下面的写法更清晰:

 

void findWinner(int total[]);



void findWinner(int total[])

{

   if ( total[DEALER] == 21 )

   {

       printf("The house wins.\n");

       return ;

   }

   

   if ( total[DEALER] > 21 )

   {

      if( total[PLAYER] > 21 )

      {

          printf("%s", "Nobody wins.\n");

          return ;

      }

   }

   if ( total[DEALER] < 21 )

   {

      if( (total[PLAYER] > 21) )

       {

            printf("The house wins.\n");

            return ;

       }

      if( (total[DEALER] >= total[PLAYER]) )

      {

          printf("The house wins.\n");

          return ;

      }

   }

   

   printf("%s%c","You win!\n",BELL);

   return;

}

 

【重构】
  从程序总体来看,无非是一个反复进行21点游戏的过程。

 

/* 21点游戏:对《写给大家看的C语言书》附录B之21点程序的重构 */



#include <stdio.h>



typedef 

   enum

   {

     NO ,

     YES,

   } 

YESNO ;   



YESNO again( void );

void game_21( void );



int main( void )

{

  

  do{

      game_21(); //一轮游戏      

  }while ( again() == YES );

  

  return 0;

}



void game_21( void )

{

   //待完成 

}



YESNO again( void )

{

   int c;

   

   puts("继续游戏(Y/N)?");

   c = getchar() ;

   

   while ( getchar() != '\n'){  //读完一行 

   } 

   

   if ( c=='y' || c == 'Y' ){

      return YES;

   }

   

   return NO;

}

 

   main()的含义很清晰,应该不用解释。这就是结构化程序设计所谓的“自顶向下”的魅力。

(未完待续)

你可能感兴趣的:(C语言)