我的C二十一点程序卡住

时间:2015-12-30 04:02:29

标签: c

#include<stdlib.h>  
#include<stdio.h>
#include<time.h>

#define CARD_MAX 52
typedef int Deck[CARD_MAX];
Deck deck;
int cardnumber = 0;
int playerwin = 0, dealerwin = 0, tie = 0;

int game();
void setupDeck(Deck deck);
void shuffleDeck(Deck deck);
void printCard(int card);
int pickCard(Deck deck, int cardnum);
void endProgram();
void playAgain();

main()
{
    char yn;

    srand(time(NULL));
    setupDeck(deck);
    shuffleDeck(deck);

    again:
    printf("Welcome! Do you wanna try your luck in a Blackjack Game? If so type 'y'.\n");
    printf("If not type 'n' to close the program: ");
    scanf_s("%c", &yn);
    getchar();

    if (yn == 'y')
        game();

    else if (yn == 'n')
    {
        printf("Looks like you aren't feeling lucky today! Comeback tomorrow!\n");
        system("pause");
    }
    else
    {
        printf("Unknown character! Try again!\n");
        goto again;
    }


}

int game()
{
    int card, cardvalue = 0, cardtype = 0, tcvp = 0, tcvd = 0;
    int aceflagp = 0, faceflagp = 0, aceflagd = 0, faceflagd = 0, bjp = 0, bjd = 0;
    int loopcounter;
    char hitorpass;

    system("cls");
    printf("Your cards:\n");
    for (loopcounter = 0; loopcounter < 2; loopcounter++)
    {
        card = pickCard(deck, cardnumber);
        cardnumber++;
        cardvalue = card % 13;
        cardtype = card / 13;
        printCard(cardvalue, cardtype);
        if (cardvalue == 1)
        {
            aceflagp++;
            cardvalue = 11;
        }
        else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
        {
            faceflagp = 1;
            cardvalue = 10;
        }
        else
            cardvalue = cardvalue;

        tcvp += cardvalue;
    }
    if (aceflagp == 1 && faceflagp == 1)
        bjp = 1;

    printf("Dealers cards:\n");

    card = pickCard(deck, cardnumber);
    cardnumber++;
    cardvalue = card % 13;
    cardtype = card / 13;
    printCard(cardvalue, cardtype);
    if (cardvalue == 1)
    {
        aceflagd++;
        cardvalue = 11;
    }
    else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
    {
        faceflagd = 1;
        cardvalue = 10;
    }
    else
        cardvalue = cardvalue;

    tcvd += cardvalue;

    card = pickCard(deck, cardnumber);
    cardnumber++;
    cardvalue = card % 13;
    cardtype = card / 13;
    if (cardvalue == 1)
    {
        aceflagd++;
        cardvalue = 11;
    }
    else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
    {
        faceflagd = 1;
        cardvalue = 10;
    }
    else
        cardvalue = cardvalue;

    tcvd += cardvalue;

    if (aceflagd == 1 && faceflagd == 1)
        bjd = 1;

    if (bjp == 1 && bjd == 1)
    {
        printf("Both sides has Blackjack! Tie!\n");
        tie++;
        playAgain();
    }
    else if (bjp == 1)
    {
        printf("Player Blackjack!\n");
        playerwin++;
        playAgain();
    }
    else if (bjd == 1)
    {
        printf("Dealer Blackjack!\n");
        dealerwin++;
        playAgain();
    }
    printf("Your card total is %d.\n", tcvp);
    again:
    printf("If you want to hit type 'h'. If you want to pass type 'p'");
    scanf_s("%c", &hitorpass);
    getchar();

    if (hitorpass == 'h')
    {
        card = pickCard(deck, cardnumber);
        cardnumber++;
        cardvalue = card % 13;
        cardtype = card / 13;
        printCard(cardvalue, cardtype);
        if (cardvalue == 1)
        {
            aceflagp++;
            cardvalue = 11;
        }
        else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
        {
            faceflagp = 1;
            cardvalue = 10;
        }
        else
            cardvalue = cardvalue;

        tcvp += cardvalue;
        if (tcvp > 21)
        {
            if (aceflagp > 0)
            {
                tcvp -= 10;
                aceflagp--;
                printf("Your card total is %d.\n", tcvp);
                goto again;
            }
            else
            {
                printf("Your hand busted. You lost!\n");
                dealerwin++;
                playAgain();
            }
        }
        else if (tcvp == 21)
        {
            printf("You have 21 in your hand can't hit more!\n");
            goto dealersturn;
        }
        else if (tcvp < 21)
        {
            printf("Your card total is %d.\n", tcvp);
            goto again;
        }

    }
    else if (hitorpass == 'p')
    {
    dealersturn:
        printf("Dealers turn:\n");
        if (tcvd < 17)
        {
            card = pickCard(deck, cardnumber);
            cardnumber++;
            cardvalue = card % 13;
            cardtype = card / 13;
            printCard(cardvalue, cardtype);
            if (cardvalue == 1)
            {
                aceflagd++;
                cardvalue = 11;
            }
            else if (cardvalue == 0 || cardvalue == 11 || cardvalue == 12)
            {
                faceflagd = 1;
                cardvalue = 10;
            }
            else
                cardvalue = cardvalue;

            tcvd += cardvalue;
            if (tcvd > 21)
            {
                if (aceflagd > 0)
                {
                    tcvd -= 10;
                    aceflagd--;
                    goto dealersturn;
                }
                else
                {
                    printf("Dealers has a total of %d. Dealers hand busted!\n", tcvd);
                    playerwin++;
                    playAgain();
                }
            }
            else if (tcvd < 17)
                goto dealersturn;
            else
            {
                if (tcvp > tcvd)
                {
                    printf("Player has %d, dealer has %d. Player won!", tcvp, tcvd);
                    playerwin++;
                    playAgain();
                }
                else if (tcvp == tcvd)
                {
                    printf("Both player and the dealer has %d. Tie!", tcvd);
                    tie++;
                    playAgain();
                }
                else
                {
                    printf("Player has %d, dealer has %d. Dealer won!", tcvp, tcvd);
                    dealerwin++;
                    playAgain();
                }
            }
        }
    }
    else
    {
        printf("Unknown character. Try again!");
        goto again;
    }

    system("pause");
}

void endProgram()
{
    printf("Thanks for playing my blackjack game! The results are:\n");
    printf("Player won %d times!\n", playerwin);
    printf("Dealer won %d times!\n", dealerwin);
    printf("There have been a tie %d times!\n", tie);
    system("pause");
}

void playAgain()
{
    char chardummy;
    again:
    printf("Would you like to play again? Type 'y' for Yes and 'n' for No.\n");
    scanf_s("%c", &chardummy);
    getchar();
    if (chardummy == 'y')
    {
        if (cardnumber >= 48)
        {
            printf("There is not enough card left in the deck!");
            endProgram();
        }
        else
            game();
    }
    else if (chardummy == 'n')
        endProgram();
    else
    {
        printf("Unknown character. Try again!");
        goto again;
    }
}

void setupDeck(Deck deck)
{
    int i;
    for (i = 0; i<CARD_MAX; i++)
    {
        deck[i] = i;
    }
}

void shuffleDeck(Deck deck)
{
    for (int i = 52 - 1; i >= 0; --i) {
        int r = rand() % (i + 1);
        int t = deck[i];
        deck[i] = deck[r];
        deck[r] = t;
    }
}

void printCard(int cardvalue, int cardtype)
{
    char cardtype2;


    if (cardtype == 0)
        cardtype2 = 'C';
    else if (cardtype == 1)
        cardtype2 = 'D';
    else if (cardtype == 2)
        cardtype2 = 'H';
    else if (cardtype == 3)
        cardtype2 = 'S';

    switch (cardvalue)
{
    case 0:
    {
        printf("*******\n");
        printf("*     *\n");
        printf("* %c   *\n", cardtype2);
        printf("*   K *\n", cardvalue);
        printf("*     *\n");
        printf("*******\n");
        break;
    }
    case 1:
    {
        printf("*******\n");
        printf("*     *\n");
        printf("* %c   *\n", cardtype2);
        printf("*   A *\n");
        printf("*     *\n");
        printf("*******\n");
        break;
    }
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
    {
        printf("*******\n");
        printf("*     *\n");
        printf("* %c   *\n", cardtype2);
        printf("*  %2d *\n", cardvalue);
        printf("*     *\n");
        printf("*******\n");
        break;
    }
    case 11:
    {
        printf("*******\n");
        printf("*     *\n");
        printf("* %c   *\n", cardtype2);
        printf("*   J *\n", cardvalue);
        printf("*     *\n");
        printf("*******\n");
        break;
    }
    case 12:
    {
        printf("*******\n");
        printf("*     *\n");
        printf("* %c   *\n", cardtype2);
        printf("*   Q *\n", cardvalue);
        printf("*     *\n");
        printf("*******\n");
        break;
    }
    }
}

int pickCard(Deck deck, int cardnum)
{
    if (cardnumber == 52)
    {
        printf("There is not enough cards left to complete the game!");
        endProgram();
    }
    else
        return deck[cardnum];

}

这是我的简单二十一点游戏的代码。由于某种原因经过几轮经销商转向不起作用。如果你能找到我不能的原因,我将不胜感激。并随时提供有关改进我的代码的提示。

2 个答案:

答案 0 :(得分:2)

您在代码中遇到以下问题,我可以从编译器警告/错误中看到。

  1. printCard的声明与其用法及其实施不符。将声明更改为:

    void printCard(int cardvalue, int cardtype);
    
  2. 明确返回main的返回类型。将其更改为:

    int main () ...
    
  3. 更改打印KJQ的行。在这些行中你不需要printf的额外参数。

    printf("*   K *\n");
    printf("*   J *\n");
    printf("*   Q *\n");
    
  4. 在上面,第一个是最重要的修复。通过这些更改,我能够毫无问题地运行您的程序。我的测试平台:Linux,gcc 4.8.4。

    提高警告级别,以便您可以检测此类警告/错误,并在将来的编程工作中修复它们。

答案 1 :(得分:0)

因为你问......: - )

除了R Sahu所说的......

最大的问题(挑战?)我注意到,我不知道你的endProgram()函数实际上是如何结束的&#39;任何东西。它调用系统(&#34;暂停&#34;)然后恢复:

void endProgram()
{
    printf("Thanks for playing my blackjack game! The results are:\n");
    printf("Player won %d times!\n", playerwin);
    printf("Dealer won %d times!\n", dealerwin);
    printf("There have been a tie %d times!\n", tie);
    system("pause);
}

这意味着pickCard()函数中的以下代码具有不可预测的行为:

int pickCard(Deck deck, int cardnum)
{
    if (cardnumber == 52)
    {
        printf("There is not enough cards left to complete the game!");
        endProgram(); // once we get here what do we return to the caller?
    }
    else
        return deck[cardnum];
}

&#34;不可预测&#34;我具体指的是:pickCard()将返回cardnumber = 52?

我怀疑 pickCard()将调用endProgram(),这是一个无效函数,除了返回之外什么都不做,然后pickCard将脱离if-else语句并且尝试向调用者返回一个整数,它可能会从调用堆栈中选择一些垃圾来发回,这可能(或可能不是)是有效的卡值。

事实证明,你在大约5个不同的地方打电话给pickCard(),有时是玩家,有时是经销商。

如果pickCard()返回 way 超出范围的值,该逻辑会发生什么?

因为你只在main()的开头调用一次shuffleDeck(),所以你最终会“耗尽”#c;&#39;甲板并获取从pickCard()返回的未定义卡值。

哪种适合你的症状&#34;它在一段时间后在经销商处破裂 ...&#34;。

所以...对于一般的清理......

我会把你在game()方法中拥有的大部分变量拿出来并使它们成为全局变量。

我会添加大量的打印语句进行调试,这样您就可以验证代码是否按照您的想法进行操作。

你对system()的调用对我来说是一个挑战:

system("cls");
system("pause");

由于您在Windows上开发,我理解您使用系统的原因(让我想起过去编写dos批处理文件的历史)。

但是......我会鼓励你放弃系统()调用并编写自己的输入&#34; helper&#34;处理scanf_s或任何你想要使用的函数。 也许这样的东西可以提示并返回用户输入的任何字符。

char prompt_and_read_char(char * msg);

我鼓励你在没有goto语句的情况下重写。

你确实在游戏()函数中尝试循环,让玩家画牌; for循环,所以奖励积分。

您的整体风格和用户互动目标是合理的,并建议您最终制作有趣的游戏。

游戏()中的代码有200多行代码,这使得它比阅读时更难。

我建议在game()函数中执行类似的操作:目标是将所有卡片绘制功能仅用于播放器或经销商。

// Global Variable definitions...
int gameInProcess = 0; // global, set to false.
int tcvp = -1; // obvious bad 
// note for global-var police: yeah, I know globals is not "good style".
// But cut our beginning programmer some slack here... this seems like the easiest way for
// them to get their game running.  (Think of it as a first step toward cleaning up the
// game() method if that helps any).

// prototypes here.

// main() here.
...etc...

int game() {
   gameInProcess = 1; // set to true.
   tcvp = 0;
   tcvd = 0;
   while( gameInProcess  ) {
      // add plenty of print statements so you see what is going on; you can clean
      //  them up later by searching on DEBUG.
      printf("DEBUG... game(): tcvp=%d tcvd=%d cardnumber=%d\n", tcvp, tcvd, cardnumber );
      game_playerDraws( ); // updates tcvp, may set gameInProcess to 0 if player win or busts.
      game_dealerDraws( ); // udpates tcvd, may set gameInProcess to 0 if dealer hits blackjack or goes bust.
      ...other functions for variations...
   }
   printf("game over, score: player=%d  dealer=%d\n", tcvp, tcvd );
   // add logic to decide winner.
   // return to caller, maybe let them decide if we'll have another game using the same deck.
}

game_playerDraws( ) {
   if( !gameInProcess ) {
      printf("game_playerDraws(): gameInProcess=%d, nothing to do.\n", gameInProcess );
      return;
   }
   // draw some cards, update globalcs if player wins or breaks.
}

game_dealerDraws( ) {
   ... do dealer-approriate things...
}

这样做的好处是,如果你放弃了牌组,你可以设置gameInProcess = 0;并且返回,一切都优雅地停止。

您可以添加一个选项以随机播放新牌组并开始另一场比赛。

但最大的好处是它会给你一个干净的方式来开始和结束每个游戏,这是你在当前版本的代码中缺少的东西。

祝你好运。你清楚地喜欢编程并且正在玩写作游戏。 坚持下去,我想你会学到很多东西。