首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >玩家类的人和AI子类

玩家类的人和AI子类
EN

Software Engineering用户
提问于 2019-10-31 16:16:50
回答 1查看 627关注 0票数 2

我希望在我的Java程序中实现两个类的分支,以便在我的游戏中区分人类和人工智能控制的玩家。游戏是异步的,因此玩家有不同的方法和行为,取决于他们在游戏开始时选择的是哪种类型的玩家。所有玩家都有共享的方法,每个Player子类都有唯一的方法,只有他们能做到。此外,当AI玩家自动做出选择时,人类玩家会收到做出决定的提示。可能有无限数量的玩家子类,每个子类都有一个人和人工智能版本。

因为Java没有真正的多重继承,所以我目前的解决方案是使用AI玩家继承的AI接口和Human继承的人工接口。这些接口中的每一个都有一个唯一的makeDecision()方法,用于每个可能的决策。从决策界面重写代码很好,因为不同类型的玩家不应该拥有相同的AI。

下面是我的代码结构的一个简单示例:

代码语言:javascript
复制
public interface AI
{
   int chooseNumber(); 
}

public interface Human 
{
    int chooseNumber();
}

public abstract class Player
{ 
    int score;
    void gainPoint()
    { 
        score++;
    }
}

public class RedPlayer extends Player
{
   void doRedThing();
}

public class RedHumanPlayer extends RedPlayer implements Human
{
    int chooseNumber()
    { 
      //Human chooses number
    }
}

public class RedAIPlayer extends RedPlayer implements AI
{
    int chooseNumber()
    {
       return 3;
    }
}

public class BluePlayer extends Player
{
    void doBlueThing();
}

public class BlueHumanPlayer extends BluePlayer implements Human
{
    int chooseNumber()
    { 
      //Human chooses number
    }
}

public class BlueAIPlayer extends BluePlayer implements AI
{
    int chooseNumber()
    {
       return 4;
    }
}

我想确定的是,这是否是在Java中设置这样一个系统的最佳实践,或者是否有一种更优化的策略。在实际执行所有编码之前,我宁愿创建一个合适的蓝图。

EN

回答 1

Software Engineering用户

回答已采纳

发布于 2019-10-31 19:18:55

我认为你的想法中的第一个错误是,在游戏的背景下,你不是真的在建模一个AIHuman,而是在建模一个Player。您只是碰巧有不同的Player实现。从游戏的角度来看,人类和人工智能玩家之间不应该有任何区别。

您首先需要考虑的是Player的接口,玩家需要做什么?我们可以将其建模如下:

代码语言:javascript
复制
public interface Player {

    int chooseNumber();

    void gainPoint();
}

然后您可以使用不同类型的Players:

代码语言:javascript
复制
public interface BluePlayer extends Player{

    void doBlueThing();

}

public interface RedPlayer extends Player{

    void doRedThing();

}

现在,基于@RomanVettner的S注释,您可以实现一个RedPlayer类和一个BluePlayer类,它们分别采用RedStrategyBlueStrategy,然后提供人工智能和人工版本的策略:

代码语言:javascript
复制
public interface Strategy {
    //interface specification
}

public interface RedStrategy extends Strategy {

    void doRedThing();

}

public interface BlueStrategy extends Strategy {

    void doBlueThing();

}

public abstract class BasePlayer<S extends Strategy> implements Player {

    private S strategy;
    private int score;

    public Player(S strategy){
        this.strategy = strategy;
    }

    public updateStrategy(S newStrategy){
        this.strategy = newStrategy;
    }

    public void gainScore(){
        this.score++;
    }

    protected S strategy(){
        return this.strategy;
    }
}

public class RedPlayerImpl extends BasePlayer<RedStrategy> implements RedPlayer {

    public RedPlayerImpl(RedStrategy strategy){
        super(strategy);
    }

    public void doRedThing(){
        this.strategy().toRedThing();
    }
}

public class RedHumanStrategy implements RedStrategy {
    //implementation for Human
}

public class RedAiStrategy implements RedStrategy {
    //implementation for AI
}

//you get the rest
...

现在游戏应该只关心Player接口,而不关心它们是如何实现的。

此外,您可以考虑使用这种方法进一步简化设计,并避免Player的大量子类。RedBlue行为以及AIHuman行为可以在构造时简单地注入到通用Player对象中。这将消除对不同类RedPlayerRedAIPlayerBlueHumanPlayer等的需求。

票数 3
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/400406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档