模拟自动售货机的找零程序。需求描述如下:
1、程序根据用户投入货币的面额及其数量,在扣除购买的商品价额后,进行找零。
2、程序需要根据售货机内现存的各种货币面额和数量,在优先分配大面额货币的条件下,进行找零。
3、暂时仅支持整数找零。
4、实际的自动售货机找零是串行化操作,因此不考虑多线程同步问题。
package org.tang.change;
/**
* 货币枚举类
* @author Tang
*
*/
public enum Currency {
/**
* 货币面额
*/
HUNDRED_YUAN(100),
FIFTY_YUAN(50),
TWENTY_YUAN(20),
TEN_YUAN(10),
FIVE_YUAN(5),
ONE_YUAN(1);
/**
* 货币面额值
*/
private int value;
public int getValue() {
return value;
}
private Currency(int value){
this.value = value;
}
}
定义货币面额的枚举类。在需要增加面额情况下,可以扩展词枚举类。但是需要保证按照面额降序排列,这是为了实现较大面额货币将被优先分配找零的目的。
package org.tang.change;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 自动售货机类
* @author Tang
*
*/
public class VendingMachine {
private static final VendingMachine MACHINE = new VendingMachine();
/**
* key表示货币面额
* value表示该面额货币在此售货机当中的存量
*/
private static Map<Currency, Integer> moneyPool = new HashMap<Currency, Integer>();
private static Log logger = LogFactory.getLog(VendingMachine.class);
static {
initMoneyPool();
}
private VendingMachine(){}
/**
* 返回自动售货机实例
* @return
*/
public static VendingMachine getInstance(){
return MACHINE;
}
/**
* 初始化零钱库存
*/
private static void initMoneyPool(){
moneyPool.put(Currency.ONE_YUAN, 4);
moneyPool.put(Currency.FIVE_YUAN, 8);
moneyPool.put(Currency.TEN_YUAN, 5);
moneyPool.put(Currency.TEN_YUAN, 5);
moneyPool.put(Currency.TWENTY_YUAN, 3);
moneyPool.put(Currency.FIFTY_YUAN, 2);
moneyPool.put(Currency.HUNDRED_YUAN, 0);
if(logger.isInfoEnabled()){
logger.info("初始化售货机零钱库量:"+getStockBalance());
}
}
/**
* 将收到的钱放入零钱库
*/
private void put(Map<Currency,Integer> putMap){
if(logger.isInfoEnabled()){
logger.info("put操作前零钱库存量:"+getStockBalance());
}
for(Map.Entry<Currency, Integer> entry : putMap.entrySet()){
Integer count = moneyPool.get(entry.getKey());
moneyPool.put(entry.getKey(),(count == null ? 0:count) + entry.getValue());
}
if(logger.isInfoEnabled()){
logger.info("put操作后零钱库存量:"+getStockBalance());
}
}
/**
* 从零钱库中取出若干零钱
* @param takeMap
*/
private void take(Map<Currency,Integer> takeMap){
if(logger.isInfoEnabled()){
logger.info("take操作前零钱库存量:"+getStockBalance());
}
for(Map.Entry<Currency, Integer> entry : takeMap.entrySet()){
Integer count = moneyPool.get(entry.getKey());
moneyPool.put(entry.getKey(),(count == null ? 0:count) - entry.getValue());
}
if(logger.isInfoEnabled()){
logger.info("take操作后零钱库存量:"+getStockBalance());
}
}
/**
* 返回当前库中零钱总额
* @return
*/
public static int getStockBalance() {
return Currency.ONE_YUAN.getValue() * moneyPool.get(Currency.ONE_YUAN)
+ Currency.FIVE_YUAN.getValue()
* moneyPool.get(Currency.FIVE_YUAN)
+ Currency.TEN_YUAN.getValue()
* moneyPool.get(Currency.TEN_YUAN)
+ Currency.TWENTY_YUAN.getValue()
* moneyPool.get(Currency.TWENTY_YUAN)
+ Currency.FIFTY_YUAN.getValue()
* moneyPool.get(Currency.FIFTY_YUAN)
+ Currency.HUNDRED_YUAN.getValue()
* moneyPool.get(Currency.HUNDRED_YUAN);
}
/**
* 找零钱
* @return
*/
public Map<Currency,Integer> giveChange(int cost, Map<Currency,Integer> putMap) {
if(putMap == null){
throw new NullPointerException();
}
int putAmount = getPutAmount(putMap);
int payAmount = putAmount - cost;
if(logger.isInfoEnabled()){
logger.info("您需要为商品支付"+cost+"元,现收您"+putAmount+"元,还需找您"+payAmount+"元。");
}
if(cost <= 0 || putAmount == 0 || payAmount < 0){
throw new IllegalArgumentException("您的入参错误");
}
put(putMap);
Map<Currency,Integer> rtMap = new HashMap<Currency,Integer>(2);
for(Currency cur : Currency.values()){
if(payAmount == 0){
break;
}
Integer count = moneyPool.get(cur);
if(count == null){
continue;
}
if(payAmount - cur.getValue() == 0){
rtMap.put(cur, 1);
payAmount = 0;
break;
}
if(payAmount - cur.getValue() > 0 && payAmount / cur.getValue() > 0 && count >= (payAmount / cur.getValue())){
rtMap.put(cur, payAmount / cur.getValue());
payAmount = payAmount % cur.getValue();
}
}
if(payAmount != 0){
take(putMap);
throw new IllegalStateException("自动售货机零钱不够了。。。您的钱将自动退还");
}
take(rtMap);
return rtMap;
}
/**
* 返回收到的总金额
* @return
*/
private int getPutAmount(Map<Currency,Integer> putMap){
if(putMap == null || putMap.isEmpty()){
return 0;
}
int val = 0;
for(Map.Entry<Currency,Integer> entry : putMap.entrySet()){
val += entry.getKey().getValue()*entry.getValue();
}
return val;
}
}
package org.tang.change;
import java.util.HashMap;
import java.util.Map;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
Map<Currency,Integer> map = new HashMap<Currency,Integer>();
//投入售货机1张50元钞
map.put(Currency.FIFTY_YUAN, 1);
//需要为商品支付金额
int cost = 31;
VendingMachine machine = VendingMachine.getInstance();
Map<Currency,Integer> rtMap = machine.giveChange(cost,map);
System.out.println("\r自动售货机找零情况如下:");
for(Map.Entry<Currency, Integer> entry : rtMap.entrySet()){
System.out.println(entry.getValue()+"张"+entry.getKey().getValue()+"元");
}
}
}
INFO 2012-10-23 20:10:35,718 org.tang.change.VendingMachine: 初始化售货机零钱库量:254
INFO 2012-10-23 20:10:35,720 org.tang.change.VendingMachine: 您需要为商品支付30元,现收您50元,还需找您20元。
INFO 2012-10-23 20:10:35,721 org.tang.change.VendingMachine: put操作前零钱库存量:254
INFO 2012-10-23 20:10:35,721 org.tang.change.VendingMachine: put操作后零钱库存量:304
INFO 2012-10-23 20:10:35,722 org.tang.change.VendingMachine: take操作前零钱库存量:304
INFO 2012-10-23 20:10:35,722 org.tang.change.VendingMachine: take操作后零钱库存量:284
自动售货机找零情况如下:
1张20元
分享到:
相关推荐
实现了一个自动售货机功能,输入钱数可以买对应的饮料,如可口可乐、雪碧等,能自动找零,界面良好
本案例模拟饮料自动售货机的销售过程。首先由顾客投币,机器显示投币金额。接下来顾客选择要购买的饮料,如果投币金额足够并且所购饮料存在,则提示用户在出口处取走饮料,同时找零。如果投币金额不足,则显示提示...
本系统为自助售货机模拟程序,可供用户和管理员使用,管理员可以通过登录实现对商品的补充和管理等操作。用户可以通过售卖页面选购自己想要的商品,进入付款页面完成付款及找零等操作。文件包含各类.class文件,和...
可在MaxPlus Ⅱ或Quartus Ⅱ等软件平台上进行仿真...将程序在MaxPlus Ⅱ软件平台上进行编译仿真,通过分析仿真结果,自动售货机系统具有商品选择、投币处理、比价、出货找零、计时、异常退币等主要功能,符合设计要求。
本源码附带了仿真程序,采用Proteus7.8进行...自动售货机 1、内置16种商品,价格不一 2、具有投币口,可投5元、1元、0.5元硬币 3、具有找零、退钱功能 4、单词交易最高价格不能超过90 5、使用继电器模拟找零和出货过程
1. 项目说明该项目模拟饮料自动售货机的销售过程。顾客先投币,系统显示投币金额。接下来顾客选择要购买的饮料,如果投币金额足够并且所购饮料存在,则提示用户取走饮料,同时找零。如果投币金额不足,显示提示信息...
应用控制台应用程序实现了字的贩卖机系统的选购界面和管理界面,根据现实中的概率编制了一个模拟验钞装置和找零功能,用户的每次操作自动记录到文件中以便管理员查看,商品和零钱数目,同时管理员可以处理钱和商品的...
模拟自动饮料机。 按屏幕所示功能,输入所选择的合法数字,输出可获得的相应饮品。 ======================自动饮料机========================= 1. 可乐 3¥ 2. 尖叫 3¥ 3. 冰峰 1.5¥ 4. 芬达 4¥ 5. 雪碧 3.5¥ 6....
自动售货机 1、内置16种商品,价格不一 2、具有投币口,可投5元、1元、0.5元硬币 3、具有找零、退钱功能 4、单词交易最高价格不能超过90 5、使用继电器模拟找零和出货过程 资料包括程序、原理图、仿真、流程图、器件...
①售货模块:模拟一个自动贩卖机的工作过程。它的一次正常交易过程为:投币→选择需要购买的商品→找币,当币值不足或商品已经销售完毕时则无法购买。 ②管理员参数配置模块:系统管理员可以在此设置商品的单价与...