
package com.itheima.ATM;import java.util.ArrayList;import java.util.Random;import java.util.Scanner;/** * ATM系统入口类 */public class ATMSystem { public static void main(String[] args) { // 1.定义一个账户类(面向对象编程) // 2. 定义一个集合容器,负责以后存储全部的账户对象,进行相关的业务操作 ArrayList<Account> accounts = new ArrayList<>(); // 里面存储的是Account类的对象 // 展示系统的首页 while (true) { System.out.println("===============黑马ATM系统===================="); System.out.println("1.账户登录"); System.out.println("2.账户开户"); Scanner sc = new Scanner(System.in); System.out.println("请选择你的操作:"); int command = sc.nextInt(); switch (command){ case 1: // 用户登录操作 login(accounts,sc);// 自己定义一个方法要接所有的账户集合和让用户输入的扫描器Scanner对象sc break; // 这里的break跳出switch分支,跳到while循环,刚开始的地方 case 2: // 用户账户开户 // 目前还没有register方法,按alt + enter键自动创建方法 register(accounts,sc); // register注册的意思, break; default: System.out.println("你输入的操作命令不正确"); // 这里应该定义一个死循环,让用户一直输入(选中要循环的部分,按ctrl + alt + t) } } } private static void login(ArrayList<Account> accounts, Scanner sc) { System.out.println("==================系统登录操作=================="); // 1.判断账户集合中是否存在账户,如果不存在账户,登录功能不能进行 if (accounts.size() == 0){ // 当输入里面的元素长度为0时代表里面没有账户对象, System.out.println("对不起,当前系统中,无任何账户,请先开户,再来登录"); return; // return这里单独使用是:结束方法 (卫语言风格) } // 2.正式进入登录操作 while (true) { System.out.println("请您输入登录卡号: "); String cardId = sc.next(); // 3.判断卡号是否存在,根据卡号去账户集合中查询账户对象 Account acc = getAccountByCardId(cardId, accounts); if (acc != null) { // 卡号存在的 // 4.让用户输入密码,认证密码 System.out.println("请您输入登录密码;"); String passWord = sc.next(); // 判断当前账户对象的密码是否与用户输入的密码一致 if (acc.getPassword().equals(passWord)){ System.out.println("恭喜你," + acc.getUserName() + "先生/女士进入系统,您的卡号是:" + acc.getCardId()); // 代码走到上面,代表登录成功, // 现在要做的事查询 转账 取款 。。。 // 展示登录后的操作页 showUserCommand(sc,acc);// 由于定义的方法要用到扫描器Scanner,所以现在要在方法中定义形参,所以在调用方法时也要传入形参 return; //这里加return干掉登录方法,结束当前login登录方法 }else { System.out.println("你输入的密码有误"); } }else { System.out.println("对不起,系统中不存在该账户卡号~~"); // 应该定义一个死循环,如果用户输入错误即让用户一直输入卡号 } } } /** * 展示登录后的操作页 */ private static void showUserCommand(Scanner sc,Account acc) { while (true) { System.out.println("=====================用户操作页========================="); System.out.println("1.查询账户"); System.out.println("2.存款"); System.out.println("3.取款"); System.out.println("4.转账"); System.out.println("5.修改密码"); System.out.println("6.退出"); System.out.println("7.注销账户"); System.out.println("请选择"); int command = sc.nextInt(); switch (command) { case 1: // 查询账户(展示当前登录的账户信息) // 让用户传参,将用户对象传下来 showAccount(acc); // 展示当前用户的方法, 将acc作为实参传进去 break; case 2: // 存款 depositMoney(acc,sc);// 调用存钱方法(depositMoney)首先ctrl + enter定义一个存钱方法里面传入账户对象 break; case 3: // 取款 drawMoney(acc,sc); break; case 4: // 转账 break; case 5: // 修改密码 break; case 6: // 退出 System.out.println("退出成功,欢迎下次光临"); return; // 用return方法,跳出当前方法 case 7: // 注销账户 break; // 定义一个默认情况,就是当上面所有的case都不满足时:就执行default语句 default: System.out.println("你输入的命令有误,请您重新输入"); // 这个时候要定义一个死循环如果用户输入错误,让用户一直输入 } } } /** * 取钱功能 * @param acc 当前账户对象 * @param sc 扫描器 */ private static void drawMoney(Account acc, Scanner sc) { System.out.println("===============用户取钱操作==================="); // 1. 判断是否足够100元 if (acc.getMoney() < 100){ System.out.println("对不起,当前账户中不够100元,不能取钱"); return; // 卫语言风格(像个卫士一样结束此方法) } while (true) { // 2.提示用户输入取钱金额 System.out.println("请您输入取款金额:"); double money = sc.nextDouble(); // 判断这个金额是否满足要求 if (money > acc.getQuotaMoney()){ // 如果取的钱大于限额quotaMoney则不能取钱 System.out.println("对不起,您当前取款金额超过每次限额,每次最多可取:" + acc.getQuotaMoney()); // 如果这里用户超过了限额,但是非要取走这个钱,可以定义死循环,一直执行这个取款操作 }else { // 如果没有超过当前余额 if (money > acc.getMoney()){ // acc.getMoney是当前对象的余额, money是取得钱 System.out.println("余额不足,你的余额是:" + acc.getMoney()); }else { // 没有超过当前余额 System.out.println("恭喜你,取钱成功,你取款得金额是:" + money + "元,成功!"); // 更新余额 acc.setMoney(acc.getMoney() - money); // acc.setMoney是往对象得成员赋值 这里用来更新数据 // 取钱结束后,将最新得余额展示给用户看(调用showAccount方法) showAccount(acc); return; // 取钱结束后,结束方法 } } } } private static void depositMoney(Account acc, Scanner sc) { System.out.println("================用户存钱操作==============="); System.out.println("请输入你的存款金额"); double money = sc.nextDouble(); // 最后总额度为: 账户本身的money(getMoney) + 存入的钱 (money) acc.setMoney(acc.getMoney() + money); // 这样已经修改了acc用户对象的值(集合中的对象也跟着修改了,因为集合存储的是对象的地址)// accounts.add(acc); //不要进行这样的操作,你操作对象,集合中存储该对象也跟着改变,因为存储的是地址 showAccount(acc); //将更新后的对象,传入到展示用户信息的方法中 } /** * 展示账户信息 * @param acc */ private static void showAccount(Account acc) { System.out.println("===================当前账户的信息如下================="); System.out.println("卡号:" + acc.getCardId()); System.out.println("户主:" + acc.getUserName()); System.out.println("余额:" + acc.getMoney()); System.out.println("限额:" + acc.getQuotaMoney()); } // 该方法是private方法,只能在本类中使用(在这里,使用private也没关系,就在这个ATMSystem类访问 /** * * @param accounts * @param sc // 由于下面要用到ScannerAPI,但是在新方法中创对象占内存,所以定义方法时,设置Scanner类 的传参即可使用该类的方法 */ private static void register(ArrayList<Account> accounts,Scanner sc) { System.out.println("===================系统开户操作======================="); // 1.创建一个账户对象,用于后期封装账户信息 Account account = new Account(); // 2.录入当前这个账户的信息,注入到账户对象中去 System.out.println("请输入账户用户名:"); String userName = sc.next(); account.setUserName(userName); // 使用自己定义的Account类的方法 while (true) { System.out.println("请输入你的密码:"); String passWord = sc.next(); System.out.println("请输入确认密码:"); String okPassword = sc.next(); if (passWord.equals(okPassword)){ // 密码认证通过,可以注入给账户对象 account.setPassword(okPassword); break; // 每次定义死循环一定要结束它,要不然后面写不了语句会报错Unreachable statement 无法到达的语句 }else { System.out.println("对不起你输入的2次密码不一致,请重新确认"); // 为了让用户输入正确,将要循环的部分加入while死循环 } } System.out.println("请你输入账户当次的限额"); // 死循环后面一定要写break要不然,这里会报错Unreachable statement double quotaMoney = sc.nextDouble(); // .nextDouble输入的是浮点型 account.setQuotaMoney(quotaMoney); // 为账户随机一个8为且与其他账户的卡号不重复的号码,(独立功能,独立成方法) String cardId = getRandomCardid(accounts);//getRandomCardid是自己创建的方法 account.setCardId(cardId); // 将新生成的cardID(不重复的) 传入这个account类中 // 3.把账户对象添加到账户集合中去 accounts.add(account); System.out.println("恭喜你," + userName + "先生/女士,您开户成功,您的卡号是:" + cardId + ",请您妥善保管卡号"); } private static String getRandomCardid(ArrayList<Account> accounts) { // 为了避免不重复,可以将集合容器传入进形参 Random r = new Random(); while (true) { // 1.先生成8位数字 String cardId = ""; // 定义一个容器,将每次遍历后的随机数字存在这个变量中// Random r = new Random(); // 定义了死循环后,这个随机数的对象就可以放到外面去,避免占用堆内存 for (int i = 0; i < 8; i++) { cardId += r.nextInt(10);// 定义随机数的范围是0-9 } // 2.判断这个这个8位的卡号是否与其他账户的卡号重复 // 根据整个卡号去查询账户的对象 Account acc = getAccountByCardId(cardId, accounts); // 这里的cardId是传入随机生成的 if (acc == null){ // 如果为null则代表这个卡号没有重复,这个卡号是一个新卡号,可以使用这个卡号作为新注册账户的卡号 return cardId; // 如果没有acc != null代表,卡号重复了,要使用死循环,再次生成新的卡号,再搜索 } } } /** * 根据卡号查询出一个账户对象出来 * cardId 卡号 * accounts 全部账户的集合 * 账户对象 | null */ private static Account getAccountByCardId(String cardId,ArrayList<Account> accounts){ // 这里的cardID是自己定义的形参 for (int i = 0; i < accounts.size(); i++) { Account acc = accounts.get(i); // acc变量是用来存储集合中遍历出来的对象, 遍历出来的对象都可以使用account对象的方法get if (acc.getCardId().equals(cardId)){ // 如果传入的卡号cardId与账户类的卡号一样,则返回该账户 return acc; } } // 当遍历整个集合中的对象的卡号都不一样是:代表没有该卡号 return null; // 查无此账户 }}
package com.itheima.ATM;
/**
* 账户类
*/
public class Account {
/**
* 成员变量,私有
*/
private String cardId;
private String userName; // 用户名
private String password; // 密码
private double money; // 账户余额
private double quotaMoney; // 每次提取的额度 // quota是定额的意思
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public double getQuotaMoney() {
return quotaMoney;
}
public void setQuotaMoney(double quotaMoney) {
this.quotaMoney = quotaMoney;
}
}