【超详细Python教学课件分享】寻宝探路

您好,感谢您一直对少儿编程、对“与非学堂”的关注。为了更好地为大家服务,诚邀您填写一份《关于少儿编程教与学的课件资源素材需求调查》,https://www.wjx.cn/jq/82398684.aspx。

图片

问卷二维码

 

 

 

课件属性分析(每项数值最高都为10):

  • 难易度:8(适用于已掌握函数、类、队列等知识的学生)

  • 趣味性:5(中等)

  • 讲授性:7(需要老师比较多的讲解,学生听讲理解、接受)

  • 启发性:5(使用了2次关键的选择题,3次关键的问答题)

 

故事背景:

小D同学总是脑洞大开,他设计了这样一个游戏:在游戏界面上画上了8*8的格子,游戏角色I在其中一个格子里,它可以一次往上下左右没有墙阻挡的地方走一格。地图上的O表示宝藏所在的位置。而W的位置表示不可穿越的墙。小D同学想让角色I在程序开始后,自动找到能够到达O处最短的一条路径。

 

作品效果要求:

完成程序的核心逻辑部分:输入一幅地图,I和O以及W的位置随意安排,W的个数任意,程序自动输出:从I到达O处按最短路线前进,需要走的步数。

数据输入保证只有一个I和O,并且一定有至少一条从I到O的路径。

 

课堂教学流程:

今天我们的任务仅需要完成游戏程序的核心逻辑部分就可以了,不需要使用游戏框架把游戏做成界面显示出来。同学们要相信,只要把核心逻辑完成了,游戏就已经完成70-80%了,界面的工作属于锦上添花了。

 

要让角色I到O,找到按最短的路线前进需要的步数,应该怎么计算呢?注意我们只要求得到这个步数就可以了,而不需要实际输出这条路线,也不需要真的有一个界面,让角色真正走起来。得到最短路线的步骤,是我们系列任务中最简单的一个。

 

(请同学们先回答这个问题后继续后面的内容)

先人工看一下,从I到O,最少需要走多少步呢?

A. 8

B. 9

C. 10

D. 11

 

大家能否数对啊?应该是9步。

 

大家看,这样一个问题其实对聪明的同学们而言,简单太容易了,对吧?

 

但是,大家不要忘了我们的任务,不是让同学们自己数出来,而是让计算机也能够根据地图的样子,自动地数出来。

 

当地图上I、O、W等变换位置的时候,我们都得让计算机一下子计算出这个步数来。

 

意思就是说,咱们的程序需要把我们人脑解决这个问题的步骤,原封不动地用代码写出来。

 

其实大家已经知道了,这种解决一个问题的步骤,就叫算法。

 

咱们怎么用代码设计出这个寻找最短路线所用步数的算法呢?

 

把我们人脑解决这个问题的步骤,用代码写出来,从这个分析我们已经知道了,完成任务至少需要两大步

 

1. 详细地思考,人脑到底是怎么解决这个问题的?

 

2. 怎么把解决这个问题的过程,用代码写出来。

 

那么我们首先要看第一大步:人脑到底是怎么解决这个问题的呢

 

(请同学们直接回答)

大家的回答五花八门啊!老师从大家的回答中,挑出了这样一些有意思的思路:

 

——直接看出来最短路线,再数。

——大概看一下总共有几条路线,数完再比较。

——倒着从O走到I,看哪条路最近。

——先知道O在I的哪个方向,比如说例子中的O在I的右上方位,那么我们走的时候尽量往右和往上走。

…… ……

 

大家回答的这些,非常好啊!每一位同学都是动了脑筋好好思考过的,值得表扬!

 

不过啊,大家的想法里面,有一些是可行的,有一些呢却不是那么准确,也不能解决问题。

 

比如说“尽量往右和往上走”的这种办法,什么叫尽量呢?万一我们偏偏只能往左走了很远再拐到左上角再往右才能到达O呢?或者先往下才有通路。“尽量”这个词太模糊了。

 

再比如说“倒着从O走到I”,这个也不是特别可行。如果你正着从I到O的最短路线找不出来,那么为什么又能保证倒着从O到I的路线好找呢?

 

我们刚才题目中也说了,I、O的位置都可以变,其实我们完全可以把它们互换位置,所以说正着找、倒着找,对解决问题并没有实质性的帮助。

 

那么“直接看出来最短路线再数”,有这个想法的同学,老师要表扬你一下啊!为什么表扬呢?因为你是超人啊!“直接看出”是一种超能力吗?如果我们的地图,不是8*8,而是80*80,你怎么直接看出呢?也不是特别可行,对不对?

 

那么我们还有最后一种想法:看一下总共几条路线,分别把每条路线的步数数完后再比较。

 

这个想法其实比较接近我们的解决思路了。为什么只是接近呢?难道不是从几条路线中比较,才能找出最短路线吗?

 

确实,最短路线是比较才可以找出来的。没有“比较”,就没有“最”。

 

但是如果要把所有的路线都找出来,其实是不太可能,或者说不太高效的。

 

举一个极端的例子:如果地图上只剩下I和O,W全部没有了,那么我们的最短路线怎么算?难道你还要把所有可能的路线都找一遍之后,再比较出最短的吗?显然不需要。

 

同学们还有没有办法,把这种想法再改进一下

 

(思考时间)

 

老师现在给大家一个任务,在纸上画出咱们这个地图,然后从I开始,向上下左右各个可以走的方向,每走一格的时候,在空白的格子里记上一个数字,表示离I走了多远,试试吧!

 

比如,像下面图片中曹老师给大家展示的:从I向左、上、右都可以走,所以在相应的格子里,都填上数字1,表示这个位置离I原来的位置,距离是1。而左上的1无路可走了,放弃它。右边的1处,只能往上走,于是在它上方格子里填上2。原来I上方的数字1处,这时可以往上走,于是在那里填上数字2,也可以从这里往右走,只不过刚才已经填了2了,所以不需要再填了。如果大家填的过程中,出现同一位置两个数字不一样,那么就改成比较小的数字。

大家试试,看一直这样,直到O的周围都填满了数字,那么是不是到O的距离就等于它周围的数字中最小的一个加1了啊?

 

(练习时间)

 

同学们都填得差不多了吧?大家说出来的结果是不是我们要得的最小步数啊?

 

一般情况下,得到的结果是对的,确实是最小步数。但是也有可能不是。如果大家一开始就挑了最长的几条路线先填,一口气填到黑,把O周围都填满了,而比较短的路线还没填数字,没来得及重新涂改O周围的数字,那就不对了。

 

那这么说来,难道我们还是必须得把所有可能的路线都填一遍,才能得到完美的最短路线步数了吗?

 

NO!这样会累死计算机的!

 

大家再来一个纸笔练习。

 

这次我们换一种思路。每一次在从I往外“扩张”数字的值时,必须保证每一个方向上上一次的离I距离更小格子都填完,都扩张完之后,再填更大的数字距离。

 

比如:像下图这样,距离I有4格距离的格子填完后,才能填距离为5的格子。所以第四排第一个5的填写时间,应该在第七排第五个4的填写时间之后。大家请再按这种方法完成练习。

(练习时间)

 

完成后的结果应该是这样的:

当我们标到9的时候,发现有一条路线已经到达O的位置了。所以完成了步数的计算:9。

 

大家看,一个更精确的人脑计算程序,就应该是这样的!同学们可以试着改变一下地图中I、O、W的情况,看看这个方法还是不是一样能用。

 

(练习时间)

 

 

好!人脑解决这个寻找最短路线所用步数,思路就是这样了。现在我们要想一想,怎么用计算机代码来实现这个思路了

 

首先的首先,要想用计算机分析问题、解决问题,我们需要把这个问题化成计算机能够懂的形式

 

什么意思呢?就是计算机怎么才能看懂这个地图啊?

 

其实要想让计算机能够处理问题,我们就需要把问题的方方面面都化为数据。大家已经学了Python的数据类型了。

 

Python里有数字、字符串、布尔值、列表、字典、元组等数据类型。我们应该选用哪一个,用来表示地图呢?(请同学们直接回答)

 

这里我们要用列表来表示这个地图。

 

列表怎么表示?因为地图有行有列,所以我们可以把它的每一行看成一个元素,这样的话,这个列表就有8个行元素。而每一行又有8个格子,所以每一个列表行元素,又应该含有8个子元素。

 

因此,我们最终要用一个二维列表,来表示整个地图。

 

大家请看,所有的空白格子,我们用字符串' '(引号中间为空格)来表示了,而其他的I、O、W,我们都用它们的字符串形式'I', 'O', 'W'表示了。注意所有的字母都要大写,以免后面出错。

 

有了这个data变量存储地图信息,我们就可以用data[7][1]表示'I',用data[1][4]表示'O'了。

 

为了方便,我们给起点的行和列索引分别用一个变量表示:

f_i = 7

f_j = 1

 

好,有了上面这些准备工作,我们就可以更进一步:怎么按刚才第二种填数字的方法,把程序写出来呢?

 

在思考写程序之前啊,同学们一定要弄懂一个问题。大家有没有思考过,两种填数字的方法,有什么本质的不同呢?

 

其实我们可以把问题看成这样:如下图。

 

 

从起点I到终点O的探路过程,其实相当于是上面这个图。从起点出发,可能有4个方向的格子跟它距离为1,然后这4个格子又分别可能有4个方向的格子(当然实际上有重复的)。第2层、第3层……一直到终点,每一层距离就增加1。

 

如果我们用第一种填数字的方法,相当于是从第1层选1格,再走到它的下一层,选1格,再走到它下一层,一直进行下去,直到终点,这样可以找到完整的一条路线。

 

改变中间的选择的格子,可以找到不同的路线。最终用路线所用的层数进行比较选最小的。

 

而第二种填数字的方法,相当于是先不着急着一层一层往终点走,而是先保证把所有的起点周围的第1层都填完之后(有几个就填几个),再填各个的第2层(也是有几个就填几个),所有第2层的格子都填完之后,再填第3层的……

 

这样,总有一个时候会填到终点,这时必定是最短的路线,而这时的层数也就是距离,其它没有填完的就不用管了,因为我们的目标已经实现了。

 

在计算机算法上,我们给这两种思路分别取了不同的名字,这里同学们可以了解一下:第一种叫做“深度优先搜索”,第二种叫做“广度优先搜索”。

 

第一种是先一条道走到黑,第二种则是每条路都同步向前推进。

 

大家注意啊,刚才老师说第二种方法更好,并不是说第二种算法永远比第一种好,算法并没有好坏之分,而只有适用不适用之分。

 

对我们求最短路线的距离这个问题,第二种广度优先搜索的算法,更适合一些。而对其他一些问题,可能就是用第一种更适合一些了。

 

大家现在已经明白咱们的方法本质是什么了。

 

可是,怎么才能做到先把第1层的格子都走完,再走第2层格子呢?

 

我们想啊,每一层可以上下左右走的格子数量还不是确定的,有可能4个(对起点而言),有可能是3个,也可能是2个、1个,或者0个(死胡同了)。

 

因此我们肯定要判断一下,在处理每一层的时候,把能够走的格子都考虑进来。这一层都考虑完之后,再考虑下一层的。

 

所以,大家仔细思考一下这个逻辑,我们要考虑一些格子,考虑另一些格子,前一批格子都填完之后,再填后一批,接着再填下一批。

 

(请同学们先回答这个问题后继续后面的内容)

要用程序实现先来的先处理,后来的后处理,而在处理原来的东西的过程中,待处理的东西又会不断增多,应该用什么编程方法?

A. 循环

B. 栈

C. 队列

D. 函数

 

大家选对了吗?这里我们要用C. 队列,才能完成任务哦!大家记住,广度优先搜索算法,总跟队列有关系。

 

那么我们应该用队列怎么完成这个程序呢?首先我们来复习一下队列的写法:

 

(练习时间)

 

 

上面的代码我们只给了大家一个最简单的队列实现方法。

 

队列可以入队、出队,入队永远在队尾,出队永远在队首。我们把出队函数增加了一个return,使得一会儿咱们可以直接使用它来保存出队的数据。is_empty()则用来判断队列是否为空。

 

有了它之后,那让我们再来思考一下整个程序的流程吧!

 

程序开始后,我们从索引为f_i, f_j的这个格子出发,用一个变量记录这时与初始格子的距离为0。

 

接着一直做下面这些事情:

(1) 一个格子进入处理队列;

(2)真正轮到(位于第一个时)这个格子时,再将它四个方向上可以走的格子也进入处理队列,同时下一层格子离初始格子的距离 = 它上一层格子的距离值+1;

(3)让队列中的第一个元素出队。

 

让我们一步一步来完成代码吧!

 

在上面第(2)条中,怎么判断哪些格子是“可以走”的,也需要有一定的技巧的。因为这个判断是需要重复很多次的,所以我们可以定义一个函数解决。

 

(练习时间)

 

 

在这个过程中,队列的数据结构已经写好了。我们应该决定:往队列里每次入队、出队的是什么东西呢?因为我们要表示一个格子,所以只需要把每个格子的i, j坐标值入队和出队就可以了,因此可以用(i, j)元组的形式。

 

我们把出发点单独在一开始就进行入队处理了。

 

在这之后,就可以用一个循环开启搜索过程了。由于整体循环次数是未定的,所以选用while循环,而一会儿我们在内部用条件来跳出循环,所以一开始写while True。

while True:

    ...

    if ...

        break

 

那么我们的循环应该什么时候终止呢?我们在格子入队时进行判断,在找到一个入队的格子,它的值为'O'时,就可以break循环了。

 

同时为了避免已经加到队列中的格子,被另一条路线重复加入到队列中,需要在每次入队时把这个格子是否访问过的值,标记为“V”,表示“已访问”。在写的过程中,注意当前上下左右的坐标表示。

while的最后一行,别忘了,让第一个元素出队。

 

(练习时间)

 

 

这样,一个能够自动计算最短路线的步数的程序,就完工了!

 

知识技巧总结:

  1. 掌握寻路算法的手工操作

  2. 了解深度优先搜索和广度优先搜索

  3. 掌握队列在广度优先搜索中的使用方法

  4. 掌握判断上下左右四个方向格子存在与否的判断方法

  5. 掌握保存每个格子距离值的方法

  6. 巩固循环、函数、类等的应用

 

课后作业:

请同学们思考在输出最短路线的步数后,如何将最短路线也输出。输入例题中的地图,输出应为:

7 , 1

6 , 1

5 , 1

4 , 1

4 , 2

3 , 2

3 , 3

3 , 4

2 , 4

1 , 4

 

 

 

 

 

 

 

 

 

与非学堂(codingclassonline)

一个专注青少年信息技术教育,探讨少儿编程的教与学,交流技巧、分享资源的公众号。

--------------------------------------


 

【课件分享】

  1. 【超详细Scratch教学课件分享】简单倒计时

  2. 【超详细Scratch教学课件分享】可暂停倒计时

  3. 【超详细Scratch教学课件分享】两位数可暂停倒计时

 

 

 

【往期每日一题】

  1. 蓝桥杯青少组选拔赛STEMA考试样题及解析(科技素养及逻辑思维)

  2. 【Scratch竞赛每日一题】旋转问题

  3. 【Scratch竞赛每日一题】雷电猴与宝箱

  4. 【Scratch竞赛每日一题】海狸的语言

  5. 【Scratch竞赛每日一题】加减大师

  6. 【Scratch竞赛每日一题】限时猜数字

  7. 【Scratch竞赛每日一题】蹦床游戏

  8. 【Scratch竞赛每日一题】来回蹓跶的小猫

  9. 【Scratch竞赛每日一题】小猫回城堡

  10. 【Scratch竞赛每日一题】薛定谔的猫累了

  11. 【Scratch竞赛每日一题】小猫狐狸赛跑

  12. 【Scratch竞赛每日一题】循环变大小

  13. 【Scratch竞赛每日一题】循环画画

  14. 【Scratch竞赛每日一题】坐标和反弹

  15. 【Scratch竞赛每日一题】北极熊快长大

  16. 【Scratch竞赛每日一题】移动与反弹

  17. 【Scratch竞赛每日一题】巧用图章

  18. 【Scratch竞赛每日一题】画线判断

  19. 【Scratch竞赛每日一题】循环变量

  20. 【Scratch竞赛每日一题】小猫克隆

  21. 【Scratch竞赛每日一题】小法师的穿墙术

  22. 【Scratch竞赛每日一题】随机数

  23. 【Scratch竞赛每日一题】小猫拿苹果

 

 

 

 

 

【近期考竞通知】

  1. 蓝桥杯青少组选拔赛 报名开始

  2. 8月编程竞赛汇总,Python、Scratch都有

  3. 2020年第二场NCT全国青少年编程能力等级测试即将启动

  4. 青少年编程能力等级测评(CPA)2020年第二季开始报名

 

 

 

【高赞原创集锦】

  1. 半部论语治天下,一段Scratch懂论语

  2. 好书推荐:《CODE》

  3. 编程却被我妈一直说成玩游戏,我该咋办?

  4. 【免费快领】Scratch编程秘籍PDF

  5. 就《从计算机世界出发窥探中西文明的差异》的补充

  6. 为什么精心制作的少儿编程课程观看的人不多?

  7. 零基础孩子的第一节Scratch课,应该学什么?

  8. Scratch晋级Python,一路要打通哪些关?

  9. 一名合格的程序员,如何让 林有有 = 没有

  10. 这些东西,比光让孩子学编程重要100倍

  11. 这位同学,Scratch代码里可不能填这么大的数字哦!

  12. 玩转Scratch,炮弹击中目标有多难?

  13. 【长文慎入】从计算机世界出发窥探中西文明的差异

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值