创建一个5*5网格世界,遵守以下规则:对不同行为进行奖励和乘法,选出最优的方案。
题目: 思路:编写程序解决问题的步骤:
首先理解问题,将问题拆分,表达出每个部分的意思。
联系各个部分,考虑特殊情况, 编写代码。
不断修改,直到自己觉得np就OK。
代码:# -*- coding: utf-8 -*-
"""
Created on Mon Apr 25 10:43:07 2022
创建5*5的矩阵
四种可能行为1234,每次行为都会得分减1
初始位置[2,1]
到达终点[5,5],得分加10,
到达得分点[2,4],得分加5,同时跳到[4,4]
障碍物[3,3],[3,4],[3,5],[4,3]
@author: lx
"""
import random
import numpy as np
'''
#生成5*5数组函数
#用numpy模块,先创建矩阵5行5列
#更改初始值为1,障碍也为1
[[0 0 0 0 0]
[0 0 0 0 0]
[0 0 1 1 1]
[0 0 1 0 0]
[0 0 0 0 0]]
'''
def array():
arr = np.zeros((5, 5), dtype=np.int32)
#障碍
arr[2][2] = 1
arr[2][3] = 1
arr[2][4] = 1
arr[3][2] = 1
# print(arr)
return arr
# array()
'''
#移动一次函数
#使用random模块生成数字模拟随机移动,移动方向用1,2,3,4代表上下左右。
#向上移动,则不能在第一行(即i!=0),类似向下(i!=4),向左(j!=0),向右(j!=4);否则为撞向边界,将次数加1,表示不计入移动。
#判断没有经过(即下一个点为0),移到这个位置并且将位置改为1用于表示已经走过;否则为1表示已经走过。
#如果移动到下一个位置那么,得分减1;否则没有移动,将次数加1,表示该次不计入移动。
(函数内优先使用参数+返回值,还是全局变量)?
'''
def move(i,j):
'''
i,j:表示数组下标,即当前位置
count:表示移动次数
score:表示得分
'''
global count,score
action = random.randint(1, 4)#随机移动
# print('方向:',action)
if action == 1 and i != 0:#向上
if arr[i-1][j]==0:
arr[i-1][j]=1
i -= 1
score-=1
else:
count+=1
#print('返回')
elif action == 2 and i != 4:#向下
if arr[i+1][j]==0:
arr[i+1][j]=1
i += 1
score-=1
else:
count+=1
#print('返回')
elif action == 3 and j != 0:#向左
if arr[i][j-1]==0:
arr[i][j-1]=1
j -= 1
score-=1
else:
count+=1
#print('返回')
elif action == 4 and j != 4:#向右
if arr[i][j+1]==0:
arr[i][j+1]=1
j += 1
score-=1
else:
count+=1
#print('返回')
else:
count+=1
#print('边界')
# print(arr)
return i,j
'''
#搜索目标函数
#从初始位置[1,0],重复调用移动一次函数,实现多次移动。
#每次移动都要使用数组下标判断,是否为结束位置[4,4],是否为跳跃位置[1,3]
#and表示两真才真;or表示两假才假。双变量控制循环,and和or的选择。(亮点)
可能依然没有到达终点,但一定不是最优解。
circle存在,是为了当移动次数count大于5次,依然可以移动搜索终点。
count存在,是为了防止循环20次,都是撞墙或者返回,依然可以移动5次搜索终点。
这时存在一个漏洞bug,circle已经为false,count依然为true(即->[1,1]->[0,1]->[0,0])
需要做特殊判断解决if count==2 and circle<0:
不能忽略了count存在的意义附加条件if count==2 and circle<0 and i==0 and j==0:
(函数内优先使用默认参数,还是局部变量)?
'''
def sousuo(arr,i=1,j=0):
'''
arr:表示初始的数组(5*5网格世界)
i,j:表示初始位置的下标(默认为1,0)
count:表示移动次数
score:表示的得分
'''
global count,score
arr[i][j] = 1#起点
count = 5#最少移动次数(不计返回和障碍)
circle = 20#控制最大循环次数(有限次循环终止)
score = 0
while count>0 or circle>0:
#特殊判断
if count==2 and circle<0 and i==0 and j==0:
#print('特殊情况')
score = -10
break
count -= 1
circle -= 1
#调用一次移动
i,j = move(i,j)
if i==4 and j==4:
#print('终点')
score += 11
break
if i==1 and j==3:
#print('跳跃')
score += 6
i=3
j=3
arr[i][j]=1
else:
#print('没有方向')
score = -10
# print()
# print(arr)
# print(score)
return score,arr
# sousuo(arr)
'''
#用计算机重复思维,不断尝试,直到找到最大的分值,并输出arr
#字典,键重复会覆盖
'''
di = {}
for cir in range(100):
arr = array()
score,arr = sousuo(arr)
di[score] = arr
a = max(list(di.keys()))
print(f'得分:{a}'+'\n',di[a])
#重复一百次,依然可能出现误差
#解决一:进一步循环1000次
#解决二:将上边封装函数,重复十次函数,取众数就ok了
结果:
出现的问题:得分:12
[[0 0 0 0 0]
[1 1 1 1 0]
[0 0 1 1 1]
[0 0 1 1 0]
[0 0 0 1 1]]
UnboundLocalError: local variable 'score' referenced before assignment
UnboundLocalError:局部变量xxx在赋值前被引用
解决:用了两次global声明变量,一个函数内用一次。
按道理我在sousuo()函数内声明了全局变量,函数内的函数move()应该能使用变量,但是报错了。还和一般的变量报错(NameError: name 'score' is not defined)不一样。
TypeError: 'numpy.ndarray' object is not callable
TypeError: 'numpy.ndarray'对象不可调用
解决:更改函数名或变量名
函数名和函数内的局部变量命名冲突导致。
如果你也学习python的话,相互关注,共同进步!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)