zoukankan      html  css  js  c++  java
  • 劣质代码评析——《写给大家看的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("
    ");
    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("
    Play 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!
    
    ",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
    ","Jack");
    135.                 points[ACELOW] += 10;
    136.                 points[ACEHIGH] += 10;
    137.                 break;
    138.       case(12): printf("%s
    ","Queen");
    139.                 points[ACELOW] += 10;
    140.                 points[ACEHIGH] += 10;
    141.                 break;
    142.       case(13): printf("%s
    ","King");
    143.                 points[ACELOW] += 10;
    144.                 points[ACEHIGH] += 10;
    145.                 break;
    146.       default : points[ACELOW] += cardDrawn;
    147.                 if(cardDrawn==1)
    148.                 { 
    149.                    printf("%s
    ","Ace");
    150.                    points[ACEHIGH]+= 11;
    151.                 }
    152.                 else
    153.                 {  
    154.                   points[ACEHIGH]+=cardDrawn;
    155.                   printf("%d
    ",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
    
    ", total[PLAYER]);
    176.    }
    177.    else
    178.    {
    179.        printf("The house stands with a total of %d
    
    ", 
    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.
    ");
    190.        return ;
    191.    }
    192.    if ( (total[DEALER] > 21) && (total[PLAYER] > 21) )
    193.    { 
    194.       printf("%s", "Nobody wins.
    ");
    195.       return ; 
    196.    }
    197.    if ((total[DEALER] >= total[PLAYER])&& (total[DEALER] < 21))
    198.    { 
    199.       printf("The house wins.
    ");
    200.       return ; 
    201.    }
    202.    if ((total[PLAYER] > 21)&& (total[DEALER] < 21))
    203.    { 
    204.       printf("The house wins.
    ");
    205.       return ; 
    206.    }
    207.    printf("%s%c","You win!
    ",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("
    ");
    226.         i++; 
    227.    }
    228.    printf("
    
    *Step right up to the Blackjack tables*
    
    ");
    229.    return ;
    230. }
    View Code

      首先来看main()函数。

    31.    int numCards;
    32.    int cards[52],playerPoints[2],dealerPoints[2],total[2];
    33.    char ans;

      31.行和32.行是这个程序所处理的基本数据对象,相比之下,33.行定义的变量ans则比蚂蚁(ant)还渺小,比鸡肋还无聊,后面会谈到原因。
      main()函数主要说了一句话(另一句是老生常谈的return 0;),是一句do-while语句:

    35.    do 
    36.    { 
            /*……*/
    62.       ans = getAns("
    Play again(Y/N)?");  
    63.    }
    64.    while(ans=='Y');

      它想实现的意图是在一局游戏结束后,由用户选择结束程序还是继续下一轮游戏。但其实说这句话其实根本用不着那个ans变量,代码可以更简洁地写为:

    35.    do 
    36.    { 
            /*……*/
    63.    }
    64.    while( getAns("
    Play again(Y/N)?") == 'Y' ) ;

      解决一个问题可能多种方法,最简洁的那种才是正道。奥卡姆剃刀告诉我们,如无必要,勿增实体。简洁是C语言的一个重要的精神特质。
      现在不难看出33.行定义的变量是完全多余的了。

    (未完待续)

  • 相关阅读:
    关于TextField
    判断一个显示对象是否移除
    不争气的Discuz!NT 3.6和MVC3整合,主要实现同步登录和注册,登出。
    我的博客是英文的
    TFS不提供 Team Foundation 服务的解决办法。
    四 为提高entity framework 性能,要注意哪些事情.
    三 EF 和ado.net 的性能对比.
    一 关于大项目的经验总结
    在.net 中,ajax 如何调用本页数据源
    关于有序guid 的使用
  • 原文地址:https://www.cnblogs.com/pmer/p/3176350.html
Copyright © 2011-2022 走看看