我正在制作纸牌游戏,其中牌被表示为JLabel,具有在游戏期间改变的名称和一些其他属性。我想将等式定义为简单地比较两张牌的全名(由字段fullName
表示)。但是,这给我的问题是我不能两次添加相同的卡(因为我在Card类中有其他可能不同的字段)。
显然,JPanel会在后台检查equals
。然后我为每张卡片添加一个独特的id
字段,在课堂上我会跟踪我创建的那种卡片的数量
private static Map<AbstractCard, Integer> idCount = new HashMap<AbstractCard, Integer>();
然后每次调用某张卡的构造函数时,我都会增加idCount
中的值。但是,如果我添加id
以及原始name
的检查,不仅地图会中断,但如果名称相同,它仍然不会添加多张卡。这就是现在的方法:
/**
* Compares this card to the specified object. The result is true if and only if
* the argument is not null and is a Card object that represents the same full name
* as this card.
* @return true if the cards are equal, otherwise false
*/
@Override
public boolean equals(Object o)
{
if (!(o instanceof AbstractCard))
return false;
else
{
AbstractCard c = (AbstractCard)o;
return this.fullName.equals(c.fullName) && this.id == c.id;
}
}
关于如何解决这个问题的任何想法?
编辑:我的hashCode
返回fullName.hashCode()
,在当前版本中我添加id
。
答案 0 :(得分:2)
修改强>
我做了以下测试,它运行良好:
private class MyLabel extends JLabel {
public MyLabel(String text) {
super(text);
}
public boolean equals(Object obj) {
return true;
}
};
public MyPanel() {
getContentPane().setLayout(new GridLayout());
getContentPane().add(new MyLabel("Label 1"));
getContentPane().add(new MyLabel("Label 2"));
getContentPane().add(new MyLabel("Label 3"));
}
你面临什么问题?
BTW:这不会解决您的问题,但equals
的JavaDoc说
请注意,一旦覆盖此方法,通常需要覆盖
hashCode
方法
如果卡片延伸JLabel
,并且您为每张卡片创建了一个实例,则根本不必覆盖equals
。确保不要将同一张卡添加到两个容器(或一个容器两次)。这也不适用于真实卡片。
将卡类与其可视化分开可能是更好的方法。你有没有考虑过不在秋千课上扩展你的卡?
您可以覆盖toString
并将其显示在JList
。
答案 1 :(得分:1)
HashMaps依赖于hashcode来找到正确的“bucket”,然后通过相等测试选择正确的元素。如果您没有覆盖hashCode(),则即使HashMap存在,HashMap也可能无法检索该项。一般来说,总是一起覆盖equals()和hashCode()。
但是,我会敦促你重新考虑你的设计。这种引用计数不是一个好主意。此外,您将过多的逻辑和模型元素混合到GUI代码中。您应该考虑采用更多的模型 - 视图 - 控制器来解决问题。让游戏完全建模,然后让UI代表模型。答案 2 :(得分:0)
我非常抱歉,这似乎一直是我自己的错。经过大量的调试和打印后,我发现我在面板中有一个参考,是另一个面板的一部分,所以我不知何故只“真的”有3张牌。在我删除了引用并改为使用新卡后,它最终显示出来并且getComponentCount
返回了4。
再一次,我很抱歉浪费你的时间。
答案 3 :(得分:0)
顺便说一句,你可能喜欢阅读这个简单game的来源。它根本不是纸牌游戏,但是GameButton
类可能会建议使用Unicode字形来表示卡的等级和套装。