题
我正在开发游戏,游戏具有不同的模式。容易,正常和困难。因此,我正在考虑如何存储游戏模式。我的第一个想法是使用数字来表示难度。
简单= 0 norman = 1难= 2
因此,我的代码将具有类似的内容:
switch(gameMode){
case 0:
//easy
break;
case 1:
//normal
break;
case 3:
//difficult
break;
}
但是我认为这有一些问题,例如,如果我添加了一种新模式,例如“ Extreme”,我需要添加案例4 ... ...似乎不是GD设计。
因此,我在想制作GameMode对象,而不同的GameMode是超级类GameMode的子类。 GameMode对象就是这样:
class GameMode{
int maxEnemyNumber;
int maxWeaponNumber;
public static GameMode init(){
GameMode gm = GameMode();
gm.maxEnemyNumber = 0;
gm.maxWeaponNumber = 0;
return gm;
}
}
class EasyMode extends GameMode{
public static GameMode init(){
GameMode gm = super.init();
gm.maxEnemyNumber = 10;
gm.maxWeaponNumber = 100;
return gm;
}
}
class NormalMode extends GameMode{
public static GameMode init(){
GameMode gm = super.init();
gm.maxEnemyNumber = 20;
gm.maxWeaponNumber = 80;
return gm;
}
}
但是我认为创建一个存储GameMode的对象似乎太“笨重”,我的“ GameMode”仅存储游戏设置的不同变量。...这是任何仅存储数据而不是制作对象的简单方法吗? thz u。
解决方案
我认为您正在尝试代表配置数据表。如果您使用支持该语言的语言,则将其放入配置文件中,或者在代码中使用文字数据。
例如,您可以将其写入C:
typedef enum difficulties {
DIFFICULTY_EASY,
DIFFICULTY_MEDIUM,
DIFFICULTY_HARD
} difficulties;
struct {
int max_enemies;
int max_weapons;
} difficulty_settings[] = {
{10, 4},
{20, 5},
{30, 6}
};
当您想读取特定设置时,例如Max_enemies在简单级别上,您可以编写difficulty_settings[DIFFICULTY_EASY].max_enemies
通过扩展表可以添加更多的配置(更多参数或更难级别),这很容易添加。
其他提示
您在这里应该实现的重要目标是集中逻辑以检索与不同级别相关的值。通过提供存储这些值的一个地方,您可以最大程度地减少代码中的位置数量,如果添加其他级别,添加其他值,等等。
类界面是该解决方案的好选择。但是,如果您的班级表示有限的配置选项,则无需使用继承。您可以从封装逻辑的单个类开始。如果您的其余代码通过类界面检索其设置,则稍后您可以引入更复杂的设计,例如每种模式的子类,如果需要对游戏的其余部分进行有限的修改,则需要进行设置。
例如,第一个实施可能是类似的
enum mode {
MODE_EASY = 0,
MODE_NORMAL = 1,
MODE_DIFFICULT = 2,
};
class gameSettings {
public gameSettings(mode GameMode) {
m_mode = GameMode;
}
public int getMaxWeaponNumber() {
int maxWeaponNumber;
switch(m_mode) {
case EASY_MODE:
maxWeaponNumber = 100;
break;
// Other mode settings.
}
return maxWeaponNumber;
}
// Other game settings....
private mode m_mode;
}
这将开关()语句的直接性与类接口的好处结合在一起。您还可以按照另一个海报建议将Switch()语句与查找表交换,或其他适合您应用的机制。
我不知道Java(这是您的示例的样子),所以我在一些简单的C#中介绍了我的想法。
这是一个主意。改用您的游戏模式作为标志。如果您从:
[Flags]
enum GameModes
{
Unknown = 0,
ModeA = 1,
ModeB = 2,
ModeC = 4,
}
现在您有1-7级可用。
GameModes Difficulty = GameModes.ModeA | GameModes.ModeB; // difficulty = 3
GameModes Difficulty = GameModes.ModeB; // difficulty = 2
此外,您显示的任何一种方法都需要您添加更多选项,该选项(模式)更改,添加等等。将您的模式模板从XML(或您选择的其他来源)读取,请将模式数据保存到可序列化的模式数据班级。我认为您不需要任何任何东西。
使用GameMode类构造函数中的开关方法。
除了一些语法问题,我认为您在正确的道路上。考虑到可能只有一种模式,我认为您不必担心内存。这是一种形式 策略模式. 。您可以将其扩展,以便模式做更多的事情。例如,也许可能有一种生成烯方法实际上创建了敌人的集合或列表,而不是基本上持有常数。这将更多的策略移至模式对象。超类中的理智默认值可以帮助避免冗余代码。
很难说在这里可以进行什么样的重构,因为有关其他课程的信息太少了。但是你可以检查 状态模式 这封装了不同状态对象中的不同行为。您扩展基本GameMode类的方法与状态模式非常相似。我认为它比开关案例块更好……如果应用良好的话,模式是可靠的做事方式。
您为什么认为开关更难曼丹?如果添加另一种模式,无论您采用哪种解决方案,都必须添加代码。
如果您添加另一个模式,我可以想到的唯一情况是您不必添加代码 gameMode
.
例如: maxenemy = 5 * gameMode;
我认为,除非您具有非常复杂的初始化来执行开关已经足够了。我知道,我知道,对象和课程都很好,而且所有爵士乐都很好,但是如果您只需要定义一些var,而事物有效,那么在开发复杂的游戏模式课程上投入时间可能不是一个有意义的解决方案(我意思是,您打算添加几种游戏模式?)。
利用 策略模式.
用爪哇术语:
public interface Strategy {
void execute();
}
public class SomeStrategy implements Strategy {
public void execute() {
System.out.println("Some logic.");
}
}
您使用如下:
Map<String, Strategy> strategies = new HashMap<String, Strategy>();
strategies.put("strategyName1", new SomeStrategy1());
strategies.put("strategyName2", new SomeStrategy2());
strategies.put("strategyName3", new SomeStrategy3());
// ...
strategies.get(s).execute();