之前我做过一个简单的纸牌游戏,我对整个程序的流程有所了解。我担心的主要问题是卡片触发器。
让我们说我们有一张名为" Guy"随着"每当你玩另一张牌时,获得2点生命"。我将如何将其合并到我的代码中?每次我打牌时,我是否必须检查盖伊是否在场上,如果他是,那么它将运行代码以获得2点生命?由于所有潜在的触发因素,当我在游戏中获得更多牌时,这似乎会使我的代码的主要部分变得非常快。我想找出最佳方法。
答案 0 :(得分:1)
在这种情况下防止代码混乱的好方法是定义哪种类型的"事件"你的游戏中可能会发生你的牌可能需要做出反应的事情。对于每个这样的事件,在卡的基类中定义一个方法(我假设你知道继承和抽象方法和类;否则,你需要首先阅读它),并实现该方法适用于每个子类。
public abstract class Card {
protected Player owner; // Assume there's a constructor that sets this
public abstract void anotherCardWasPlayed(Card theOtherCard);
}
public class GuyCard extends Card {
public void anotherCardWasPlayed(Card theOtherCard) {
owner.gainLife(2);
}
}
每当您的游戏中发生特定事件时,请遍历所有卡并调用相应的方法。
如果大多数卡片类不需要为特定活动做任何事情,您可能希望将该方法设为非abstract
,这样您就不必在卡片课程对它不感兴趣。
以控制事件流的一些额外代码为代价,这使得每张卡的特殊规则的代码保存在该卡的类中。这种方法基本上是Observer pattern,在Java框架中非常普遍。
如果您对要互动的卡片组有特殊规则,请查看Double dispatch模式。
答案 1 :(得分:1)
正如Aasmund Eldhuset所提到的,观察者模式是一个很好的方式。解决这个问题的另一种方法是让卡片自己注册以进行通知。这种方法的一个很好的例子是Swing的Observer和Observable。
它们有点陈旧,并不是真正的类型安全,但我们可以做得更好而不需要太多努力。
import com.google.common.collect.ImmutableList;
import java.util.HashSet;
import java.util.Set;
/** Like Observable, but type-safe */
public class Event<T> {
/** Like Observer, but type-safe */
public interface EventWatcher<T>{
void onEvent(Event<T> event, T arg);
}
private final Set<EventWatcher<T>> Watchers = new HashSet<>(10);
/** Adds a watcher that will be receive events. */
public void addWatcher (EventWatcher<T> watcher) {
if (null != watcher) {
synchronized(Watchers) {
Watchers.add(watcher);
}
}
}
/** Removes a watcher, so that it no longer receives events. */
public void removeWatcher (EventWatcher<T> watcher) {
if (null != watcher) {
synchronized(Watchers) {
Watchers.remove(watcher);
}
}
}
/** Removes all watchers attached to this instance. */
public void clearWatchers () {
synchronized(Watchers) {
Watchers.clear();
}
}
/** Notifies all of the watchers for this object, passing them 'arg'. */
public void fire(T arg) {
if (null == arg) {
return;
}
// Freeze the list of watchers to be notified
ImmutableList<EventWatcher<T>> copy_of_watchers;
synchronized(Watchers) {
copy_of_watchers = ImmutableList.copyOf(Watchers);
}
// Release the monitor before heading off to execute arbitrary code.
for(EventWatcher<T> watcher : copy_of_watchers) {
watcher.onEvent(this, arg);
}
}
}
使用Java 1.8 lambdas非常简单,没有它们就不会有麻烦。在你的情况下,它看起来像这样:
public interface Card {
void drawnFrom(Deck source);
}
public class AwesomeCard implements Card {
public void drawnFrom(Deck source) {
source.CardDrawnEvent.addWatcher((Event<Card> event, Card arg) -> {
// Give the owner Life
});
}
}
public class Deck {
public Event<Card> CardDrawnEvent = new Event<>();
public Card draw() {
Card drawn_card = new AwesomeCard();
drawn_card.drawnFrom(this);
CardDrawnEvent.fire(drawn_card);
return drawn_card;
}
}