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日

相关文章

  • WPF+SkiaSharp实现自绘拖曳小球

    WPF 是一种跨平台、络人机交互(HCI)的技术,而 SkiaSharp 是一种用于高效地进行 2D 图形渲染的跨平台、高性能的图形库。这两者的结合可以实现一些非常炫酷的效果,比如实现自绘拖曳小球。 本攻略将分为以下几个步骤: 创建 WPF 窗口; 在 WPF 窗口中引用 SkiaSharp 和 SkiaSharp.Views.Wpf,并在 XAML 中定义…

    C# 2023年6月6日
    00
  • C#网络编程之Socket编程

    下面我将为您详细讲解“C#网络编程之Socket编程”的完整攻略。 简介 Socket编程是指使用套接字(Socket)进行网络编程,其主要功能是实现不同计算机之间的数据通信。C#作为一种通用的高级语言,可以使用Socket编程实现网络通讯的功能。 Socket编程基础知识 1. Socket概述 Socket(套接字)是网络编程中的一个抽象概念,它负责提供…

    C# 2023年6月1日
    00
  • c#中object、var和dynamic的区别小结

    针对这个问题,我整理了一份详细讲解“C#中Object、var和dynamic的区别”的攻略,下面是详细讲解: Object、var和dynamic的区别小结 在C#编程中,object、var和dynamic是三个常用的类型。虽然它们都可以存储任意类型的数据,但它们的行为却截然不同。 1. Object Object是C#中所有类型的基类,也是一个基本的数…

    C# 2023年5月15日
    00
  • 详解C#读取Appconfig中自定义的节点

    下面是详解C#读取Appconfig中自定义的节点的完整攻略。 一、准备工作 在开始之前,需要先在App.config配置文件中定义自定义节点。可以按照以下格式添加: <configuration> <configSections> <section name="customSection" type=&qu…

    C# 2023年5月15日
    00
  • C#测量程序运行时间及cpu使用时间实例方法

    下面我将详细讲解一下如何在C#测量程序运行时间及 CPU 使用时间的实例方法。 步骤一:获取系统时间 为了测量程序运行时间和 CPU 使用时间,我们需要获取系统时间。可以使用 C# 的 System.DateTime 类来获取当前系统时间,并将其转换为毫秒数。例如: DateTime start = DateTime.Now; 这将创建一个名为“start”…

    C# 2023年6月1日
    00
  • Net Core全局配置读取管理方法ConfigurationManager

    在本文中,我们将详细讲解如何在.NET Core中使用ConfigurationManager全局配置读取管理方法,并提供两个示例说明。 准备工作 在开始之前,您需要安装以下软件: .NET Core SDK 使用ConfigurationManager读取配置 在.NET Core项目中添加System.Configuration.Configuratio…

    C# 2023年5月16日
    00
  • 用C#编写ActiveX控件(三)

    那么让我们详细讲解一下”用C#编写ActiveX控件(三)”的完整攻略。 什么是ActiveX控件 ActiveX是一种软件组件技术,它允许应用程序在多个不同的操作系统和应用程序之间共享代码。ActiveX控件是一种可以在Web浏览器中嵌入的交互式控件。 为什么用C#编写ActiveX控件 C#是一种非常流行的编程语言,它有着丰富的库和框架,同时也具有强大的…

    C# 2023年6月7日
    00
  • C# WinForm实现自动更新程序之客户端的示例代码

    好的!本文将详细讲解“C# WinForm实现自动更新程序之客户端的示例代码”的完整攻略,包括以下内容: 前置知识 客户端代码示例 示例说明 前置知识 在讲解“C# WinForm实现自动更新程序之客户端的示例代码”之前,需要掌握一些前置知识: C#语言的基础语法 WinForm应用程序的基础知识 HTTP协议的基本原理及其在.NET中的应用 XML文档的基…

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