I am coding a cost function for a game. Players have a hand of n < 14
Resources of the following possible types:
Fire, Air, Water, Earth, Good, Evil, Law, Chaos, Void
这些被细分为两类:元素(火、气、水、土)和哲学(善、恶、法、混沌).玩家采取的行动有cost个,可以是资源或类别的任意组合.
- 示例成本:
[Fire, Air, Evil, Philosophy, Philosophy]
cost中的每个资源必须由玩家hand中的相应资源支付.成本中的类别可以由该类别中的任何资源填充.成本也可能包括Any
,可以由任何资源类型填充.要支付费用,玩家必须从hand个资源中拿出select个资源,然后单击该操作.这将触发一个求值函数,如果selected个资源满足cost,则返回True
.
Void
是一种"通配符"资源,可用于支付任何其他资源的费用.(这并不适用于其他情况-玩家无法通过使用其他资源支付Void
美元的费用.)
- 上述示例成本的有效付款为
[Void, Void, Air, Good, Good]
我目前很难理解如何实现这一点.我当前的判断函数无法处理类别或Void
的替换;它只是判断精确的等效性:
/** Returns true if the resources currently selected by the player
* satisfy the @cost of the option selected */
evaluatePayment(cost: Resource[]): boolean {
let isValidPayment: boolean = true;
if (cost) {
const playerSelectedResources: Resource[] = this.playerHand
.filter(r => r.isSelected)
.map(hr => hr.type);
// Check that selected resources cover cost
const missingCost = cost.filter(r => playerSelectedResources.indexOf(r));
// Check that no additional resources are selected
const excessPaid = playerSelectedResources.filter(r => cost.indexOf(r));
if (missingCost.length > 0 || excessPaid.length > 0) {
isValidPayment = false;
}
}
return isCostSelected;
}
根据反馈,以下是问题的更好表述:
enum Resource {
FIRE,
AIR,
WATER,
EARTH,
GOOD,
EVIL,
LAW,
CHAOS,
VOID,
ELEMENT, // This can only appear in a Cost, never a Payment
PHILOSOPHY, // This can only appear in a Cost, never a Payment
ANY // This can only appear in a Cost, never a Payment
}
export const ElementResources: Resource[] = [Resource.FIRE, Resource.AIR, Resource.WATER, Resource.EARTH];
export const PhilosophyResources: Resource[] = [Resource.GOOD, Resource.EVIL, Resource.LAW, Resource.CHAOS];
function isValidExactPayment(cost: Resource[], payment: Resource[]): boolean {
/** Logic here
* Returns True if payment matches cost exactly,
* according to the rules above */
}
更多示例:
/** Example 1 */
const cost: Resource[] = [Resource.WATER, Resource, EVIL];
isValidExactPayment(cost, [Resource.WATER, Resource.EVIL]); // true
isValidExactPayment(cost, [Resource.EVIL, Resource.VOID]); // true
isValidExactPayment(cost, [Resource.VOID, Resource.EVIL]); // true, order should not matter
isValidExactPayment(cost, [Resource.WATER, Resource.VOID]); // true
/** Example 2 */
const cost: Resource[] = [Resource.VOID];
isValidExactPayment(cost, [Resource.VOID]); // true
isValidExactPayment(cost, [Resource.EVIL]); // false
/** Example 3 */
const cost: Resource[] = [Resource.GOOD];
isValidExactPayment(cost, [Resource.GOOD]); // true
isValidExactPayment(cost, [Resource.VOID]); // true
isValidExactPayment(cost, [Resource.EVIL]); // false
/** Example 4 */
const cost: Resource[] = [Resource.AIR, Resource.PHILOSOPHY, Resource.PHILOSOPHY];
isValidExactPayment(cost, [Resource.AIR, Resource.EVIL, Resource.CHAOS]); // true
isValidExactPayment(cost, [Resource.VOID, Resource.GOOD, Resource.GOOD]); // true
isValidExactPayment(cost, [Resource.AIR, Resource.CHAOS, Resource.VOID]); // true
/** Example 5 */
const cost: Resource[] = [Resource.ELEMENT]
isValidExactPayment(cost, [Resource.FIRE]); // true
isValidExactPayment(cost, [Resource.AIR]); // true
isValidExactPayment(cost, [Resource.WATER]); // true
isValidExactPayment(cost, [Resource.EARTH]); // true
isValidExactPayment(cost, [Resource.VOID]); // true
/** Example 6 */
const cost: Resource[] = [Resource.WATER, Resource.ANY, Resource.ANY]
isValidExactPayment(cost, [Resource.WATER, Resource.WATER, Resource.WATER]); // true
isValidExactPayment(cost, [Resource.FIRE, Resource.FIRE, Resource.FIRE]); // false
isValidExactPayment(cost, [Resource.VOID, Resource.WATER, Resource.LAW]); // true
/** Example 7 */
const cost: Resource[] = [Resource.FIRE, Resource.EVIL, Resource.PHILOSOPHY, Resource.ELEMENT];
isValidExactPayment(cost, [Resource.FIRE, Resource.EVIL, Resource.EVIL, Resource.EARTH]); // true
isValidExactPayment(cost, [Resource.FIRE, Resource.EVIL, Resource.EVIL, Resource.VOID]); // true
isValidExactPayment(cost, [Resource.VOID, Resource.EVIL, Resource.GOOD, Resource.WATER]); // true
我目前很难理解如何实现更复杂的成本判断功能.