C#实现一个控制台的点餐系统

C#实现一个控制台的点餐系统完整攻略

需求分析

点餐系统需要实现以下功能:

  1. 展示菜单
  2. 输入点餐内容和数量
  3. 确认订单及计算总价
  4. 退出程序

设计实现

数据结构

点餐系统需要用到的数据结构有:

  • 菜品类别 Category
  • 菜品类 Dish
  • 菜单类 Menu
  • 订单类 Order

具体定义如下:

// 菜品类别
public enum Category
{
    饮料,
    小吃,
    主食
}

// 菜品类
public class Dish
{
    public string Name { get; }
    public Category Category { get; }
    public decimal Price { get; }

    public Dish(string name, Category category, decimal price)
    {
        Name = name;
        Category = category;
        Price = price;
    }
}

// 菜单类
public class Menu
{
    private readonly List<Dish> _dishes;

    public Menu()
    {
        _dishes = new List<Dish>
        {
            new Dish("可乐", Category.饮料, 2.00m),
            new Dish("薯条", Category.小吃, 5.50m),
            new Dish("烤鸡翅", Category.小吃, 12.00m),
            new Dish("汉堡", Category.主食, 15.50m),
            new Dish("烤肉拌饭", Category.主食, 18.00m)
        };
    }

    public IReadOnlyList<Dish> Dishes => _dishes.AsReadOnly();
}

// 订单类
public class Order
{
    private readonly Dictionary<Dish, int> _items;

    public Order()
    {
        _items = new Dictionary<Dish, int>();
    }

    public void AddItem(Dish item, int quantity)
    {
        if (quantity < 0)
        {
            throw new ArgumentException("数量不能为负数。", nameof(quantity));
        }

        if (quantity == 0)
        {
            // 数量为 0,删除该项
            RemoveItem(item);
        }
        else
        {
            _items[item] = quantity;
        }
    }

    public void RemoveItem(Dish item)
    {
        _items.Remove(item);
    }

    public IReadOnlyDictionary<Dish, int> GetItems()
    {
        return _items;
    }

    public decimal GetTotalPrice()
    {
        return _items.Sum(item => item.Key.Price * item.Value);
    }
}

控制台界面

控制台界面需要显示菜单、接收用户输入、显示订单等信息。实现如下:

public class ConsoleUI
{
    private readonly Menu _menu;
    private readonly Order _order;

    public ConsoleUI()
    {
        _menu = new Menu();
        _order = new Order();
    }

    public void Run()
    {
        ShowMenu();

        while (true)
        {
            ReadInput(out var dish, out var quantity);

            if (dish == null)
            {
                // 用户输入 quit 退出程序
                break;
            }

            _order.AddItem(dish, quantity);

            ShowOrder();
        }

        Console.WriteLine("感谢光临!");
    }

    private void ShowMenu()
    {
        Console.WriteLine("欢迎光临,我们的菜单如下:");
        foreach (var group in _menu.Dishes.GroupBy(dish => dish.Category))
        {
            Console.WriteLine(group.Key);
            foreach (var dish in group)
            {
                Console.WriteLine($"{dish.Name, -20} {dish.Price, 6}");
            }
            Console.WriteLine();
        }
    }

    private void ShowOrder()
    {
        Console.WriteLine($"当前订单:共 {_order.GetItems().Count} 件商品,总价 {_order.GetTotalPrice():C2}");
        foreach (var item in _order.GetItems())
        {
            Console.WriteLine($"{item.Key.Name, -20} {item.Value, 2} × {item.Key.Price, 6:C2} = {(item.Key.Price * item.Value), 8:C2}");
        }
    }

    private void ReadInput(out Dish dish, out int quantity)
    {
        Console.Write("请输入菜名(quit 结束):");
        var input = Console.ReadLine();

        if (string.IsNullOrEmpty(input))
        {
            dish = null;
            quantity = 0;
            return;
        }

        if (input == "quit")
        {
            dish = null;
            quantity = 0;
            return;
        }

        var dishes = _menu.Dishes.Where(d => d.Name.StartsWith(input, StringComparison.OrdinalIgnoreCase)).ToList();
        if (dishes.Count == 0)
        {
            Console.WriteLine("找不到该菜品。");
            ReadInput(out dish, out quantity);
            return;
        }

        Console.Write("请输入数量:");
        input = Console.ReadLine();

        if (!int.TryParse(input, out quantity))
        {
            Console.WriteLine("请输入有效的数量。");
            ReadInput(out dish, out quantity);
            return;
        }

        if (quantity <= 0)
        {
            Console.WriteLine("数量不能为负数或零。");
            ReadInput(out dish, out quantity);
            return;
        }

        dish = dishes.Count == 1 ? dishes[0] : SelectDish(dishes);
    }

    private static Dish SelectDish(List<Dish> dishes)
    {
        Console.WriteLine("请选择菜品:");
        for (var i = 0; i < dishes.Count; i++)
        {
            Console.WriteLine($"{i + 1}: {dishes[i].Name}");
        }

        while (true)
        {
            var input = Console.ReadLine();

            if (!int.TryParse(input, out var index))
            {
                Console.WriteLine("请输入有效的数字编号。");
                continue;
            }

            if (index < 1 || index > dishes.Count)
            {
                Console.WriteLine("编号超出范围。");
                continue;
            }

            return dishes[index - 1];
        }
    }
}

示例说明

下面是两个示例说明:

示例一

用户输入的序列为:

汉堡
2

程序会输出当前订单并等待用户输入:

当前订单:共 1 件商品,总价 31.00元
汉堡                  2 ×  15.50 =     31.00

示例二

用户输入的序列为:

卤肉饭

程序会提示找不到该菜品并要求用户重新输入:

找不到该菜品。
请输入菜名(quit 结束):

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#实现一个控制台的点餐系统 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • C#实现前向最大匹、字典树(分词、检索)的示例代码

    如果要实现分词和检索功能,可以用前向最大匹配和字典树算法。在C#中实现这两个功能,可以按照以下步骤进行: 实现前向最大匹配算法 前向最大匹配算法是将待分词的文本从左到右进行扫描,每次取出最长的词作为分词结果。为了实现该算法,需要将待分词的文本和词典中的词进行转换,以便进行匹配。下面是C#中的前向最大匹配算法示例代码: public static List&l…

    C# 2023年5月31日
    00
  • Aspose.Cells组件导出excel文件

    以下是”Aspose.Cells组件导出excel文件”的完整攻略: 1. Aspose.Cells组件简介 Aspose.Cells 是一款强大且灵活的 Excel 文件处理工具,它能帮助我们快速创建、读取、操作和导出 Excel 文件。Aspose.Cells 支持多种格式的 Excel 文件,包括 XLS、XLSX、XLSB、CSV 和 TXT 等格式…

    C# 2023年5月31日
    00
  • 详解如何在ASP.NET Core中应用Entity Framework

    如何在 ASP.NET Core 中应用 Entity Framework Entity Framework 是一个对象关系映射(ORM)框架,可以将数据库中的数据映射到 .NET 对象中。在 ASP.NET Core 中,可以使用 Entity Framework 来访问和操作数据库。本攻略将详细介绍如何在 ASP.NET Core 中应用 Entity …

    C# 2023年5月17日
    00
  • ASP.NET(C#) String, StringBuilder 与 StringWriter性能比较

    ASP.NET是一种广泛使用的Web应用程序框架,C#是一种强类型面向对象的编程语言。在开发ASP.NET应用程序时,我们常常需要使用字符串操作,其中包括String、StringBuilder和StringWriter这三种不同的类型。这三种类型有着不同的性能特点,需要根据具体的情况来选择使用。 1. String String是C#中常用的字符串类型,它…

    C# 2023年6月3日
    00
  • C#开发windows服务实现自动从FTP服务器下载文件

    下面是详细说明: 一、前置条件 电脑上安装Visual Studio(建议版本大于2015)。 确保安装了.NET Framework 4及以上版本。 需要有一个FTP账号和FTP服务器。 二、创建Windows服务应用程序 1. 打开Visual Studio,点击“新建项目”; 2. 选择“Windows服务”类型,并起名为“FTPDownloadSer…

    C# 2023年6月1日
    00
  • WPF开发之实现一种三轴机械手控件

    WPF开发之实现一种三轴机械手控件,涉及到的技术栈有WPF、XAML、C#等。下面按照步骤来介绍实现这种控件的攻略。 一、设计控件的外观 首先我们需要考虑机械手控件的外观设计,我们可以使用WPF提供的绘图功能,来绘制出控件的外观,比如:机械臂的手臂、手掌、手指等。 在WPF开发中,我们设计控件的外观采用的是XAML,XAML是一种基于XML的标记语言,可以在…

    C# 2023年6月6日
    00
  • C#实现线程安全的简易日志记录方法

    下面我将详细讲解“C#实现线程安全的简易日志记录方法”的完整攻略。 1. 什么是线程安全日志记录方法? 在多线程程序中,多个线程同时进行日志写入时会引发竞争条件,可能导致丢失部分日志或产生不一致的日志。为了解决这个问题,我们需要使用线程安全的日志记录方法,保证每个线程可以正确地写入自己的日志信息,而不会与其他线程产生冲突。 线程安全的日志记录方法可以保证在多…

    C# 2023年6月1日
    00
  • asp实现读取数据库输出json代码

    下面是ASP实现读取数据库输出JSON格式的完整攻略。 第一步:连接数据库 首先,我们需要连接数据库。在ASP中,我们可以使用ADODB库来连接数据库。以下是连接字符串的示例代码: Set conn = Server.CreateObject("ADODB.Connection") conn.Open "Provider=Mic…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部