我希望在我的Java程序中实现两个类的分支,以便在我的游戏中区分人类和人工智能控制的玩家。游戏是异步的,因此玩家有不同的方法和行为,取决于他们在游戏开始时选择的是哪种类型的玩家。所有玩家都有共享的方法,每个Player子类都有唯一的方法,只有他们能做到。此外,当AI玩家自动做出选择时,人类玩家会收到做出决定的提示。可能有无限数量的玩家子类,每个子类都有一个人和人工智能版本。
因为Java没有真正的多重继承,所以我目前的解决方案是使用AI玩家继承的AI接口和Human继承的人工接口。这些接口中的每一个都有一个唯一的makeDecision()方法,用于每个可能的决策。从决策界面重写代码很好,因为不同类型的玩家不应该拥有相同的AI。
下面是我的代码结构的一个简单示例:
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中设置这样一个系统的最佳实践,或者是否有一种更优化的策略。在实际执行所有编码之前,我宁愿创建一个合适的蓝图。
发布于 2019-10-31 19:18:55
我认为你的想法中的第一个错误是,在游戏的背景下,你不是真的在建模一个AI或Human,而是在建模一个Player。您只是碰巧有不同的Player实现。从游戏的角度来看,人类和人工智能玩家之间不应该有任何区别。
您首先需要考虑的是Player的接口,玩家需要做什么?我们可以将其建模如下:
public interface Player {
int chooseNumber();
void gainPoint();
}然后您可以使用不同类型的Players:
public interface BluePlayer extends Player{
void doBlueThing();
}
public interface RedPlayer extends Player{
void doRedThing();
}现在,基于@RomanVettner的S注释,您可以实现一个RedPlayer类和一个BluePlayer类,它们分别采用RedStrategy和BlueStrategy,然后提供人工智能和人工版本的策略:
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的大量子类。Red和Blue行为以及AI和Human行为可以在构造时简单地注入到通用Player对象中。这将消除对不同类RedPlayer、RedAIPlayer、BlueHumanPlayer等的需求。
https://softwareengineering.stackexchange.com/questions/400406
复制相似问题