C # прототип блэкджека

Aug 18 2020

Я хотел бы получить отзывы о моем коде, я новичок в программировании на C #, но у меня есть некоторые знания о Lua и Python. Есть ли что-нибудь, что мне нужно изменить / очистить, чтобы сделать его более простым?

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);
    }
  }
}

Ответы

6 JansthcirlU Aug 18 2020 at 22:18

Я сам сделал похожий проект, это действительно весело!

1. Отслеживание результатов

Первое, что я заметил, это то, что вы отслеживаете сумму значений для игрока и, предположительно, также для дилера, но на самом деле счет руки может резко измениться во время игры.

1.1. Мягкие тоталы в блэкджеке

В блэкджеке есть понятие « мягкие итоги», что означает, что общая сумма может иметь различное значение в зависимости от того, есть туз или нет. Например, если у игрока есть туз (1) и 7, это фактически считается как 18 (11 + 7). Но если тот же игрок вытянет еще 7, их сумма будет 15 (1 + 7 + 7). Ценность туза меняется по мере того, как вы берете больше карт, поэтому вам будет легче вести счет, если вы каким-то образом держите карты отдельно друг от друга. Это можно сделать с помощью коллекций.

1.2. Коллекции

Коллекции - это такие вещи, как массивы (которые вы уже использовали), списки и словари. Список целых чисел - хороший кандидат для представления текущей коллекции карт игрока (или дилера), потому что они могут изменять размер без жалоб. Более того, списки имеют встроенные функции для получения суммы всех чисел внутри них, минимального и максимального значений списка и многого другого. Вы можете использовать эти встроенные функции в своих интересах, а также тот факт, что вы всегда знаете числа внутри списка, чтобы определить, является ли чья-то общая сумма мягкой или нет.

2. Игровой цикл

В реальной жизни в блэкджек играют с ограниченным количеством карт, но, конечно, в коде вам не о чем беспокоиться. Если (не) удачливый игрок продолжает вытягивать тузов, он в конечном итоге все равно наберет 21 и закончит раунд. Однако, поскольку вы не можете предсказать, когда игрок (или крупье) проиграет, вы можете использовать так называемый игровой цикл. Игровой цикл для блэкджека начинает выполнение всей игровой логики, как только игрок или дилер подтверждает, что они хотят взять карту, и как только он завершится, он попросит повторить, если необходимо.

2.1. Условия выбора другой карты

Вы заметите, что игрок имеет большую свободу в блэкджеке, он может продолжать вытягивать карты, пока не наберет 21 или не перейдет, на этом раунд для них заканчивается. Однако у дилера такой свободы нет. Вы можете найти более подробную информацию в Интернете.

В любом случае, если подумать, и игрок, и дилер в какой-то момент принимают решение, брать или не брать другую карту. Вы проверяете наличие "Y"или "N"когда получаете ввод, что имеет смысл.

2.2. Перевод ввода текста на trueилиfalse

Ваш DrawChoiceметод изменяет a в boolзависимости от ввода игрока, но вы также можете реорганизовать этот метод, чтобы он получал stringи возвращал bool. Таким образом, вы можете напрямую перевести ввод пользователя в true(да, дайте мне еще одну карту) или false(нет, мне не нужна другая карта). Это могло выглядеть примерно так:

// 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";

Возвращаясь к идее игрового цикла, теперь у вас есть условие, которое определяет, будет ли игровой цикл продолжаться или нет. Одна возможная реализация была бы такой:

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. Карты для рисования

Блэкджек - карточная игра, поэтому вы будете часто тянуть карты, будь то игрок или крупье. Если что-то часто происходит в игре, как правило, неплохо превратить это в метод, чтобы вам не приходилось писать одну и ту же логику в разных местах.

Ваша текущая реализация рисует случайное значение между минимумом и максимумом вашего массива карточек. Из документации мы узнаем следующее:

Next(Int32 minValue, Int32 maxValue)

32-битовое целое число со знаком, большее или равное или minValueменьшее чем maxValue; то есть диапазон возвращаемых значений включает, minValue но не включает maxValue. Если minValueравно maxValue, minValueвозвращается.

Поэтому, когда вы пишете Next(1, 10)(от min и max), вы получите максимум 9. Другая проблема заключается в том, что даже если вы исправите реализацию до Next(1, 11), у вас будут равные шансы получить любое значение от 1 до 10. Но поскольку есть несколько карточек в колоде со значением 10 они должны появляться чаще, чем не 10 карт.

К счастью, в вашем массиве уже есть правильное распределение карточек, поэтому вместо этого вы можете сгенерировать допустимую случайную позицию, чтобы получить соответствующее значение из вашего массива.

В конце концов, то, что у вас получится, будет выглядеть примерно так:

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;
}

А затем вы даже можете сделать что-то вроде этого, чтобы многократно вытягивать карты:

// 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;
}

Надеюсь это поможет! Удачи и приятного времяпровождения!

9 Heslacher Aug 18 2020 at 14:33

Несколько заметок, чтобы вы могли улучшить свой код:

int sum1 = draw1 + draw2;

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

Это никогда не будет правдой, потому что

  • у вас на картах нет туза, что означает возможное значение одиннадцать.
  • maxValueв Random.Next(int minValue, int maxValue)этом исключительном верхней границе случайного числа возвращенного.

В void drawChoice(bool contChoice)аргументе методы contChoiceявляется типом значения. Вы не можете изменить его так, как думаете. После выхода из метода, независимо от того, ввел ли пользователь y или n, значение cont1остается false. Вы должны изменить сигнатуру метода, чтобы не было аргументов, но чтобы вернуть bool.

if (cont1 == true)  

поскольку cont1уже является bool, вам не нужно сравнивать его с bool. Вы можете просто использовать его как условие, например, if (cont1)и если вам нужно проверить, нужна ли falseвам переменная типа bool if (!cont1).

3 rball Aug 19 2020 at 00:27

Я не уверен, насколько я могу быть здесь полезен, но ИМХО вам нужно провести полноценный обзор кода, чтобы кто-то рассказал вам код. Здесь куча «неправильных», но, сказав, что мне интересно, какова ваша цель с C # - вы просто пишете что-то быстрое, чтобы изучить синтаксис, или вы хотите лучше понять, как создавать что-то на C #.

Если бы кто-то пришел ко мне с этим в профессиональной обстановке, я первым делом сказал бы им: «Вы должны уметь это протестировать». Затем я бы поговорил о TDD и действительно попытался указать, как этот код структурирован, чтобы делать слишком много. Здесь нет абстракций, и все очень процедурно. Каждый класс должен делать одну вещь. Люди, я уверен, будут со мной спорить по этому поводу. В любом случае, то, что у вас только 1 класс, плохо.

А потом просто общие «2-х минутные быстрые советы по C #». Я бы использовал перечисления для карт, поэтому вместо 10, 10, 10 у меня было бы 10, валет, дама, туз. Вместо этого используйте var. if (cont1 == true)такое же, как if(cont1). Используйте более именованные переменные: просто глядя на cont1, я не понимаю, что это значит.

JansthcirlU также представила коллекции. Глядя на этот код, не похоже, что вы их понимаете, поэтому я бы тоже здесь сосредоточился.

Продолжайте кодировать :)