【问题标题】:Suggestions/improvements on my simple Blackjack program对我的简单二十一点计划的建议/改进
【发布时间】:2020-04-20 08:55:47
【问题描述】:

我正努力在下学期的课堂上抢占先机,所以我制作了这个基本版本的 Blackjack 来开始了解 C 的基础知识,我希望你有任何想法可以帮助我更好地理解 C 和它的正常编码实践。

C 中的很多东西对我来说都是新的,因为我有 JAVA 的背景,所以如果我在函数声明、使用指针时犯了错误,或者我正在考虑如何解决问题不正确,应该以完全不同的方式做事,请告诉我。

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

const int handSize = 2;

int randCard(int *isAce);

int sumCards(int cards[], int *hasAce[2]);

int main() {
    srand(time(NULL));

    int playGame = 0;

    int dealerIsAce[handSize];
    int *dealerAcePointers[handSize];
    int playerIsAce[handSize];
    int *playerAcePointers[handSize];

    for (int i = 0; i < handSize; i++) {
        dealerIsAce[i] = 0;
        playerIsAce[i] = 0;

        dealerAcePointers[i] = &dealerIsAce[0];
        playerAcePointers[i] = &playerIsAce[0];
    }

    int dealerCards[] = {randCard(dealerAcePointers[0]), randCard(dealerAcePointers[1])};
    int playerCards[] = {randCard(playerAcePointers[0]), randCard(playerAcePointers[1])};

    int dealerSum;
    int playerSum;
    do {
        printf("The dealer:\n? + %d\n\n", dealerCards[1]);

        dealerSum = sumCards(dealerCards, dealerAcePointers);
        if (dealerSum > 17) {
            dealerCards[0] = dealerSum;
            dealerCards[1] = randCard(dealerAcePointers[1]);
        }

        playerSum = sumCards(playerCards, playerAcePointers);
        printf("You:\n%d + %d = %d", playerCards[0], playerCards[1], playerSum);
        if (playerSum > 21) {
            printf(" BUSTED");
            playGame = 1;
        } else {
            printf("\nWould you like to \"hit\" or \"stand\"?\n");
        }

        if (playGame == 0) {
            char stream[10];
            if (strcmp(gets(stream), "hit") == 0) {
                playerCards[0] = playerSum;
                playerCards[1] = randCard(playerAcePointers[1]);
            } else {
                playGame = 1;
            }
        }
    } while (playGame == 0);

    if (playerSum > 21) {
        if (dealerSum > 21) {
            printf("\nTie!");
        } else {
            printf("\nDealer Wins!");
        }
    } else {
        if (playerSum > dealerSum) {
            printf("\nPlayer Wins!");
        } else if (playerSum == dealerSum) {
            printf("\nTie!");
        } else if (playerSum < dealerSum) {
            printf("\nDealer Wins!");
        }
    }
    return 0;
}

int randCard(int *isAce) {
    int card = rand() % 13 + 2;
    if (card > 11) {
        card = 10;
    } else if (card == 11) {
        *isAce = 1;
    }
    return card;
}

int sumCards(int cards[], int *hasAce[2]) {
    int sum = cards[0] + cards[1];
    if (sum > 21 && *hasAce[0] == 1) {
        sum -= 10;
        *hasAce[0] = *hasAce[1];
        if (*hasAce[1] == 1) {
            *hasAce = 0;
        }
    }
    return sum;
}

【问题讨论】:

  • 你好。最好尝试其他社区来解决此类问题,例如 [codereview](codereview.stackexchange.com/)。

标签: c blackjack


【解决方案1】:

正如评论者所提到的,这可能会更好地在其他地方提出,但无论如何我都会提供一些意见。以上都是观点,我说的大家可能会不同意。

顺便说一句,我完全无视二十一点的规则,并假设你所有的逻辑都是正确的。

首先,代码中没有任何 cmets。你提到这是为了一堂课,因此评论更加重要,因为一些穷人必须破译其中的大量内容才能弄清楚他们做了什么。 (顺便说一句,注释代码很重要,我总是使用“我会在几个月内弄清楚它的作用”的方法)

main() 中有这么多东西是不寻常的。我个人会将其分解为不同的功能。然后你也可以考虑将它放在一个单独的文件中,并带有一个用于函数声明的头文件。

handSize 被用作常量,您可以将其设为预处理器宏:#define HAND_SIZE 2

do-while 循环可以替换为while(true) 循环,然后在完成后使用“break”关键字进行转义(您当前正在设置playGame = 1。这还有一个优点是没有if(playGame == 0) 条件。此外,在 C 中,布尔变量为 1 表示真,0 表示假,所以当你完成循环。这种情况的特殊之处在于您实际上是想跳出,而不是运行到循环的末尾。

gets() 出于安全原因在 C11 中被删除 (Implicit declaration of 'gets')

关于更完整的节目点。这些更加主观,而且主要是我解决问题的方法:

我个人会让dealerCards 和 playerCards 足够大以容纳最大可能的牌数(我认为在二十一点中是5?)并将它们初始化为0。目前您正在将当前牌的总和分配给第一个元素dealerCards 数组的值,这意味着这些值不是实际的卡片。

我不会使用单独的数组来跟踪卡片是否是 ace,而是为 {EMPTY_SLOT, ACE, TWO, ..., JACK, QUEEN, KING} 创建一个枚举,然后将其存储在我的 Cards 数组中。然后randCard 可以只返回枚举的一个成员,并且不带任何参数,sumCards 只是遍历数组并对其求和。这也意味着您可以向他们显示用户的实际手,而不仅仅是总数。

出于参考目的,我已将您的代码修改为我将如何操作。逻辑可能并不完美(或与二十一点完全相同的版本),但这是我为“C 语言程序二十一点”作业提交的那种东西。注:这也可以通过更多的 cmets 来实现,尤其是顶部的一个块,用于解释一般结构是什么。

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

#define HAND_SIZE 5

typedef enum
{
  // Technically I didn't need to set the values, as they are the defaults but
  // it's good to be explicit when you're using the order for something.
  EMPTY = 0,
  ACE = 1,
  TWO = 2,
  THREE,
  FOUR,
  FIVE,
  SIX,
  SEVEN,
  EIGHT,
  NINE,
  TEN,
  JACK,
  QUEEN,
  KING
} card_t; // Types you typedef generally end _t as a convention.


// These should be in a separate header, but I'm keeping this in 1 file for StackOverflow
card_t randCard();
int sumCards(card_t cards[]);
void play();

int main()
{
    srand(time(NULL));

    play();

    return 0;
}

card_t randCard()
{
    int card = rand() % 13 + 1;
    return (card_t)card;
}

int sumCards(card_t cards[])
{
  int total = 0;
  int num_aces = 0;

  for (int i = 0; i < HAND_SIZE; i++) {
    switch(cards[i]) {
      case ACE:
        num_aces++;
        total += 11;
        break;
      case JACK:
      case QUEEN:
      case KING:
        total += 10;
        break;
      default:
        total += (int)cards[i]; // Relying here on the fact that the cards are in the correct order.
        break;
    }
  }

  while (num_aces > 0 && total > 10) {
    total -= 10;
    num_aces--;
  }

  return total;
}

void play()
{
  card_t playerCards[HAND_SIZE];
  card_t dealerCards[HAND_SIZE];
  card_t dealerKnown[HAND_SIZE]; // Equivalent to dealer cards, but with first 2 elements blank

  for (int i = 0; i < HAND_SIZE; i++) {
    playerCards[i] = EMPTY;
    dealerCards[i] = EMPTY;
    dealerKnown[i] = EMPTY;
  }

  playerCards[0] = randCard();
  playerCards[1] = randCard();
  dealerCards[0] = randCard();
  dealerCards[1] = randCard();

  int num_cards = 2;

  while(num_cards <= HAND_SIZE) {
    printf("The dealer: ? + %d\n\n", sumCards(dealerKnown));

    if (sumCards(dealerCards) > 17) {
      dealerCards[num_cards] = randCard();
    }

    int playerSum = sumCards(playerCards);
    printf("Your total: %d\n", playerSum);
    if (playerSum > 21) {
      printf("BUSTED\n");
      break;
    } else {
      printf("Would you like to \"hit\" or \"stand\"?\n");
    }

    char stream[10];
    if (strcmp(fgets(stream, sizeof(stream), stdin), "hit\n") != 0) {
      break;
    }

    playerCards[num_cards] = randCard();

    num_cards++;
  }

  printf("\n"); // Printing the new line separately rather than at the beginning of all the strings below

  int playerSum = sumCards(playerCards);
  int dealerSum = sumCards(dealerCards);

  if (playerSum > 21) {
    if (dealerSum > 21) {
      printf("Tie!");
    } else {
      printf("Dealer Wins!");
    }
  } else {
    if (playerSum > dealerSum) {
      printf("Player Wins!");
    } else if (playerSum == dealerSum) {
      printf("Tie!");
    } else if (playerSum < dealerSum) {
      printf("Dealer Wins!");
    }
  }

  printf("\n");
}

【讨论】:

    猜你喜欢
    • 2012-01-03
    • 2013-10-07
    • 2011-02-02
    • 1970-01-01
    • 2018-09-10
    • 2012-03-15
    • 2014-03-26
    • 2016-12-29
    • 1970-01-01
    相关资源
    最近更新 更多