用python编写猴子吃桃问题_人工智能猴子摘香蕉

用python编写猴子吃桃问题_人工智能猴子摘香蕉Java实现人工智能实验一,猴子摘香蕉,图形化展示

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

人工智能课程实验一的任务,写出猴子摘香蕉问题的知识表示,并用代码实现推理过程

问题描述

一个房间里,天花板上挂有一串香蕉,有一只猴子可在房间里任意活动(到处走动,推移箱子,攀登箱子等)。设房间里还有一只可被猴子移动的箱子,且猴子登上箱子时才能摘到香蕉,问猴子在某一状态下(设猴子位置为A,香蕉位置在B,箱子位置为C),如何行动可摘取到香蕉。

知识表示

知识表示的方法是有很多,如一阶谓词、产生式、语义网、框架等等。这里选择的是产生式表示的方法

知识的产生式表示

在这里插入图片描述

综合数据库

(ON, HOLD, Monkey, Banana, Box)
ON=0:猴子在地板上
ON=1:猴子在箱子上
HOLD=0:猴子没有抓到香蕉
HOLD=1:猴子抓到了香蕉
Monkey:猴子的位置
Banaba:香蕉的位置
Box: 箱子的位置

规则库

  1. IF 猴子位置= =箱子位置= =香蕉位置
    AND 猴子ON箱子
    THEN 猴子HOLD香蕉
  2. IF 猴子位置= =箱子位置= =香蕉位置
    AND 非(猴子ON 箱子)
    THEN 猴子ON箱子
  3. IF 猴子位置= =箱子位置!=香蕉位置
    AND 猴子ON 箱子
    THEN 非(猴子ON箱子)
  4. IF 猴子位置= =箱子位置!=香蕉位置
    AND 非(猴子ON 箱子)
    THEN猴子位置= =箱子位置= =香蕉位置
  5. IF 猴子位置!=箱子位置= =香蕉位置
    AND非(猴子ON箱子)
    THEN 猴子位置= =箱子位置
  6. IF 猴子位置!=箱子位置!=香蕉位置
    AND非(猴子ON箱子)
    THEN 猴子位置==箱子位置
    结束状态(1,1,B,B,B)

算法实现

其实用python实现最便捷,但我没有安装python环境(没写过python我是菜鸡)所以就用了Java实现,但思路不够清晰,写的很啰嗦呜呜呜
顺便做出了图形化界面,用的是学CS61b时候白嫖的StdDraw标准绘图库,把因为jdk版本问题,没有用StdDraw.java文件 ,直接把StdDraw.class文件放在lib问价夹里并在IDE里添加依赖路径就可以用了,而且IntelliJ IDEA会直接把.class文件decompile成.java文件显示,哦吼~

class设计

根据PEAS设计class
在这里插入图片描述
在这里插入图片描述
猴子是Agent,所以将Monkey作为主类。
显然:猴子可以移动,箱子可以被猴子推走,香蕉可以被摘下来,他们都可以移动,都需要有横纵坐标 以显示在图形界面不同的位置上。设计一个抽象类movable,包含他们共同的属性(横纵坐标,图片文件路径等)以及方法(显示图片)
因为只需要考虑三个位置ABC,就把问题化简了。
ps:StdDraw设定的画布原点在正中间

public abstract class movable { 
   
    public int X;
    public int Y;
    public String imgFileName;
    public static int A = -40;
    public static int B = 2;
    public static int C = 40;
    public static final int ceiling = 50;
    public static final int floor = -30;
    public static final int onBox = 10;
    public static final int inHand = 20;

    public void draw(){ 
   
        StdDraw.picture(X,Y,imgFileName);
    }
}

箱子和香蕉直接extent即可

public class Banana extends movable{ 
   
    public Banana(int B){ 
   
        this.X = B;
        if(HOLD.isHOLD())
            this.Y = inHand;
        this.Y = ceiling;
        imgFileName = "data/banana.png";
    }
}
///
public class Box extends movable{ 
   

    public Box(int C){ 
   
        this.X = C;
        this.Y = floor;
        imgFileName = "data/box.png";
    }
}

对于ON HOLD两种状态,定义成了两个静态类,方便判断

public class ON { 
   
    private static final int yes = 1;
    private static final int no = 0;
    private static int status;
    public static boolean isON(){ 
   
        return status == yes;
    }
    public static void setYes(){ 
   
        status = yes;
    }
    public static void setNo(){ 
   
        status = no;
    }
    public static void setStatus(int arg){ 
   
        status = arg;
    }
    public static int getStatus(){ 
   
        return status;
    }
}

public class HOLD { 
   
    private static final int yes = 1;
    private static final int no = 0;
    private static int status;
    public static boolean isHOLD(){ 
   
        return status == yes;
    }
    public static void setYes(){ 
   
        status = yes;
    }
    public static void setNo(){ 
   
        status = no;
    }
    public static void setStatus(int arg){ 
   
        status = arg;
    }
    public static int getStatus(){ 
   
        return status;
    }
}

最后就是主类monkey

因为猴子的动作(推箱子,走向箱子)等等都需要知道或改变箱子、香蕉的位置,从逻辑性和复用性的角度考虑,肯定是将实例化后的箱子,香蕉作为参数传入给猴子拥有的方法比较合理。但我只是为了完成这个实验所以干脆把Box、Banana 作为猴子的成员变量

StdDraw显示动画的原理:t时刻在(x,y)处显示图片1,清空画布,t+dt 时刻在(x+dx,y+dy)处显示图片1,达到视觉上的移动效果。所以为了在空白处显示每一步对应的产生式变化,我用allsteps存储每一步状态,每次更新的时候清空画布并且显示目前为止经历的状态,有些凌乱,都不是重点

import java.util.ArrayList;
import java.util.List;

public class Monkey extends movable{ 
   
    Box box;
    Banana banana;
    List<List<Character>> allSteps = new ArrayList<>();
    public Monkey(int A){ 
   
        this.X = A;
        if(ON.isON())
            this.Y = onBox;
        else this.Y = floor;
        imgFileName = "data/monkey.png";
    }
    public void firstStep(){ 
   
        List<Character> init = new ArrayList<>();
        init.add(run.status.get(ON.getStatus()));
        init.add(run.status.get(HOLD.getStatus()));
        init.add(run.status.get(this.X));
        init.add(run.status.get(this.banana.X));
        init.add(run.status.get(this.box.X));
        allSteps.add(init);
        showStep();
    }
    public void moveToBox(){ 
   
        this.X = box.X;
        List<Character> sb = new ArrayList<>();
        sb.add(run.status.get(ON.getStatus()));
        sb.add(run.status.get(HOLD.getStatus()));
        sb.add(run.status.get(this.X));
        sb.add(run.status.get(this.banana.X));
        sb.add(run.status.get(this.box.X));
        allSteps.add(sb);
        showStep();
    }
    public void pushToBanana(){ 
   

        this.X = banana.X;
        box.X = banana.X;
        List<Character> sb = new ArrayList<>();
        sb.add(run.status.get(ON.getStatus()));
        sb.add(run.status.get(HOLD.getStatus()));
        sb.add(run.status.get(this.X));
        sb.add(run.status.get(this.banana.X));
        sb.add(run.status.get(this.box.X));
        allSteps.add(sb);
        showStep();
    }
    public void climbOn(){ 
   

        ON.setYes();
        this.Y = onBox;
        List<Character> sb = new ArrayList<>();
        sb.add(run.status.get(ON.getStatus()));
        sb.add(run.status.get(HOLD.getStatus()));
        sb.add(run.status.get(this.X));
        sb.add(run.status.get(this.banana.X));
        sb.add(run.status.get(this.box.X));
        allSteps.add(sb);
        showStep();
    }
    public void climbDown(){ 
   

        ON.setNo();
        this.Y = floor;
        StdDraw.clear();
        List<Character> sb = new ArrayList<>();
        sb.add(run.status.get(ON.getStatus()));
        sb.add(run.status.get(HOLD.getStatus()));
        sb.add(run.status.get(this.X));
        sb.add(run.status.get(this.banana.X));
        sb.add(run.status.get(this.box.X));
        allSteps.add(sb);
        showStep();
    }
    public void grasp(){ 
   

        HOLD.setYes();
        this.banana.Y = inHand;
        List<Character> sb = new ArrayList<>();
        sb.add(run.status.get(ON.getStatus()));
        sb.add(run.status.get(HOLD.getStatus()));
        sb.add(run.status.get(this.X));
        sb.add(run.status.get(this.banana.X));
        sb.add(run.status.get(this.box.X));
        allSteps.add(sb);
        showStep();
    }
    private void showStep(){ 
   
        int Line = 70;
        int addLine = -5;
        StdDraw.clear();
        this.box.draw();
        this.draw();
        this.banana.draw();
        for(List<Character> list:allSteps){ 
   
            StdDraw.text(-60,Line, list.toString());
            Line += addLine;
        }
        StdDraw.text(movable.A,-65,"A");
        StdDraw.text(movable.B,-65,"B");
        StdDraw.text(movable.C,-65,"C");
        StdDraw.show();
        StdDraw.pause(1000);
    }

}

最后就是run这个运行类,main函数在这里(包含规则库),从txt文件读取五元组的初始状态,需要从字符到坐标再到字符进行一些转化
规则库才是这个实验的重点,所以写了注释,虽然很简单

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class run { 
   
    public static final Map<Integer,Character> status = new HashMap<>();
    private static void defineStatus(){ 
   
        status.put(-40,'A');
        status.put(2,'B');
        status.put(40,'C');
        status.put(0,'0');
        status.put(1,'1');
    }
    private static int charToPosition(char c){ 
   
        switch (c){ 
   
            case 'A':return movable.A;
            case 'B':return movable.B;
            case 'C':return movable.C;
            default:return 0;
        }
    }
    public static Monkey readArgs(String path){ 
   
        //从文件中读取初始状态
        //猴子,香蕉,箱子的位置以及是否猴子是否在箱子上,是否拿着香蕉
        In in = new In(path);
        ON.setStatus(in.readInt());
        HOLD.setStatus(in.readInt());
        in.readChar();
        Monkey monkey = new Monkey(charToPosition(in.readChar()));
        in.readChar();
        monkey.banana = new Banana(charToPosition(in.readChar()));
        in.readChar();
        monkey.box = new Box(charToPosition(in.readChar()));
        //对于一些不合理的输入报警
        assert !ON.isON() || monkey.X == monkey.box.X
                :"illegal position when on box";
        assert !HOLD.isHOLD() ||
                (monkey.X == monkey.box.X) && (monkey.X == monkey.banana.X)
                :"illegal position when hold banana";
        assert !HOLD.isHOLD() || ON.isON():"hold banana but not on box";
        return monkey;
    }

    public static void main(String[] args) { 
   
        defineStatus();
        //读取txt文件
        String fileName = args[0];
        Monkey monkey = readArgs(fileName);
        //画面双缓冲防抖
        StdDraw.enableDoubleBuffering();
        //画布大小
        StdDraw.setScale(-80,80);
        StdDraw.clear();
        //展示猴子香蕉箱子初始状态
        monkey.box.draw();
        monkey.draw();
        monkey.banana.draw();
        monkey.firstStep();
        StdDraw.show();
        StdDraw.pause(1000);
        if(HOLD.isHOLD()){ 
   
            //如果猴子已经拿到香蕉直接展示
            //对于猴子拿到香蕉却没有站在箱子上的不合法输入在读取文件时报警
            StdDraw.show();
        }
        else if(ON.isON()){ 
   
            //如果猴子没拿到香蕉但站在箱子上
            //则观察箱子是否和香蕉在同一个位置
            if(monkey.banana.X!= monkey.X){ 
   
                //如果不在同一个位置,需要猴子先
                //下箱子,推箱子到香蕉位置,爬箱子
                monkey.climbDown();
                monkey.pushToBanana();
                monkey.climbOn();
            }//然后拿到香蕉。如果在同一个位置直接拿香蕉
            monkey.grasp();
        }else{ 
   //如果猴子没有站在箱子上
            //要观察箱子是否和猴子在同一个位置,
            //以及箱子是否和香蕉在同一个位置
            if(monkey.box.X!= monkey.X){ 
   
                if(monkey.box.X!=monkey.banana.X){ 
   
                    //如果猴子和箱子不在同一个位置,箱子和香蕉也不在同一个位置
                    monkey.moveToBox();//猴子需要走到箱子处
                    monkey.pushToBanana();//推箱子到香蕉处
                    monkey.climbOn();//爬上箱子
                    monkey.grasp();//拿香蕉
                }else{ 
   //如果猴子和箱子不在同一个位置,箱子和香蕉在同一个位置
                    monkey.moveToBox();//猴子只要走到箱子处,不用推箱子
                    monkey.climbOn();//直接爬箱子
                    monkey.grasp();//拿香蕉
                }
            }
            else{ 
   //如果猴子没有在箱子上但和箱子在同一个位置
                if(monkey.box.X!=monkey.banana.X){ 
   
                    //猴子推箱子到香蕉处
                    monkey.pushToBanana();
                }//爬上箱子
                monkey.climbOn();
                monkey.grasp();//拿香蕉
            }
        }
    }
}

最后,运行的效果如下

用到的lib,In和StdDraw

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/189454.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python数组操作方法_python 数组赋值

    python数组操作方法_python 数组赋值python列表数组类型,用中括号代表,具有顺序关系,可以修改,是最常用的数组bracket=[‘b’,’r’,’a’,’c’,’k’,’e’,’t’]pyhon元组数组类型,用小括号代表,具有顺序关系,不可以修改,是只读型数组,用来保护不需要改变的数据parentheses=(‘p’,’a’,’r’,’e’,’n’,’t’,’h’,’e’,’s’,’e’,’s’)python字典数组

    2022年8月13日
    8
  • 贴片器件的识别[通俗易懂]

    贴片器件的识别[通俗易懂]前言实际板子上,贴片原件一般就较小,如果想知道贴片原件值,而且贴片件上有些标识.如果能辨别标识的含义,就不用将器件查下来量了。如果眼神不好(或者原件实在太小了),可以用工业显微镜拍下来,再识别原件上印刷的器件标识。在显微镜下,光滑好看的焊点,也变的那么粗糙:)慢慢记录,见到能用标识识别的器件,就记录一下。笔记0贴片电阻看到0R电阻电阻上画了一个小方框…

    2022年8月21日
    7
  • Win10下安装Ubuntu20.04双系统,看这一篇就够了

    Win10下安装Ubuntu20.04双系统,看这一篇就够了前言:既然你都找到这了,相信对Linux和Ubuntu已经有了一定的了解,这里就不再做过多的赘述,直接步入正题了。由于各种原因我已经反复装了七八遍的Ubuntu(从16.04到20.04都装过几次),发现不同版本的Ubuntu安装过程都大同小异,就决定拿最新版的20.04来和大家分享一下。由于安装过程中我不知道怎么截图,有些的配图是手机拍摄的,敬请谅解。…

    2022年7月24日
    7
  • intellij idea 激活码[免费获取]

    (intellij idea 激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.htmlML…

    2022年3月21日
    126
  • Java之GUI编程(一)

    Java之GUI编程(一)

    2022年1月25日
    50
  • Codeforces Round #257 (Div. 1)449A – Jzzhu and Chocolate(贪婪、数学)

    Codeforces Round #257 (Div. 1)449A – Jzzhu and Chocolate(贪婪、数学)

    2022年1月9日
    42

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号