餐馆点餐和菜单管理系统(控制台版本)

这个系统主要涉及两个方面,第一个就是关于餐厅客户根据菜单点餐,并根据所吃的食品计算消费金额,并打印小票,第二个就是管理员对餐厅提供的菜式进行管理,对菜单进行增删改查操作,当然菜单也是保存在文本文件之中,只是在系统运行的时候,菜单信息和客户的点餐信息会保存到集合之中,当对菜单信息有更改的时候,也会写入到文本文件当中。

1.客户点餐
2.菜单管理

1.客户点餐

客户点餐的基本流程是首先将所有的菜式信息打印到客户面前,然后提示用户输入菜式编号和数量,确定之后询问是否继续,如果是则重复上面的点餐步骤,不是那就是要结账了,并且打印出小票。

1.打印所有菜式信息
2.要求用户选择菜式和所选菜式数量
3.询问客户是否继续点餐,是则循环第2步,否则进行下一步
4.根据客户所点过的菜式结账,并打印出小票

1.1 打印菜单信息

    /*
     * 打印菜单信息
     */
    public static void printMenu() throws IOException {
//        readMenu(array, "menu.txt");
        StringBuilder sb = new StringBuilder();

        int maxLength = 0;
        for (int i = 0; i < array.size(); i++) {
            Bean b = array.get(i);
            int length = b.getMenuName().length();
            if (length > maxLength) {
                maxLength = length;
            }
        }
        int num = 0;
        if (maxLength % 5 == 0) {
            num = maxLength / 5;
        } else {
            num = maxLength / 5 + 1;
        }

        sb.append("编号\t");
        sb.append("菜名");
        for (int i = 0; i < num; i++) {
            sb.append("\t");
        }
        sb.append("价格\t\n");
        for (int i = 0; i < array.size(); i++) {
            Bean b = array.get(i);
            sb.append(b.getMenuId()).append("\t");
            int length = b.getMenuName().length();
            int step = 0;
            if (length % 5 == 0) {
                step = num - length / 5 + 1;
            } else {
                step = num - length / 5;
            }
            sb.append(b.getMenuName());
            for (int j = 0; j < step; j++) {
                sb.append("\t");
            }
            sb.append(b.getMenuPrice()).append("\t\n");
        }
        System.out.println(sb.toString());
    }

打印菜单的时候,打印其中的数据都没有什么,不过在打印的格式上面确实下了功夫的,就是要使用\t来保持对齐,而且菜名的字数是不定的,这个是琢磨了比较长的时间才弄出来的。

因为这个系统会时常要求用户输入选择,因此就将它抽取为一个方法,使用起来也比较方便。

/*
 * 实现系统录入
 */
public static String myScanner() {
    Scanner sc = new Scanner(System.in);
    String data = sc.nextLine();
    return data;
}

1.2 要求用户选择菜式和所选菜式数量

也是将点餐这个操作抽取为一个方法

/*
 * 具体点餐
 */
public static void order(ArrayList<Bean> arr) {
    System.out.println("请输入你选择的菜式编号:");
    String xId = Tool.myScanner();
    System.out.println("请输入你选择的菜式数量:");
    String xNumber = Tool.myScanner();
    Bean b = Data.findMenu(xId);
    b.setMenuNumber(xNumber);
    arr.add(b);
}

当然是将上面这个点餐操作放在一个循环之中,由用户来决定是继续点餐还是直接结账

1.3 结账,并打印出小票

/*
 * 打印小票
 */
public static void printTicket(ArrayList<Bean> arr) {
    if(arr.isEmpty()){
        System.out.println("您还没点餐,暂无小票");
        return;
    }
    int maxLength = 0;
    for (int i = 0; i < arr.size(); i++) {
        Bean b = arr.get(i);
        int length = b.getMenuName().length();
        if(length>maxLength){
            maxLength = length;
        }
    }
    int num = 0;
    if(maxLength%5==0){
        num = maxLength/5;
    }else{
        num = maxLength/5+1;
    }
    StringBuilder sb = new StringBuilder();
    sb.append("编号\t");
    sb.append("菜名");
    for (int i = 0; i < num-"菜名".length()/5; i++) {
        sb.append("\t");
    }
    sb.append("单价\t");
    sb.append("数量\t");
    sb.append("总计\t\n");

    double allSum = 0;
    for (int i = 0; i < arr.size(); i++) {
        Bean b = arr.get(i);
        double sum = sum(b);

        sb.append(b.getMenuId() + "\t");
        int length = b.getMenuName().length();
        /*if(length<6){
            sb.append(b.getMenuName() + "\t\t");
        }else{
            sb.append(b.getMenuName() + "\t");
        }*/
        sb.append(b.getMenuName());
        int step = 0;
        if(length%5==0){
            step = num-length/5+1;
        }else{
            step = num-length/5;
        }
        for (int j = 0; j < step; j++) {
            sb.append("\t");
        }
        sb.append(b.getMenuPrice() + "\t");
        sb.append(b.getMenuNumber() + "\t");
        sb.append(sum + "\t\n");

        allSum += sum;
    }
    System.out.println(sb.toString());
    System.out.println("总计:" + allSum);
}

打印小票的时候也要注意小票上数据的格式,主要还是使用\t使数据保持对齐,这个是和用户最开始点餐时打印所有的菜式信息一样的。

其中在计算总花费的时候计算每种菜式的花费时,也抽取了一个方法,用来计算每种菜式花费了多少,其实就是这种菜式的单价乘以这种菜式的数量

/*
 * 实现价格统计
 */
public static double sum(Bean b) {
    double sum = 0;
    String menuNumber = b.getMenuNumber();
    String menuPrice = b.getMenuPrice();
    double number = Double.parseDouble(menuNumber);
    double price = Double.parseDouble(menuPrice);
    sum = number * price;
    return sum;
}

2.菜单管理

菜单管理就是管理员对所有的菜式信息进行的修改,首先需要登录,以此来验证身份确实是管理员,当然也不能无限验证,因此会有次数限制,验证完成之后,就可以对菜式信息进行操作,主要的就是增删改查了,对菜式信息的修改也会同步到文本文件当中,这样等下一次客户使用系统点餐的时候,所有的菜式信息就是全新的,也只有这样才能保证菜式信息的正确。

1.登录验证身份
2.对菜式信息进行操作,并保存到文本文件之中

2.1 登录验证身份

for (int i = 0; i < 3; i++) {
        System.out.print("用户名:");
        String user = Tool.myScanner();
        System.out.print("密码:");
        String password = Tool.myScanner();

        if (user.isEmpty() || password.isEmpty()) {
            if (2 - i != 0) {
                System.out.println("用户名或密码不能为空!请重新输入");
                System.out.println("您还有" + (2 - i) + "次机会!");
            } else {
                System.out.println("用户名或密码不能为空!");
                System.out.println("您的机会已用完,该账号已被锁定,请联系管理员!");
                System.exit(0);
            }
        } else if (!("admin".equalsIgnoreCase(user))
                || !("123".equalsIgnoreCase(password))) {
            if (2 - i != 0) {
                System.out.println("用户名或密码错误!请重新输入");
                System.out.println("您还有" + (2 - i) + "次机会!");
            } else {
                System.out.println("用户名或密码错误!");
                System.out.println("您的机会已用完,该账号已被锁定,请联系管理员!");
                System.exit(0);
            }
        } else {
            System.out.println("登陆成功");
            break;
        }
    }

写完之后感觉代码还蛮多的,其实逻辑还是蛮简单的,将判断放在循环当中,如果在指定的次数没有完成验证,那就代表验证次数用完了,就不能再运行了,而在验证的过程中,用户名或密码为空以及两者与预设的不一样,那都代表一次验证的失败,需要进行下一次验证。

2.2 对菜式信息进行操作

2.2.1 查看所有菜式信息

这里的查看所有菜式信息和用户点餐时首先打印所有的菜是一样的,都是调用的一个方法,那就是Data.printMenu();方法。

private static void showAllItems() throws IOException {
    ArrayList<Bean> arr = Data.array;
    if (arr.size() == 0) {
        System.out.println("抱歉,暂时还没有菜式添加进来");
        return;
    }
    Data.printMenu();
}
2.2.2 增加新的菜式
private static void addItem() throws IOException {
    ArrayList<Bean> arr = Data.array;
    String id;
    while (true) {
        System.out.println("请输入新菜式编号:");
        id = Tool.myScanner();
        if (id.isEmpty() || id.contains(",")) {
            if (id.isEmpty()) {
                System.out.println("菜式编号不能为空,请重新输入!");
                continue;
            }
            if (id.contains(",")) {
                System.out.println("菜式编号不能包含逗号,请重新输入!");
                continue;
            }
        }
        boolean exit = false;
        ;
        for (int i = 0; i < arr.size(); i++) {
            Bean a = arr.get(i);
            String menuId = a.getMenuId();
            if (menuId.equals(id)) {
                exit = true;
            }
        }
        if (exit) {
            System.out.println("您输入的菜式编号已经存在,请重新输入");
        } else {
            break;
        }
    }
    String name;
    while (true) {
        System.out.println("请输入新菜式名称:");
        name = Tool.myScanner();
        if (name.isEmpty() || name.contains(",")) {
            if (name.isEmpty()) {
                System.out.println("菜式名称不能为空,请重新输入!");
                continue;
            }
            if (name.contains(",")) {
                System.out.println("菜式名称不能包含逗号,请重新输入!");
                continue;
            }
        }
        boolean exit2 = false;
        for (int i = 0; i < arr.size(); i++) {
            Bean c = arr.get(i);
            String menuName = c.getMenuName();
            if (menuName.equals(name)) {
                exit2 = true;
            }
        }
        if (exit2) {
            System.out.println("您输入的菜式名称已经存在,请重新输入");
        } else {
            break;
        }
    }
    String price;
    while (true) {
        System.out.println("请输入新菜式价格:");
        price = Tool.myScanner();
        if (price.isEmpty() || price.contains(",")) {
            if (price.isEmpty()) {
                System.out.println("菜式价格不能为空,请重新输入!");
                continue;
            }
            if (price.contains(",")) {
                System.out.println("菜式价格不能包含逗号,请重新输入!");
                continue;
            }
        } else {
            break;
        }
    }
    Bean b = new Bean();
    b.setMenuId(id);
    b.setMenuName(name);
    b.setMenuPrice(price);
    arr.add(b);
    System.out.println("添加成功!");
    Data.array = arr;
    Data.writeFile(arr);
}

增加新的菜式主要是增加菜式的编号、名称和价格,在增加的时候要注意它们各自输入的格式,比如不能为空,而菜式编号和名称还要不能重复,最后一点便是这三者之中都不能包含逗号,因为在将一个菜式保存到文本文件中的时候,是用逗号将这三者隔开的,如果它们本身之中还包含逗号,那在读取的时候肯定会发生错误,因此是不能包含逗号的

1,三者均不能为空
2.菜式编号和名称都不能重复
3.三者之中都不能包含逗号
2.2.3 删除菜式
private static void removeItem() throws IOException {
    ArrayList<Bean> arr = Data.array;
    String id;
    while(true){
        System.out.println("请输入要删除菜式的编号:");
        id = Tool.myScanner();
        if(id.isEmpty()){
            System.out.println("要删除的菜式id不能为空,请重新输入");
        }else{
            break;
        }
    }
    int index = -1;
    for (int i = 0; i < arr.size(); i++) {
        Bean b = arr.get(i);
        String menuId = b.getMenuId();
        if (menuId.equals(id)) {
            index = i;
        }
    }
    if(index==-1){
        System.out.println("您输入的菜式id不存在,请选择其它操作");
    }else{
        arr.remove(index);
        System.out.println("删除菜式成功");
    }
    Data.array = arr;
    Data.writeFile(arr);
}

删除菜式是根据输入的编号进行删除的,如果输入的编号为空或者编号在之前的菜单中不存在,那就无法删除成功了

1.输入编号不能为空
2.输入编号不能在菜单中不存在
2.2.4 修改菜式
private static void changeItem() throws IOException {
    ArrayList<Bean> arr = Data.array;
    String id;
    while(true){
        System.out.println("请输入要修改菜式的编号:");
        id = Tool.myScanner();
        if(id.isEmpty()){
            System.out.println("要修改的菜式id不能为空,请重新输入");
        }else{
            break;
        }
    }
    int index=-1;
    for (int i = 0; i < arr.size(); i++) {
        Bean b = arr.get(i);
        String menuId = b.getMenuId();
        if(menuId.equals(id)){
            index = i;
        }
    }
    if(index==-1){
        System.out.println("要修改的菜式id不存在,请重新选择操作");
    }else{

        String name;
        while (true) {
            System.out.println("请输入菜式的新名称:");
            name = Tool.myScanner();
            if (name.isEmpty() || name.contains(",")) {
                if (name.isEmpty()) {
                    System.out.println("菜式名称不能为空,请重新输入");
                    continue;
                }
                if(name.contains(",")){
                    System.out.println("菜式名称不能包含逗号,请重新输入");
                    continue;
                }
            }else{
                break;
            }
        }


        String price;
        while (true) {
            System.out.println("请输入菜式的新价格:");
            price= Tool.myScanner();
            if (price.isEmpty() || price.contains(",")) {
                if (price.isEmpty()) {
                    System.out.println("菜式价格不能为空,请重新输入");
                    continue;
                }
                if(price.contains(",")){
                    System.out.println("菜式价格不能包含逗号,请重新输入");
                    continue;
                }
            }else{
                break;
            }
        }

        Bean d = new Bean();
        d.setMenuId(id);
        d.setMenuName(name);
        d.setMenuPrice(price);
        arr.set(index, d);
        System.out.println("修改成功");
        Data.array = arr;
        Data.writeFile(arr);
    }
}

修改菜式信息的时候,是根据输入的菜式编号进行修改的,因此输入的菜式编号不能为空,也不能在之前的菜单中不存在,只有输入已有的菜式编号才能进行修改,找到了编号对应的菜式之后就要输入新的菜式名称和新的价格进行修改,按照之前的要求,也是都不能为空和不能包含逗号的。

2.3 读取和写入菜式信息到菜单中

在管理员对系统中的菜式信息有所操作之后,那就应该将菜式信息重新写入到文本文件之中,每次程序启动的时候,为了方便客户点菜时得到最新的菜式信息,都应该去文本文件之中读取一次菜式信息,这样就能保证菜单中的菜式信息始终是保持同步的。

那这里就有两个操作,就是将文本文件中的菜式信息读取到集合之中,另一个就是将集合中的菜式信息写入到文本文件之中。

/*
 * 从文本文件中加载菜单信息
 */
public static void readMenu(String fileName)
        throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(fileName));

    String line;
    while ((line = br.readLine()) != null) {
        String[] data = line.split(",");
        Bean b = new Bean();
        b.setMenuId(data[0]);
        b.setMenuName(data[1]);
        b.setMenuPrice(data[2]);
        array.add(b);
    }
    br.close();
}

/*
 * 将菜单信息写入到文本文件之中
 */
public static void writeFile(ArrayList<Bean> arr) throws IOException {
    BufferedWriter bw = new BufferedWriter(new FileWriter("menu.txt"));

    for (int i = 0; i < arr.size(); i++) {
        Bean b = arr.get(i);
        StringBuilder sb = new StringBuilder();
        sb.append(b.getMenuId()).append(",");
        sb.append(b.getMenuName()).append(",");
        sb.append(b.getMenuPrice());
        bw.write(sb.toString());
        bw.newLine();
        bw.flush();
    }
    bw.close();
}

3.总结

学习编程阅读是一方面,多敲代码大概就是另一方面吧,阅读很多书可以知道很多知识点,读得多了更可能会获得更多的细节,而敲代码完成某个功能,则需要将多个知识点联系起来使用,可以对知识的联合使用有更多的把握,因此这两点可以说是相辅相成吧。

项目的代码还是放到我的GitHub账号之中,网址是:餐馆点餐和菜单管理系统(控制台版本)

坚持原创技术分享,您的支持将鼓励我继续创作!