2018-2-22 再练习广度优先搜索,题:炸怪兽
2小时。
先是是纠错,通过对代码运行过程的测试。发现是变量打错。以及录入地图❌。
重构练习题,改使用while..end代替for in.
⚠️ : 在while(k <= n)中如果用到next,为了不陷入死♻️,注意条件的判断, 一般要在next前k += 1。
题:爆炸小子炸怪兽
代码:
# 地图
map = [
["#","#","#","#","#","#","#","#","#","#","#","#","#"],
["#","g","g",".","g","g","g","#","g","g","g",".","#"],
["#","#","#",".","#","g","#","g","#","g","#","g","#"],
["#",".",".",".",".",".",".",".","#",".",".","g","#"],
["#","g","#",".","#","#","#",".","#","g","#","g","#"],
["#","g","g",".","g","g","g",".","#",".","g","g","#"],
["#","g","#",".","#","g","#",".","#",".","#",".","#"],
["#","#","g",".",".",".","g",".",".",".",".",".","#"],
["#","g","#",".","#","g","#","#","#",".","#","g","#"],
["#",".",".",".","g","#","g","g","g",".","g","g","#"],
["#","g","#",".","#","g","#","g","#",".","#","g","#"],
["#","g","g",".","g","g","g","#","g",".","g","g","#"],
["#","#","#","#","#","#","#","#","#","#","#","#","#"]
]
# 地图副本book,用于标记走过的点。用compact复制出新的array。
# 因为不能嵌套复制。需要用map
book = map.map{|item| item.compact }
# 输出地图(对输出结果进行美化)
i = 0
n = map.size
n.times do |x|
print "#{x} "
end
print "\n"
while i < n
j= 0
while j < n
case map[i][j]
when "#"
print "◼︎ "
when "g"
print "☿ "
when "."
print " "
end
j += 1
end
print "\n"
i += 1
end
# 杀怪统计Method
def getnum(startx, starty, map)
# 四个方向各自统计杀怪数,加到sum中
sum = 0
x = y = 0
# 向下,遇到“#”,停止。(爆炸受阻)
x = startx
y = starty
while map[x][y] != "#"
if map[x][y] == "g"
sum += 1
end
x += 1
end
# 上
x = startx
y = starty
while map[x][y] != "#"
if map[x][y] == "g"
sum += 1
end
x -= 1
end
# 右
x = startx
y = starty
while map[x][y] != "#"
if map[x][y] == "g"
sum += 1
end
y += 1
end
# 左
x = startx
y = starty
while map[x][y] != "#"
if map[x][y] == "g"
sum += 1
end
y -= 1
end
return sum
end
# 设定开始起点位置
print "请输入起点坐标x:\n"
startx = gets.to_i
print "请输入起点坐标y:\n"
starty = gets.to_i
# wide first search
x = []
y = []
# 指针head , tail(队列最后一位的后面空白处)
head = 0
tail = 1
x[head] = startx
y[head] = starty
# 坐标点周边的四个方向,目的是访问相邻的4个点
next_direction = [
[0, 1],#右
[1, 0],#下
[0,-1],#左
[-1,0] #上
]
# 统计最大击杀
kill_max = 0
max_x = max_y = 0
# 边界的判断
nx = map[0].size - 2
ny = map.size - 2
# 大循环,wide first search
while head < tail
# 每个坐标点周边点的情况判定。
k = 0
while k <= 3
tx = x[head] + next_direction[k][0]
ty = y[head] + next_direction[k][1]
# 界限
if tx < 1 || tx > nx || ty <1 || ty > ny
# k += 1必不可少,否则会死循环。用for语法的话可以避免。
k += 1
next
end
# 判断是否是平地,而且没有走过
if map[tx][ty] == "." && book[tx][ty] == "."
# 在地图上标记已经走过
book[tx][ty] = "X"
x << tx
y << ty
# 队列尾巴的后一位,用于判断是否结束大循环
tail += 1
# 统计杀怪数量,调用Method
sum_kill = getnum(tx, ty, map)
if sum_kill > kill_max
kill_max = sum_kill
max_x = tx
max_y = ty
end
end
k += 1
end
# 头部指针前移动
head += 1
end
p "最大击杀#{kill_max}"
p "坐标:(#{max_x},#{max_y})"