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日

相关文章

  • ASP.NET中ListView(列表视图)的使用前台绑定附源码

    下面我将为您讲解如何在ASP.NET中使用ListView控件进行列表视图的展示,以及如何在前台绑定数据和附源码。 一、什么是ListView控件 ListView控件是ASP.NET Web应用程序中用于呈现数据列表的一种控件,它可以使用模板来定制呈现方式,提供了更丰富的数据呈现方式,比如表格、列表、瓷砖等。 二、ListView控件的使用方法 1. 新建…

    C# 2023年6月3日
    00
  • 10个C#程序员经常用到的实用代码片段

    下面我就来为大家详细讲解“10个C#程序员经常用到的实用代码片段”的完整攻略。 1. 字符串中查找是否存在指定字符示例 在C#中,我们经常需要查找字符串中是否存在指定的字符,可以用以下代码片段: bool isCharExist = myString.Contains("a"); 其中,myString为要搜索的字符串,”a”为要查找的字…

    C# 2023年5月15日
    00
  • 简单掌握Windows中C#启动外部程序进程的方法

    下面我将详细介绍如何在Windows中使用C#启动外部程序进程的方法。 1. 引用命名空间 在使用C#启动外部程序进程前,需要先引用System.Diagnostics命名空间,该命名空间包含了一个名为Process的类,用于处理进程相关操作。 using System.Diagnostics; 2. 创建Process对象 创建Process对象是启动外部…

    C# 2023年6月7日
    00
  • C#修改MAC地址类的实例

    首先我们需要明确一下”C#修改MAC地址类的实例”到底指什么。MAC地址是指网络适配器(网卡)上的物理地址,每张网卡都有唯一的MAC地址,它的作用是在局域网中进行唯一标识和寻址。而”C#修改MAC地址类的实例”指的是通过C#编程语言编写一个可以修改MAC地址的类,并实例化这个类,这样我们就可以在程序中使用这个类来修改MAC地址。 下面是具体的攻略: 1. 了…

    C# 2023年6月7日
    00
  • redis缓存数据库中数据的方法

    Redis缓存数据库中数据的方法 Redis 是一种高性能的缓存数据库,它支持多种数据结构和操作,可以用于缓存、消息队列、分布式锁等场景。本攻略将介绍 Redis 缓存数据库中数据的方法,包括数据的添加、查询、修改和删除等操作。 连接 Redis 在进行 Redis 操作之前,需要先连接 Redis 数据库。可以使用 StackExchange.Redis …

    C# 2023年5月17日
    00
  • 基于C#实现简单离线注册码生成与验证

    前言本篇攻略将介绍如何使用C#语言实现一个简单的离线注册码生成器与验证器,可适用于需要对软件进行授权的情形,如商业软件、企业内部软件等。首先我们将讲解注册码的生成方法,然后是注册码的验证方法,最后我们会给出完整的示例说明,希望这篇攻略对大家有所帮助。 一、注册码生成器的实现注册码生成器主要包括两个功能:生成唯一的机器码和根据机器码生成注册码。下面是代码实现:…

    C# 2023年6月6日
    00
  • C# 委托(delegate) 的小例子

    下面是我对 “C# 委托(delegate) 的小例子”的详细讲解攻略。 1.什么是委托(delegate) 在C#中,“委托(delegate)”是一个类,它允许我们将方法作为参数传递,然后在一个地方调用任意方法。委托可以认为是函数指针,它指向一个或多个方法。委托的实例在调用时会调用一个方法。 2.如何定义委托 定义委托需要使用delegate关键字,一个…

    C# 2023年6月7日
    00
  • C# winform打印excel的方法

    下面是关于如何使用C# WinForm打印Excel的完整攻略,包含以下几个步骤: 1. 引用Excel Interop 要打印Excel,需要使用Microsoft Excel Interop库。这个库需要先引用才能在程序中使用。下面是引用Excel Interop的具体步骤: 在Visual Studio的工具栏中选择“项目”。 在项目中选择“添加引用”…

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