加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

小信息学复赛题汉诺塔LOGO编程详解A

(2024-06-01 09:57:00)
标签:

林老师

pclogo

mswlogo

fmslogo

分类: WinXP~7~8~10运行Logo语言
小信息学复赛题汉诺塔LOGO编程详解A
  小信息学复赛题汉诺塔LOGO编程详解A
        厦门市教育局-市科协官方联办的2023年小学生LOGO语言竞赛复赛 “汉诺塔”动态作图题是一个值得深入研究的练习题。汉诺塔是一个源远流长的经典命题。无论是小学还是中学的任何一门编程语言(LOGO、C、C++、PASCAL、PYTHON、VB、QB)差不多都会讨论到汉诺塔编程。但SCRATCH是不讨论汉诺塔编程的,且使用C++语言、PASCAL等语言编程一般都只能以文字输出结果,难以用图形输出显示。所有的教程、教科书都教你使用“递归”编程——用递归编程4层的LOGO汉诺塔的范例在MSWLogo-FMSLogo自带的演示程序里面就有一个,但是这个“原装”的程序毛病多多,画图中“盘”会出现许多不连续的“断口”,大家可以自己打开来运行看看。而厦门地区的这道题明确只运行3层的汉诺塔,除了初始状态画面外,总共只有7个画面,其实可以另辟蹊径用“依样画葫芦”的方式来画。这样的编程思路非常地“不传统”、“不经典”,可是难度就大大降低了,在参赛中会省下不少时间。我们小学生自己编写的汉诺塔LOGO程序,无论是“依样画葫芦”式的,还是“递归”式的,似乎都要比LOGO编程系统中自带的演示程序要强许多——所有人都可以自己来评判一下。
小信息学复赛题汉诺塔LOGO编程详解A

      现在来考虑怎么使用“依样画葫芦”的方式来画3层的汉诺塔:

      1. 我们定义从大到小的盘号:ph变量为3、2、1。
      2.  3个盘的颜色(画框的颜色及填充色)是:ph*2。对应的颜色是6、4、2,就是黄红绿三种颜色。
      3. 每个盘都是从底部中央用3个Π门框形的“半框”组成的。半框的宽度:bank可以这样子计算::ph*20+20。这就满足了题目中要求三个盘宽度为160、120、80的要求。
      先画两个Π“半框”,然后移动到完整框中填色,再移动会到框底中央,接着画第3个Π“半框”移动到盘的上方中央。这有个好处,上面如果还有盘方便继续画,没有盘了就画中央直立的黑色的杆。
      4. 我们所说的“依样画葫芦”是定义3、2、1盘的8个画面(初始状态加上移动的7个画面)的“动作表”,其实是每一个画面3 根杆上盘的分布状态表:
  make "dzb [  ;定义搬盘运动作的表
    [321 0 0]
    [32 0 1]
    [3 2 1]
    [3 21 0]
    [0 21 3]
    [1 2 3]
    [1 0 32]
    [0 0 321]]
这个表的数据很简单,如果看不懂就无法理解整个程序。这是整个程序的核心。
      5. 现在我们用for[i 1 8][  ];显示从初始状态到搬运完成的8个画面
      每个画面依次读取一组类似[321 0 0]这样的数据,分别表示3根杆上各有哪些盘。有321数字的就有对应的盘。在单个321数字中,左边数字的盘在下面,右边数字的盘在上面,数字为0的杆上没有盘。
      画好一个画面按照题目要求wait 50延时,然后CS清屏,再读取下一组数据继续画。
      用一个hzz画塔盘子程序画所有8个画面的汉诺塔,真正是“依样画葫芦”,找规律画图,其中并没有任何“递归”运算操作。

      这种不包含递归的汉诺塔编程,在所有的类似编程中是独树一帜的,巧妙、简单、易懂、高效。
     
源程序

to hnt_3
  make "dzb [  ;定义搬盘运动作的表
    [321 0 0]
    [32 0 1]
    [3 2 1]
    [3 21 0]
    [0 21 3]
    [1 2 3]
    [1 0 32]
    [0 0 321]]
  for[i 1 8][  ;显示从初始状态到搬运完成的8个画面
    make "zt item :i :dzb ;读取当前画面状态数据
    cs ht
    pu setxy -350 -2      ;画底线
    setpc 0 setpensize 5
    pd setx 350
    for[j 1 3][           ;画当前状态3个柱子上塔盘
      make "dq item :j :zt ;读取当前柱子数据
      pu setxy :j*200-400 0 ;当前柱子底部定位
      pd hzz              ;调用画塔盘子程序
       
    wait 50   ;形成动画的时间间隔          
    ]
end

to hzz ;画塔盘子程序
  make "n count :dq   ;读取当前柱子盘层数
  if :dq<>0[          ;只有数据不为0才有盘子可画
    for[k 1 :n][      ;画n层盘子
      make "ph item :k :dq  ;读取要画的这一个盘号
      setpensize 1
      setpc :ph*2     ;盘的线条颜色
      setfc :ph*2     ;盘的填充色
      make "bank :ph*20+20 ;计算盘的半个宽度
      pd lt 90 hbk hbk         ;画盘框
      pu rt 90 fd 10 pd fill   ;画好整个盘后填色
      pu bk 10 lt 90 hbk lt 90 ;运动到盘的上中点
      ]
    pd setpc 0 setpensize 5 sety 100 ;画顶部剩余柱子
    ]
  if :dq=0 [          ;画无塔盘的空柱子
    pd setpc 0 setpensize 5 fd 100
     ]
end

to hbk ;画盘子半个框的子程序
  pd fd :bank rt 90 fd 20 rt 90 fd :bank
end


小信息学复赛题汉诺塔LOGO编程详解A
小信息学复赛题汉诺塔LOGO编程详解A


小信息学复赛题汉诺塔LOGO编程详解A

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有