用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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 十天征服单片机百度云_郭天祥十天征服单片机视频下载地址

    十天征服单片机百度云_郭天祥十天征服单片机视频下载地址高级教材《十天学会单片机和C语言编程》ed2k://|file|[十天学会单片机和C语言编程].Lesson1.rar|449712628|262b8896ad6828cd33ed7189fe94cb2d|h=76MXIF34BFV3VUPLLBN3ASNOVCACHTO3|7b&Y0}8J9w,P0E:|-}’Oed2k://|file|[十天学会单片机和C语言编程]…

  • 2022 pycharm 激活码【2022最新】2022.03.10

    (2022 pycharm 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~1…

  • 使用reaver傻瓜式破解wifi之利用路由器WPS漏洞[通俗易懂]

    使用reaver傻瓜式破解wifi之利用路由器WPS漏洞[通俗易懂]跟这篇破解教程一样,网上破解教程多是基于路由器的WPS漏洞破解,但是这样的路由器只占少数。一般wifi是依据WPA/WPA2加密的,因此想要破解一般的wifi,还得破解这个协议,虽然近期这个协议也被破解了,不过也是很不容易的。刚入门破解,不是很熟悉,在网上找各种破解资料,终于破解成功了临近工作室的wifi,沾沾自喜~本文破解wifi针对一些路由器的WPS(Wi-fipro…

  • Matlab保存图片的几种方法「建议收藏」

    Matlab保存图片的几种方法「建议收藏」写在前面:本文系作者原创,转载或引用请注明文章出处,多谢!Matlab中保存图片有很多函数可以用到,本文将简单总结三种保存图像的方法,其他的日后补充。1、保存一幅经过处理的图像,又不希望损失其分辨率:采用imwrite()函数例:想保存图像img,可以写:imwrite(img,adressString);%adressString表示输出地址如果希望同时输出多张图片,可以这样定义string:adressString=[‘D:\picture\’sprintf(‘%0.4d’,nu

  • 服务网关配置_服务网关作用

    服务网关配置_服务网关作用目录第一章Gateway介绍1.1、什么是Gateway1.2、为啥用Gateway第二章Gateway三大核心第三章Gateway工作流程第四章Gateway路由功能4.1、项目准备与启动4.2、工程搭建与测试4.3、配置自定义路由4.4、禁止默认的路由4.5、配置动态的路由4.6、用代码来配路由4.7、为下章节做准备第五章Gateway断言功能5.1、谓词:Path5.2、谓词:After5.3、谓词:Before5.4、谓词:Between5.5、谓词:Cookie5.6、谓词:Header

    2022年10月10日
  • iOS 内存字节对齐

    iOS 内存字节对齐

发表回复

您的电子邮箱地址不会被公开。

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