gpt4 book ai didi

java - 三合会不出现战斗? (Java Set 缺少一项)

转载 作者:行者123 更新时间:2023-12-02 08:38:11 25 4
gpt4 key购买 nike

我有来自两家公司 asoft 和 bsoft 的代码。我也无法改变。这是我的情况的简化版本,我确信有足够的信息来查找导致问题的原因。

bsoft提供了IGang,它代表一个可以与其他帮派作战的帮派。

package bsoft;

public interface IGang {
/** @return negative, 0, or positive, respectively
* if this gang is weaker than, equal to, or stronger
* than the other
*/
public int compareTo(IGang g);
public int getStrength();
public String getName();
public void attack(IGang g);
public void weaken(int amount);
}

asoft提供GangWar,允许IGang进行战斗:

package asoft;
import java.util.*;
import bsoft.*;
/** An `IGang` ordered by identity (name) */
public interface ComparableGang extends IGang, Comparable<IGang> {}

package asoft;
import java.util.*;

public class GangWar {
public final Set<ComparableGang> gangs = new TreeSet<ComparableGang>();
public void add(ComparableGang g) {gangs.add(g);}
public void doBattle() {
while (gangs.size() > 1) {
Iterator<ComparableGang> i = gangs.iterator();
ComparableGang g1 = i.next();
ComparableGang g2 = i.next();
System.out.println(g1.getName() + " attacks " + g2.getName());
g1.attack(g2);
if (g2.getStrength() == 0) {
System.out.println(g1.getName() + " smokes " + g2.getName());
gangs.remove(g2);
}
if (g1.getStrength() == 0) {
System.out.println(g2.getName() + " repels " + g1.getName());
gangs.remove(g1);
}
}
for (ComparableGang g : gangs) {
System.out.println(g.getName() + " now controls the turf!");
}
}
}

它需要额外的约束,即您提供给它的GangComparable,大概这样它就可以按名称排序或避免重复。每个帮派(以任意顺序,为简单起见,此处使用设定顺序)攻击另一个帮派,直到只剩下一个帮派(或者没有帮派,如果最后两个帮派平局)。我编写了一个 ComparableGang 的简单实现来测试它:

import asoft.*;
import bsoft.*;
import java.util.*;

class Gang implements ComparableGang {
final String name;
int strength;

public Gang(String name, int strength) {
this.name = name;
this.strength = strength;
}

public String getName() {return name;}
public int getStrength() {return strength;}

public int compareTo(IGang g) {
return strength - g.getStrength();
}

public void weaken(int amount) {
if (strength < amount) strength = 0;
else strength -= amount;
}

public void attack(IGang g) {
int tmp = strength;
weaken(g.getStrength());
g.weaken(tmp);

}

public boolean equals(Object o) {
if (!(o instanceof IGang)) return false;
return name.equals(((IGang)o).getName());
}
}

class Main {
public static void main(String[] args) {
GangWar gw = new GangWar();
gw.add(new Gang("ballas", 2));
gw.add(new Gang("grove street", 9));
gw.add(new Gang("los santos", 8));
gw.add(new Gang("triads", 9));
gw.doBattle();
}
}

测试一下...

$ java Main
ballas attacks los santos
los santos repels ballas
los santos attacks grove street
grove street repels los santos
grove street now controls the turf!

问题是,黑社会不会出现在战斗中。事实上,在 doBattle() 开始处打印 gangs.size() 会返回 3 而不是 4。为什么呢?如何解决?

最佳答案

The problem is, triads do not show up to the fight. In fact, printing gangs.size() right at the start of doBattle() returns 3 instead of 4. Why?

两者triadsgrove street强度为 9。因此它们在 Gang.compareTo 方面相等(实现Comparable)。因此,TreeSet 中只允许有一个。 .

如果您不想删除排序顺序重复的项目,请不要使用 TreeSet ...

编辑:ComparableGang接口(interface)描述表明了预期的内容:

/** An `IGang` ordered by identity (name) */
public interface ComparableGang extends IGang, Comparable<IGang> {}

您的compareTo方法“按身份(名称)”排序 - 它按强度排序。说实话,这首先是一个相当愚蠢的界面,因为它对于 asoft 来说是非常简单的。创建一个类 public class GangNameComparator : Comparator<IGang> ,然后将其作为树集的比较器(如果他们想按名称排序)提供。

但是,由于他们建议您应该实现比较,因此您需要按照界面描述进行操作:

public int compareTo(IGang g) {
return name.compareTo(g.getName());
}

但是...正如您在评论中指出的那样(以及罗布的回答中指出的那样),这与打破惯例的命名 IGang 相矛盾。描述:

public interface IGang {
/** @return negative, 0, or positive, respectively
* if this gang is weaker than, equal to, or stronger
* than the other
*/
public int compareTo(IGang g);
}

不可能实现ComparableGang满足其自己的文档和 IGang文档。这基本上是由 asoft 的设计所打破的。

任何代码都应该能够使用IGang实现,了解IGang ,并依赖于IGang之后的实现契约(Contract)。然而,asoft 打破了这一假设,要求扩展 IGang 的接口(interface)中具有不同的行为。 .

他们在 ComparableGang 中添加更多要求是合理的。 ,只要它们不违反 IGang现有要求.

请注意,这是 C# 和 Java 之间的一个重要区别。在 C# 中,具有相同签名的两个不同接口(interface)中的两个函数可以组合成一个继承它们的接口(interface),并且 the two methods remain distinct and accessible 。在Java中,这两个方法是完全抽象的并且具有相同的签名,因此是considered to be the same method并且实现组合接口(interface)的类只有一个这样的方法。所以在Java ComparableGang无效,因为它不能有满足 ComparableGang 契约和 IGang 契约的compareTo() 实现。

关于java - 三合会不出现战斗? (Java Set 缺少一项),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15795058/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com