我正在建立一个扑克游戏。在我的申请中,我有一个班级ChipSet
。 ChipSet
基本上是5个整数的数组(每个颜色扑克筹码一个)。
public class ChipSet {
public static final int WHITE_VALUE = 1;
public static final int RED_VALUE = 2;
public static final int GREEN_VALUE = 5;
public static final int BLUE_VALUE = 10;
public static final int BLACK_VALUE = 20;
public static final int[] VALUES = new int[]{WHITE_VALUE, RED_VALUE, GREEN_VALUE, BLUE_VALUE, BLACK_VALUE};
protected int[] chips;
public ChipSet(int[] chips) {
if (chips == null || chips.length != 5)
throw new IllegalArgumentException("ChipSets should contain exactly 5 integers!");
// store a copy of passed array
this.chips = new int[5];
for (int i = 0; i < this.chips.length; i++) {
this.chips[i] = chips[i];
}
}
public int getSum() {
return chips[0] * WHITE_VALUE +
chips[1] * RED_VALUE +
chips[2] * GREEN_VALUE +
chips[3] * BLUE_VALUE +
chips[4] * BLACK_VALUE;
}
}
现在如果我有ChipSet
数组[0,0,2,1,0]
(5 + 5 + 10 = 20)并且我想使用我的ChipSet
支付16美元单位。我必须交换芯片才能实现这一目标。
我需要的是一种尽可能高效交换的算法(尽可能少地交换筹码)以使这种付款成为可能。付款只会减去阵列中的筹码数量,以便剩余的钱在付款后仍然在ChipSet
。我该怎么做?
我需要的是这种方法:
public boolean exchangeToMakeAvailable(int goal) {
// algorithm to exchange chips as efficient as possible
// store the new values in the array, making sure the sum is still the same
// return whether it has succeeded (false when the sum is less than the requested amount)
}
如果你能帮我解决这个问题,我将不胜感激。
例如:
在算法之前,我有一个带有数组[0,0,2,1,0]
的ChipSet,其总和为20.我想支付16个单位的费用。使用算法后,我会尽可能进行最有效的交换,在这种情况下算法会将数组更改为[1,2,1,1,0]
,其总和也是20,但现在我可以支付16。付款ChipSet
将包含数组[0,2,0,0,0]
。
我希望我的问题很明确,如果不是,请发表评论,我会进一步解释。
答案 0 :(得分:2)
这是一个编辑,我完全重写了我的答案。
**游戏角度的问题** 该玩家有2个绿色筹码(5分)和1个蓝色(10分)。这总计20分。现在玩家想要购买一个费用为16分的游戏图标。玩家有足够的钱购买物品。因此,玩家支付16分,但他会给予商店正确支付的积分。
现在我写了一个完成所有工作的工作示例。
代码
Program.java
import java.util.Arrays;
public class Program {
public static void main(String[] args) {
// Setting up test environment
Player player = new Player("Borrie", new int[]{0,0,0,0, 230});
int itemCost = 16626;
// Pay for item
System.out.printf("First we check if the player can pay with it's current ChipSet");
if (!player.canPayWithChipSet(player.getChips(), 5)) {
if (player.exchangeChips(5)) {
System.out.printf("\n\nThe players ChipSet:" + Arrays.toString(player.getChips().chips));
System.out.printf("\nThe players ChipSet has been succesfully exchanged.");
} else {
System.out.printf("\n\nThe players ChipSet:" + Arrays.toString(player.getChips().chips));
System.out.printf("\nThe players ChipSet was not able to be exchanged.\n");
}
} else {
System.out.printf("\n\nThe player can pay exact with it's original ChipSet. No need to exchange.");
}
}
}
Player.java
import java.util.ArrayList;
import java.util.Arrays;
public class Player {
private String name;
private ChipSet chips;
private int points = 0;
public Player(String name, int[] chips) {
this.name = name;
this.chips = new ChipSet(chips);
this.points = this.chips.getSum();
}
public boolean exchangeChips(int cost) {
ChipSet newChipSet = exchangePlayerChipSet(this.chips.getChips(), cost);
if (newChipSet == null) {
return false;
} else {
this.chips = newChipSet;
return true;
}
}
public ChipSet exchangePlayerChipSet(int[] originalChipValues, int cost) {
ChipSet newChipSet = null;
// Create possible combinations to compare
ArrayList<ChipSet> chipSetCombos = createCombinations(this.chips.getChips());
// Filter the chipset based on if it's able to pay without changing chips
System.out.printf("\n\n---- Filter which of these combinations are able to be payed with without changing chips ----");
ArrayList<ChipSet> filteredCombos = filterCombinations(chipSetCombos, cost);
// Compare the filtered chipsets to determine which one has changed the least
if (!filteredCombos.isEmpty()) {
newChipSet = compareChipSets(originalChipValues, filteredCombos);
}
return newChipSet;
}
private ArrayList<ChipSet> createCombinations(int[] array) {
ArrayList<ChipSet> combos = new ArrayList<>();
int[] startCombo = array;
System.out.printf("Player has " + getTotalPoints(startCombo) + " points in chips.");
System.out.printf("\nPlayer has these chips (WHITE,RED,GREEN,BLUE,BLACK): " + Arrays.toString(startCombo));
while (startCombo[4] != 0) {
startCombo = lowerBlack(startCombo);
if (getTotalPoints(startCombo) == points) {
combos.add(new ChipSet(startCombo));
}
}
while (startCombo[3] != 0) {
startCombo = lowerBlue(startCombo);
if (getTotalPoints(startCombo) == points) {
combos.add(new ChipSet(startCombo));
}
}
while (startCombo[2] != 0) {
startCombo = lowerGreen(startCombo);
if (getTotalPoints(startCombo) == points) {
combos.add(new ChipSet(startCombo));
}
}
while (startCombo[1] != 0) {
startCombo = lowerRed(startCombo);
if (getTotalPoints(startCombo) == points) {
combos.add(new ChipSet(startCombo));
}
}
System.out.printf("\n\n---- Creating variations on the players chips ----");
System.out.printf("\nVariation (all worth " + getTotalPoints(startCombo) + " points):\n");
int teller = 1;
for (ChipSet a : combos) {
System.out.printf("\nCombo " + teller + ": " + Arrays.toString(a.getChips()));
teller++;
}
return combos;
}
private ArrayList<ChipSet> filterCombinations(ArrayList<ChipSet> combinations, int cost) {
ArrayList<ChipSet> filteredChipSet = new ArrayList<>();
combinations.stream().filter((cs) -> (canPayWithChipSet(cs, cost))).forEach((cs) -> {
filteredChipSet.add(cs);
});
return filteredChipSet;
}
// This method has be worked out
public boolean canPayWithChipSet(ChipSet cs, int cost) {
ChipSet csOrig = new ChipSet(cs.chips);
ChipSet csCopy = new ChipSet(cs.chips);
int counterWhite = 0;
int counterRed = 0;
int counterGreen = 0;
int counterBlue = 0;
int counterBlack = 0;
while (20 <= cost && cost > 0 && csOrig.getChips()[4] != 0) {
csOrig.getChips()[4] -= 1;
cost -= 20;
counterBlack++;
}
while (10 <= cost && cost > 0 && csOrig.getChips()[3] != 0) {
csOrig.getChips()[3] -= 1;
cost -= 10;
counterBlue++;
}
while (5 <= cost && cost > 0 && csOrig.getChips()[2] != 0) {
csOrig.getChips()[2] -= 1;
cost -= 5;
counterGreen++;
}
while (2 <= cost && cost > 0 && csOrig.getChips()[1] != 0) {
csOrig.getChips()[1] -= 1;
cost -= 2;
counterRed++;
}
while (1 <= cost && cost > 0 && csOrig.getChips()[0] != 0) {
csOrig.getChips()[0] -= 1;
cost -= 1;
counterWhite++;
}
if (cost == 0){
System.out.printf("\nCombo: %s can pay exact. With %d white, %d red, %d green, %d blue an %d black chips", Arrays.toString(csCopy.chips),counterWhite,counterRed,counterGreen,counterBlue,counterBlack);
return true;
} else {
System.out.printf("\nCombo: %s cannot pay exact.\n\n\n", Arrays.toString(csCopy.chips));
return false;
}
}
private ChipSet compareChipSets(int[] originalChipValues, ArrayList<ChipSet> chipSetCombos) {
ChipSet newChipSet;
int[] chipSetWaardes = originalChipValues; // originele chipset aantal van kleur
int[] chipSetCombosDifferenceValues = new int[chipSetCombos.size()];
int teller = 1;
System.out.printf("\n\n---- Calculate differences between players stack and it's variations ----");
for (ChipSet cs : chipSetCombos) {
int aantalWhite = cs.getChips()[0];
int aantalRed = cs.getChips()[1];
int aantalGreen = cs.getChips()[2];
int aantalBlue = cs.getChips()[3];
int aantalBlack = cs.getChips()[4];
int differenceWhite = Math.abs(chipSetWaardes[0] - aantalWhite);
int differenceRed = Math.abs(chipSetWaardes[1] - aantalRed);
int differenceGreen = Math.abs(chipSetWaardes[2] - aantalGreen);
int differenceBlue = Math.abs(chipSetWaardes[3] - aantalBlue);
int differenceBlack = Math.abs(chipSetWaardes[4] - aantalBlack);
int totalDifference = differenceWhite + differenceRed + differenceGreen + differenceBlue + differenceBlack;
chipSetCombosDifferenceValues[teller - 1] = totalDifference;
System.out.printf("\nCombo " + teller + ": " + Arrays.toString(cs.getChips()) + " = " + totalDifference);
teller++;
}
newChipSet = chipSetCombos.get(smallestValueOfArrayIndex(chipSetCombosDifferenceValues));
System.out.printf("\n\nThe least different ChipSet is: " + Arrays.toString(newChipSet.getChips()) + " ");
return newChipSet;
}
private int smallestValueOfArrayIndex(int[] array) {
int huidigeWaarde = array[0];
int smallestIndex = 0;
for (int j = 1; j < array.length; j++) {
if (array[j] < huidigeWaarde) {
huidigeWaarde = array[j];
smallestIndex = j;
}
}
return smallestIndex;
}
private int[] lowerBlack(int[] array) {
return new int[]{array[0], array[1], array[2], array[3] + 2, array[4] - 1};
}
private int[] lowerBlue(int[] array) {
return new int[]{array[0], array[1], array[2] + 2, array[3] - 1, array[4]};
}
private int[] lowerGreen(int[] array) {
return new int[]{array[0] + 1, array[1] + 2, array[2] - 1, array[3], array[4]};
}
private int[] lowerRed(int[] array) {
return new int[]{array[0] + 2, array[1] - 1, array[2], array[3], array[4]};
}
private int getTotalPoints(int[] array) {
return ((array[0] * 1) + (array[1] * 2) + (array[2] * 5) + (array[3] * 10) + (array[4] * 20));
}
public String getName() {
return this.name;
}
public int getPoints() {
return this.points;
}
public ChipSet getChips() {
return chips;
}
}
ChipSet.java
public class ChipSet {
public static final int WHITE_VALUE = 1;
public static final int RED_VALUE = 2;
public static final int GREEN_VALUE = 5;
public static final int BLUE_VALUE = 10;
public static final int BLACK_VALUE = 20;
public static final int[] VALUES = new int[]{WHITE_VALUE, RED_VALUE, GREEN_VALUE, BLUE_VALUE, BLACK_VALUE};
protected int[] chips;
public ChipSet(int[] chips) {
if (chips == null || chips.length != 5) {
throw new IllegalArgumentException("ChipSets should contain exactly 5 integers!");
}
// store a copy of passed array
this.chips = new int[5];
for (int i = 0; i < this.chips.length; i++) {
this.chips[i] = chips[i];
}
}
public int getSum() {
return chips[0] * WHITE_VALUE
+ chips[1] * RED_VALUE
+ chips[2] * GREEN_VALUE
+ chips[3] * BLUE_VALUE
+ chips[4] * BLACK_VALUE;
}
public int[] getChips() {
return this.chips;
}
}
一些解释:
我们创造了一些交易芯片的子方法,因为它的芯片更低。所以 例如black = 2 blues。然后我们按顺序创建5个循环。该 第一个检查是否还有黑色芯片,如果是,则减少1个黑色 添加2个蓝调。如果总和,请将此新组合保存在列表中 新ChipSet中的芯片等于原始ChipSets值。环 继续,直到没有黑人为止。然后检查是否存在 是蓝色并重复相同的过程,直到没有红色 了。现在我们列出了X值的所有可能变化 芯片。
您可以根据此过滤ChipSets 如果你可以与他们支付X点而不需要交换。我们遍布所有 前一部分中创建的ChipSets的可能组合。如果你 可以使用ChipSet进行支付而无需将其添加到filteredList中 ChipSets。结果是只有有效ChipSets的文件列表。
对于每个ChipSet,我们计算a中所有颜色的芯片数量 ChipSet并用它减去原始芯片组的芯片数量。 你取这个的绝对值,并将所有这些的总和 原始和组合颜色的差异。现在我们有一个 代表与原始差异的数字。现在我们所有人 要做的就是比较所有ChipSets的差异号码。唯一的那个 我们用来分配给玩家的差异最小。
简单呵呵
答案 1 :(得分:0)
你可以试试binpacking。对芯片进行分类并选择最合适的芯片。然后计算它剩下的数量,并交换芯片或冲洗并重复。