// получаем максимальный номинал из перечисления, который есть в запасах и который меньше указанной суммы:
        private static Banknote_values max_available_value_less_than(uint summ, Banknote_values max_value)
        {
            var banknote_value = ((max_value == Banknote_values.how_many_banknotes_values)? max_value - 1 : max_value);

            while ((Banknote.get_banknote_value_by_text(banknote_value) > summ) ||
                   (banknotes_stock_for_check[Convert.ToInt32(banknote_value)].get_banknote_quantity() == 0))
            {
                if (banknote_value == Banknote_values.ten_rubles)
                {
                    break;
                }
                // переходим к более низкому номиналу, пока номинал превышает сумму или в нулевом количестве
                banknote_value--;
            }
            return(banknote_value);
        }
Exemple #2
0
        // статический метод (используем без создания объекта) для получения номинала по значению из перечисления кпюр
        public static uint get_banknote_value_by_text(Banknote_values some_banknote)
        {
            switch (some_banknote)
            {
            case Banknote_values.ten_rubles: return(10);

            case Banknote_values.fifty_rubles: return(50);

            case Banknote_values.one_hundred_rubles: return(100);

            case Banknote_values.two_hundred_rubles: return(200);

            case Banknote_values.five_hundred_rubles: return(500);

            case Banknote_values.one_thousand_rubles: return(1000);

            case Banknote_values.two_thousand_rubles: return(2000);

            case Banknote_values.five_thousand_rubles: return(5000);

            default: return(0);
            }
        }
        // функция проверяет, можем ли мы выдать заданную сумму и заполняет массив купюр (достоинство-количество),
        // которыми можно выдать. Возвращает истину, если всё получилось и ложь - если нет.
        private bool check_and_withdrawal(bool by_large_values)
        {
            label_no_result.Visible = false;
            uint users_wish = 0; // в этой переменной будем хранить сумму, которую хочет получить пользователь

            // СНАЧАЛА ПРОВЕРЯЕМ, НОРМАЛЬНУЮ ЛИ СУММУ ХОЧЕТ ПОЛЬЗОВАТЕЛЬ
            try
            {
                // пытаемся получить сумму из окошка для неё, если там не число - ловим ошибку
                users_wish = Convert.ToUInt32(textBox_for_summ.Text);
            }
            catch
            {
                MessageBox.Show("Запрашиваемая сумма не корректна!");
            }
            if (users_wish == 0)
            // 0 - нормальное число, но не в данном случае
            {
                label_no_result.Text = "Введите ненулевую и недробную сумму";
                return(false);
            }
            // если пользователь хочет больше, чем есть - тоже сразу нет:
            uint ATM_balanсe = ATM.how_much_money();

            if (users_wish > ATM_balanсe)
            {
                label_no_result.Text = "В банкомате нет столько денег!\nПроверьте баланс и попробуйте ввести сумму меньше.";
                return(false);
            }
            // если пользователь хочет более мелкие деньги, чем есть, то тоже нет:
            if (users_wish % Banknote.get_banknote_value_by_text(min_available_value()) != 0)
            {
                label_no_result.Text  = "Минимальная доступная купюра: ";
                label_no_result.Text += Banknote.get_banknote_value_by_text(min_available_value());
                label_no_result.Text += "р. Скорректируйте сумму для выдачи с учётом этого.";
                return(false);
            }

            // для каждой транзакции будем заполнять массив с проверочными остатками заново:
            banknotes_stock_for_check.Clear();

            // пара сокращений:
            Banknote_values min_value = Banknote_values.ten_rubles;
            Banknote_values max_value = Banknote_values.how_many_banknotes_values;

            if (by_large_values) // нужна выдача крупными купюрами, о мелких не беспокоимся, просто копируем данные
            {
                for (var value = min_value; value < max_value; value++)
                {
                    Banknote next_banknote = new Banknote(Banknote.get_banknote_value_by_text(value), ATM.how_many_banknotes_of(value));
                    banknotes_stock_for_check.Add(next_banknote);
                }
            }
            else // нужна выдача мелкими купюрами, тут код подлиннее, чтобы сразу понять, какими купюрами можем обойтись
            {
                // изначально полагаем максимальную мелкую купюру равной 200р
                Banknote_values max_small_value      = Banknote_values.two_hundred_rubles;
                uint            summ_of_small_values = 0; // будем считать сумму, которую можем выдать мелкими купюрами

                // копируем остатки банкомата в массив для проверки выдачи суммы, считаем сумму мелких купюр:
                for (var value = min_value; value < max_value; value++)
                {
                    Banknote next_banknote = new Banknote(Banknote.get_banknote_value_by_text(value), ATM.how_many_banknotes_of(value));
                    banknotes_stock_for_check.Add(next_banknote);
                    if (value <= max_small_value)
                    {
                        summ_of_small_values += next_banknote.get_summ();
                        // если посчитали всю сумму мелкими купюрами, и её не хватает, то добавляем к мелким следующую купюру
                        if ((value == max_small_value) && (summ_of_small_values < users_wish))
                        {
                            max_small_value++;  // мы не будем проверять здесь, что значение выйдет за предел диапазона, т.к. уже проверили, что всех денег банкомата для суммы хватит
                        }
                    }
                }
                max_value = max_small_value;  // ограничиваем максимальный номинал максимальной мелкой купюрой, которой хватит для выдачи суммы мелкими купюрами
            }

            // очистим массив снимаемых купюр, будем пополнять его по мере набора желаемой суммы
            try_to_withdraw.Clear();

            // сумма, которую снимаем:
            uint total_summ_to_withdraw = 0;

            // ЖАДНЫЙ АЛГОРИТМ, подбираем купюры для выдачи начиная с самой крупной подходящей:
            while (users_wish > 0) // будем уменьшать это значение по мере подбора банкнот
            {
                // идём от наиболее больших сумм, это же проверка, так мы быстрее наберём нужную сумму
                Banknote_values max_enum_value = max_available_value_less_than(users_wish, max_value);
                var             max_available_banknote_value = Banknote.get_banknote_value_by_text(max_enum_value);

                // максимально "доступный" номинал по факту может оказаться и не доступным:
                if (banknotes_stock_for_check[Convert.ToInt32(max_enum_value)].get_banknote_quantity() == 0)
                {
                    // тогда мы не можем эту купюру использовать и набор суммы завершён
                    label_no_result.Text  = "Не удаётся набрать запрашиваемую сумму, не хватает каких-то купюр.\n";
                    label_no_result.Text += "Попробуйте ввести сумму ";
                    label_no_result.Text += Convert.ToString(total_summ_to_withdraw);
                    // очистим уже частично заполненный массив снимаемых купюр:
                    try_to_withdraw.Clear();
                    return(false);           // проверка окончена
                }
                // ИНАЧЕ продолжаем, добавляем купюру в список для снятия:
                banknotes_stock_for_check[Convert.ToInt32(max_enum_value)].substract_banknote();
                try_to_withdraw.Add(max_available_banknote_value);
                total_summ_to_withdraw += max_available_banknote_value;
                users_wish             -= max_available_banknote_value;
            }
            // дошли до сюда, значит набрали всю сумму

            // скрываем кнопки и поле для суммы, готовим текст о результате
            textBox_for_summ.Visible      = false;
            button_by_small_value.Visible = false;
            button_by_large_value.Visible = false;

            // снимаем все подобранные банкноты по очереди, и печатаем их неповторяющиеся номиналы
            var    used_banknote            = try_to_withdraw[0]; // это для печати, сохраняем номинал первой банкноты на выдачу
            var    number_of_used_banknotes = 0;                  // это тоже для печати
            string info_about_banknotes     = "\nиспользованы купюры:\n" + used_banknote;

            foreach (var value in try_to_withdraw)
            {
                ATM.withdraw_banknote(value);
                if (value != used_banknote)           // показываем количество для выданной купюры
                {
                    info_about_banknotes    += " x " + number_of_used_banknotes + '\n' + value;
                    used_banknote            = value; // начинаем рассматривать следующую
                    number_of_used_banknotes = 0;
                }
                number_of_used_banknotes++;
            }
            info_about_banknotes += " x " + number_of_used_banknotes;   // добавляем информацию о количестве последней выданной купюры

            label_for_positive_result.Text    = "ВЫДАНА СУММА " + total_summ_to_withdraw;
            label_for_positive_result.Text   += info_about_banknotes;
            label_for_positive_result.Visible = true;

            return(true);
        }
Exemple #4
0
 // получаем имеющееся количество купюр определённого номинала:
 public static uint how_many_banknotes_of(Banknote_values banknote_value)
 {
     return(banknotes_stock[Convert.ToInt32(banknote_value)].get_banknote_quantity());
 }