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#代码实现微信跳一跳自动脚本,可以自动完成跳跃并获得高分。 步骤:1. 准备工作:安装Visual Studio、Android手机模拟器及ADB驱动;2. 安装ADB驱动:将手机连接到电脑,安装对应的ADB驱动;3. 获取跳一跳的截屏:使用ADB命令获取手机屏幕截图; adb shell …

    C# 2023年6月6日
    00
  • C#简单实现发送socket字符串

    首先我们需要了解什么是Socket。Socket是用于网络通信的一种机制,可以实现进程之间的通信,也可以实现不同计算机之间的通信。它是一种可以处理网络通信数据的抽象概念,通常与TCP/IP协议族一起使用。 在C#中,我们可以使用Socket类实现网络通信。下面我们来详细讲解一下C#简单实现发送socket字符串的攻略。 第一步:创建Socket对象 我们可以…

    C# 2023年6月8日
    00
  • .Net Core使用Coravel实现任务调度的完整步骤

    .Net Core使用Coravel实现任务调度的完整步骤 Coravel是一个轻量级的任务调度库,可以帮助我们在.Net Core应用程序中实现任务调度。在本文中,我们将介绍如何使用Coravel实现任务调度的完整步骤。 步骤一:安装Coravel 在使用Coravel之前,需要先安装Coravel。可以使用NuGet包管理器安装Coravel。 Inst…

    C# 2023年5月16日
    00
  • 浅析C#中的Main(String[] args)参数输入问题

    浅析C#中的Main(String[] args)参数输入问题 在C#中,我们通常会使用Main方法作为程序的入口点,此方法的输入参数一般表示程序启动时传递给程序的命令行参数。本文将深入浅出,对C#中的Main方法参数输入问题进行探讨。 Main方法定义 在C#中,Main方法通常定义为静态方法,其格式如下: static void Main(string[…

    C# 2023年5月15日
    00
  • C#中加载dll并调用其函数的实现方法

    C#中加载dll并调用其函数的实现方法,一般可以通过以下步骤来完成。 引用DLL文件 在Visual Studio中,可以通过在项目中添加现有项的方式来引用DLL文件。在添加时,需要确保所添加的DLL文件与项目的目标平台以及.NET Framework版本一致。可以通过鼠标右键单击项目,选择“属性”,打开项目属性对话框,然后在其中进行设置。 导入DLL中的函…

    C# 2023年5月15日
    00
  • 微信公众平台开发之自定义菜单.Net代码解析

    微信公众平台开发之自定义菜单.Net代码解析 本文将详细讲解在.Net平台下,如何进行微信公众平台的自定义菜单开发,并附带两个样例说明。 前置要求 一台拥有.NET平台开发环境的计算机 已经完成微信公众号认证并获取了公众号的基本信息(如AppID、AppSecret) 至少掌握基本的微信公众平台接口调用方式 开发思路 获取Access Token 使用Acc…

    C# 2023年5月31日
    00
  • C#微信开发之微信公众号标签管理功能

    C#微信开发之微信公众号标签管理功能攻略 简介 本文将为读者介绍如何在C#中使用微信开发工具包开发微信公众号中标签管理功能。标签管理功能可用于公众号中对粉丝进行标记或分类,方便后续进行针对性推送。 前置条件 在开始开发之前,开发者需要准备以下内容: 在微信公众平台中创建一个公众号,并获取该公众号的AppId和AppSecret; 在Visual Studio…

    C# 2023年5月31日
    00
  • c#生成站点地图(SiteMapPath)文件示例程序

    当我们在建立一个网站时,通常需要建立一个站点地图文件 (SiteMapPath) 来帮助用户更好的理解我们网站的目录结构,帮助用户更好的导航。 下面我将详细讲解如何用 C# 生成站点地图文件,同时提供两个示例程序: 站点地图文件的基础 什么是站点地图文件 站点地图文件是一种可供搜索引擎和网站访问者使用的页面列表,其中包含了站点中的所有页面和与每个页面相关的元…

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