Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 交易纸牌游戏中纸牌效果的基本逻辑/流程_Java - Fatal编程技术网

Java 交易纸牌游戏中纸牌效果的基本逻辑/流程

Java 交易纸牌游戏中纸牌效果的基本逻辑/流程,java,Java,我以前做过一个简单的纸牌游戏,我对程序的整体流程有一些想法。我最关心的是卡片触发器 假设我们有一张名为“Guy”的牌,效果是“每当你玩另一张牌时,获得2点生命”。我将如何将其合并到我的代码中?每次我玩一张牌,我是否必须检查盖伊是否在场,如果他在场,它将运行代码获得2条生命?由于所有潜在的触发因素,当我在游戏中获得更多的牌时,这似乎会很快地扰乱我代码的主要部分。我想找出实现这一点的最佳方法。防止代码在这种情况下变得混乱的一个好方法是定义您的卡牌可能需要响应的游戏中可能发生的“事件”。对于每一个这样

我以前做过一个简单的纸牌游戏,我对程序的整体流程有一些想法。我最关心的是卡片触发器


假设我们有一张名为“Guy”的牌,效果是“每当你玩另一张牌时,获得2点生命”。我将如何将其合并到我的代码中?每次我玩一张牌,我是否必须检查盖伊是否在场,如果他在场,它将运行代码获得2条生命?由于所有潜在的触发因素,当我在游戏中获得更多的牌时,这似乎会很快地扰乱我代码的主要部分。我想找出实现这一点的最佳方法。

防止代码在这种情况下变得混乱的一个好方法是定义您的卡牌可能需要响应的游戏中可能发生的“事件”。对于每一个这样的事件,在卡片的基类中定义一个方法(我假设您了解继承和抽象方法和类;否则,您需要先了解它),并在每个子类中适当地实现该方法

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);
    }
}
每当游戏中发生特定事件时,循环所有卡牌并调用相应的方法

如果大多数卡片类不需要为特定事件执行任何操作,那么您可能希望将该方法设置为非抽象的,这样您就不必在对它不感兴趣的卡片类中实现它

以控制事件流的额外代码为代价,这会将每张卡的特殊规则的代码保留在该卡的类中。这种方法本质上是Java框架中非常普遍的方法


如果您对交互的卡片对有特殊规则,请查看模式。

正如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);
        }
    }
}
import com.google.common.collect.ImmutableList;
导入java.util.HashSet;
导入java.util.Set;
/**类似于可观察,但类型安全*/
公开课活动{
/**与Observer类似,但类型安全*/
公共接口事件观察程序{
void onEvent(事件,T参数);
}
私有最终集观察者=新哈希集(10);
/**添加将接收事件的监视程序*/
public void addWatcher(EventWatcher-watcher){
if(null!=观察者){
同步(观察者){
Watchers.add(watcher);
}
}
}
/**删除观察程序,使其不再接收事件*/
public void removeWatcher(事件观察者观察者){
if(null!=观察者){
同步(观察者){
观察者。移除(观察者);
}
}
}
/**删除连接到此实例的所有观察者*/
公共无效清除者(){
同步(观察者){
Watchers.clear();
}
}
/**通知此对象的所有观察者,并将其传递为“arg”*/
公共空间火灾(T参数){
if(null==arg){
返回;
}
//冻结要通知的观察者列表
观察者的不可变列表副本;
同步(观察者){
copy_of_watchers=ImmutableList.copyOf(watchers);
}
//在出发执行任意代码之前释放监视器。
for(EventWatcher-watcher:U-watchers的副本){
watcher.onEvent(这个,arg);
}
}
}
对于Java1.8Lambdas来说,使用它非常简单,没有它们也不会很麻烦。在您的情况下,它看起来是这样的:

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;
  }
}
公共接口卡{
来自(甲板源)的无效图纸;
}
公共类AwesomeCard实现了一个{
公共作废图纸(甲板来源){
source.CardDrawnEvent.addWatcher((事件,卡参数)->{
//给主人生命
});
}
}
公务舱甲板{
公共事件CardDrawnEvent=新事件();
公众卡提款(){
卡片绘制\卡片=新卡片();
从(本)中提取的卡;
卡德拉瓦内万特火(抽卡);
回款卡;
}
}

太棒了,这正是我想要的。所以我只是想确保我理解,例如,每当我玩一张牌时,我都会在场上的每张牌上循环,并为场上的每张牌调用另一个cardwasplay函数。那么,如果这张牌没有另一个CardWasplayed功能(如果我有一张牌,当你玩一张牌时,它不起作用),这是如何工作的呢。我是否只定义函数,而将其留空?运行空白函数会使程序变慢吗?没错。假设所有卡片类都扩展了
card
,它们必须有
另一个cardplayed()
,因为该方法在
card
中声明为抽象,所以所有非抽象子类都必须实现它。或者,如果您在
卡片
中使用空主体使其非抽象,则不重写它的子类将继承空方法。调用一个空方法需要几十或几百纳秒,所以我不会担心,除非你有数百万张卡:-)这是一个通过使用多态性和正确覆盖得到便利的例子:你可以有一个
实例的列表,而不知道每一张卡是什么类型,您只需对它们中的每一个调用另一个cardplayed()
,并确信正确的操作将发生。