hw10-游戏智能

作业要求

P&D 过河游戏智能帮助实现,程序具体要求:

  • 实现状态图的自动生成
  • 讲解图数据在程序中的表示方法
  • 利用算法实现下一步的计算

作业内容

代码和视频
智能状态设置

参考了往届博客的状态图,以实现自动过河的牧师和魔鬼有限状态机。
在这里插入图片描述

代码设计

1.本次的重点AutoMove类。首先该类设计为单例模式,通过静态变量autoMove来调用该类的方法。然后声明所需变量。

    public static AutoMove autoMove = new AutoMove();
    public FirstController firstScene;
    private int devilNum;
    private int priestNum;
    private int BoatCoast; // -1 -> left, 1 -> right.
    //P:船运载一个牧师
    //D:船运载一个恶魔
    //PP:船运载两个牧师
    //DD:船运载两个恶魔
    //PD:船运载一个牧师,一个恶魔
    private enum Boataction {empty, P, D, PP, DD, PD }
    private bool isFinished = true;
    private Boataction nextState;
    private int count = 0;
    private int num = 0;

    private AutoMove() { }

2.然后是每次点击Next按钮将会直接调用的move函数,该函数首先调用getNext函数得到当前岸边的状态,确认接下来要进行的过程,再调用DoAction函数执行流程。

    public void move()
    {
        if (isFinished)
        {
            isFinished = false;
            Debug.Log(count);
            int[] fromCount = firstScene.fromCoast.GetobjectsNumber();
            priestNum = fromCount[0];
            devilNum = fromCount[1];
            BoatCoast = firstScene.boat.get_State();
            if (count == 0)
            {
                nextState = getNext();
                if ((int)nextState >= 3)
                {
                    num = 2;
                }
                else if ((int)nextState > 0) num = 1;
                else num = 0;
                count++;
            }
            Debug.Log("next state is " + nextState);
            DoAction();
        }
    }

3.DoACtion主要是按顺序调用各种模拟点击动作。

    private void DoAction()
    {
        if (count == 1 && num != 0)
        {
            if (nextState == Boataction.D)
            {
                devilOnBoat();
            }
            else if (nextState == Boataction.DD)
            {
                devilOnBoat();
            }
            else if (nextState == Boataction.P)
            {
                priestOnBoat();
            }
            else if (nextState == Boataction.PP)
            {
                priestOnBoat();
            }
            else if (nextState == Boataction.PD)
            {
                priestOnBoat();
            }
            count++;
        }
        else if (num == 2 && count == 2)
        {
            if (nextState == Boataction.DD)
            {
                devilOnBoat();
            }
            else if (nextState == Boataction.PP)
            {
                priestOnBoat();
            }
            else if (nextState == Boataction.PD)
            {
                devilOnBoat();
            }
            count++;
        }
        else if((num == 1 && count == 2) || (num == 2 && count == 3) || (num == 0 && count == 1))
        {
            firstScene.MoveBoat();
            count++;
        }
        else if ((num == 1 && count >= 3) || (num == 2 && count >= 4) || (num == 0 && count>=2))
        {
            GetOffBoat();
        }
        isFinished = true;
    }

4.DoAction函数进行的动作分为三种,第一种devilOnBoat模拟点击魔鬼让其上船,第二种priestOnBoat模拟点击牧师,第三种船移动。

   private void GetOffBoat()
    {
        if((priestNum == 0 && devilNum == 2) || (priestNum == 0 && devilNum == 0))
        {
            if (firstScene.boat.get_State() == -1)
            {
                foreach (var x in firstScene.boat.passenger)
                {
                    if (x != null)
                    {
                        firstScene.ObjectIsClicked(x);
                        break;
                    }
                }
                if (firstScene.boat.isEmpty()) count = 0;
            }
            else count = 0;
        }
        else if (((priestNum == 0 && devilNum == 1)) && firstScene.boat.get_State() == 1)
        {
            count = 0;
        }
        else
        {
            foreach (var x in firstScene.boat.passenger)
            {
                if (x != null && x.getType() == 1)
                {
                    firstScene.ObjectIsClicked(x);
                    count = 0;
                    break;
                }
            }
            if (count != 0)
            {
                foreach (var x in firstScene.boat.passenger)
                {
                    if (x != null)
                    {
                        firstScene.ObjectIsClicked(x);
                        count = 0;
                        break;
                    }
                }
            }
        }
    }

    private void priestOnBoat()
    {
        if(BoatCoast == 1)
        {
            foreach(var x in firstScene.fromCoast.passengerPlaner)
            {
                if (x!=null && x.getType() == 0)
                {
                    firstScene.ObjectIsClicked(x);
                    return;
                }
            }
        }
        else
        {
            foreach (var x in firstScene.toCoast.passengerPlaner)
            {
                if (x != null && x.getType() == 0)
                {
                    firstScene.ObjectIsClicked(x);
                    return;
                }
            }
        }
    }

    private void devilOnBoat()
    {
        if (BoatCoast == 1)
        {
            foreach (var x in firstScene.fromCoast.passengerPlaner)
            {
                if (x != null && x.getType() == 1)
                {
                    firstScene.ObjectIsClicked(x);
                    return;
                }
            }
        }
        else
        {
            foreach (var x in firstScene.toCoast.passengerPlaner)
            {
                if (x != null && x.getType() == 1)
                {
                    firstScene.ObjectIsClicked(x);
                    return;
                }
            }
        }
    }

5.得到下一步的方法根据状态图确认下一步进行的操作和目标。

 private Boataction getNext()
    {
        Boataction next = Boataction.empty;
        if (BoatCoast == 1)
        {
            if (devilNum == 3 && priestNum == 3)//3P3DB
            {
                next = Boataction.PD;
            }
            else if (devilNum == 2 && priestNum == 3)//3P2DB
            {
                next = Boataction.DD;
            }
            else if (devilNum == 1 && priestNum == 3)//3P1DB
            {
                next = Boataction.PP;
            }
            else if (devilNum == 2 && priestNum == 2)//2P2DB
            {
                next = Boataction.PP;
            }
            else if (devilNum == 3 && priestNum == 0)//3DB
            {
                next = Boataction.DD;
            }
            else if (devilNum == 1 && priestNum == 1)//1P1DB
            {
                next = Boataction.PD;
            }
            else if (devilNum == 2 && priestNum == 0)//2DB
            {
                next = Boataction.D;
            }
            else if (devilNum == 1 && priestNum == 2)//2P1DB
            {
                next = Boataction.P;
            }
            else if (devilNum == 2 && priestNum == 1)//1P2DB
            {
                next = Boataction.P;
            }
            else if (devilNum == 1 && priestNum == 0)//1DB
            {
                next = Boataction.D;
            }
            else if(devilNum == 3 && priestNum == 2)//2P3DB
            {
                next = Boataction.D;
            }
            else next = Boataction.empty;
        }
        else
        {
            if (devilNum == 2 && priestNum == 2)//2P2D
            {
                next = Boataction.empty;
            }
            else if (devilNum == 1 && priestNum == 3)//3P1D
            {
                next = Boataction.empty;
            }
            else if (devilNum == 2 && priestNum == 3)//3P2D
            {
                next = Boataction.D;
            }
            else if (devilNum == 0 && priestNum == 3)//3P
            {
                next = Boataction.empty;
            }
            else if (devilNum == 1 && priestNum == 1)//1P1D
            {
                next = Boataction.D;
            }
            else if (devilNum == 2 && priestNum == 0)//2D
            {
                next = Boataction.D;
            }
            else if (devilNum == 1 && priestNum == 0)//1D
            {
                next = Boataction.empty;
            }
            else next = Boataction.empty;
        }
        return next;
    }
参考博客

https://blog.csdn.net/Kiloveyousmile/article/details/71727667

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值