劣质代码评析——《写给大家看的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()的含义很清晰,应该不用解释。这就是结构化程序设计所谓的“自顶向下”的魅力。

(未完待续)

posted @ 2013-07-12 16:56  garbageMan  阅读(1336)  评论(7编辑  收藏  举报