Java 用一定数量的硬币归还零钱
我想实现一个自动咖啡自动售货机。机器预先装满硬币(例如10枚5美分硬币、20枚10美分硬币等) 我希望用户输入一定的金额(插入货币)减去咖啡的价格(例如120美分),然后根据自动售货机中可用的硬币将零钱退回 我是这样开始的:Java 用一定数量的硬币归还零钱,java,Java,我想实现一个自动咖啡自动售货机。机器预先装满硬币(例如10枚5美分硬币、20枚10美分硬币等) 我希望用户输入一定的金额(插入货币)减去咖啡的价格(例如120美分),然后根据自动售货机中可用的硬币将零钱退回 我是这样开始的: final int [] coins = {200, 100, 50, 20, 10, 5}; …但是我怎样才能给它们一个像10=5这样的值,因为有5枚10美分的硬币?你可以把它们存储在地图上,例如 然后,您将使用硬币的价值作为关键,使用金额作为价值。 例如: Map&
final int [] coins = {200, 100, 50, 20, 10, 5};
…但是我怎样才能给它们一个像10=5这样的值,因为有5枚10美分的硬币?你可以把它们存储在地图上,例如 然后,您将使用硬币的价值作为关键,使用金额作为价值。 例如:
Map<Integer, Integer> coins = new HashMap<>();
coins.put(10, 5); //5 10-cent coins
(如果您不熟悉enum
s,则每个条目基本上都被命名为类的最终静态实例)
现在我们有了存储硬币的方法,我们将创建一个类来包装和处理这些数据CoinDispender
听起来是个好名字
public class CoinDispenser {
private final Map<Coin, Integer> coinCount = new HashMap<>();
public enum Coin {...}
}
很简单,对吧?是时候继续下一个方法了,getChange(int-amount)
。这种方法的算法非常简单,去掉了大硬币的拳头。这是v1:
public Map<Coin, Integer> getChange(int amount) {
List<Coin> types = Arrays.asList(Coin.values());
Collections.reverse(types);
Map<Coin, Integer> ret = new HashMap<>();
fillWithDefault(ret);
int amountLeft = amount;
for (Coin c: types) {
while (amountLeft >= c.value && getCoinCount(c) > 0) {
amountLeft -= c.value;
ret.put(c, ret.get(c) + 1);
addCoins(c, -1);
}
}
return ret;
}
我们还有最后一个错误。假设我们有
1个25美分
和5个10美分
,然后我们尝试抽取50美分,它将抛出IllegalArgumentException(“硬币不足!!”)
。如果您浏览getchangeinpl
的逻辑,这是有意义的,因为我们首先尝试绘制大硬币-Quarter
,在这种情况下-我们绘制一个,因此我们有5个一角硬币
,没有Quarters
来弥补25美分
。我把这个留给读者作为练习。2个快速的可能性是:1)2个数组(一个带有硬币值,第二个带有机器中硬币数量),或2)散列(键是硬币值,值是硬币数量)。我建议你用#算法标记这个问题,您可能会得到更多的关注…考虑一下,但我可以覆盖该值吗?e、 g.put(10,4);在机器发出一个10克拉硬币后,或者有没有更聪明的方法来覆盖/编辑是的,如果机器发出一个10克拉硬币,你就可以做硬币。投入(10,硬币。获得(10)-1);谢谢,那我就试试看!谢谢你的回答,我明天会仔细看一看,但到目前为止,这看起来还不错。因此,如果客户要插入一美元,它将类似于:if(readInt(“此处插入硬币”)==100{vm.addCoins(Coin.dollar,1);}?是的,或者等于一美元的任何硬币组合。如果要添加美元
硬币,则必须更改半美元(50)代码>硬币的行
枚举到半美元(50),美元(100)
因为Coin
的条目必须按顺序排列,否则getChange
中的逻辑将不再有效。这是一个答案,它有代码,但它没有解释为什么它是一个好答案。它也没有解释您为满足实际需求而采取的步骤。我确信这段代码是有效的,但它对教学几乎没有帮助;它只鼓励主动复制和粘贴。@Makoto有帮助吗?我加了一点解释。它提供了更多的解释(这足以让我消除我的反对票),但感觉有点…太多了。
public enum Coin {
Penny (1),// each coin and it's value
Nickle (5),
Dime (10),
Quarter (25),
HalfDollar (50);
/** The value of the coin in cents. */
public final int value;
Coin(int value) {this.value = value;}
}
Map<Coin, Integer> coinCount = new HashMap<>();
public class CoinDispenser {
private final Map<Coin, Integer> coinCount = new HashMap<>();
public enum Coin {...}
}
public class CoinDispenser {
private final Map<Coin, Integer> coinCount = getDefaultMap();
public void addCoins(Coin type, int amount) {
coinCount.put(type, amount + getCoinCount(type));
}
public int getCoinCount(Coin type) {
return coinCount.get(type);
}
// We can't start with an empty map
private static Map<Coin, Integer> getDefaultMap() {
Map<Coin, Integer> ret = new HashMap<>();
for (Coin c: Coin.values())
ret.put(c, 0);
return ret;
}
public enum Coin {...}
}
public Map<Coin, Integer> getChange(int amount) {
List<Coin> types = Arrays.asList(Coin.values());
Collections.reverse(types);
Map<Coin, Integer> ret = new HashMap<>();
fillWithDefault(ret);
int amountLeft = amount;
for (Coin c: types) {
while (amountLeft >= c.value && getCoinCount(c) > 0) {
amountLeft -= c.value;
ret.put(c, ret.get(c) + 1);
addCoins(c, -1);
}
}
return ret;
}
public Map<Coin, Integer> getChange(int amount) {
Map<Coin, Integer> ret = getDefaultMap();
if (getChangeImpl(amount, false, getDefaultMap())) {// if we have the right coins...
getChangeImpl(amount, true, ret);// Do the real thing
return ret;
}
throw new IllegalArgumentException("Insufficient coins!!");// fall through case
}
private boolean getChangeImpl(int amount, boolean isMock, Map<Coin, Integer> out) {
...
for (Coin c: types)
while (amountLeft >= c.value && getCoinCount(c) > 0) {
...
if (isMock == false)// if this is the real thing
addCoins(c, -1);// remove one coin from inventory
}
return amountLeft == 0;// if we have the correct coins, this will be zero
}