Protótipo C# Blackjack

Aug 18 2020

Gostaria de algum feedback sobre meu código, sou novo em codificação com C #, mas tenho algum conhecimento em Lua e Python. Existe alguma coisa que eu preciso mudar/limpar para torná-lo mais simplificado?

using System;
using System.Linq;

class MainClass {
  public static void Main () {
    int[] cards = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10};

    Console.WriteLine("Welcome to Blackjack. Here are your draws.");
            
    Random drawCard = new Random();
    int draw1 = drawCard.Next(cards.Min(), cards.Max());
    int draw2 = drawCard.Next(cards.Min(), cards.Max());

    Console.WriteLine("You recieved a " + draw1 + " card!");
    Console.WriteLine("You recieved a " + draw2 + " card!");
            
    int sum1 = draw1 + draw2;

    if (sum1 == 21) //Blackjack Ending
    {
      Console.WriteLine("Congratulations! You got " + sum1 + "!");
    }


    else if (sum1 >= 11) //Choice of 3rd draw 
    {
      Console.WriteLine("Is " + sum1 + " enough?");
      bool cont1 = false;  

      drawChoice(cont1); //Call the draw choice function


      if (cont1 == true)
      {
        int draw3 = drawCard.Next(cards.Min(), cards.Max());
        Console.WriteLine("You drawed a " + draw3 + " card!");
        
        int sum2 = draw3 + sum1;
        Console.WriteLine("You have a total of " + sum2 + ".");

        if (sum2 > 21) Console.WriteLine("Game Over!");
      }


      else //NPC's turn starts
      {

      }
    }


    else //Player has less than 11 cards, auto draw
    {
      Console.WriteLine("You have a total of " + sum1 + ".");
      Console.WriteLine("You will be forced to draw another card.");

      int draw3 = drawCard.Next(cards.Min(), cards.Max());
      Console.WriteLine("You drawed a " + draw3 + " card!");

      int sum2 = draw3 + sum1;
      Console.WriteLine("You have a total of " + sum2 + ".");
    }
  }


  static void drawChoice(bool contChoice) //Function for player to choose whether to draw 
  {
    Console.WriteLine("Would you like to draw another card? Y/N");       
    string choice1 = Console.ReadLine();


    if (choice1 == "Y" || choice1 == "y")
    {
      contChoice = true;
      Console.WriteLine(contChoice);
    }


    else if (choice1 == "N" || choice1 == "n")
    {
      contChoice = false;
      Console.WriteLine(contChoice);
    }
  }
}

Respostas

6 JansthcirlU Aug 18 2020 at 22:18

Na verdade, eu mesmo fiz um projeto semelhante, é muito divertido!

1. Acompanhando as pontuações

A primeira coisa que notei é que você acompanha a soma dos valores para o jogador e presumivelmente também para o dealer, mas a pontuação de uma mão pode realmente mudar drasticamente durante o jogo.

1.1. Totais suaves no blackjack

O Blackjack tem esse conceito chamado soft totals, o que significa que a soma total pode ter um valor diferente dependendo se há um ás ou não. Por exemplo, se um jogador tem um ás (1) e um 7, isso realmente conta como 18 (11 + 7). Mas se esse mesmo jogador tirar mais 7, o total será 15 (1 + 7 + 7). O valor do ás muda conforme você compra mais cartas, então você terá mais facilidade em manter as pontuações se de alguma forma mantiver as cartas separadas umas das outras. Isso pode ser feito usando coleções.

1.2. Coleções

Coleções são coisas como arrays (que você já usou), listas e dicionários. Uma lista de números inteiros é um bom candidato para representar a coleção atual de cartas de um jogador (ou do dealer), porque elas podem mudar de tamanho sem reclamar. Além disso, as listas têm funções internas para obter a soma de todos os números dentro delas, os valores mínimo e máximo da lista e muito mais. Você pode usar essas funções integradas a seu favor, bem como o fato de sempre saber os números dentro da lista para determinar se o total de alguém é suave ou não.

2. Repetição do jogo

O jogo de blackjack é jogado com um número finito de cartas na vida real, mas é claro que no código você não precisa se preocupar com isso. Se um jogador (azarado) continuar comprando ases, eventualmente ainda atingirá 21 e encerrará a rodada. No entanto, como você não pode prever quando um jogador (ou o dealer) vai perder, você pode usar algo chamado loop de jogo. O loop de jogo para blackjack começa a executar toda a lógica do jogo uma vez que um jogador ou o dealer confirma que deseja tirar uma carta, e uma vez terminada a execução, ele pedirá para repetir se necessário.

2.1. Condições para escolher outro cartão

Você notará que o jogador tem muita liberdade no blackjack, ele pode continuar comprando cartas até chegar a 21 ou passar, ponto em que a rodada termina para eles. O dealer, no entanto, não tem essa liberdade. Você pode encontrar mais informações sobre isso online.

De qualquer forma, se você pensar sobre isso, tanto o jogador quanto o dealer, em algum momento, tomam a decisão de comprar ou não outra carta. Você faz uma verificação para "Y"ou "N"quando recebe uma entrada, o que faz sentido.

2.2. Traduzindo entrada de texto para trueoufalse

Seu DrawChoicemétodo altera a booldependendo da entrada do jogador, mas você também pode refatorar esse método para que ele receba a stringe retorne um bool. Dessa forma, você pode traduzir diretamente a entrada do usuário para true(sim, me dê outro cartão) ou false(não, não quero outro cartão). Pode ser algo assim:

// One option
public static bool DrawChoice(string input)
{
    if (input == "Y" || input == "y") // You could also use input.ToLower() == "y"
    {
        return true;
    }
    else // If it's not "Y" or "y", it's gonna be "N" or "n"
    {
        return false;
    }

//  else if (input == "N" || input == "n")
//  {
//      return false;
//  }
}

// Alternative one-liner
public static bool DrawChoice2(string input) => input.ToLower() == "y";

Voltando à ideia de um loop de jogo, agora você tem uma condição que determina se o loop de jogo continua ou não. Uma possível implementação seria esta:

string choice = Console.ReadLine();
while (DrawChoice(choice)) // No need to write "== true" or "== false"
{
    // Stuff that happens if a player or the dealer draws another card
    choice = Console.ReadLine() // Ask again once the game logic has executed
}
// Stuff that happens when the loop ends

2.3. Cartões de desenho

Blackjack é um jogo de cartas, portanto você estará comprando muitas cartas, seja para um jogador ou para o dealer. Se algo acontece com frequência no jogo, geralmente é uma boa ideia transformá-lo em um método para que você não precise escrever a mesma lógica em lugares diferentes.

Sua implementação atual desenha um valor aleatório entre o mínimo e o máximo de sua matriz de cartas. A partir da documentação, aprendemos o seguinte:

Next(Int32 minValue, Int32 maxValue)

Um inteiro com sinal de 32 bits maior ou igual a minValuee menor que maxValue; ou seja, o intervalo de valores de retorno inclui, minValue mas não maxValue . Se for minValueigual a maxValue, minValueé retornado.

Então, quando você escreve Next(1, 10)(de mínimo e máximo), você obterá no máximo um 9. Outro problema é que, mesmo se você corrigir a implementação para Next(1, 11), terá probabilidades iguais de obter qualquer valor de 1 a 10. Mas como há vários cartões no baralho que tem o valor de 10, eles devem aparecer com mais frequência do que as cartas que não são 10.

Felizmente, sua matriz já possui a distribuição correta de cartões, portanto, você pode gerar uma posição aleatória válida para obter o valor correspondente de sua matriz.

No final do dia, o que você terá será mais ou menos assim:

public static int DrawCard()
{
   int[] cards = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };
   int card;
   // Implement random draw here
   return card;
}

E então você pode até fazer algo assim para comprar cartas repetidamente:

// You could also use a list, which is more flexible
public static int[] DrawCard(int count)
{
    int[] drawn = new int[count];
    for (int i = 0; i < count; i++)
    {
        drawn[i] = DrawCard();
    }
    return drawn;
}

Espero que isto ajude! Boa sorte e divirta-se!

9 Heslacher Aug 18 2020 at 14:33

Apenas algumas observações para que você possa melhorar seu código:

int sum1 = draw1 + draw2;

if (sum1 == 21) //Blackjack Ending
{
  Console.WriteLine("Congratulations! You got " + sum1 + "!");
}

Isso nunca será verdade, porque

  • você não tem em nenhum lugar nas cartas um ás que significa ter um valor possível de onze.
  • o maxValuein Random.Next(int minValue, int maxValue)é o limite superior exclusivo do número aleatório retornado.

No void drawChoice(bool contChoice)método, o argumento contChoiceé um tipo de valor. Você não pode modificá-lo como você pensa. Depois de sair do método, independentemente de o usuário ter digitado y ou n, o valor de cont1ainda é false. Você deve alterar a assinatura do método para não ter argumentos, mas retornar um arquivo bool.

if (cont1 == true)  

porque cont1já é um bool, você não precisará compará -lo com um bool. Você pode simplesmente usá-lo como condição if (cont1)e se precisar verificar se uma variável bool falsevocê usaria if (!cont1).

3 rball Aug 19 2020 at 00:27

Não tenho certeza de como posso ser útil aqui, mas IMHO, você precisa ter uma revisão completa do código com alguém que fale com você sobre o código. Há um monte de coisas "erradas" aqui, mas, tendo dito isso, estou me perguntando qual é o seu objetivo com C # - você está apenas criando um script para aprender a sintaxe ou deseja entender melhor como arquitetar coisas em C #.

Se alguém me procurasse com isso em um ambiente profissional, a primeira coisa que eu diria: "Você precisa ser capaz de testar isso". Eu então falaria sobre TDD e realmente tentaria apontar como esse código é estruturado para fazer muito. Não há abstrações e tudo é muito processual. Cada classe deve fazer 1 coisa. Tenho certeza de que as pessoas discutirão comigo sobre esse ponto. De qualquer forma, o fato de você ter apenas 1 aula é ruim.

Além disso, apenas para "dicas rápidas de C # de 2 minutos". Eu usaria enumerações para as cartas, então ao invés de 10, 10, 10, eu teria 10, Valete, Dama, Ás. Em vez disso, use var. if (cont1 == true)é o mesmo que if(cont1). Use variáveis ​​com nomes melhores: Olhando apenas para cont1, não tenho ideia do que isso significa.

JansthcirlU também criou coleções. Olhando para este código, parece que você não os entende, então eu realmente me concentraria aqui também.

Continue codificando :)