C# 可能具有挑战性:如何在这个解谜程序中实现解谜逻辑?

C# 可能具有挑战性:如何在这个解谜程序中实现解谜逻辑?,c#,logic,C#,Logic,我正在尝试制作一个解决日本益智游戏“河流智商测试”的程序。我知道,我可以只查找解决方案,但现在这将不是一个有趣和有教育意义的事情,不是吗?:) 以下是游戏的目标: 使用木筏,用户可以将人员运送过河,用户必须将所有人员从左侧运送到右侧。每次使用木筏时,木筏都会停留在另一侧,直到有人从另一侧驾驶木筏到另一侧,以吸引更多的人 左侧有以下人员开始出发: 1名囚犯 1名警察 1父亲 两个儿子 一位母亲 两个女儿 以下是类的层次结构: 乘客 领航员 母公司 母亲 父亲 警察 囚犯 孩子 女儿

我正在尝试制作一个解决日本益智游戏“河流智商测试”的程序。我知道,我可以只查找解决方案,但现在这将不是一个有趣和有教育意义的事情,不是吗?:)

以下是游戏的目标:

使用木筏,用户可以将人员运送过河,用户必须将所有人员从左侧运送到右侧。每次使用木筏时,木筏都会停留在另一侧,直到有人从另一侧驾驶木筏到另一侧,以吸引更多的人

左侧有以下人员开始出发:

  • 1名囚犯
  • 1名警察
  • 1父亲
  • 两个儿子
  • 一位母亲
  • 两个女儿
以下是类的层次结构:

乘客
  • 领航员
    • 母公司
      • 母亲
      • 父亲
    • 警察
  • 囚犯
  • 孩子
    • 女儿
    • 儿子
必须遵守以下规则:

  • 一次只有两个人在木筏上
  • 只有警察、父亲和母亲才能驾驶木筏
  • 在没有警察在场的情况下,不能在其他人在场的情况下将囚犯放在木筏上或河的任何一边
  • 父亲不能在没有母亲在场的情况下,与任何一个女儿在木筏上或河的任何一边
  • 如果父亲不在场,母亲不能和儿子一起坐在木筏上或河的两边
我需要完成的是:

  • 使用尝试和错误解决逻辑直到解决难题的逻辑
  • 打印最终成功解决方案的逻辑
  • 检查是否每个人都到了另一边的逻辑
这是我目前的代码:

程序类(求解逻辑应在此处) 乘客阶级 筏级
我认为你从未学过序言。这些问题在PROLOG中是经典的,更重要的是,PROLOG只处理问题的本质。当我在标题中看到逻辑和谜题时,很明显你需要一种逻辑语言。我知道你要求C#,但这不是一个OO问题,正如你说的,这是一个逻辑问题

见第229页第8.3节。传教士和食人族 请注意,解决方案比问题中的所有代码都要小。别误会我的意思,很多年前我是同一条船上的,双关语的意思

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

编辑

不过,C#不能解决那种问题吗

PROLOG有一个内置的,这就是在给定规则的情况下寻找解决方案的工作。您可以从头开始创建一个,这比解决最初的问题要困难,但是John Pool在C#中提供了PROLOG的开源实现。虽然您可以查看源代码以了解PROLOG是如何工作的,但代码经过了大量优化,因此除非您首先理解PROLOG,否则很难理解

如果你知道F#或函数式语言?也许会有帮助

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

从这些关键词和短语开始,在这里搜索互联网和问题

统一
句法统一
反向链接
推理机

prolog的工作原理

您可以在任何支持递归的语言中相对轻松地实现这一点,
使用回溯,一种简单的算法/技术

举例来说:

您有问题状态(两边的人)
您有一个枚举所有可能的交叉点的函数
从那个状态开始,并尝试每一个

如果交叉正常,则会将新状态添加到历史记录中,
从新的状态调用自己。
返回时,将从历史记录中删除状态
然后尝试下一个交叉路口。
当它用完交叉口时,它返回给它的调用者

您需要历史记录,因为唯一的终端状态是目标。
否则您可能会进入循环:
A组穿过一条路,然后往回走,再往回走,等等。
或者A穿过一条路,B穿过后面,B返回,A返回,等等


(很抱歉,我不知道如何使代码格式化程序在这里工作。)

要求我们解决逻辑与查找逻辑有何不同?尝试实现暴力方法。系统地尝试所有组合,直到找到正确的组合并打印出来。而这种系统化的方法正是我很难弄明白的。我知道这涉及到迭代和循环,可能还有嵌套循环,但我不知道如何进行。谢谢,我会研究的。不过,c#不能解决那种问题吗?只是好奇。
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();
    }
}
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;
    }
}
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;
    }
}
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);
        }
    }
}