c# - 关于基于类的文本冒险游戏设计的质疑。

标签 c# oop delegates adventure

我整个夏天都在学习 C#,现在我想利用我目前所做的一切来制作一个小项目。我决定开发一种基于文本的冒险游戏。

游戏的基本结构将涉及多个区域(或房间)。进入房间后,将输出描述和一些您可以采取的行动;在那个房间里检查、捡起、使用东西的能力;可能是战斗系统等。一个扇区最多可以连接 4 个其他扇区。

无论如何,在纸上写下关于如何为此设计代码的想法,我正在摸索我的部分代码的结构。

我已经决定了一个玩家类,以及一个委托(delegate)关卡/地牢/区域的“关卡”类。该级别类别将由许多相互关联的“部门”组成。在任何给定时间,玩家都会出现在关卡中的某个特定区域。

所以这里是困惑:

从逻辑上讲,人们会期待一种方法,例如 player.Move(Dir d)
这种方法应该改变关卡对象中的“当前扇区”字段。这意味着 Player 类需要了解 Level 类。嗯。 Level 可能必须操纵 Player 对象(例如,玩家进入房间,被某物伏击,从库存中丢失一些东西。)所以现在 Level还需要持有对 Player 对象的引用吗?

这感觉不太好;一切都必须持有对其他一切的引用。

这时我想起了从我正在使用的书中读到过关于委托(delegate)的内容。虽然我知道 C++ 中的函数指针,但关于委托(delegate)的章节中提供了带有某种“基于事件”编程观点的示例,对此我没有太多启发。

这给了我按如下方式设计类的想法:

玩家:

class Player
{
    //...

    public delegate void Movement(Dir d);   //enum Dir{NORTH, SOUTH, ...}

    public event Movement PlayerMoved;

    public void Move(Dir d)
    {        
        PlayerMoved(d);

        //Other code...
    }

}

等级:

class Level
{
    private Sector currSector;
    private Player p;
    //etc etc...

    private void OnMove(Dir d)
    {
        switch (d)
        {
            case Dir.NORTH:
                //change currSector
                //other code
                break;

                //other cases
        }
    }

    public Level(Player p)
    {
        p.PlayerMoved += OnMove;  
        currSector = START_SECTOR;
        //other code
    }

    //etc...
}

这样做好吗?
如果委托(delegate)章节不是这样呈现的,我就不会想到使用这样的“事件”。那么在不使用回调的情况下实现这一点的好方法是什么?

我习惯于发布非常详细的帖子......抱歉 v__v

最佳答案

“游戏”类会包含大部分信息,例如玩家和当前房间。对于移动玩家等操作,Game 类可以根据房间的关卡 map 将玩家移动到不同的房间。

游戏类将管理游戏各个组件之间的所有交互。

将事件用于类似这样的事情会带来事件困惑的危险。如果您不小心,您最终会导致事件相互触发并溢出您的堆栈,这将导致在特殊情况下使用标志来关闭事件,以及一个不太容易理解的程序。

更新:

为了使代码更易于管理,您可以将主要类之间的一些交互建模为类本身,例如 Fight 类。使用接口(interface)使您的主类能够执行某些交互。 (请注意,我冒昧地发明了一些您​​可能不希望在您的游戏中使用的东西)。

例如:

// Supports existance in a room.
interface IExistInRoom { Room GetCurrentRoom(); }

// Supports moving from one room to another.
interface IMoveable : IExistInRoom { void SetCurrentRoom(Room room); }

// Supports being involved in a fight.
interface IFightable
{
  Int32 HitPoints { get; set; }
  Int32 Skill { get; }
  Int32 Luck { get; }
}

// Example class declarations.
class RoomFeature : IExistInRoom
class Player : IMoveable, IFightable
class Monster : IMoveable, IFightable

// I'd proably choose to have this method in Game, as it alters the
// games state over one turn only.
void Move(IMoveable m, Direction d)
{
  // TODO: Check whether move is valid, if so perform move by
  // setting the player's location.
}

// I'd choose to put a fight in its own class because it might
// last more than one turn, and may contain some complex logic
// and involve player input.
class Fight
{
  public Fight(IFightable[] participants)

  public void Fight()
  {
    // TODO: Logic to perform the fight between the participants.
  }
}

在您的问题中,您确定了这样一个事实,即如果您在 Player 类中插入诸如 Move 方法之类的东西,那么您将有许多类必须相互了解。这是因为像移动这样的东西既不属于玩家也不属于房间 - 移动会相互影响两个对象。通过对主要对象之间的“交互”进行建模,您可以避免其中的许多依赖性。

关于c# - 关于基于类的文本冒险游戏设计的质疑。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3267638/

相关文章:

java - 我的应用程序中的内存管理错误

ios - 我的协议(protocol)和委托(delegate)不起作用?

ios - UIPopoverController + UINavigationController = 委托(delegate)问题

c# - 如何防止 Log4Net 截断异常?

c# - 如何在 C# 中调整图像大小?

c# - ProgressBar 从另一个线程更新

c# - Convert.ToInt32 和 (int) 有什么区别?

Perl:测试类是否存在

c# - 当不能选择多重继承时如何重用代码?

ios - 如何保存倒数计时器的进度?