文档章节

斯坦福编程方法学作业讲解3---Karel机器人三大定律(上)

woshishubi
 woshishubi
发布于 2017/03/24 22:23
字数 3876
阅读 217
收藏 1

阿西莫夫机器人三大定律?

2016年,master横空出世,在网络平台上取得对中日韩顶尖棋手60连胜0负1平的逆天战绩,1平还是因为棋手掉线。网络有很多有趣的段子: 李世石赢AlphaGo,可能是人类对机器围棋的最后一场胜利。同时关于机器超越人类的担忧,像以前科幻电影各种机器人战胜人类的事好像不再是杞人忧天。不过阿西莫夫的《我,机器人》中提到机器人三大法则:

第一定律:机器人不伤害人类个体,或者目睹人类将遭受危险而袖手不管。

第二定律:机器人必须服从人给予它的命令,当该命令与第零定律或者第一定律冲突时例外。

第三定律:机器人在不违反第零,第一,第二定律的情况下要尽可能保护自己的生存。

看到这三大定律,悬着的心才稍微安定下来。

Karel机器人三大定律?

Karel是一个弱小,还有点缺陷的机器人,他还不足以对人类产生威胁,但是它也有自己的定律。那它的定律是什么?我们先看一个任务。Karel很忙,经常接受到各种任务。

Karel从当前街角开始,不断往前走,边走边放方块,直到将这一行都填满。如下图:

拿到这个任务很高兴,写了一个新的方法createBeeperLine(),总共就6次,如下面代码:

public void createBeeperLine(){

		   putBeeper();
		   move();

		   putBeeper();
		   move();

		   putBeeper();
		   move();

		   putBeeper();
		   move();

		   putBeeper();
		   move();

		   putBeeper();

}

Karel顺利完成任务,值得庆祝一下。但是这个方法好像有些问题,如果100行,难道我们要重复写move,  putBeerper, 100次吗?好像很傻一样。有没有一种办法处理这种重复的事。

Karel的第二定律

Karel的第二定律就是:我们总是不断重复着昨天的故事。

怎么直接就第二定律了,那第一定律是什么?

第一定律,我们之前已经体验过了:我们很多时候总是按照顺序执行任务,比如大家都是先上小学,然后上中学,最后上大学,这样按顺序执行的。

那程序如何处理反复执行的事情了?程序员称这个为循环,有两种方式,一种是for 循环,for语句用于当你想按预定的次数重复执行一组命令的时候,while语句用于当你想在某些条件满足时候,重复执行一组命令的时候。

我们先看看for循环,等讲完第三条定律的时候,再看看while循环。

循环有四个要素:

1)        开始的时候,

2)        结束的时候,

3)        迭代因子(计数器递增或者递减),也就是从开始到结束,比如电梯从1楼上到10楼,每一次递进1楼,没有递进,永远停留在开始,形成死循环。

4)        循环要做的事,比如在我们刚才的任务里,反复做的事就是putBeeper(),move()。

我们看一看for循环的语法结构.

for (int  i  =  0;  i  <= count; i = i + 1; )
{
   重复执行的语句。
}

int  i;i 是一个变量,这个跟初中代数变量的意思相近,就是值可以变化,比如定义x 变量,x 可以等于不同的数。int 表示变量的类型是整形,也就是i 必须是一个整数。同样表示小数的变量,类型是double,float,必须定义一个小数型的变量格式为:double  j = 5.20;

int  i = 0:表示i是 一个整形变量,我们将0赋值给i。

我们看看for循环的结构i= 0;就是开始的时候。 i < count; count就是结束的时候, i= i+ 1 ;就是迭代因子,每次递进1步,然后{}体内就是循环的内容。

我们看看for循环的流程图

for (int  i  =  0(初始化部分);  i  <= count(条件判断); i = i + 1; (迭代因子))

{

     重复执行的语句。(循环体)

}

 

我们再回到最初的任务,怎么将下面的代码改成循环

public void createBeeperLine(){

		   putBeeper();
		   move();

		   putBeeper();
		   move();

		   putBeeper();
		   move();

		   putBeeper();
		   move();

		   putBeeper();
		   move();

		   putBeeper();

}

 

总共有放了6个方块,那么我们改写代码如下:

	public void createBeeperLine(){
		   
		   for (int i = 0; i < 6; i++){
		      putBeeper();
		      move();
		   }

	}

我们简单看一下for循环代码执行顺序

那么程序的执行顺序就是 ‚  ‚ ƒ„‚ƒ„‚ƒ„‚ƒ„‚ƒ„‚ƒ„ƒ„‚ƒ„‚ƒ„‚ƒ„‚ƒ„‚ƒ„

这里我们对for循环基本很熟悉。

我们把刚才代码测试一下是否完成了预期的目标。

是不是我们再一次体会到了这个世界的恶意,Karel执行完上面的循环撞墙了。

当它走到角落里放完Beeper之后不能再往前走了。我们只能循环5次了,我们把判断条件改为 i  <  5,试试。好像Karel没有撞墙,但是新的问题又出现了,最后一个位置是空的

解决这个问题很容易,等循环结束之后,我们在最后的位置执行putBeeper的命令,就完美解决问题。

代码如下:

	public void createBeeperLine(){
		
			for (int i = 0; i < 5; i++){
				putBeeper();
				move();
			}

			putBeeper();
	}

结果如下:

现在我们已经非常熟悉了for循环。Karel现在又接收到了新任务,将整个屏幕都填满方块。

我们执行完放满一行的任务之后,Karel现在处在屏幕第1街第6道,也就是第1街的最右边,现在Karel如何执行填满第2行的任务:首先上到第2街,然后调整好方向,然后接着执行createBeeperLine()命令。

我们把相应的代码写在Run方法里出来:

turnLeft();
move();
turnLeft();
createBeeperLine();

好像完成了我们的任务,Karel虽然有点残疾,但是他也有普通人没有的功能,就是倒立行走,跟西毒欧阳锋一样,倒立行走。

我们完成了第二行的任务。我们看看第三行怎么做?

是不是调整好方向就跟其他行没什么区别,如何调整方向?

向右转,往上走一步,然后再向右转,是不是跟第一行一样了?

我们把相应的代码写出来:

turnRight();

move();

turnRight();

createBeeperLine();

是不是第三行也放好了。我们继续这样放好第四行,第五行…直到最后一行。是不是顺利完成任务了。

 

大家回过头看看,是不是觉得这个方法一样不科学,他们是不是在重复着做某些内容。

第一行,第三行,第五行….奇数行是不是方向相同?

第二行,第四行,第六行…..偶数行是不是方向相同?

但是奇数行与偶数行不一致,有没有办法用一个循环解决?

有的人马上想到以放两行为一个循环,这样是不是比较完美地解决问题。我们先试试,先完成放两行的命令:

	public void createBeeperTwoLine(){
		createBeeperLine();
		turnLeft();
		move();
		turnLeft();
		createBeeperLine();
	}

放完两行之后,如果我们要继续再放两行是不是先要走上去,那么执行的命令的是先向右转,然后前进一步,然后再向传,是不是可以重复进行第二次放两行的命令:

我们现在可以向以前一样重复执行放两行的命令了,那么我们现在可以完整的写下代码:

	public void run(){
		for ( int k = 0 ; k < 3 ; k++){
			createBeeperTwoLine();
			turnRight();
			move();
			turnRight();
		}
	}

Karel的第三定律

这样是不是能够完成我们的任务,我们把代码检验一下,满怀期待,再一次感受到世界的恶意,是不是我们放完了,机器人并没有像我们预计的那样停下来,继续往上走,碰壁了。

我们如何解决这个问题,如果我们知道已经到了最后一行的时候,是不是可以告诉机器人不往前走了,我们现在来看Karel的第三大定律:人生总是充满着很多选择:比如向左走,还是向右走?对于我们的karel机器人当前遇到的问题是:是不是到了最后一行?是的话,不向上走了,如果没到,就继续向上走了?我们在程序有什么语法对应这种需要选择的情况。我们看看经典的if语句

if(条件检测){

   只有当条件满足时才会执行的语句

}else{

   只有当条件不满足时才会执行的语句

}

女生都是这种语句使用高手,谈过恋爱的男生都知道,女生一旦想要达成某项目标的时候,比如想让你给她买个包的时候,她都会用上这个语句:

if (你是不是不爱我了){

    如果是,就分手。

}else{

    如果不是,就买包。

}

基本这招屡试不爽。当然,有时候只有if,也就是意味着else的情况什么也不做。我们后面会经常见到。

 

比如我们怎么修改刚才的代码,可以避免机器人完成任务之后继续往上走撞墙,是不是如果是最后一行,就不往上走了,如果不是,那么机器人继续往向上走。对应的else的代码就是什么也不做了,完整代码如下:

	public void run(){
		for ( int k = 0 ; k < 3 ; k++){
			 createBeeperTwoLine();
			 if (k != 2){
				 turnRight();
				 move();
				 turnRight();
			 }
		}
	}

是不是完美地解决了这个撞墙的问题。

 

好,我们现在想想一次循环完成放两行的代码有什么缺陷?如果总行数是偶数的话,每次执行两行这样没有任何问题,但是如果总行数是奇数,比如7行,这个代码是不是不行。我们如何解决?是不是我们得先判断一下是不是奇数行,还是偶数行,又是一次判断。

 

我们有没有更好的解决方案,我们还是回到最初的地方去?

我们将任务分解成两件事:先铺满一行,如果是最后一行就结束任务,如果不是Karel就到上一行,然后接着铺满一行,如此反复。我们现在考虑如何完成这个任务了。我们可以看到在不同的行,Karel想往上走一步,行为是不一样:比如Karel完成铺满一行的时候,如果Karel现在面朝东方的,它要上去,是需要完成以下几个命令:

1)        向左转。

2)        往前走一步。

3)        向左转,调整方向。

如果Karel现在面朝西方,则与这个命令相反。

如果我们有一个命令能判断Karel现在是面朝东方,还是西方,就能完美解决这个任务。这个世界不仅仅让你感觉到恶意,但是更多的时候,是更多的善意,正如你所愿,系统真的提供了完整的命令:

facingEast() :Karel是不是面朝东方的;

facingWest():Karel是不是面朝西方的;

当然也有北方和南方:

facingNorth():Karel是不是面朝北方的;

facingSouth():Karel是不是面朝南方的;

 

我们判断是不是Karel现在面朝东方还是西方,便是很容易了。

if(Karel是不是面朝东方的){

    是的话,做什么?
}
else{

    不是的话,做什么?
}

 

具体的代码如下:

public void run( ){

		for ( int k = 0 ; k <6 ; k++){
		      createBeeperLine();
		      moveToNextLine ();
		}

	}



	public void moveToNextLine (){

		if (facingEast()){
			turnLeft ();
			move();
		    turnLeft ();
		}else{
			turnRight();
		    move();
            turnRight();
        }
	}

 

是不是很清楚了?是不是又感觉大功告成了。我们测试一下,是不是再次发现世界的恶意,大家发现问题在哪?是不是又没有停下来?我们如何去解决这个问题。留给大家自己去做一做。

 

我们在这里是不是经常遇到大小差一的错误(off by one)就是指某个变量的最大值和最小值可能会和正常值差1,或者循环多执行一次/少执行一次。一般在临界情况时发生。我们在边界条件要格外注意,在我们这里经常遇到多走一步撞墙,少做一次,方块放不全的问题。比如小学时候经典问题如果你要建造一个100米长的栅栏,其栅栏柱间隔为10米,那么你需要多少根栅栏柱呢?11根或9根都是正确答案,而10根却是不正确的答案。一只青蛙掉在井底.井深10米,青蛙白天爬三米,晚上向下掉2米,问青蛙几天爬上来?这样经典问题,我们常常在最后边界条件出了问题。

关于Off by one 有个既浪漫又悲伤的笑话:

有一个男孩他爱上了一个女孩,女孩知道后接见了他,

男孩见到女孩之后更爱她了,就对女孩说出了心里话。

女孩就说你在我的窗下等上100天我就会爱上你!

男孩就高兴的答应了,从那天开始,男孩每天都在窗下等着就着样一天又一天,

一个星期又一个星期的过去了,男孩不论刮风还是下雨都痴痴的等在窗下,

但是窗户从来都没打开过,但是女孩吗她当然会信守诺言的!

可是到了女孩数到99天男孩再一次看着窗户,

傍晚他回身了,微笑着走了没有回头,从此在没人看到过他。

为什么?

因为女孩是程序员,她从零开始计数的。

 

我们这里是不是循环多了一次,最后结束到了第6行时候,铺完最后一行的时候是不是应该停下来,我们如何去修改这个问题?大家想一想就有办法了。

我们基本上能完成铺满整个屏幕的问题,但是现在又有了新的问题,我们现在做的都是已经知道具体的行数或者列数的。我们现在要适用于所有的地图该如何做?当我们不知道地图大小的时候,机器人是否有办法顺利完成任务。这个任务留在下一次课再探讨。

 

今天我们总结一下机器人三大定律:

1)        顺序

2)        循环

3)        选择

在程序的世界,只有这三种情况,暂时没见到第四种情况。就像牛顿运动三大定律一样,所有宏观物体运动,大到星球,小到分子,电子运动,无比符合三大定律。

所有的代码要么是顺序,要么循环,要么选择。没有第四种选择。

 

欢迎收看我们的下一节课:机器人三大定律(下),我们继续使用这三种情况完成更复杂的任务,比如适应所有的地图。

 

 

 

 

© 著作权归作者所有

woshishubi
粉丝 4
博文 4
码字总数 13467
作品 0
武汉
私信 提问
加载中

评论(1)

woshishubi
woshishubi
我们建立一个交流群,群号486649186
斯坦福自然语言处理习题课1——绪论

对于技术人员来说,如果要问当前最热门的技术是什么?我想大家一定会回答是人工智能技术。而在人工智能技术中,哪个技术方向最火呢?大家肯定会回答是深度学习技术。如果我们要问在深度学习技...

最老程序员闫涛
2018/11/06
0
0
自动化领域最值得关注的十大人机协作机器人

  据国际机器人联盟预测,到2020年全球工业机器人的销量将比2016年大幅增长77%。而人机协作机器人作为人类的得力伙伴,帮助人类在汽车、电子等行业共同完成工作,凭借其灵活、智能的特点,...

中国机器人
2018/01/10
0
0
中国人口将迎来负增长,这是旷视们的机会

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dQCFKyQDXYm3F8rB0/article/details/86570423 作者 | 阿司匹林 出品 | AI科技大本营 1 月 16 日,人工智能创业...

AI科技大本营
01/18
0
0
这是你的芯片!不,这是你的芯片!

清晨6点,沉浸在深深的梦乡里,我追逐着恋人在草地上嬉笑、奔跑、打滚,杠铃般的笑声弥漫了整个梦境...... 我眼前突然一片明亮,半空中悬浮闪现出一个巨大的6:00字样,在眼前抖来抖去,扭来扭...

zarknight
2017/05/07
0
0
开源书籍-JavaScript 编程精解

《JavaScript 编程精解》(Eloquent JavaScript)第三版,是由马尔奇·哈弗贝克(Marlin Haverbeke)JavaScript程序员编写的JS入门书籍,Marlin Haverbeke通晓多种编程语言,在Web开发方面积累...

marsdream
2018/06/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Angular 英雄编辑器

应用程序现在有了基本的标题。 接下来你要创建一个新的组件来显示英雄信息并且把这个组件放到应用程序的外壳里去。 创建英雄组件 使用 Angular CLI 创建一个名为 heroes 的新组件。 ng gener...

honeymoose
今天
4
0
Kernel DMA

为什么会有DMA(直接内存访问)?我们知道通常情况下,内存数据跟外设之间的通信是通过cpu来传递的。cpu运行io指令将数据从内存拷贝到外设的io端口,或者从外设的io端口拷贝到内存。由于外设...

yepanl
今天
6
0
hive

一、hive的定义: Hive是一个SQL解析引擎,将SQL语句转译成MR Job,然后再在Hadoop平台上运行,达到快速开发的目的 Hive中的表是纯逻辑表,就只是表的定义,即表的元数据。本质就是Hadoop的目...

霉男纸
今天
3
0
二、Spring Cloud—Eureka(Greenwich.SR1)

注:本系列文章所用工具及版本如下:开发工具(IDEA 2018.3.5),Spring Boot(2.1.3.RELEASE),Spring Cloud(Greenwich.SR1),Maven(3.6.0),JDK(1.8) Eureka: Eureka是Netflix开发...

倪伟伟
昨天
13
0
eclipse常用插件

amaterasUML https://takezoe.github.io/amateras-update-site/ https://github.com/takezoe/amateras-modeler modelGoon https://www.cnblogs.com/aademeng/articles/6890266.html......

大头鬼_yc
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部