BasicGames Python 源码解析 02 Amazing

阅读更多:apachecn/python-code-anal

这个游戏会接收用户输入的长和宽,动态生成一个迷宫。

改进自 Frank Palazzolo 的版本。

导入

import random
import os
from time import sleep

常量

# 定义移动方向常量
GO_LEFT, GO_UP, GO_RIGHT, GO_DOWN = [0, 1, 2, 3]
# 定义连通方向常量
CONN_DOWN = 1
CONN_RIGHT = 2

get_width_length()

# 从用户输入获取迷宫的长和宽
def get_width_length():
    while True:
        try:
            width, length = input('What are your width and length?').split(',')
            width = int(width)
            length = int(length)
            if width != 1 and length != 1:
                return (width, length)
            print('Meaningless dimensions. Try again.')
        except ValueError:
            print('Meaningless dimensions. Try again.')

get_possible_dirs()

# 返回从一个格子的可移动方向
def get_possible_dirs(row, col, width, length, used):
    possible_dirs = [GO_LEFT,GO_UP,GO_RIGHT,GO_DOWN]
    # 如果不是最左边,并且左面一格没有访问
    # 那左边就是可以访问的,以此类推
    if col==0 or used[row][col-1]!=0:
        possible_dirs.remove(GO_LEFT)
    if row==0 or used[row-1][col]!=0:
        possible_dirs.remove(GO_UP)
    if col==width-1 or used[row][col+1]!=0: 
        possible_dirs.remove(GO_RIGHT)
    if row==length-1 or used[row+1][col]!=0:
        possible_dirs.remove(GO_DOWN)   
    return possible_dirs

get_next_used()

# 获取某个位置的下一个已访问格子
def get_next_used(row, col, used):
    length, width  = len(used), len(used[0])
    while True:
        if col != width - 1:
            col += 1
        elif row != length - 1:
            row, col = row + 1, 0
        else:
            row, col = 0, 0
        if used[row][col] != 0:
            break
    return row, col
# 打印迷宫
def print_maze(walls, used, enter_col):
    # 每次打印之前先清屏
    os.system('cls')
    length, width = len(walls), len(walls[0])
    # 打印最上方的墙壁
    for col in range(width):
        # 如果是入口,就把它打开
        if col==enter_col:
            print('*  ',end='')
        else:
            print('*--',end='')
    print('*')
    for row in range(length):
        # 打印格子
        print('|',end='')
        for col in range(width):
            # 区分已访问和未访问
            cell_ch = '  ' if used[row][col] != 0 else '><'
            # 区分格子右边是否有墙壁
            if walls[row][col] | CONN_RIGHT == walls[row][col]:
                print(cell_ch + ' ',end='')
            else:
                print(cell_ch + '|',end='')
        print()
        # 打印格子下方的墙壁
        for col in range(width):
            # 区分格子下方是否有墙壁
            if walls[row][col] | CONN_DOWN == walls[row][col]:
                print('*  ',end='')
            else:
                print('*--',end='')
        print('*')
    # 短暂停留避免一闪而过
    sleep(0.1)

main()

# 程序的主要逻辑
def main():
    print(' '*28+'AMAZING PROGRAM')
    print(' '*15+'CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY')
    print()
    print()
    print()

    # 获取用户输入的长和宽
    width, length = get_width_length()
    # used 数组保存格子是否访问过
    # 0 表示未访问,其它数字表示该格子是第几个访问的
    used = [[0]*width for _ in range(length)]
    # wall 保存右边和下边是不是连通的
    # 0:不连通,1:下侧连通,2:右侧连通,3:右侧和下侧连通
    walls = [[0]*width for _ in range(length)]

    # 随机选取入口
    enter_col=random.randint(0,width-1)
    # 将起始位置定义为入口
    row,col=0,enter_col
    # 定义已访问格子数量
    count=1
    # 设置入口已访问
    used[row][col]=count
    # 每次格式发生变化都会打印迷宫,下同
    print_maze(walls, used, enter_col)

    # 在所有格子都已访问之前执行循环
    while count!=width*length:
        # 获取当然位置的可移动方向
        possible_dirs = get_possible_dirs(row, col, width, length, used)
        
        if len(possible_dirs)!=0:
            # 如果可以移动,那么随机选一个方向来移动
            # 并且把墙拆掉
            direction=random.choice(possible_dirs) 
            if direction==GO_LEFT:
                col=col-1
                walls[row][col] |= CONN_RIGHT
            elif direction==GO_UP:
                row=row-1 
                walls[row][col] |= CONN_DOWN
            elif direction==GO_RIGHT:
                walls[row][col] |= CONN_RIGHT    
                col=col+1
            elif direction==GO_DOWN:
                walls[row][col] |= CONN_DOWN
                row=row+1
            # 更新计数,设置已访问
            count=count+1
            used[row][col]=count
            print_maze(walls, used, enter_col)
        else:
            # 否则,选取下一个已访问的格子重复这个步骤
            # 因为外面已经检查了是否可移动,
            # 这里只检查已访问就可以了
            row, col = get_next_used(row, col, used)

    # 最后,随机选择出口
    col=random.randint(0,width-1)
    row=length-1
    walls[row][col]=walls[row][col]+1
    
    print_maze(walls, used, enter_col)
    

if __name__ == '__main__': main()
posted @ 2022-02-11 17:06  绝不原创的飞龙  阅读(27)  评论(0编辑  收藏  举报