第四节:3X3扩张+for循环遍历|编程农场“我真是游戏啊,怎么玩我跟上课一样?”

视频文稿

打开编程农场,农场主告诉我们上次的客户又追加了对农场的投资,这一次农场直接扩张为3X3的草地,又引入了新的作物,解锁了更多科技树。

农场主还告诉我们,农场的草已经多到堆不下了,要求我们多种植新作物,高效利用农场,并且明天客户还会来参观,不过只会停留一会儿,这期间要体现农场对客户的欢迎。

我们来看看农场主今天的任务:

  第一:草不再是收获的主要目标作物了,要优先收获灌木和新作物,充分利用全部草地;

  第二:无人机前五秒需要一边工作一边表演,之后高效工作;

今天的任务比以往都要更难一些,确实得认真对待了。

目前土地扩张成了3X3,解锁了for循环,运算符;编辑器扩展了debug功能,print() 函数;引入了新作物——胡萝卜,胡萝卜只能在土壤上生长,新增 till()耕地函数,能够把草地变成土壤,值得留意的是种植胡萝卜需要消耗一份草和一份灌木。

我们先来解决如何在3X3草地上高效收获灌木和胡萝卜作物的问题;

首先我们的整体思路是:虽然任务要求优先收获灌木和胡萝卜,但是胡萝卜的种植又需要消耗草和灌木,当然我们现在有很多草和灌木的储备,但是也得预防农场主会卖掉所有储备的草和灌木这种情况,所以我们一开始需要先收获草和灌木,不能马上就种胡萝卜,但也要保证后面胡萝卜和灌木的收获占大多数。

大方向确定了,剩下就是敲定每一个步骤,尽量确保高效利用无人机和土地了。

咱们再整理下目前三种作物的基本情况:

我们知道草可以自发在草地上生长,比如灌木收割后草能自发生长,生长时间0.5秒;

再一个,灌木可以在草地和土地上生长,不过无法自发生长,需要我们进行种植,灌木种植不消耗东西,但基础生长时间在 3.2 到 4.8 秒之间;

新作物胡萝卜,只能在土地上生长,种植需要先将草地转变为土地,需要耕地,且种植消耗一份草和一份灌木,基础生长时间在 4.8 到 7.2 秒之间;

同时,农场编辑器允许我们用的指令只有这16个,其他都不能用。

emmm如何充分利用这九块草地,高效收获灌木和胡萝卜呢?

作为大橘农场花费3000草聘请来的新手程序员,我们有六个步骤,

首先第一步:我们需要重置农场状态 我们现在先解决的是高效工作的部分,但表演部分肯定是在工作之前,表演期间农场状态肯定有所变化,使用重置函数可以减少一些麻烦;clear() 但是重置函数有个小问题,如果刚重置无人机下方的草是生长状态,这时候无法收割成熟的草,所以我们还需要在中间插入任意一个耗费时间的操作,避免跳过对第一块草的收获;这里我们随便用来一个后空翻;

第二步:确定主循环

由于我们需要持续种植和收获,这里应该要使用While无限循环。这样程序会一直运行直到手动停止。

while True:

第三步:我们要解决如何让无人机在整个农场移动的问题

想来农场解锁for循环就是为了帮助我们解决这个问题的。for 循环用来让程序依次重复执行一组操作,而不需要手动写多次代码。 在农场中,我们可以用双层 for 循环来“遍历”每一块地:外层循环控制无人机在南北方向一行行移动我们用“row”来作为这个循环的变量名字,内层循环控制无人机在东西方向一列列操作,我们用col来作为这个循环的变量名。 这样,程序就能让无人机自动走遍整个 3×3 的农场,每块地都不落下。

并且为了优化无人机移动效率,我们采用了蛇形路径:偶数行从左到右移动,奇数行从右到左移动,奇偶数可用遍历行的变量row通过对2取余来判断,余数为0则是偶数,否则就是奇数。 这样就避免了每次无人机回到行首的额外移动。

for row in range(get_world_size()):      # 遍历每一行
    for col in range(get_world_size()):  # 遍历每一列
        
        # 蛇形移动逻辑
        if col < get_world_size() - 1:   # 不是最后一列时才水平移动
            if row % 2 == 0:             # 偶数行向右移动
                move(East)
            else:                      # 奇数行向左移动  
                move(West)
    
    # 换行移动:完成一行后向北移动(除非是最后一行)
    if row < get_world_size() - 1:
        move(North)

第四步:收割与种植

处理无人机收获与种植问题,我们采用是去程+返程的两种不同模式,去程时无人机先判断是否有成熟作物收获,若收获就接着耕地并种植灌木;返程时同样先判断是否有成熟作物收获,若收获就种植胡萝卜,如果种植失败则无操作。

# 去程:先耕地并种植灌木
if can_harvest(): # 检查当前位置是否可以收获
        harvest()  # 收获作物
        till()  # 耕地
        plant(Entities.Bush)  # 种植灌木
        
# 返程:种植胡萝卜
if can_harvest(): # 当前格收获(收割成熟的灌木)
        harvest()  # 收获成熟作物
        plant(Entities.Carrot)  # 种植胡萝卜

第五步:回程

前面第三步我们只是解决了正向遍历农场的问题,但在无限循环下,不设计让无人机返回起点再开启下一轮循环的话,会产生很多不确定性。再设计反向蛇形遍历,原路返回,路上还能进行收获和种植操作,高效利用无人机。

# 蛇形原路返回阶段
for row in range(get_world_size() - 1, -1, -1):  # 从最北边开始,向南遍历每一行
    for col in range(get_world_size()):  # 在每一行内遍历所有列
        
        # 如果不是最后一列,进行水平移动
        if col < get_world_size() - 1:
            # 返程时偶数行向左移动,奇数行向右移动
            # 这样能与去程的移动路径完全对称,实现原路返回
            if row % 2 == 0:
                move(West)   # 偶数行向左移动(与去程方向相反)
            else:
                move(East)   # 奇数行向右移动(与去程方向相反)
    
    # 行末移动到下一行(向南移动),最后一行不需要再移动
    if row > 0:
        move(South)  # 向南移动到下一行,继续返程收获

最后,整合代码,执行。

我们看到农场重置后,无人机从起点开始,按照蛇形路线依次遍历整个农场:

去程阶段(从南到北):

  • 在每个地块上,无人机先判断是否有作物可收获;如果有成熟作物,就执行收割,随后立即耕地并种植灌木。
  • 如果没有作物可收获,直接移动到下一个位置。
  • 在每一行内部:
    • 当行号为偶数时,无人机从西向东移动;
    • 当行号为奇数时,无人机从东向西移动;
  • 到达每行末尾时,如果还未到最北边,无人机就向北移动进入下一行。

返程阶段(从北到南):

  • 无人机沿着与去程完全对称的蛇形路径原路返回。
  • 在每个地块上,如果发现有成熟作物,无人机就执行收割,然后尝试种植胡萝卜,若因为任何原因无法种植则继续移动。
  • 在移动过程中:
    • 返程时偶数行从左向右移动,奇数行从右向左移动;
    • 到达每行末尾时,如果不是最后一行,就向南移动进入下一行。

通过这样的循环模式,无人机在去程主要处理灌木的种植和收获,在返程则专注于胡萝卜的种植,同时部分草地收获后不进行种植而是等待自发长草,也确保我们草的储备不会断同时不占多数满足优先收获新作物的要求;

# 重置农场
clear()
do_a_flip()
# 主循环:持续执行种植和收获
while True:
        # 遍历每一行(从南到北)
        for row in range(get_world_size()):
                # 遍历每一列(从西到东)
                for col in range(get_world_size()):
                        # 检查当前位置是否可以收获
                        if can_harvest():
                                harvest()  # 收获作物
                                # 去程:先耕地并种植灌木
                                till()  # 耕地
                                plant(Entities.Bush)  # 种植灌木
                        
                        # 如果不是最后一列,则水平移动
                        if col < get_world_size() - 1:
                                # 偶数行向右移动,奇数行向左移动(蛇形路径)
                                if row % 2 == 0:
                                        move(East)
                                else:
                                        move(West)
                
                # 移动到下一行(向北移动),除非是最后一行
                if row < get_world_size() - 1:
                        move(North)
        
        # 蛇形原路返回收获阶段
        for row in range(get_world_size() - 1, -1, -1):  # 从最北边开始,向南遍历每一行
                for col in range(get_world_size()):  # 在每一行内遍历所有列
                        # 当前格收获(收割成熟的灌木)
                        if can_harvest():
                                harvest()  # 收获成熟作物
                                # 返程:种植胡萝卜
                                plant(Entities.Carrot)  # 种植胡萝卜
                        
                        # 如果不是最后一列,进行水平移动
                        if col < get_world_size() - 1:
                                # 返程时偶数行向左移动,奇数行向右移动
                                if row % 2 == 0:
                                        move(West)   # 偶数行向左移动
                                else:
                                        move(East)   # 奇数行向右移动
                
                # 行末移动到下一行(向南移动),最后一行不需要再移动
                if row > 0:
                        move(South)  # 向南移动到下一行,继续返程收获

大功告成,代码较长,但仅凭给定的指令和我们价值3000份草的脑袋也想不到更简单的方案了,如果有大佬有更优方案,欢迎评论区留言~

解决了无人机高效工作的部分,剩下的5秒钟客户专供程序就简单了。

现有指令没有能控制时间的,那我们就用固定耗时的动作指令来充数好了,毕竟3000草工资的程序员能指望有什么艺术细胞吗?

套用第三步的遍历程序,我们加入收割并种植灌木和胡萝卜,同时打印欢迎语句的程序代表一边工作一边表演,程序执行完刚好5秒左右,农场主应该挑不出我们的毛病吧?

合并,提交给农场主!

大家觉得我们这次的程序能让农场主涨点工资吗?

完整代码

clear()
for r in range(get_world_size()):      # 遍历每一行
		for i in range(get_world_size()):  # 遍历每一列
				
				# 分层处理策略
				if r == 0 and i == 0:  # 第一格
					if can_harvest():
						harvest()
					print("大橘农场")
				
				elif r == 0 and i == 1:  # 第二格
					if can_harvest():
						harvest()
					plant(Entities.Bush)
					print("欢迎您的到来")
				
				elif r == 0 and i == 2:  # 第三格
					if can_harvest():
						harvest()
					till()
					plant(Entities.Carrot)
					print("爸爸")
					break  # 结束
				
				# 蛇形移动逻辑
				if i < get_world_size() - 1 and r == 0 and i < 2:   # 只在第一行前两格移动
						if r % 2 == 0:             # 偶数行向右移动
								move(East)
						else:                      # 奇数行向左移动  
								move(West)
		
		# 如果已经完成第三格工作,跳出外层循环
		if r == 0 and i == 2:
				break
		
		# 换行移动:完成一行后向北移动(除非是最后一行)
		if r < get_world_size() - 1:
				move(North)
				
# 重置农场
clear()
do_a_flip()
# 主循环:持续执行种植和收获
while True:
	# 遍历每一行(从南到北)
	for row in range(get_world_size()):
		# 遍历每一列(从西到东)
		for col in range(get_world_size()):
			# 检查当前位置是否可以收获
			if can_harvest():
				harvest()  # 收获作物
				# 去程:先耕地并种植灌木
				till()  # 耕地
				plant(Entities.Bush)  # 种植灌木
			
			# 如果不是最后一列,则水平移动
			if col < get_world_size() - 1:
				# 偶数行向右移动,奇数行向左移动(蛇形路径)
				if row % 2 == 0:
					move(East)
				else:
					move(West)
		
		# 移动到下一行(向北移动),除非是最后一行
		if row < get_world_size() - 1:
			move(North)
	
	# 蛇形原路返回收获阶段
	for row in range(get_world_size() - 1, -1, -1):  # 从最北边开始,向南遍历每一行
		for col in range(get_world_size()):  # 在每一行内遍历所有列
			# 当前格收获(收割成熟的灌木)
			if can_harvest():
				harvest()  # 收获成熟作物
				# 返程:种植胡萝卜
				plant(Entities.Carrot)  # 种植胡萝卜
			
			# 如果不是最后一列,进行水平移动
			if col < get_world_size() - 1:
				# 返程时偶数行向左移动,奇数行向右移动
				if row % 2 == 0:
					move(West)   # 偶数行向左移动
				else:
					move(East)   # 奇数行向右移动
		
		# 行末移动到下一行(向南移动),最后一行不需要再移动
		if row > 0:
			move(South)  # 向南移动到下一行,继续返程收获

视频

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容