可能具有挑战性:如何在这个拼图求解程序中实现求解逻辑?

Arm*_*ode 5 c# logic

我正在尝试制作一个解决日本益智游戏"河流智商测试"的程序,我知道,我可以查找解决方案,但这不会很有趣,现在就教育了吗?:)

这是游戏的目标:

使用筏,用户可以将人们运送过河,用户必须将所有人从左侧传送到右侧.每次使用木筏时,它都停留在另一侧,直到那边的人再次将它引导到另一侧以吸引更多的人.

左侧有以下人员开始:

  • 1个囚犯
  • 1名警察
  • 1父亲
  • 2个儿子
  • 1母亲
  • 2个女儿

这是类的层次结构:

乘客

  • 飞行员
      • 母亲
      • 父亲
    • 警察
  • 囚犯
  • 儿童
    • 女儿
    • 儿子

必须遵守以下规则:

  • 一次只有2人在木筏上.
  • 只有警察,父亲和母亲可以驾驶木筏
  • 在没有警察在场的情况下,囚犯不能在其他人在场的情况下放置在筏子或河的两边.
  • 在没有母亲在场的情况下,父亲不能在筏子里或河的两边与任何一个女儿在一起.
  • 在没有父亲在场的情况下,母亲不能在河上或河的两边与任何一个儿子在一起.

我需要完成的是:

  • 使用反复试验逻辑直到解决难题的逻辑
  • 打印最终成功解决方案的逻辑
  • 检查是否每个人都到另一边的逻辑.

这是我目前的代码:

程序类(解决逻辑应该在这里)

class Program
{
    Side _leftSide = new Side(Side.RL_Side.RL_LeftSide);
    Side _rightSide = new Side(Side.RL_Side.RL_RightSide);
    Raft _myRaft = new Raft();
    static void Main(string[] args)
    {
        // TODO: put systematic trial-and-error solving logic here
        // TODO: make sure that successful solution is printed to console



        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

PassengerList类

public class PassengerList : List<Passenger>
{
    public bool CheckRulesObeyed()
    {
        bool isPoliceman = isPresent<Policeman>();
        bool isPrisoner = isPresent<Prisoner>();
        bool isFather = isPresent<Father>();
        bool isSon = isPresent<Son>();
        bool isMother = isPresent<Mother>();
        bool isDaughter = isPresent<Daughter>();
        // ----------------------------------------------
        bool isPrisoner_NonPoliceman = (isPrisoner && (isFather || isMother || isDaughter || isSon));

        bool isPrisonerRuleViolated = (!(isPoliceman && isPrisoner) && isPrisoner_NonPoliceman);
        bool isDaughterRuleViolated = ((isFather && isDaughter) && !isMother);
        bool isSonRuleViolated = ((isMother && isSon) && !isFather);

        bool AreAllRulesObeyed = !(isPrisonerRuleViolated && isDaughterRuleViolated && isSonRuleViolated);

        return AreAllRulesObeyed;
    }

    private bool isPresent<T>() where T: Passenger
    {
        foreach (Passenger p in this)
        {
            if (p is T)
                return true;
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

边课(如河边)

public class Side
{
    public enum RL_Side
    { 
        RL_RightSide,
        RL_LeftSide
    }

    public RL_Side _whichSide;

    public PassengerList _myPeople;

    public Side(RL_Side side)
    {
        _whichSide = side;
        _myPeople = new PassengerList();

        // left side starts with all the people
        if (_whichSide == RL_Side.RL_LeftSide)
        {
            _myPeople.Add(new Prisoner());
            _myPeople.Add(new Policeman());
            _myPeople.Add(new Father());
            _myPeople.Add(new Son());
            _myPeople.Add(new Son());
            _myPeople.Add(new Mother());
            _myPeople.Add(new Daughter());
            _myPeople.Add(new Daughter());
        }
    }

    public bool didEveryoneMakeItToRightSide()
    {
        if (_whichSide == RL_Side.RL_RightSide)
        { 
            // TODO: implement logic that checks and returns if everyone is on the right side.

        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

筏类

public class Raft
{
    public Side _mySide;
    public PassengerList _myPassengers;

    public void ChangeSides(Side Destination)
    {
        _mySide = Destination;
    }

    public bool LoadRaft(Pilot myPilot, Passenger myPassenger)
    {
        bool areRulesObeyed = true;
        _myPassengers.Add(myPilot);
        _myPassengers.Add(myPassenger);

        areRulesObeyed = _myPassengers.CheckRulesObeyed();

        if (areRulesObeyed == false)
        {
            UnloadRaft();
        }

        return areRulesObeyed;

    }
    public void UnloadRaft()
    {
        foreach (Passenger p in _myPassengers)
        {
            _mySide._myPeople.Add(p);
            _myPassengers.Remove(p);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Guy*_*der 4

我认为你从来没有学过PROLOG。这些问题在PROLOG中都是经典的,更重要的是PROLOG只处理问题的本质。当我在标题中看到逻辑和谜题时,很明显你需要一种逻辑语言。我知道你要求 C#,但这不是一个 OO 问题,正如你所说,这是一个逻辑问题。

请参阅Prolog 深度编程第 229 页第 8.3 节。传教士和食人族 请注意,解决方案比问题中的所有代码都要小。别误会我的意思,很多年前我也经历过同样的情况,双关语。

我认识的一些最好的程序员处理这样的问题不是为了解决方案,而是因为要自己解决这些问题,他们知道他们会学到一些重要的东西,以后可以使用。花几个月的时间来了解 PROLOG 如何解决这个问题,你会比别人给你建议要好得多。如果你不理解递归以及人工智能如何解决问题,那么当你得到解决方案时你就会明白了。

编辑

那么,C# 是否无法解决此类问题呢?

PROLOG 有一个内置的推理引擎反向链接,它的作用是在给定规则的情况下找到解决方案。您可以从头开始创建一个,这比解决最初的问题更难,但是有一个用 C# 实现的 PROLOG 开源实现,即John Pool 的C#Prolog。虽然您可以查看源代码来了解 PROLOG 的工作原理,但代码经过了大量优化,因此除非您先了解 PROLOG,否则不容易理解。

如果您了解 F# 或函数式语言,如何用纯函数式语言实现 prolog 解释器?可能有帮助。

基本上,问题归结为创建一组规则,然后尝试规则的组合,直到得到满足所有规则的结果。

从这些关键字和短语开始,在此处搜索互联网和问题。

统一
语法统一
回链 推理
引擎
prolog 的工作原理