You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

我的C语言纸牌游戏程序获胜计数错误,是什么原因导致的?

纸牌游戏compareCards判定逻辑异常问题修复

问题描述

我开发了一款对比两名玩家手牌、按指定规则判定每轮胜负的纸牌游戏,胜负判定逻辑封装在compareCards函数中,函数返回true代表玩家1本轮获胜,返回false代表玩家2本轮获胜。我在游戏运行函数的循环内调用该函数,循环次数与每名玩家的发牌数量一致。但目前compareCards函数存在异常,部分轮次无法匹配判定条件,最终游戏结束时两名玩家的获胜计数结果错误,我尝试调整多处条件判断逻辑均未定位到问题。

compareCards函数说明:看似随机的轮次会触发函数末尾的打印语句,说明判定逻辑漏过了所有预设条件分支,对应代码如下:

bool compareCards(char *card1, char *card2)
{
    char card1Face = card1[0];
    char card2Face = card2[0];

    //if card1 is A/K/Q/J and card2 is num
    if ((card1Face >= 'A' && card1Face <= 'Z') && !(card2Face >= 'A' && card2Face <= 'Z'))
    {
        return true;
    }
    //if card1 is num and card2 is A/K/Q/J
    else if (!(card1Face >= 'A' && card1Face <= 'Z') && (card2Face >= 'A' && card2Face <= 'Z'))
    {
        return false;
    }

    //if card1 and card2 both A/K/Q/J
    else if ((card1Face >= 'A' && card1Face <= 'Z') && (card2Face >= 'A' && card2Face <= 'Z'))
    {
        //test for A
        if (card1Face == 'A' && card2Face != 'A')
        {
            return true;
        }
        else if (card1Face != 'A' && card2Face == 'A')
        {
            return false;
        }
        //test for K
        if (card1Face == 'K' && card2Face != 'K')
        {
            return true;
        }
        else if (card1Face != 'K' && card2Face == 'K')
        {
            return false;
        }
        //test for Q
        if (card1Face == 'Q' && card2Face != 'Q')
        {
            return true;
        }
        else if (card1Face != 'Q' && card2Face == 'Q')
        {
            return false;
        }
        //test for J
        if (card1Face == 'J' && card2Face != 'J')
        {
            return true;
        }
        else if (card1Face != 'J' && card2Face == 'J')
        {
            return false;
        }
    } //end cards are face cards

    //If card1 and card2 are nums
    else if ((card1Face >= '1' && card1Face <= '9') && (card2Face >= '1' && card2Face <= '9'))
    {
        //if card1 is 10 and card2 is not
        if (card1Face == '1' && card2Face != '1')
        {
            return true;
        }
        //if card2 is 10 and card1 is not
        else if (card1Face != '1' && card2Face == '1')
        {
            return false;
        }
        //if card1 higher than card2
        else if (card1Face > card2Face)
        {
            return true;
        }
        //if card1 lower than card2
        else if (card1Face < card2Face)
        {
            return false;
        }
    } //end cards are nums

    //if card1 and card2 same face value
    else if (card1Face == card2Face)
    {
        char card1Suit = card1[strlen(card1) - 1];
        char card2Suit = card2[strlen(card2) - 1];

        //test for spade
        if (card1Suit == 'S')
        {
            return true;
        }
        else if (card2Suit == 'S')
        {
            return false;
        }
        //test for Hearts
        if (card1Suit == 'H')
        {
            return true;
        }
        else if (card2Suit == 'H')
        {
            return false;
        }
        //test for Diamonds
        if (card1Suit == 'D')
        {
            return true;
        }
        else if (card2Suit == 'D')
        {
            return false;
        }
        //test for Clubs
        if (card1Suit == 'C')
        {
            return true;
        }
        else if (card2Suit == 'C')
        {
            return false;
        }
    }
    printf("IF THIS PRINTS UH OH");
    return EXIT_SUCCESS;
}

游戏主逻辑playGame函数代码如下:

void playGame(void)
{
    srand(time(NULL));

    //initialize deck
    char *(*deck)[13] = initializeDeck();
    deck = shuffleDeck(deck);

    bool quit = false;

    while (1)
    {
        printHeaderDeal();

        //user input loop
        while (1)
        {
            fflush(stdin);
            char choice = getchar();

            //if enter to deal
            if (choice == '\n')
            {
                break;
            }
            //if q to quit
            else if (choice == 'q' || choice == 'Q')
            {
                printf("You chose to quit\n");
                quit = true;
                break;
            }
            //handling wrong input
            else
            {
                printf("Incorrect choice! Please choose ENTER to deal or q to quit. \n");
                scanf("%*[^\n]%*c");
            }
        } //end user input

        //if quit selected break from loop
        if (quit == true)
        {
            break;
        }

        int numCardsToDeal;

        //user selects number of cards to deal
        while (1)
        {
            printf("How many cards would you like to deal? 2-20\n");

            scanf(" %d", &numCardsToDeal);
            scanf("%*[^\n]");

            //set range = even number between 2-20
            if (numCardsToDeal >= 2 && numCardsToDeal <= 20)
            {
                if (numCardsToDeal % 2 == 1)
                {
                    printf("Players must have same amount of cards in hand. Pick an even amount to deal.\n");
                }
                else
                {
                    break;
                }
            }
            else
            {
                printf("Incorrect selection.\n");
            }
        }//end num to deal selection and validation

        //call deal cards and subtract the return value from the remaining card total
        cardsRemaining -= dealCards(deck, numCardsToDeal);

        bool result;

打印玩家手牌、调用比较函数、按轮次统计获胜次数的逻辑代码:

int length1 = sizeof(player1Hand)/sizeof(player1Hand[0]);
    printf("\n\n");
    printf("Player 1 hand: ");
    for(int i = 0; i < length1; i++)
    {
        printf("[%s]", player1Hand[i]);
    }
    printf("\n\n");

    int length2 = sizeof(player2Hand)/sizeof(player2Hand[0]);
    printf("Player 2 hand: ");
    for(int i = 0; i < length2; i++)
    {
        printf("[%s]", player2Hand[i]);
    }
    printf("\n\n");

    //loop through player hands based on num of dealt cards, call compareCards on each iteration and store results of each comparison
    for (int i = 0; i < (numCardsToDeal / 2); i++)
    {
        result = compareCards(player1Hand[i], player2Hand[i]);

        if (result == true)
        {
            player1Wins++;
        }
        else if (result == false)
        {
            player2Wins++;
        }
    }

    //if run out of cards end game
    if (cardsRemaining == 0)
    {
        printf("No more cards remaining in deck. Game over.\n\n");
        break;
    }

} //end game

printf("Total wins for player 1: %d\n", player1Wins);
printf("Total wins for player 2: %d\n", player2Wins);
free(deck);

问题根因

1. 判定分支覆盖不全

  • 当两张字母牌为A/K/Q/J以外的大写字母且面值不等时,字母判断块内无匹配分支,也不会进入后续同面值判断分支,直接漏到函数末尾
  • 当牌面值字符不在A-Z或1-9范围内时,也会触发漏判
  • 若花色为小写字母(如s/h等),同面值的花色判断分支也会全部漏过

2. 异常分支返回值错误

触发漏判时函数返回EXIT_SUCCESS,该宏定义值为0等价于false,会被主逻辑判定为玩家2获胜,直接导致胜场计数错误

3. 主逻辑潜在问题

  • fflush(stdin)属于C标准未定义行为,不同编译器实现效果不稳定,可能导致输入逻辑异常
  • 若player1Hand/player2Hand为动态分配的指针数组,sizeof计算的长度是指针本身大小而非数组元素个数,会导致打印手牌时出现乱码

修复方案

1. 完善compareCards函数逻辑

  • 字母牌判断块兜底:两张都是合法字母牌(A/K/Q/J)且不等时,按A>K>Q>J规则直接比较返回
  • 花色判断统一转为大写,兼容小写输入
  • 函数末尾添加兜底返回逻辑,覆盖所有边缘场景
  • 替换异常分支的EXIT_SUCCESS为符合规则的bool返回值

2. 修复主逻辑问题

  • 替换fflush(stdin)为scanf("%*[^\n]%*c")清空输入缓冲区
  • 打印手牌时用numCardsToDeal/2作为循环长度,替代sizeof计算的结果

内容的提问来源于stack exchange,提问作者chessfordays

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:15:09