交易卡游戏中卡片效果的基本逻辑/流程

时间:2015-02-12 00:13:17

标签: java

之前我做过一个简单的纸牌游戏,我对整个程序的流程有所了解。我担心的主要问题是卡片触发器。

让我们说我们有一张名为" Guy"随着"每当你玩另一张牌时,获得2点生命"。我将如何将其合并到我的代码中?每次我打牌时,我是否必须检查盖伊是否在场上,如果他是,那么它将运行代码以获得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;
  }
}