1.JAVA小项目(零钱通)

一、说明

博客内容:B站韩顺平老师的视频,以及代码的整理。此项目分为两个版本:

  1. 面向过程思路实现
  2. 面向对象思路实现
    韩老师视频地址:【【零基础 快速学Java】韩顺平 零基础30天学会Java】 https://www.bilibili.com/video/BV1fh411y7R8/?p=342\&share_source=copy_web\&vd_source=656bca56998f14127313f0283f22ac0a
    【注意】:仅限学习,如有侵权,请联系本人删除。

项目实现--面向过程思路

先贴代码,项目的完整代码如下:

java 复制代码
package smallchange;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

/**
 * @author cdj
 * @Version1.0
 */
public class SmallChangeSys {

    // 1. 先完成显示菜单,并可以选择菜单,给出对应提示
    // 2. 完成零钱通明细
    // 3. 完成收益入账
    // 4. 完成消费
    // 5. 退出
    // 6. 用户输入4退出时,给出提示"你要退出吗? y/n",必须要正确的输入y/n,否则循环输入指令,直到输入y 或者 n
    // 7. 在收益入账和消费时,判断金额是否合理,并给出相应的提示

    public static void main(String[] args) {

        // 定义相关的变量
        boolean loop = true;
        Scanner sc = new Scanner(System.in);
        String key = "";

        // 2.完成零钱通明细
        // (1) 可以把收益入账和消费,保存到数组 (2)可以使用对象 (3)简单的会可以使用String拼接
        String detils = "------------------零钱通明细--------------------";

        // 3. 完成收益入账,完成功能驱动程序员增加新的变化和代码
        // 定义新的变量
        double money = 0;
        double balance = 0;
        Date date = null;   // data 是 java.util.Data类型,表示日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");    // 可以用于日期格式化的

        // 4. 消费
        // 定义新的变量,保存消费的原因
        String note = null;


        do{

            System.out.println("\n===================零钱通菜单================");
            System.out.println("\t\t\t\t\t1 零钱通明细");
            System.out.println("\t\t\t\t\t2 收益入账");
            System.out.println("\t\t\t\t\t3 消费");
            System.out.println("\t\t\t\t\t4 退             出");

            System.out.print("请选择(1-4): ");
            key = sc.nextLine();

            // 使用 switch 分支控制
            switch (key){
                case "1":
                    System.out.println(detils);
                    break;
                case "2":
                    System.out.print("收益入账金额:");
                    money = sc.nextDouble();
                    // 清空输入缓冲区
                    sc.nextLine();
                    // money 的值应该校验
                    // 找出不正确的金额条件,然后给出提示,就直接break
                    if(money <= 0){
                        System.out.println("收益入账金额需要大于0");
                        break;
                    }
                    balance += money;
                    // 获取当前日期
                    date = new Date();
                    // 拼接收益入账信息到details
                    detils += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
                    break;

                case "3":
                    System.out.print("收益消费金额:");
                    money = sc.nextDouble();
                    sc.nextLine();  // 清空输入缓冲区
                    // money 的值应该校验 TODO
                    // 找出金额不正确的情况
                    if(money <= 0 || money > balance){
                        System.out.println("你的消费金额应该在 0-" + balance);
                        break;
                    }
                    System.out.print("消费说明: ");
                    note = sc.next();
                    sc.nextLine();
                    balance -= money;
                    // 拼接消费信息到details
                    date = new Date(); // 获取到当前时间
                    detils += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t" + balance;
                    break;
                case "4":
                    // 用户输入4退出时,给出提示"你要退出吗? y/n",必须要正确的输入y/n
                    // (1) 定义一个变量 choice,接收用户的输入
                    // (2) 使用 while + break,来处理接收的输入时 y 或者 n
                    // (3) 退出while后,再判断choice是y还是n,就可以决定是否退出。
                    // (4) 建议一段代码完成一个小功能,尽量不要混在一起
                    String choice = "";
                    while (true) {  // 要求用户必须输入 y/n,否则就一直循环
                        System.out.println("你确定要退出吗? y/n");
                        choice = sc.nextLine();
                        if ("y".equals(choice) || "n".equals(choice)) {
                            break;
                        }
                    }
                    // 当用户退出后,再进行判断
                    if (choice.equals("y")) {
                        loop = false;
                    }
                    break;
                default:
                    System.out.println("选择有误,请重新选择");
            }

        }while(loop);

        System.out.println("------------------退出了零钱通项目------------------");
    }
}

代码思路

先看一下项目需求(资料来源:【【零基础 快速学Java】韩顺平 零基础30天学会Java】 https://www.bilibili.com/video/BV1fh411y7R8/?p=335\&share_source=copy_web\&vd_source=656bca56998f14127313f0283f22ac0a)

首先先理一下需要完成的几个功能:

  1. 界面显示
  2. 零钱通明细
  3. 收益入账
  4. 消费
  5. 退出

将这几个功能分别完成(一个代码块只实现一个功能)

1.界面显示

在界面显示的时候,我们需要完成的任务有以下两个:

  • (1) 完成显示菜单
  • (2) 可以选择菜单,并给出对应提示
    关于任务(1),我们可以考虑直接使用Println语句将菜单打印出来:
java 复制代码
 System.out.println("\n===================零钱通菜单================");
            System.out.println("\t\t\t\t\t1 零钱通明细");
            System.out.println("\t\t\t\t\t2 收益入账");
            System.out.println("\t\t\t\t\t3 消费");
            System.out.println("\t\t\t\t\t4 退             出");

实现了任务(1)之后,我们需要考虑的就是如何使得我们可以根据提示进行选择。那我们就需要去思考,哪个语句可以提供选择功能,很自然的想到了switch语句。先看一下switch语句的语法:

java 复制代码
switch (expression) {
    case value1:
        // 当 expression 的值等于 value1 时执行这里的代码
        // 可以有多行代码
        break;
    case value2:
        // 当 expression 的值等于 value2 时执行这里的代码
        // 可以有多行代码
        break;
    // 可以有更多的 case 语句
    default:
        // 当 expression 的值与所有 case 不匹配时执行这里的代码
}

switch语法可以得出:我们需要定义一个expression让我们去选择哪条case语句。根据菜单给的提示,我们选择定义一个String类型的变量,去存储我们的选择。由于我们需要去输入我们的选择,那我们就需要一个输入的功能Scanner

由以上分析,我们就可以搭建一个程序框架:

java 复制代码
public class SmallChangeSys {

    // 1. 先完成显示菜单,并可以选择菜单,给出对应提示
    public static void main(String[] args) {

        // 定义相关的变量
        Scanner sc = new Scanner(System.in);
        String key = "";

        System.out.println("\n===================零钱通菜单================");
        System.out.println("\t\t\t\t\t1 零钱通明细");
        System.out.println("\t\t\t\t\t2 收益入账");
        System.out.println("\t\t\t\t\t3 消费");
        System.out.println("\t\t\t\t\t4 退             出");

        System.out.print("请选择(1-4): ");
        key = sc.nextLine();

        // 使用 switch 分支控制
        switch (key){
            case "1":
				// TODO
                break;
            case "2":
                // TODO
                break;
            case "3":
            	// TODO
                break;
            case "4":
            	// TODO
                break;
            default:
            	// TODO
                break;
    }
}

上述代码能让我们完成任务(1)和任务(2),但是它只能执行一次,选择一个功能。我们需要多次执行,而且考虑到不管什么情况,都会执行一次。那就想到do while。先看一下do while的语法:

java 复制代码
do {
    // 循环体代码块
} while (condition);

while 关键字后面跟着一个循环条件。只要循环条件为 true,循环将继续执行;否则循环终止。为了使我们退出循环的时候方便,这里我们选择定义一个bool类型的变量loop。当我们需要退出时,只需要将它置为false即可。将上述代码修改:

java 复制代码
public class SmallChangeSys {

    // 1. 先完成显示菜单,并可以选择菜单,给出对应提示
    public static void main(String[] args) {

        // 定义相关的变量
        Scanner sc = new Scanner(System.in);
        String key = "";
        boolean loop = true;

		do {
		
			System.out.println("\n===============零钱通菜单==============");
	        System.out.println("\t\t\t\t\t1 零钱通明细");
	        System.out.println("\t\t\t\t\t2 收益入账");
	        System.out.println("\t\t\t\t\t3 消费");
	        System.out.println("\t\t\t\t\t4 退出");

	        System.out.print("请选择(1-4): ");
	        key = sc.nextLine();
	        
				 // 使用 switch 分支控制
	        switch (key){
	            case "1":
	            	// 零钱通明细
					// TODO
	                break;
	            case "2":
	            	// 收益入账
	                // TODO
	                break;
	            case "3":
	            	// 消费
	            	// TODO
	                break;
	            case "4":
	            	// 退出
	            	// TODO
	                break;
	            default:
	            	// TODO
	                break;
			}while (loop)   
    }
}

这样,整个程序的框架就已经搭建好了。下面使用代码块分别实现各个功能。

2. 零钱通明细

我们需要实现下图功能,那我们就需要一个变量进行显示。实现的方式有三种

  1. 把收入入账和消费,保存到数组(数组扩容比较麻烦)
  2. 使用对象
  3. 使用String拼接
    此处考虑使用String进行拼接,所以需要定义一个String类型的变量:
java 复制代码
String detils = "------------------零钱通明细--------------------";

在定义完变量后,我们需要把它放入菜单的选择中(case1),当我们需要查看明细时,只需要将这个字符串打印出来即可(在后续操作过程中有可能会修改字符串)。

java 复制代码
case "1":
	System.out.println(detils);
	break;

3.收益入账

首先需要一个变量用来存储收益,所以先定义一个存储收益的变量money:

java 复制代码
double money = 0;

我们的代码中已经有一个sc用于交互,所以money的值可以直接由我们输入。但是在编写代码过程中我发现如果没有清除缓存的话,代码会直接跳转到switch中的defalut语句,所以在输入money加入了一个清理缓存的语句:

java 复制代码
money = sc.nextDouble();
sc.nextLine();  // 清空输入缓冲区

当我们有收益时,我们的余额也会发生改变,所以此处我们添加一个存储余额的变量balacnce:

java 复制代码
double balance = 0;

有了balance用来存储余额,在实现收益功能的代码块中,自然balance += money。再看一下打印的信息里面还有一个data信息,所以需要添加时间相关的信息:

java 复制代码
Date date = null;   // data 是 java.util.Data类型,表示日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");    // 可以用于日期格式化的
java 复制代码
date = new Date();

因为我们用的时String进行的拼接,那么现在要将新增的记录拼接到我们的details中:

java 复制代码
// 拼接收益入账信息到details
detils += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;

注意看拼接的过程中是先拼接了一个\n,所以无论最终我们的details有多长,它都只是一个变量。

最终收益入账功能实现的代码如下:

java 复制代码
case "2":
	 System.out.print("收益入账金额:");
	 money = sc.nextDouble();
	 // 清空输入缓冲区
	 sc.nextLine();
	 // money 的值应该校验
	 // 找出不正确的金额条件,然后给出提示,就直接break
	 if(money <= 0){
	     System.out.println("收益入账金额需要大于0");
	     break;
	 }
	 balance += money;
	 // 获取当前日期
	 date = new Date();
	 // 拼接收益入账信息到details
	 detils += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
	 break;

除去上述将的内容,在其中还添加了检验money值得功能。

其它功能实现方式和上述方式大同小异,此处就不再进行书写。

总结

在项目实现过程中,首先是分析项目的需求,然后根据项目的需求将整个代码的框架搭建出来。在搭建过程中,遵循每个代码块实现一个功能,并且在需要什么变量的时候就定义什么变量(根据实际需求去定义变量)。在听课过程中,韩老师给的两个建议是十分重要的:

  1. 一段代码完成一个小功能,不要混在一起。
  2. 找出不正确的条件用来判断,而不是找正确的条件。

项目实现--面向对象思路

先贴代码,分为两个文件

  1. SmallChangeSysOOP:实现各种功能
  2. SmallChangeSysAPP:调用
    SmallChangeSysOPP代码如下:
java 复制代码
package smallchange.oop;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

/**
 * @author cdj
 * @Version1.0
 * 完成零钱通的各个功能
 * 将各个功能对应一个方法
 */
public class SmallChangeSysOOP {

    // 属性
    boolean loop = true;
    Scanner sc = new Scanner(System.in);
    String key = "";
    String detils = "------------------零钱通明细---------------";
    double money = 0;
    double balance = 0;
    Date date = null;   // data 是 java.util.Data类型,表示日期
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");    // 可以用于日期格式化的
    String note = null;

    // 显示菜单,并可以选择
    public void mainMenu() {

        do{
            System.out.println("\n===================零钱通菜单================");
            System.out.println("\t\t\t\t\t1 零钱通明细");
            System.out.println("\t\t\t\t\t2 收益入账");
            System.out.println("\t\t\t\t\t3 消费");
            System.out.println("\t\t\t\t\t4 退             出");

            System.out.print("请选择(1-4): ");
            key = sc.nextLine();

            // 使用 switch 分支控制
            switch (key){
                case "1":
                    this.detail();
                    break;
                case "2":
                    this.income();
                    break;

                case "3":
                    this.pay();
                    break;
                case "4":
                    this.exit();
                    break;
                default:
                    System.out.println("选择有误,请重新选择");
            }

        }while(loop);
    }

    // 零钱通明细
    public void detail() {
        System.out.println(detils);
    }

    // 完成收益入账
    public void income() {
        System.out.print("收益入账金额:");
        money = sc.nextDouble();
        // 清空输入缓冲区
        sc.nextLine();
        // money 的值应该校验
        // 找出不正确的金额条件,然后给出提示,就直接break
        if(money <= 0){
            System.out.println("收益入账金额需要大于0");
            return; // 退出方法,不再执行后面的方法
        }
        balance += money;
        // 获取当前日期
        date = new Date();
        // 拼接收益入账信息到details
        detils += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
    }

    // 消费
    public void pay() {
        System.out.print("收益消费金额:");
        money = sc.nextDouble();
        sc.nextLine();  // 清空输入缓冲区
        // money 的值应该校验 TODO
        // 找出金额不正确的情况
        if(money <= 0 || money > balance){
            System.out.println("你的消费金额应该在 0-" + balance);
            return;
        }
        System.out.print("消费说明: ");
        note = sc.next();
        sc.nextLine();
        balance -= money;
        // 拼接消费信息到details
        date = new Date(); // 获取到当前时间
        detils += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t" + balance;
    }

    // 退出
    public void exit() {
        String choice = "";
        while (true) {  // 要求用户必须输入 y/n,否则就一直循环
            System.out.println("你确定要退出吗? y/n");
            choice = sc.nextLine();
            if ("y".equals(choice) || "n".equals(choice)) {
                break;
            }
        }
        // 当用户退出后,再进行判断
        if (choice.equals("y")) {
            loop = false;
            System.out.println("------------------退出了零钱通项目------------------");
        }
    }
}

SmallChangeSysAPP代码如下:

java 复制代码
package smallchange.oop;

/**
 * @author cdj
 * @Version1.0
 * 调用SmallChangeSysOOP 对象
 */
public class SmallChangeSysAPP {
    public static void main(String[] args) {
        new SmallChangeSysOOP().mainMenu();
    }
}

在Structure(使用alt+7打开)界面下可以查看OOP类下面的属性和方法:

将其中的各个功能封装进OOP类下面的方法中,后续我们只用调用它的方法就可以了。对于其它人想用我们的代码,或者说后续添加方法,都是比面向过程更加方便的。

相关推荐
励志成为嵌入式工程师28 分钟前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉1 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer1 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq1 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml41 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~1 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616882 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7892 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java2 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山2 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js