我正在开发一款游戏,游戏有不同的模式。简单,正常,困难。 所以,我正在考虑如何存储游戏模式。我的第一个想法是使用数字来表示难度。
Easy = 0 Normal = 1 Difficult = 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”只存储游戏设置的不同变量....这是否只是存储数据而不是制作对象的简单方法?你好。
答案 0 :(得分:2)
我认为您正在尝试表示配置数据表。如果您使用支持该语言的语言,或者在代码中使用文字数据,请将其放在配置文件中。
例如,您可以在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
通过扩展表格可以轻松添加更多配置(更多参数或更多难度级别)。
答案 1 :(得分:1)
我不知道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(或您选择的其他来源)读取模式模板,保存模式数据进入一个可序列化的类。我认为你不应该需要基类扩展。
答案 2 :(得分:1)
您应该拥有的首要目标是集中逻辑以检索与不同级别相关的值。通过提供存储这些值的一个位置,如果添加另一个级别,添加其他值等,则最小化代码中需要更改的位置数。
类接口是此解决方案的不错选择。但是,如果您具有由该类表示的有限数量的配置选项,则没有理由需要使用继承。您可以从封装逻辑的单个类开始。如果其余代码通过类接口检索其设置,您可以稍后引入更复杂的设计,例如每种模式的子类,如果有必要对游戏的其余部分进行有限的修改。
例如,第一个实现可能类似于
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()语句的直接性和类接口的好处。您还可以使用查找表替换switch()语句,如另一张海报所示,或者适合您的应用程序的其他一些机制。
答案 3 :(得分:0)
在GameMode类的构造函数中使用switch方法。
答案 4 :(得分:0)
除了一些语法问题,我认为你走在正确的轨道上。考虑到可能只有一种模式,我认为你不必担心内存。这是strategy pattern的一种形式。你可以扩展它,以便模式做得更多。例如,代替基本上只是持有常量,也许可能有一个generateEnemies方法实际上创建了一组敌人或一组敌人。这会将更多策略移动到模式对象中。超类中的Sane默认值有助于避免冗余代码。
答案 5 :(得分:0)
很难说这里可以进行什么样的重构,因为关于其他类的信息太少了。但是你可以检查State pattern,它封装了不同状态对象中的不同行为。扩展基本GameMode类的方法与状态模式非常相似。我认为它比switch-case-block更好......如果应用得好,模式就是可靠的做事方式。
答案 6 :(得分:0)
为什么你认为开关更难保持?如果您添加其他模式,则无论您采用何种解决方案,都必须添加代码。
如果您添加其他模式,我可以想到的唯一情况是您不必添加代码,如果您从gameMode
的值生成游戏参数。
例如:maxenemy = 5 * gameMode;
我认为,除非你有非常复杂的初始化来执行切换是绰绰有余的。我知道,我知道,对象和类都很好,所有的爵士乐,但如果你只需要定义几个变量并且事情有效,那么投入时间来开发一个复杂的游戏模式类可能毕竟不是一个有益的解决方案(I是的,你打算添加多少种游戏模式?)。
答案 7 :(得分:0)
用Java术语:
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();