turtle迷宫探索python递归

# encoding:utf-8
import turtle
from random import randint


def get_maze_list(file_path):
    """根据文本生成迷宫列表,文本包含1,2,S,E,以空格间隔,1,2为墙,S为起始点,E为终点"""
    with open(file_path) as f:
        lines = f.readlines()
    return [_.strip().split(' ') for _ in lines]


def draw_maze(list_maze):
    # 分别代表起点的x,y坐标位置,行数,列数,结合global返回数值
    global x_start, y_start, ci_start, ri_start

    for ri in range(len(list_maze)):
        for ci in range(len(list_maze[0])):
            # 如果为墙则画灰色正方形
            if list_maze[ri][ci] in ['1', '2']:
                draw_cell(ci, ri)
            # 如果为起点,则返回全局变量,同时标记为青色点
            elif list_maze[ri][ci] == 'S':
                # cell_size为主程序变量,代表迷宫图形中一个单元格的像素尺寸,迷宫列表与迷宫图形相对位置一致,即列数方向一致,行数方向相反
                x_start, y_start = (ci - cols_count * 0.5 + 0.5) * cell_size, (rows_count * 0.5 - ri - 0.5) * cell_size
                ci_start, ri_start = ci, ri
                draw_dot(ci, ri, 'cyan')
            # 如果为终点,则标记红点
            elif list_maze[ri][ci] == 'E':
                draw_dot(ci, ri, 'red')


def skip_to(x, y, pen):
    """turtle跳跃至指定坐标点"""
    pen.up()
    pen.goto(x, y)
    pen.down()


def draw_cell(ci, ri):
    # cell_size为主程序变量,代表迷宫图形中一个单元格的像素尺寸,(x,y)分别为单元格的左上角坐标
    x, y = (ci - cols_count * 0.5) * cell_size, (rows_count * 0.5 - ri) * cell_size
    skip_to(x, y, t_cell)
    # 随机颜色,RGB需要一致,否则可能不是灰色
    n = randint(110, 150)
    t_cell.color((n, n, n), (n, n, n))
    t_cell.begin_fill()
    for _ in range(4):
        t_cell.forward(cell_size)
        t_cell.right(90)
    t_cell.end_fill()


def draw_dot(ci, ri, color):
    # cell_size为主程序变量,代表迷宫图形中一个单元格的像素尺寸,(x,y)分别为单元格的左上角坐标向右下方偏移cell_size*0.5,即x+0.5,y-0.5
    x, y = (ci - cols_count * 0.5) * cell_size + cell_size * 0.5, (rows_count * 0.5 - ri) * cell_size - cell_size * 0.5
    skip_to(x, y, t_cell)
    t_cell.dot(int(cell_size * 0.5), color)


def draw_path(ci, ri, color='blue'):
    # cell_size为主程序变量,代表迷宫图形中一个单元格的像素尺寸,(x,y)分别为单元格的左上角坐标向右下方偏移cell_size*0.5,即x+0.5,y-0.5
    x, y = (ci - cols_count * 0.5) * cell_size + cell_size * 0.5, (rows_count * 0.5 - ri) * cell_size - cell_size * 0.5
    t_line.pencolor(color)
    t_line.goto(x, y)


def search_next(list_maze, ci, ri):
    # 如果为终点,返回
    if list_maze[ri][ci] == 'E':
        draw_path(ci, ri)
        return True
    elif list_maze[ri][ci] in ['1', '2', 'TRIED']:
        return False
    elif not (0 <= ci < cols_count and 0 <= ri < rows_count):
        return False

    draw_path(ci, ri)
    # 走过标记
    list_maze[ri][ci] = 'TRIED'

    # 下一步四个方向,改变方向会影响优先级
    for x_add, y_add in [(-1, 0),(0, 1), (0, -1), (1, 0)]:
        # 关键代码,调用自己
        isfound = search_next(list_maze, ci + x_add, ri + y_add)
        if isfound:
            draw_path(ci, ri, 'green')
            return True
        else:
            draw_path(ci, ri, 'red')
    return False


if __name__ == '__main__':
    list_maze = get_maze_list(r'../turtle练习/301.txt')
    rows_count, cols_count, cell_size = len(list_maze), len(list_maze[0]), 20

    scr = turtle.Screen()
    scr.tracer(0)
    scr.colormode(255)
    # 设置窗口大小
    scr.setup(cols_count * cell_size, rows_count * cell_size)

    t_cell, t_line = turtle.Turtle(), turtle.Turtle()
    for t in [t_cell, t_line]:
        t.hideturtle()
    t_line.pensize(cell_size * 0.2)

    # 绘制迷宫图
    draw_maze(list_maze)
    # turtle跳到起点,参数为实际坐标点,非行/列数
    skip_to(x_start, y_start, t_line)
    # 开启动画
    scr.tracer(1)
    # 调用递归函数
    search_next(list_maze, ci_start, ri_start)
    turtle.done()


在这里插入图片描述

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 2 0 2 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 2 0 0 0 0 0 0 0 0 0 1
1 0 1 0 1 0 1 0 1 2 1 2 1 0 1 2 1 2 1 0 1 2 1 0 1 2 1 2 1 0 1 2 1
1 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 2 0 2 0 0 0 0 0 0 0 2 0 0 0 1
1 1 1 0 1 2 1 2 1 2 1 0 1 2 1 0 1 2 1 0 1 0 1 0 1 0 1 0 1 2 1 0 1
1 1 0 0 S 0 0 0 0 0 0 0 2 0 2 0 0 0 0 0 0 0 2 0 2 0 2 0 0 0 2 0 1
1 1 1 0 1 0 1 2 1 2 1 2 1 0 1 0 1 2 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 0 0 2 0 0 0 2 0 0 0 0 0 2 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1
1 1 1 0 1 0 1 2 1 0 1 0 1 0 1 2 1 2 1 0 1 0 1 0 1 0 1 2 1 0 1 2 1
1 1 0 0 2 0 0 0 0 0 2 0 2 0 0 0 2 0 2 0 2 0 2 0 2 0 0 0 2 0 2 0 1
1 1 1 0 1 0 1 0 1 0 1 2 1 2 1 2 1 0 1 2 1 0 1 0 1 0 1 2 1 0 1 0 1
1 1 0 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 0 0 2 0 0 0 1
1 1 1 0 1 2 1 2 1 0 1 2 1 2 1 0 1 0 1 2 1 2 1 2 1 2 1 2 1 0 1 0 1
1 1 0 0 2 0 0 0 0 0 0 0 0 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 1
1 1 1 2 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 2 1 0 1 0 1 2 1 0 1 2 1
1 1 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 2 0 0 0 2 0 2 0 1
1 1 1 2 1 0 1 2 1 2 1 2 1 2 1 2 1 0 1 0 1 2 1 0 1 2 1 0 1 0 1 0 1
1 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 0 0 0 0 2 0 2 0 0 0 1
1 1 1 0 1 2 1 2 1 0 1 2 1 2 1 0 1 2 1 0 1 0 1 0 1 2 1 0 1 2 1 0 1
1 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 0 E 2 0 2 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值