python数列求和1+11+111前n项_Python Robot 综合练习 (十一)

修正后的版本。

控制迷宫寻宝机器人

在这个项目中,你将使用刚刚学到的知识,尝试根据要求,编写代码,来控制一个机器人,在模拟环境中行走,并找到目标宝藏。

机器人所在的模拟环境中,会包含这样几个因素:机器人的起点、障碍物、宝藏箱。你的任务包括:

分析模拟环境的数据

控制机器人随机行动

(可选)控制机器人走到终点

一个良好的含有注释的代码,可以让你的程序可读性更高,尝试为你自己的代码添加相应的注释。

第一节 分析模拟环境的数据

首先,只有足够了解机器人所在的环境,我们的机器人才能成功找到目标宝藏,因此首先我们来对机器人所在环境的数据进行分析。在这个部分,会考察你对数据结构、控制流的了解。

1.1 理解模拟环境数据的储存格式

首先我们思考这样的问题:如何存储模拟环境的数据呢?

我们将我们的模拟环境抽象成一个格子世界,每个格子按照坐标编号进行标记;每个格子中会有四个情况,分别为普通格子(可通行)、机器人的起点(可通行)、障碍物(不可通行)、宝藏箱(目标点)。例如,一个模拟环境就可以抽象成3行4列的格子世界,并按这按这样的方法进行存储:

environment = [[0,0,0,2],

[1,2,0,0],

[0,2,3,2]]

我们用了一个列表来保存虚拟世界的数据。外层列表中的每一个元素依然是一个列表,它代表模拟环境中每行的数据。而对于这个列表中的每个元素都是一个数,它们的含义是:

0: 普通格子(可通行)

1: 机器人的起点(可通行)

2: 障碍物(不可通行)

3: 宝藏箱(目标点)

那么,根据上述的数据,这个迷宫的第二行第一列,是我们机器人的起点。

注:我们描述的迷宫的坐标位置(第一行第一列),和迷宫下标索引的值(如 (0,0))是不一样的,请注意下标的问题。

如下的代码,使用了辅助函数,读取了模拟环境的数据,并保存在了 env_data 变量中。

import helper

env_data = helper.fetch_maze()

print(env_data)

maze-id 1-1544451683

[[3, 2, 2, 2, 2, 2, 2, 2, 1],

[0, 0, 2, 2, 2, 2, 2, 0, 0],

[2, 0, 0, 2, 2, 2, 0, 0, 2],

[2, 2, 0, 0, 2, 0, 0, 2, 2],

[2, 2, 2, 0, 0, 0, 2, 2, 2]]

[[3, 2, 2, 2, 2, 2, 2, 2, 1], [0, 0, 2, 2, 2, 2, 2, 0, 0], [2, 0, 0, 2, 2, 2, 0, 0, 2], [2, 2, 0, 0, 2, 0, 0, 2, 2], [2, 2, 2, 0, 0, 0, 2, 2, 2]]

任务1:在如下代码中,请写代码获得这些值:

模拟环境的长和宽

模拟环境中第3行第6列元素

#TODO 1模拟环境的行数

rows = None

rows = len(env_data)

# print(rows)

#TODO 2模拟环境的列数

columns = None

columns = len(env_data[0])

#TODO 3取出模拟环境第三行第六列的元素

row_3_col_6 = None

row_3_col_6 = env_data[2][5]

print("迷宫共有", rows, "行", columns, "列,第三行第六列的元素是", row_3_col_6)

5

迷宫共有 5 行 9 列,第三行第六列的元素是 2

1.2 分析模拟环境数据

接着我们需要对模拟环境的中的数据进行分析。请根据如下的指示,计算相应的值。

任务2:在如下代码中,请计算模拟环境中,第一行和第三列的障碍物个数。

提示:可以用循环完成。

#TODO 4计算模拟环境中,第一行的的障碍物个数。

number_of_barriers_row1 = None

for item in env_data[0]:

if item == 2:

if number_of_barriers_row1 == None:

number_of_barriers_row1 = 0

number_of_barriers_row1 += 1

#TODO 5计算模拟环境中,第三列的的障碍物个数。

number_of_barriers_col3 = None

for index in range(rows):

for i,item in enumerate(env_data[index]):

if i == 2 and item == 2:

if number_of_barriers_col3 == None:

number_of_barriers_col3 = 0

number_of_barriers_col3 += 1

print("迷宫中,第一行共有", number_of_barriers_row1, "个障碍物,第三列共有", number_of_barriers_col3, "个障碍物。")

迷宫中,第一行共有 7 个障碍物,第三列共有 3 个障碍物。

%run -i -e test.py RobotControllortTestCase.test_cal_barriers

.

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

Ran 1 test in 0.001s

OK

任务3:在如下代码中:

创建一个名为 loc_map 的字典,它有两个键值,分别为 start 和 destination,对应的值分别为起点和目标点的坐标,它们以如 (0,0) 的形式保存为元组。

从字典中取出 start 对应的值,保存在 robot_current_loc 对应的变量中,这个变量表示小车现在的位置。

# 定义起点终点常量

START_VAL = 1

END_VAL = 3

# 获取机器人起点、终点坐标

def get_location(world, value):

"""

获取机器人的位置

world -- list 虚拟位置

value -- 位置值

"""

for x in range(rows):

for y in range(columns):

if world[x][y] == value:

return(x, y)

# TODO 6按照上述要求创建字典

loc_map = {

'start':get_location(env_data, START_VAL),

'destination':get_location(env_data, END_VAL)

}

robot_current_loc = None #TODO 7保存机器人当前的位置

robot_current_loc = loc_map['start']

%run -i -e test.py RobotControllortTestCase.test_cal_loc_map

.

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

Ran 1 test in 0.001s

OK

第二节 控制机器人随机漫步

在这一步中,你需发出指令,控制机器人在环境中随机行动。它会考察你对控制流、调用函数的知识。

2.1 控制机器人行动

我们的机器人能够执行四个动作:向上走 u、向下走 d、向左走 l、向右走 r。但是,由于有障碍,很多时候机器人的行动并不能成功。所以在这里,你需要实现一个函数,来判断机器人在某个位置,执行某个移动动作是否可行。

任务4:在下方代码中,实现名为 is_move_valid_special 的函数,它有两个输入,分别为机器人所在的位置坐标 loc,以及即将执行的动作 act,如 (1,1) 及 u。接着它的返回是一个布尔值,表明小车在 loc 位置下,是否可以执行动作 act。

提示1:可以读取上方定义的 env_data 变量,来读取模拟环境的数据。

提示2:在实现函数后,请删去下方的 pass 代码。

提示3:我们需要处理边界的情况,即机器人走到了虚拟环境边界时,是不能够走出虚拟环境的。

def is_move_valid_special(loc, act):

"""

Judge wether the robot can take action act

at location loc.

Keyword arguments:

loc -- tuple, robots current location

act -- string, robots meant action

"""

row_loc = loc[0] # 当前位置行号

col_loc = loc[1] # 当前位置列号

#TODO 8

if act == 'u':

if (row_loc - 1 >= 0) and (env_data[row_loc -1][col_loc] != 2):

return True

else:

return False

elif act == 'd':

if (row_loc + 1 <= len(env_data) - 1) and (env_data[row_loc + 1][col_loc] != 2):

return True

else:

return False

elif act == 'l':

if (col_loc - 1 >= 0) and (env_data[row_loc][col_loc - 1] != 2):

return True

else:

return False

elif act == 'r':

if col_loc + 1 <= len(env_data[0]) - 1 and (env_data[row_loc][col_loc + 1] != 2):

return True

else:

return False

else:

return False

# print(is_move_valid_special((0,0), 'r'))

%run -i -e test.py RobotControllortTestCase.test_is_move_valid_special

.

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

Ran 1 test in 0.001s

OK

任务5:在下方代码中,重新实现一个名为 is_move_valid 的函数,它有三个输入,分别为模拟环境的数据 env_data、机器人所在的位置坐标 loc、以及即将执行的动作 act。它的返回值与此前一样,是一个布尔值,表明小车在给定的虚拟环境中的 loc 位置下,是否可以执行动作 act。

def is_move_valid(env_data, loc, act):

"""

Judge wether the robot can take action act

at location loc.

Keyword arguments:

env -- list, the environment data

loc -- tuple, robots current location

act -- string, robots meant action

"""

row_loc = loc[0]

col_loc = loc[1]

#TODO 9

if act == 'u':

if (row_loc - 1 >= 0) and (env_data[row_loc -1][col_loc] != 2):

return True

else:

return False

elif act == 'd':

if (row_loc + 1 <= len(env_data) - 1) and (env_data[row_loc + 1][col_loc] != 2):

return True

else:

return False

elif act == 'l':

if (col_loc - 1 >= 0) and (env_data[row_loc][col_loc - 1] != 2):

return True

else:

return False

elif act == 'r':

if col_loc + 1 <= len(env_data[0]) - 1 and (env_data[row_loc][col_loc + 1] != 2):

return True

else:

return False

else:

return False

%run -i -e test.py RobotControllortTestCase.test_is_move_valid

.

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

Ran 1 test in 0.001s

OK

任务6:请回答:

在任务4及任务5中的实现的两个函数中,env_data 这个变量有什么不同?

调用is_move_valid函数,参数为env_data_、loc_、act_,如果在函数内修改env_data是否会改变env_data_的值?为什么?

提示:可以尝试从变量作用域的角度回答该问题1。

提示:可以尝试从可变类型变量和不可变类型变量的角度回答该问题2。

回答:

1、它们的区别在于前者是全局变量,后者是局部变量。

Python 同多数编程语言一样,也有全局变量与局部变量的概念,两者的本质区别就是在于作用域。

简单来说,全局变量是在全局范围内都可以访问,如果要修改它需要加上global字段,而局部变量是在某个函数中声明的,只能在该函数中调用它。

2、Python的每个对象都分为可变和不可变,主要的核心类型中,数字、字符串、元组是不可变的,列表、字典是可变的。可变参数作为参数是传引用到函数,所以在函数中对形参的修改会改变实参的值

2.2 机器人可行动作

任务7:编写一个名为 valid_actions 的函数。它有两个输入,分别为虚拟环境的数据 env_data,以及机器人所在的位置 loc,输出是一个列表,表明机器人在这个位置所有的可行动作。

提示:可以尝试调用上方定义的is_move_valid函数。

## TODO 10 从头定义、实现你的函数

def valid_actions(env_data, loc):

"""

Judge wether the robot can take action act

at location loc.

Keyword arguments:

env_data -- list, the environment data

loc -- tuple, robots current location

"""

acts = [] # 可移动的位置

all_acts = ['u','d','l','r']

for act in all_acts:

is_move = is_move_valid(env_data, loc, act)

if is_move == True:

acts.append(act)

return acts

%run -i -e test.py RobotControllortTestCase.test_valid_actions

.

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

Ran 1 test in 0.001s

OK

2.3 移动机器人

当机器人收到一个动作的时候,你机器人的位置应发生相应的变化。

任务8:编写一个名为 move_robot 的函数,它有两个输入,分别为机器人当前所在的位置 loc 和即将执行的动作 act。接着会返回机器人执行动作之后的新位置 new_loc。

##TODO 11 从头定义、实现你的函数

def move_robot(loc, act):

"""

move robot

Keyword arguments:

act -- list, the environment data

loc -- tuple, robots current location

"""

# 新的位置

new_loc = ()

row_loc = loc[0]

col_loc = loc[1]

if act == 'u':

new_loc = (row_loc - 1, col_loc)

elif act == 'd':

new_loc = (row_loc + 1, col_loc)

elif act == 'l':

new_loc = (row_loc, col_loc - 1)

elif act == 'r':

new_loc = (row_loc, col_loc + 1)

return new_loc

%run -i -e test.py RobotControllortTestCase.test_move_robot

.

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

Ran 1 test in 0.001s

OK

2.4 随机移动机器人

接着,我们尝试在虚拟环境中随机移动机器人,看看会有什么效果。

任务9:编写一个名为 random_choose_actions 的函数,它有两个输入,分别为虚拟环境的数据 env_data,以及机器人所在的位置 loc。机器人会执行一个300次的循环,每次循环,他会执行以下任务:

利用上方定义的 valid_actions 函数,找出当前位置下,机器人可行的动作;

利用 random 库中的 choice 函数,从机器人可行的动作中,随机挑选出一个动作;

接着根据这个动作,利用上方定义的 move_robot 函数,来移动机器人,并更新机器人的位置;

当机器人走到终点时,输出“在第n个回合找到宝藏!”。

提示:如果机器人无法在300个回合内找到宝藏的话,试试看增大这个数字,也许会有不错的效果 :P

##TODO 12 从头实现你的函数

import random

def random_choose_actions(env_data, robot_current_loc):

for i in range(500):

print("第{}个回合...".format(i))

acts = valid_actions(env_data, robot_current_loc)

act = random.choice(acts)

is_move = is_move_valid(env_data, robot_current_loc, act)

if is_move == True:

new_loc = move_robot(robot_current_loc, act)

robot_current_loc = new_loc

if env_data[new_loc[0]][new_loc[1]] == 3:

print("在第{}个回合找到宝藏!".format(i))

break

# 运行

random_choose_actions(env_data, robot_current_loc)

第0个回合...

第1个回合...

第2个回合...

第3个回合...

第4个回合...

第5个回合...

第6个回合...

第7个回合...

第8个回合...

第9个回合...

第10个回合...

第11个回合...

第12个回合...

第13个回合...

第14个回合...

第15个回合...

第16个回合...

第17个回合...

第18个回合...

第19个回合...

第20个回合...

第21个回合...

第22个回合...

第23个回合...

第24个回合...

第25个回合...

第26个回合...

第27个回合...

第28个回合...

第29个回合...

第30个回合...

第31个回合...

第32个回合...

第33个回合...

第34个回合...

第35个回合...

第36个回合...

第37个回合...

第38个回合...

第39个回合...

第40个回合...

第41个回合...

第42个回合...

第43个回合...

第44个回合...

第45个回合...

第46个回合...

第47个回合...

第48个回合...

第49个回合...

第50个回合...

第51个回合...

第52个回合...

第53个回合...

第54个回合...

第55个回合...

第56个回合...

第57个回合...

第58个回合...

第59个回合...

第60个回合...

第61个回合...

第62个回合...

第63个回合...

第64个回合...

第65个回合...

第66个回合...

第67个回合...

第68个回合...

第69个回合...

第70个回合...

第71个回合...

第72个回合...

第73个回合...

第74个回合...

第75个回合...

第76个回合...

第77个回合...

第78个回合...

第79个回合...

第80个回合...

第81个回合...

第82个回合...

第83个回合...

第84个回合...

第85个回合...

第86个回合...

第87个回合...

第88个回合...

第89个回合...

第90个回合...

第91个回合...

第92个回合...

第93个回合...

第94个回合...

第95个回合...

第96个回合...

第97个回合...

第98个回合...

第99个回合...

第100个回合...

第101个回合...

第102个回合...

第103个回合...

第104个回合...

第105个回合...

第106个回合...

第107个回合...

第108个回合...

第109个回合...

第110个回合...

第111个回合...

第112个回合...

第113个回合...

第114个回合...

第115个回合...

第116个回合...

第117个回合...

第118个回合...

第119个回合...

第120个回合...

第121个回合...

第122个回合...

第123个回合...

第124个回合...

第125个回合...

第126个回合...

第127个回合...

第128个回合...

第129个回合...

第130个回合...

第131个回合...

第132个回合...

第133个回合...

第134个回合...

第135个回合...

第136个回合...

第137个回合...

第138个回合...

第139个回合...

第140个回合...

第141个回合...

第142个回合...

第143个回合...

第144个回合...

第145个回合...

第146个回合...

第147个回合...

第148个回合...

第149个回合...

第150个回合...

第151个回合...

第152个回合...

第153个回合...

第154个回合...

第155个回合...

第156个回合...

第157个回合...

第158个回合...

第159个回合...

第160个回合...

第161个回合...

第162个回合...

第163个回合...

第164个回合...

第165个回合...

第166个回合...

第167个回合...

第168个回合...

第169个回合...

第170个回合...

第171个回合...

第172个回合...

第173个回合...

第174个回合...

第175个回合...

第176个回合...

第177个回合...

第178个回合...

第179个回合...

第180个回合...

第181个回合...

第182个回合...

第183个回合...

第184个回合...

第185个回合...

第186个回合...

第187个回合...

第188个回合...

第189个回合...

第190个回合...

第191个回合...

第192个回合...

第193个回合...

第194个回合...

第195个回合...

第196个回合...

第197个回合...

第198个回合...

第199个回合...

第200个回合...

第201个回合...

第202个回合...

第203个回合...

第204个回合...

第205个回合...

第206个回合...

第207个回合...

第208个回合...

第209个回合...

第210个回合...

第211个回合...

第212个回合...

第213个回合...

第214个回合...

第215个回合...

第216个回合...

第217个回合...

第218个回合...

第219个回合...

第220个回合...

第221个回合...

第222个回合...

第223个回合...

第224个回合...

第225个回合...

第226个回合...

第227个回合...

第228个回合...

第229个回合...

第230个回合...

第231个回合...

第232个回合...

第233个回合...

第234个回合...

第235个回合...

第236个回合...

第237个回合...

第238个回合...

第239个回合...

第240个回合...

第241个回合...

第242个回合...

第243个回合...

第244个回合...

第245个回合...

第246个回合...

第247个回合...

第248个回合...

第249个回合...

第250个回合...

第251个回合...

第252个回合...

第253个回合...

第254个回合...

第255个回合...

第256个回合...

第257个回合...

第258个回合...

第259个回合...

第260个回合...

第261个回合...

第262个回合...

第263个回合...

第264个回合...

第265个回合...

第266个回合...

第267个回合...

第268个回合...

第269个回合...

第270个回合...

第271个回合...

第272个回合...

第273个回合...

在第273个回合找到宝藏!

为者常成,行者常至

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值