namespace PizzaApp
{
    public partial class PizzaOrder : Form
    {
        // Initializing the toppings to its cost
        // Double type since it could have decimal points
        public double Small = 5.50;
        public double Medium = 11.75;
        public double Large = 15.00;
        public double Pepperoni = 0.75;
        public double Onion = 0.75;
        public double Mushroom = 0.75;
        public double BlackOlives = 0.75;
        public double Pineapple = 0.75;
        public double ExtraCheese = 0.75;

        public static double Cost = 0.00; // Keeps track of total cost
        

        public PizzaOrder()
        {
            InitializeComponent();
        }

        private void orderButton_Click(object sender, EventArgs e)
        {
           
            // If small size pizza radio button is checked, I do cost - 1.50 because 2 ingredients are free
            if (smallRadioButton.Checked == true)
            {
                Cost += Small;
                Cost -= 1.50;
            }
            // If medium size pizza radio button is checked, I do cost - 2.25 because 3 ingredients are free
            if (mediumRadioButton.Checked == true)
            {
                Cost += Medium;
                Cost -= 2.25;
            }
            // If large size pizza radio button is checked, I do cost - 3.00 because 4 ingredients are free
            if (largeRadioButton.Checked == true)
            {
                Cost += Large;
                Cost -= 3.00;
            }


            //Ingredrients if statements
            if (pepperoniCheckBox.Checked == true)
            {
                Cost += Pepperoni;

            }
            if (onionCheckBox.Checked == true)
            {
                Cost += Onion;

            }
            if (mushroomCheckBox.Checked == true)
            {
                Cost += Mushroom;

            }
            if (blackOlivesCheckBox.Checked == true)
            {
                Cost += BlackOlives;

            }
            if (pineappleCheckBox.Checked == true)
            {
                Cost += Pineapple;

            }
            if (extraCheeseCheckBox.Checked == true)
            {
                Cost += ExtraCheese;

            }

           
        }

        private void sizeGroupBox_Enter(object sender, EventArgs e)
        {

        }

        private void ingredientsGroupBox_Enter(object sender, EventArgs e)
        {

        }

        private void PizzaOrder_Load(object sender, EventArgs e)
        {

        }

        private void priceLabel_Click(object sender, EventArgs e)
        {
          
        }

        private void totalPriceTextBox_TextChanged(object sender, EventArgs e)
        {
            totalPriceTextBox.Text = Cost.ToString();
        }
    }
}

Например, когда пользователь берет маленькую пиццу, 2 из 6 ингредиентов являются бесплатными (средний - 3, а большой - 4 бесплатных ингредиента). Я не мог найти другого способа реализовать это, поэтому просто вычел бесплатные ингредиенты из размера пиццы. Теперь я застрял на том, как заставить пользователя выбирать хотя бы эти бесплатные ингредиенты, чтобы пицца не стоила меньше начальной цены.

c#
1
Nicholas Grammatopoulos 15 Окт 2021 в 14:14

3 ответа

Лучший ответ

Является ли частью ваших требований то, что пользователь не может есть пиццу с одной начинкой, даже если он не хочет ни одну из пяти других? Потому что в противном случае вы вводите ограничение, которого не должно быть, что делает это проблемой XY.

Я предполагаю, что этого ограничения быть не должно. Также обратите внимание, что я пытаюсь внести минимальные изменения в ваш код, а не переделывать его с большим количеством наворотов, потому что я предполагаю, что это задача для новичков.
С самого начала я бы подошел к этому по-другому, но это был бы более продвинутый подход, и он потребовал бы переписывания всего вашего решения с нуля, что здесь несколько не по теме и не является хорошим уроком для вас.

Проблема здесь в том, что ваша задача требует рассмотрения группы начинок (« первые два [из списка выбранных начинок] бесплатны»), но ваш код учитывает только каждый флажок каждой начинки по отдельности. В его нынешнем виде ваш код не рассматривает сбор начинок как группу.

Я заметил, что все начинки стоят одинаково. Это данность? Или возможно, что начинки могут иметь разные цены?

Если все начинки всегда стоят одинаково , вычисления очень просты. Общая стоимость начинки составляет:

([amount_of_toppings] - 2) * [price_of_a_topping]

Когда amount_of_toppings меньше или равно 2, вам даже не нужно его вычислять.

Как узнать количество начинки? Ну ты посчитай галочки.

public double GetToppingsTotalPrice()
{
    int counter = 0;

    if(pepperoniCheckBox.Checked) 
        counter++;

    if(onionCheckBox.Checked) 
        counter++;

    // and so on

    if(counter > 2)
        return (counter-2) * this.toppingPrice;
    else
        return 0; 
}

Если начинки могут иметь разные цены , вам нужна дополнительная информация. Как вы решаете, какие начинки бесплатные? Можно было предположить, что самые дешевые будут бесплатными, но это следует подтвердить в описании.

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

При выполнении таких операций с коллекцией LINQ - простой и понятный способ сделать это, поэтому я собираюсь использовать его в этом решении.

public double GetToppingsTotalPrice()
{
    List<double> addedToppingPrices = new List<double>();

    if(pepperoniCheckBox.Checked) 
        addedToppingPrices.Add(this.Pepperoni);

    if(onionCheckBox.Checked) 
        addedToppingPrices.Add(this.Onion);

    // and so on

    // Stop here if there aren't any paid toppings.
    if(addedToppingPrices.Count() <= 2)
        return 0;

    return addedToppingPrices
             .OrderBy(x => x)  // Sort from cheapest to most expensive
             .Skip(2)          // Skip the first two
             .Sum(x => x);     // Sum the remaining numbers
}
0
Flater 15 Окт 2021 в 11:37

Это распространенный недостаток кода для начинающих, заключающийся в отсутствии абстракции / разделения между пользовательским интерфейсом и логикой данных / бизнес-логики. Подумайте об использовании правильного подхода ООП, тогда все быстро станет казаться намного яснее.

Примере:

public enum PizzaSize
{
    Small,
    Medium,
    Large
}

public class PizzaTopping
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class PizzaOrder
{
    private static readonly Dictionary<PizzeSize, decimal> pizzaPrices = new Dictionary<PizzeSize, decimal>
    {
         { PizzaSize.Small, 5.5m },
         { PizzaSize.Medium, 11.75m },
         { PizzaSize.Large, 15m },
    };
    
    private static readonly Dictionary<PizzeSize, decimal> freeToppingsCounts = new Dictionary<PizzeSize, decimal>
    {
         { PizzaSize.Small, 2 },
         { PizzaSize.Medium, 3 },
         { PizzaSize.Large, 4 },
    };
    
    public PizzaSize Size { get; set; }
    public List<PizzaTopping> Toppings { get; set; } = new List<PizzaTopping>();
    
    public decimal GetTotalPrice()
    {
        var totalPrice = pizzaPrices[this.Size];
        var freeToppings = freeToppingsCounts[this.Size];
        var counter = 0;
        foreach (var topping in this.Toppings.OrderBy(x => x.Price))
        {
            counter++;
            if (counter > freeToppings)
            {
                totalPrice += topping.Price;
            }
        }
        return totalPrice;
    }
}


public class PizzaOrderForm : Form
{
    var order = GetPizzaOrder(); // create your order from the UI here
    var totalPrice = order.GetTotalPrice();
}

(Отказ от ответственности: я быстро взломал это вместе в Блокноте, это не должно быть идеальным, просто чтобы выразить свою точку зрения.)

2
marsze 15 Окт 2021 в 11:54

Я бы начал с определения класса, который содержит ссылку на соответствующий флажок и цену за это значение.

public class Topping
{
    public CheckBox Selector {get;}
    public double Cost {get;}

    public Topping(CheckBox selector, double cost)
    {
       this.Selector = selector;
       this.Cost = cost;
    }
}

А затем определите в форме массив Topping вместо набора дискретных переменных для каждой из них:

public partial class PizzaOrder : Form
{
   private Topping[] toppings = new Topping[]{
        new Topping(pepperoniCheckBox, 0.75),
        new Topping(onionCheckBox, 0.75),
        new Topping(mushroomCheckBox, 0.75),
        new Topping(blackOlivesCheckBox, 0.75),
        // .. etc
   };

Это полезно, так как теперь вы можете определить количество выбранных начинок (все отмеченные).

var numToppingsSelected = toppings.Where(x => x.Selector.Checked).Count();

Вы также можете получить IEnumerable<Topping> из выбранных - возможно, закажите их по Cost и пропустите самые дешевые 2, прежде чем получите общую стоимость оставшегося выбора.

var selectedToppings = toppings.Where(x => x.Selector.Checked).OrderBy(x => x.Cost);
var selectedToppingsExceptFirst2 = selectedToppings.Skip(2);
var costOfRemainingToppings = selectedToppingsExceptFirst2.Sum(x => x.Cost);

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

1
Jamiec 15 Окт 2021 в 11:35