`
Will_Turner
  • 浏览: 68068 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

自动售货机的找零程序模拟

阅读更多

模拟自动售货机的找零程序。需求描述如下:

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元
 
分享到:
评论

相关推荐

    自动售货机MFC

    实现了一个自动售货机功能,输入钱数可以买对应的饮料,如可口可乐、雪碧等,能自动找零,界面良好

    饮料自动售货机源程序(孔令德,叶瑶,c++)

    本案例模拟饮料自动售货机的销售过程。首先由顾客投币,机器显示投币金额。接下来顾客选择要购买的饮料,如果投币金额足够并且所购饮料存在,则提示用户在出口处取走饮料,同时找零。如果投币金额不足,则显示提示...

    Java 期末设计自助售货机模拟程序

    本系统为自助售货机模拟程序,可供用户和管理员使用,管理员可以通过登录实现对商品的补充和管理等操作。用户可以通过售卖页面选购自己想要的商品,进入付款页面完成付款及找零等操作。文件包含各类.class文件,和...

    自动售货机的VHDL设计程序

    可在MaxPlus Ⅱ或Quartus Ⅱ等软件平台上进行仿真...将程序在MaxPlus Ⅱ软件平台上进行编译仿真,通过分析仿真结果,自动售货机系统具有商品选择、投币处理、比价、出货找零、计时、异常退币等主要功能,符合设计要求。

    基于51单片机的自动售货机+仿真+代码+原理图

    本源码附带了仿真程序,采用Proteus7.8进行...自动售货机 1、内置16种商品,价格不一 2、具有投币口,可投5元、1元、0.5元硬币 3、具有找零、退钱功能 4、单词交易最高价格不能超过90 5、使用继电器模拟找零和出货过程

    c++课程设计 自动饮料售卖机 源代码

    1. 项目说明该项目模拟饮料自动售货机的销售过程。顾客先投币,系统显示投币金额。接下来顾客选择要购买的饮料,如果投币金额足够并且所购饮料存在,则提示用户取走饮料,同时找零。如果投币金额不足,显示提示信息...

    一个自动贩卖机系统C#控制台应用程序

    应用控制台应用程序实现了字的贩卖机系统的选购界面和管理界面,根据现实中的概率编制了一个模拟验钞装置和找零功能,用户的每次操作自动记录到文件中以便管理员查看,商品和零钱数目,同时管理员可以处理钱和商品的...

    C语言实现自动售卖机

    模拟自动饮料机。 按屏幕所示功能,输入所选择的合法数字,输出可获得的相应饮品。 ======================自动饮料机========================= 1. 可乐 3¥ 2. 尖叫 3¥ 3. 冰峰 1.5¥ 4. 芬达 4¥ 5. 雪碧 3.5¥ 6....

    473.基于51单片机的售货机(仿真).rar

    自动售货机 1、内置16种商品,价格不一 2、具有投币口,可投5元、1元、0.5元硬币 3、具有找零、退钱功能 4、单词交易最高价格不能超过90 5、使用继电器模拟找零和出货过程 资料包括程序、原理图、仿真、流程图、器件...

    Labview自动贩卖机

    ①售货模块:模拟一个自动贩卖机的工作过程。它的一次正常交易过程为:投币→选择需要购买的商品→找币,当币值不足或商品已经销售完毕时则无法购买。 ②管理员参数配置模块:系统管理员可以在此设置商品的单价与...

Global site tag (gtag.js) - Google Analytics