题目
运用python语言,以及吉祥物karel编写一个算法,让karel在奇数方格和偶数方格(例如5x5,4x4)中,都能处于底端的中点位置,并在中点朝东放下一个beeper,如下图所示:
我的思路
要位置最后在中点,可以对奇数方格和偶数方格进行分类讨论:
(1)奇数方格
例如5×5,这个时候中点就在从左往右数或者从右往左数的第3个位置;
(2)偶数方格
例如6×6,这个时候中点就在从左往右数的第3和第4个位置,而本题说对于偶数方格,应该在靠左边的位置,因此也为第3个位置。
本题的难点在于,如何利用karel的基础动作(包括move,put/pick_beeper等)以及python语法(包括while, if循环语句),让karel移动的位置在最后的中点。
如果karel可以执行一些动作,最后自主地停在中点的条件是什么呢?
如果只是让karel单纯的移动,它必然不可能知道自己哪里是中点,那么这个时候是不是可以考虑引入put/pick_beeper,如果让karel在最左边缘放一个beeper,向右移动,最右边缘也放一个beeper,然后转身,把右边缘的beeper捡起,放在前一个位置,左边缘同理,并重复这个动作,直到两个beeper挨在一起,这个挨在一起的地方就是karel要停下来的中点位置。
撰写代码
from karel.stanfordkarel import *
## 先在最右边放置beeper,再在最左边放置beeper:
def main():
while front_is_clear() and no_beepers_present():
move()
put_beeper()
turn_around_and_move()
while front_is_clear() and no_beepers_present():
move()
put_beeper()
turn_around_and_move() #转两下左边,再向前一步
while no_beepers_present(): #当向前一步的结果是没有beeper存在,就需要执行一个拿起和放下beeper,使其越来越近的循环
cycle() #因此定义一个cycle,但是如果向前一步的结果有beeper,这个时候就不需要循环这个动作了
pick_beeper()
turn_around_and_move()
if facing_west():
turn_left()
turn_left()
def turn_around_and_move():
turn_left()
turn_left()
move()
def cycle():
while front_is_clear() and no_beepers_present():
move()
pick_beeper()
turn_around_and_move()
put_beeper()
move()
while front_is_clear() and no_beepers_present():
move()
if beepers_present():
pick_beeper()
turn_around_and_move()
put_beeper() #cycle开始于左边缘的右边一步,结束于两个beeper相邻
move()
while front_is_clear() and no_beepers_present():
move()
if __name__ == '__main__':
main()
代码成功运行
My coding style feedback
代码优化
def cycle环节实在是太冗余了,可读性很差,逻辑太复杂,其实一个while循环就可以搞定,因此可以简化为:
def cycle():
while front_is_clear() and no_beepers_present():
move()
pick_beeper()
turn_around_and_move()
put_beeper()
move()