1、说明:

1.1、华容道游戏

华容道是中国的一种传统游戏,有曹操、关羽、张飞等,分别用不同形状、大小的小块表示,游戏的目标是将曹操从特定位置走到出口、即为获胜。

1.2、设计前提和限制:

当前版本尚未图形化,考虑用数字代表曹操、关羽等不同角色,使用键盘操控移动游戏。

2、代码及说明

==========

#!python
import copy
import time

#2.1 历史和已支持功能

##Author: Lijun
#
#History:
#V0.4   2022-01-18
#增加功能:1)在运行过程中增加“自动完成”功能,可以自动模拟完成并打印结果。
#
#V0.3   2021-12-18
#增加功能:增加初始场景,游戏可以从多个初始场景中选择1个。
#
#V0.2   2021-12-16
#增加功能:返回上一步;返回上一步后,删除本步骤、上一步变为最后一步;如果没有上一步则菜单不显示
#V0.1   2021-12-15
#实现基础功能:一种初始化图形,可以人工操作游戏,游戏成功有提示
#
#
#
#
#Guanyu=11 (*1) ;关羽2*1(水平*竖直,下同) 横条,1个
#zhang/zhao/ma/huang = x
#                                        x   (*4,2-5) ;张飞/赵云/马超/黄忠 1*2竖条,4个
#zu = x (*4,6-9)    ;小卒, 1*1块,4个
#caocao = 00
#                00 (*1)   ;曹操,2*2块,1个
#
#

#2.2 数据结构说明

#数据结构:
#华容道主要数据结构的定义,如下:

#2.2.1 游戏角色

#类型:list,
#组成:[id(字符型),name(字符串),width(数字),height(数字),loc_row(数字),loc_col(数字)]
#分别代表:代号0-9,名字,占的行数,占的列数,角色左上角1个块的行位置,角色左上角块的列位置
#其中:0曹操为2*2的方块,1关羽为1*2(1行2列)的长方形,2-5张飞、赵云、黄忠、马超为2*1(2行1列)的长方形,6-9小卒为1*1的小方块。

#2.2.2局型role

#类型:list,
#组成:[[角色0],[角色1],....[角色9]]
#是由10个游戏角色按顺序构成的list,分别表示曹操、关羽、4个张赵马黄、4个小卒的信息

#2.2.3节点Node

#类型:list
#组成:[当前role,前一role,前一role到当前role需要移动的角色,移动方向,当前局面nodeid,前一局面nodeid,当前role的diff判决值]
#自动求解时需要用到的局型关系状态。包含局型、前置局型、从前置局型变为当前局型移动角色、局型ID、局型判决函数值等信息。用于求解从当前状态到最终状态的解决路径。

#2.3.4 角色result

#类型:二位数组list
#组成:[row][col]
#一个7行4列的数组,各位置的值为该位置对应的角色代号,用于打印局势图
#
#
#
#

#初始化游戏设置
def init_conf():
    global role
    global history
    global auto_play
        
    role = []        #角色清单,用于保存各角色属性(长宽、位置等)
    history=[]       #历史角色清单的历史动作列表,用于游戏返回上一步
    orig=[]          #自动游戏时的初始局面
#    auto_play=False  #设置是否自动游戏,如果自动,则会使用openeded表、closed表

#2.3初始化游戏地图和角色位置

#2.3.1定义角色位置

#初始化游戏地图,设定各角色的位置,目前包括6个官方地图和3个测试地图,测试地图和根据目的自行添加。
def init_map():
    while True:
        map = input('''Welcome to HuaRongDao, Please choose a map to play:
    1、横刀立马
    2、齐头并前
    3、兵分三路
    4、屯兵东路
    5、左右布兵
    6、前挡后阻
    7、测试地图
    8、测试地图2
    9、测试地图3
    请输入(1-9):''')

try:
            map=int(map)
        except:
            pass
#        print("Map is",map)
        if(map==1):        
            #1、地图“横刀立马”
            #张曹曹马
            #飞操操超
            #赵关羽黄
            #云卒卒忠
            #卒    卒
            #口门门口
            role.append(['0','Caocao',2,2,1,2])
            role.append(['1','Guanyu',2,1,3,2])
            role.append(['2','Zhangfei',1,2,1,1])
            role.append(['3','Zhaoyun',1,2,3,1])
            role.append(['4','Machao',1,2,1,4])
            role.append(['5','Huangzhong',1,2,3,4])
            role.append(['6','xiaozu',1,1,4,2])
            role.append(['7','xiaozu',1,1,4,3])
            role.append(['8','xiaozu',1,1,5,1])
            role.append(['9','xiaozu',1,1,5,4])
            break
        elif(map==2):            
            #2、地图“齐头并前”
            #张曹曹赵
            #飞操操云
            #卒卒卒卒
            #马关羽黄
            #超    忠
            #口门门口
            role.append(['0','Caocao',2,2,1,2])
            role.append(['1','Guanyu',2,1,4,2])
            role.append(['2','Zhangfei',1,2,1,1])
            role.append(['3','Zhaoyun',1,2,1,4])
            role.append(['4','Machao',1,2,4,1])
            role.append(['5','Huangzhong',1,2,4,4])
            role.append(['6','xiaozu',1,1,3,1])
            role.append(['7','xiaozu',1,1,3,2])
            role.append(['8','xiaozu',1,1,3,3])
            role.append(['9','xiaozu',1,1,3,4])
            return
        elif(map==3):
            #3、地图“兵分三路”
            #卒曹曹卒
            #张操操赵
            #飞关羽云
            #马卒卒黄
            #超    忠
            #口门门口
            role.append(['0','Caocao',2,2,1,2])
            role.append(['1','Guanyu',2,1,3,2])
            role.append(['2','Zhangfei',1,2,2,1])
            role.append(['3','Zhaoyun',1,2,2,4])
            role.append(['4','Machao',1,2,4,1])
            role.append(['5','Huangzhong',1,2,4,4])
            role.append(['6','xiaozu',1,1,1,1])
            role.append(['7','xiaozu',1,1,1,4])
            role.append(['8','xiaozu',1,1,4,2])
            role.append(['9','xiaozu',1,1,4,3])
            return
        elif(map==4):
            #4、地图“屯兵东路”
            #曹曹张赵
            #操操飞云
            #关羽卒卒
            #马黄卒卒
            #超忠
            #口门门口
            role.append(['0','Caocao',2,2,1,1])
            role.append(['1','Guanyu',2,1,3,1])
            role.append(['2','Zhangfei',1,2,1,3])
            role.append(['3','Zhaoyun',1,2,1,4])
            role.append(['4','Machao',1,2,4,1])
            role.append(['5','Huangzhong',1,2,4,2])
            role.append(['6','xiaozu',1,1,3,3])
            role.append(['7','xiaozu',1,1,3,4])
            role.append(['8','xiaozu',1,1,4,3])
            role.append(['9','xiaozu',1,1,4,4])
            return
        elif(map==5):
            #5、地图“左右布兵”
            #张曹曹赵
            #飞操操云
            #  马黄
            #卒超忠卒
            #卒关羽卒
            #口门门口
            role.append(['0','Caocao',2,2,1,2])
            role.append(['1','Guanyu',2,1,5,2])
            role.append(['2','Zhangfei',1,2,1,1])
            role.append(['3','Zhaoyun',1,2,1,4])
            role.append(['4','Machao',1,2,3,2])
            role.append(['5','Huangzhong',1,2,3,3])
            role.append(['6','xiaozu',1,1,4,1])
            role.append(['7','xiaozu',1,1,4,4])
            role.append(['8','xiaozu',1,1,5,1])
            role.append(['9','xiaozu',1,1,5,4])
            return
        elif(map==6):
            #6、地图“前挡后阻”
            #曹曹关羽
            #操操马张
            #赵黄超飞
            #云忠卒卒
            #卒    卒
            #口门门口
            role.append(['0','Caocao',2,2,1,2])
            role.append(['1','Guanyu',2,1,5,2])
            role.append(['2','Zhangfei',1,2,1,1])
            role.append(['3','Zhaoyun',1,2,1,4])
            role.append(['4','Machao',1,2,3,2])
            role.append(['5','Huangzhong',1,2,3,3])
            role.append(['6','xiaozu',1,1,4,1])
            role.append(['7','xiaozu',1,1,4,4])
            role.append(['8','xiaozu',1,1,5,1])
            role.append(['9','xiaozu',1,1,5,4])
            return
        elif(map==7):
            #7、测试地图
            #关羽马张    
            #赵黄超飞
            #云忠
            #卒曹曹卒
            #卒操操卒
            #口门门口
            role.append(['0','Caocao',2,2,4,2])
            role.append(['1','Guanyu',2,1,1,1])
            role.append(['2','Zhangfei',1,2,1,4])
            role.append(['3','Zhaoyun',1,2,2,1])
            role.append(['4','Machao',1,2,1,3])
            role.append(['5','Huangzhong',1,2,2,2])
            role.append(['6','xiaozu',1,1,4,1])
            role.append(['7','xiaozu',1,1,4,4])
            role.append(['8','xiaozu',1,1,5,1])
            role.append(['9','xiaozu',1,1,5,4])
            return
        elif(map==8):
            #8、测试地图2
            #关羽马张    
            #赵黄超飞
            #云忠
            #曹曹卒卒
            #操操卒卒
            #口门门口
            role.append(['0','Caocao',2,2,4,1])
            role.append(['1','Guanyu',2,1,1,1])
            role.append(['2','Zhangfei',1,2,1,4])
            role.append(['3','Zhaoyun',1,2,2,1])
            role.append(['4','Machao',1,2,1,3])
            role.append(['5','Huangzhong',1,2,2,2])
            role.append(['6','xiaozu',1,1,4,3])
            role.append(['7','xiaozu',1,1,4,4])
            role.append(['8','xiaozu',1,1,5,3])
            role.append(['9','xiaozu',1,1,5,4])
            return
        elif(map==9):
            #9、测试地图3
            #关羽马张    
            #赵黄超飞
            #云忠
            #曹曹卒卒
            #操操卒卒
            #口门门口
            role.append(['0', 'Caocao', 2, 2, 1, 2])
            role.append(['1', 'Guanyu', 2, 1, 3, 2])
            role.append(['2', 'Zhangfei', 1, 2, 1, 1])
            role.append(['3', 'Zhaoyun', 1, 2, 3, 1])
            role.append(['4', 'Machao', 1, 2, 1, 4])
            role.append(['5', 'Huangzhong', 1, 2, 3, 4])
            role.append(['6', 'xiaozu', 1, 1, 6, 3])
            role.append(['7', 'xiaozu', 1, 1, 5, 3])
            role.append(['8', 'xiaozu', 1, 1, 6, 2])
            role.append(['9', 'xiaozu', 1, 1, 5, 4])
            return
        else:
            print("\nWrong selection!")

#2.3.2角色位置更新到result数组

#根据地图位置更新各角色站位结果
def updatelocation(rolex):    
    result = [['x' for i in range(5)] for j in range(7)]
    result[6][1]=' '
    result[6][4]=' '    
    for x in rolex:
    #    print(x)
        row = x[4]
        for rowcnt in range(x[3]):
            col = x[5]
            for colcnt in range(x[2]):
    #            print(row,col)
                result[row][col]=x[0]
                col = col +1
            row = row +1
    return(result)

#2.3.2从result数组打印角色站位信息

#打印各角色站位结果
def prtresult(resultx):
    print("\n")
    for row in range(1,7):
        for col in range(1,5):
            print(resultx[row][col],end="")
        print('')

#菜单,目前没用到
'''def prtmenu():
    while True:
        print('0-----begin game')
        print('1-----exit')
        print('\n\n Please input 0/1')
        select = input()
        if(select == '1'):
            break
        elif (select =='0'):
            print('game start')
            break
'''

#2.4游戏角色的移动

#2.4.1判断角色是否可以移动,并输出可以移动的所有方向

#判断是否可以移动,返回可以移动的方向left,right,up,down
#获取移动角色的左上角初始位置,以及宽度、高度
#代号,名字,宽度,高度,左上角行位置,左上角列位置
def move_judge(master,rolex):
#获取各角色的xy坐标、以及宽度、高度
    pos_row=rolex[master][4]
    pos_col=rolex[master][5]
    pos_row_cnt=rolex[master][2]
    pos_col_cnt=rolex[master][3]

#更新节点位置
    result=updatelocation(rolex)
#    prtresult(result)

#初始化角色可以移动方向的结果
    direct=[]
    
#判断是否能向左移动
    left_flag='F'
#第一列的不能左移
    if(pos_col<=1):
        pass
#        print('不能向左移动')
    else:
#只有当左边列、与角色相同高度行的所有格子都是x时才可以左移
        for row in range(pos_col_cnt):
            if(result[pos_row+row][pos_col-1]=='x'):
                pass
                left_flag='T'
            else:
                left_flag='F'
                break
    if(left_flag=='T'):
#        print(master, "can move left!")
        direct.append("left")
#        return("left")

#判断是否能向右移动
    right_flag='F'
#角色的当前x坐标加上宽度大于4则不能右移
    if(pos_col+pos_row_cnt>4):
        pass
#        print('不能向右移动')
    else:
#只有当右边列、与角色相同高度行的所有格子都是x时才可以右移
        for row in range(pos_col_cnt):
            if(result[pos_row+row][pos_col+pos_row_cnt]=='x'):
                pass
                right_flag='T'
            else:
                right_flag='F'
                break
    if(right_flag=='T'):
#        print(master,"can move right!")
        direct.append("right")
#        return("right")

#判断是否能向上移动
    up_flag='F'
#第一行的不能上移
    if(pos_row<=1):
        pass
#        print('不能向上移动')
    else:
#只有当上边行、与角色相同高度列的所有格子都是x时才可以上移
        for col in range(pos_row_cnt):
            if(result[pos_row-1][pos_col+col]=='x'):
                pass
                up_flag='T'
            else:
                up_flag='F'
                break
    if(up_flag=='T'):
#        print(master,"can move up!")
        direct.append("up")
#        return("up")

#判断是否能向下移动
    down_flag='F'
#角色的当前y坐标加上高度大于6则不能下移
    if(pos_row+pos_col_cnt>6):
        pass
#        print('不能向下移动')
    else:
#只有当下边行、与角色相同高度列的所有格子都是x时才可以下移
        for col in range(pos_row_cnt):
            if(result[pos_row+pos_col_cnt][pos_col+col]=='x'):
                down_flag='T'
            else:
                down_flag='F'
                break
    if(down_flag=='T'):
#        print(master,"can move down!")
        direct.append("down")
        
#    if(len(direct)>0):
#        print('this time:',master,'can move',direct)
    return(direct)

#2.4.2将给定局型中的特定角色按特定方向移动,并输出下一局型

#移动
def move(master,rolex,direct,result):
#    print("Move"+ str(master))
#    pass
#数据结构:
#role[id,name,width,height,loc_row,loc_col]
#代号,名字,宽度,高度,左上角行位置,左上角列位置

#打印可移动的方向
    prtstr=""
    for yy in range(len(direct)):
#        print(yy,direct[yy],end='   ')
        prtstr=prtstr+str(yy)+"-"+direct[yy]
        if(yy != len(direct)-1):
            prtstr=prtstr+","
        else:
            prtstr=prtstr+",x to exit):"

if len(direct) >= 2:
        inputx=input("\n please choose direct("+prtstr)
        if(inputx=='x' or inputx=='X'):
            exit
        else:
            direct = direct[int(inputx)]
    else:
        direct = direct[0]

last_role=copy.deepcopy(rolex)
    if (direct == 'left'):
        last_role[master][5]=rolex[master][5]-1
    if (direct == 'right'):
        last_role[master][5]=rolex[master][5]+1
    if (direct == 'up'):
        last_role[master][4]=rolex[master][4]-1
    if (direct == 'down'):
        last_role[master][4]=rolex[master][4]+1
    print(last_role)
    return(last_role)

#2.4.3获取某一给定局型所有可能的后续局型组合Node清单

def move_mult(posit):
#用于自动化情况下,从过一种局面产生该局面下可移动角色变成的几种后续局面
#输入是opened表中的一个数据,如下,
#[当前role,前一role,移动角色,移动方向,当前局面nodeid,前一局面nodeid]
#输出数据结构也是上面结构形成的list,list的任一元素也即opened表的数据元素形式:
#其中role局面的数据结构:
#role[id,name,width,height,loc_row,loc_col]
#代号,名字,宽度,高度,左上角行位置,左上角列位置
#id范围0-9分别代表各种角色

#0、初始化
    global opened
    global closeed
    next_role_list=[]
    this_role = copy.deepcopy(posit[0])  #当前局面
    this_nodeid = posit[4]  #当前局面nodeid
    
#1、检查各角色哪些可以移动,分别向什么方向移动
    for x in range(0,10):
        all_direct=move_judge(x,this_role)
        if(len(all_direct)<1):
           pass

#2、如果可以移动,则执行移动,并生成所有新局面列表
        else:
           for y in range(len(all_direct)):
               next_role = copy.deepcopy(this_role)
               direct = all_direct[y]
               if (direct == 'left'):
                   next_role[x][5]=next_role[x][5]-1
               if (direct == 'right'):
                   next_role[x][5]=next_role[x][5]+1
               if (direct == 'up'):
                   next_role[x][4]=next_role[x][4]-1
               if (direct == 'down'):
                   next_role[x][4]=next_role[x][4]+1
               next_role_list.append([next_role, this_role, x, direct, '', this_nodeid,0]) #next nodeid set to null
                             
                     
#3、返回当前局面所有下一条局面清单
#    print('next_role_list:')
#    for x in range(len(next_role_list)):
#        print(next_role_list[x])
    return(next_role_list)

'''
for i in range(10):
    x=move_judge(i,role)
    print(x)

'''

#2.5 判断结果

#2.5.1判断是否获胜

#曹操走到出口位置,即其左上角方块位置为5行、2列即为获胜。
def check_win(rolex):
    if(rolex[0][4]==5 and rolex[0][5]==2):
        return("Success!")
    else:
        return("Fail!")

#2.5.2判断两种局型是否一致

def check_match(orig,dest):
#作用:比较两种局型是否一致,
#包括2/3/4/5(关张马黄)的位置,如果1-2相同,但2/3/4/5组合相同,也认为等价相同。
#包括6/7/8/9的位置,如果0-5等价相同,且6/7/8/9的组合位置相同,也认为两个局型一致,返回True。
#orig,dest的结构即role的组结构,由0-9共10个如下的单个角色的list构成:
#role[id,name,width,height,loc_row,loc_col]
#代号,名字,宽度,高度,左上角行位置,左上角列位置

#v0:粗略的比较方式
#    if(orig == dest):
#        return True
#    else:
#        return False

#v1:增加了2-9准确匹配的方式方式
    chkflag = True
#先看0-1(曹操关羽)是否一致,如果有一个不同直接返回不一致
    for cnt in range(0,2):
       if(orig[cnt] != dest[cnt]):
#            print('orig is: dest is:',orig[cnt],dest[cnt])
            chkflag = False
            return(chkflag)

#然后看2-5,方法是取2-5所有4个元素的xy坐标位置,然后获得乘数,如果乘数相同则4个位置的组合是匹配的
    product1 = 1
    product2 = 1
    for cnt in range(2,6):
#            print(orig[cnt][4]*10+orig[cnt][5],dest[cnt][4]*10+orig[cnt][5])
            product1 = product1 * (orig[cnt][4]*10+orig[cnt][5])
            product2 = product2 * (dest[cnt][4]*10+dest[cnt][5])
#    print('product1,product2',product1,product2)
    if(product1 != product2):
            chkflag = False
            return(chkflag)
    
#然后看6-9,方法是取6-9所有4个元素的xy坐标位置,然后获得乘数,如果乘数相同则4个位置的组合是匹配的
    product1 = 1
    product2 = 1
    for cnt in range(6,10):
#            print(orig[cnt][4]*10+orig[cnt][5],dest[cnt][4]*10+orig[cnt][5])
            product1 = product1 * (orig[cnt][4]*10+orig[cnt][5])
            product2 = product2 * (dest[cnt][4]*10+dest[cnt][5])
#    print('product1,product2',product1,product2)
    if(product1 != product2):
            chkflag = False
#    if(orig!=dest):
#       print('two equals\n',orig,'\n',dest)
    return(chkflag)

#2.5.3判断某种局型的判决值(优先值)

def diff(node):
#这是一个判决函数,用来判断当前node与最终结果的差距,差值越小表明效果越好,在进行自动计算时,A*算法将diff值低的优先分析。
#输入类型是局型
#思路:
#1、曹操(role的第0条)的位置越接近目标位置(6,2)越好,考虑x或y每差1增加150.
#当曹操y<4时,曹操最好在边上、方便往下移动,因此x为2时额外增加100(1/3不用).
#2、关羽(role的第1条)的位置,靠边比中间好,也就是x=1或x=3时,值为0;为2时,增加200.
#3、如果关羽在曹操的下方,则增加150(关羽横坐标与曹操相同)
#4、张赵马黄越靠上越好,考虑每向下1格,增加50
#5、如果出口的两个格子的任意一个被占用,则增加10(两个则增加20)
    
    diff_value = 0
#    print('node[0],node[1]',node[0],node[1])
    cc_loc_x = node[0][4]
    cc_loc_y = node[0][5]
    gy_loc_x = node[1][4]
    gy_loc_y = node[1][5]
    zf_loc_x = node[2][4]
    zy_loc_x = node[3][4]
    mc_loc_x = node[4][4]
    hz_loc_x = node[5][4]
    
    diff_value = diff_value + (6-cc_loc_x)*300
    diff_value = diff_value + gy_loc_x * 150
    diff_value = diff_value + (zf_loc_x+zy_loc_x+mc_loc_x+hz_loc_x)*50

if(cc_loc_x <= 4):
        if(cc_loc_y==2):
            diff_value= diff_value + 50
    else:
        if(cc_loc_y==1):
            diff_value = diff_value + 50
        elif(cc_loc_y==3):
            diff_value = diff_value + 50
#判断出口两个格子是否被占用,只有在曹操比较靠下的时候才判断
        result = updatelocation(node)
        for col in range(2,4):
    #        print(result[6][col])
            if(result[6][col]!='x'):
                  diff_value = diff_value + 25        
#如果关羽在曹操下层,则关羽的位置很重要
    if(gy_loc_x > cc_loc_x):          
        if(gy_loc_x==cc_loc_x+1 and gy_loc_y==cc_loc_y):
            diff_value = diff_value + 100
        if(gy_loc_y==2):
            diff_value = diff_value + 100
        
    return(diff_value)

#2.6自动处理

#2.6.1 自动计算

def autoplay(role):
    global max_nodeid
    max_nodeid = 1
    global opened
    global closed
    opened =[]
    closed=[]
#节点的定义:
#包含局势role(0-9共10个角色信息构成的list,)(列表)、前一局势role(列表)、前面到本局势的移动角色\
#角色的移动方向(字符串)、当前局势nodeid(数值)、前一局面nodeid(数值)、局势diff值(数值,diff函数计算)
    opened.append([copy.deepcopy(role),'NULL','','',1,0,diff(copy.deepcopy(role))])
#    print('add to opened:',opened[-1])
    handleOpen()

#2.6.2 向open表插入局型组合Node

#A*算法,根据diff值将diff值小的内容插入到open表的前面,node的最后一项就是diff值
def addOpen(node):
#    print('node diff, last diff',node[6], opened[-1][6])
    if(len(opened)==0 or node[6]>=opened[-1][6]):
        opened.append(node)
#        print('append opened',node)
#        print('new opened is:',opened)
#        result=updatelocation(node[0])
#        prtresult(result)            
    else:
        for i in range(len(opened)):
            if(node[6]<opened[i][6]):
#                print('lenth is opened is:',len(opened),'this node is:',node[0],'nodeid is:',node[4],'diff is:',node[6])
#                print('insert opened',node)
                opened.insert(i,node)
                break

#2.6.3 处理open表

#用于处理Open表
#方法是:如果Open表非空,则:
#1)按照顺序对open表的每个角色进行所有方向的移动,
#将移动后的新状态节点添加进open表;如果过程中找到了满足条件
#的目的状态节点,则停止处理并返回打印结果;
#如果新获得的序列已存在与open、close表,则不再添加。
#2)将该节点加入close表;
#3)从open表中删除该节点;
#
#open表格式:当前role,前一role,前一role到当前role需要移动的角色,移动方向,当前局面nodeid,前一局面nodeid,当前role的diff判决值
def handleOpen():
    global opened
    global closed
    global max_nodeid
    global begin_time
    global end_time

begin_time = int(time.time())
    
    while True:
          if len(opened)==0:
                break

#如果用A* 算法,就每次从0开始,否则用下句的for循环
          x=0
#        for x in range(len(opened)):
          tmpOpen=copy.deepcopy(opened[x])

#          print('opened updated, now is node No.:', opened[x][5])
#打印当前处理的node形状
#          result=updatelocation(opened[x][0])
#          prtresult(result)
          this_node = copy.deepcopy(opened[x])
          tmp = move_mult(this_node)
#          print(tmp)
#          print(opened)
#          print('tmp length is',len(tmp))
          for y in range(len(tmp)):
                  flag=False
                  
#检查新节点是否已经在open表中,如在将不添加
                  for jj in range(len(opened)):
#                        print('tmp[y][0]is',tmp[y][0])
#                        print('opened[x][0]is',opened[x][0])

#                        if tmp[y][0]==opened[jj][0]:
#原有判断还不够精细,需要增加同等项6/7/8/9四个小卒组合位置相同的,也认为是同一局型。
                        if(check_match(tmp[y][0],opened[jj][0])==True):
                            flag=True
#                            print('flag opened set to True','tmp =','open[',jj,']=',tmp[y][0])
#                            print('role is',role)
#                            print('opened is',opened)
                        
#检查新节点是否已经在closed表中,如在将不添加
                  for kk in range(len(closed)):
#                         print('tmp[',y,'][0]is',tmp[y][0])
#                         print('closed[',kk,'][0]is',closed[kk][0])
#                         if tmp[y][0]==closed[kk][0]:
#改为使用函数check_match
                        if(check_match(tmp[y][0],closed[kk][0])==True):
                            flag=True
#                            print('falg close set to True')
                
                  if(flag==False):
                      max_nodeid = max_nodeid +1
#统计分析的节点数量
#                      if max_nodeid%50>=0 and max_nodeid%50 < 1:
#                        print(int(max_nodeid/50)*50,'nodes get!')
#                        print('已完成:',len(closed),'剩余:',len(opened))                      
                      tmp[y][4]=max_nodeid      #将新生成的节点赋上nodeid编号
                      tmp[y][6]=diff(tmp[y][0]) #将新生成的节点的最后一位补充上diff值
#参考前行“next_role_list.append([next_role, this_role, x, direct, '', this_nodeid,0]) #next nodeid set to null"

#A*算法用addOpen,A算法用open.append
#                      opened.append(tmp[y])
#                      print('tmp[y] is:',tmp[y])
                      addOpen(tmp[y])
#                     print('新增节点',next_role, this_role, x, direct, max_nodeid, this_nodeid)
#                      print('新增open节点', tmp[y][5],':----',tmp[y][2],'move',tmp[y][3],'---->',tmp[y][4])
#                      tmp_pos=updatelocation(tmp[y][1])
#                      prtresult(tmp_pos)
#                      tmp_pos2=updatelocation(tmp[y][0])
#                      prtresult(tmp_pos2)
#                      print('add opened node',tmp[y][0])
#                  else:
#                      print('node',tmp[y][0], 'already exists in opened or closed!')
#检查是否成功
                  if(check_win(tmp[y][0])=="Success!"):
                    print('Success!')
#                    print('final is:',tmp[y])
#                    print('opened[0] is:',opened[0])
                    closed.append(tmpOpen)
#                    print('add to closed:',opened[0])
                    closed.append(tmp[y])
#                    print('add to closed:',tmp[y])                    
                    opened.remove(opened[0])
#                    print('add close node',opened[x])
                    print('Totally',max_nodeid,'nodes ayalyzed,find the result.')
                    print('已完成:',len(closed),'剩余:',len(opened),'diffold:',tmpOpen[6],'diffnew:',tmp[y][6])
#                    print('closed is:',closed)
                    prtAnswer(closed)
                    print('Success!')
                    end_time = int(time.time())
                    print('Caculating time:',end_time-begin_time,'seconds.')
                    exit("We find it!")
          closed.append(tmpOpen)
          opened.remove(tmpOpen)
#          print(len(closed),'nodes closed!')
#          print('add close node',opened[x][5])
#          print('节点分析完毕,移入closed节点:', opened[x][4],'已完成:',len(closed),'剩余:',len(opened))
          if((len(closed)+len(opened))%100>=0 and (len(closed)+len(opened))%100<1):
              print('已完成:',len(closed),'剩余:',len(opened),'diffold:',tmpOpen[6],'diffnew:',opened[0][6])   
              tmp_pos=updatelocation(tmpOpen[0])
              prtresult(tmp_pos)
    else:
        print('No answer!')
        end_time = int(time.time())
        print('Caculating time:',end_time-begin_time)

#2.7打印结果

#2.7.1 打印自动计算的结果

#打印结果,方法是从close表最后一条开始,查找其前一个节点,
#直到前一节点为0,并将所有查到的序列写入step,打印出step
#即得到所有的变化过程。
#node: [当前role,前一role,移动角色,移动方向,当前局面nodeid,前一局面nodeid,diff]
def prtAnswer(closed):
      step=[closed[-1]]
#      print('closed is:',closed)
#      print('Step is:',step)
      nodePrt=closed[-1][5]   #最后节点父节点的ID
#      print('prt nodeid is:',nodePrt)
      while True:
            for x in range(len(closed)):
                  if(nodePrt==closed[x][4]):    #从closed表找上一节点的父节点,即节点ID等于后一节点父节点ID
                        step.insert(0,closed[x])
#                        print('Step is:',step)
                        nodePrt=closed[x][5]    #更新父节点ID
            if(nodePrt==0):
                  break
      print('\n Totally',len(step),' steps, as below:')
      for x in range(len(step)):
            print('\nStep',x,', id:',step[x][4],end='')
            if(x==0):
                print('(Begin)',end='')
            if(x==len(step)-1):
                print('(Final)')
            if(x%5==0 or x==len(step)-1):
                result = updatelocation(step[x][0])
                prtresult(result)
            if(x<len(step)-1):
                print('     ----',step[x+1][2],'move', step[x+1][3],'---->',end='')
#      print('Finished!')

#2.8主程序

#主程序    
#result=updatelocation(role)
#prtresult(result)
print('\n')
init_conf()
init_map()
while True:
    result=updatelocation(role)
    prtresult(result)
    print("\n\n")
    if(len(history)>1):
        select = input('Target: Move Caocao--0000--block to exit\n Choose an item to move,x to exit, b to back, a to autoplay: ')
    else:
        select = input('Target: Move Caocao--0000--block to exit\n Choose an item to move,x to exit, a to autoplay: ')
    if(select=='b' or select=='B'):
        if(len(history)>1):
            print('before:',history)
            history.pop()
            print('after:',history)
            rolex=copy.deepcopy(history[-1])
            print('last:',rolex)
        else:
            print("\n cannot go back, please choose again")
    elif(select in "0123456789"):
       direct = move_judge(int(select),role)
       if(direct!=[]):
            role=move(int(select),role,direct,result)
            history.append(copy.deepcopy(role))
            if(check_win(role)=="Success!"):
                print("\n Congratulations! You Win!")
                break
       else:
           print("\n cannot move, please choose again")
    elif(select=='a' or select=='A'):
        auto_play=True
        autoplay(role)
        break
    elif (select =='x' or select=='X'):
        print('good bye')
        break

3、游戏 效果

=====================
执行效果如下:

3.1、自动游戏效果

Welcome to HuaRongDao, Please choose a map to play:
    1、横刀立马
    2、齐头并前
    3、兵分三路
    4、屯兵东路
    5、左右布兵
    6、前挡后阻
    7、测试地图
    8、测试地图2
    9、测试地图3
    请输入(1-9):2

2003
2003
6789
4115
4xx5
 xx

Target: Move Caocao--0000--block to exit
 Choose an item to move,x to exit, a to autoplay: a
已完成: 36 剩余: 64 diffold: 2700 diffnew: 2700

2003
2003
4x95
46x5
1178
 xx
已完成: 103 剩余: 197 diffold: 1850 diffnew: 1850

4235
4235
00x6
009x
11x8
 7x
已完成: 361 剩余: 439 diffold: 1300 diffnew: 1300

42x5
4235
113x
6800
x700
 9x
已完成: 362 剩余: 438 diffold: 1300 diffnew: 1300

423x
4235
11x5
6800
x700
 9x
Success!

Step 0 , id: 1(Begin)

2003
2003
6789
4115
4xx5
 xx
     ---- 1 move down ---->
Step 1 , id: 2     ---- 7 move down ---->
Step 2 , id: 4     ---- 6 move right ---->
Step 3 , id: 7     ---- 4 move up ---->
Step 4 , id: 15     ---- 1 move left ---->
Step 5 , id: 18

2003
2003
4689
47x5
11x5
 xx
     ---- 8 move down ---->
Step 6 , id: 24     ---- 9 move left ---->
Step 7 , id: 30     ---- 5 move up ---->
Step 8 , id: 43     ---- 8 move down ---->
Step 9 , id: 45     ---- 7 move right ---->
Step 10 , id: 46

2003
2003
4695
4x75
118x
 xx
     ---- 6 move down ---->
Step 11 , id: 51     ---- 8 move right ---->
Step 12 , id: 62     ---- 7 move down ---->
Step 13 , id: 79     ---- 9 move down ---->
Step 14 , id: 100     ---- 0 move down ---->
Step 15 , id: 128

2xx3
2003
4005
4695
1178
 xx
     ---- 7 move down ---->
Step 16 , id: 129     ---- 7 move left ---->
Step 17 , id: 131     ---- 9 move down ---->
Step 18 , id: 137     ---- 6 move right ---->
Step 19 , id: 145     ---- 9 move down ---->
Step 20 , id: 153

2xx3
2003
4005
4x65
11x8
 79
     ---- 6 move down ---->
Step 21 , id: 161     ---- 0 move down ---->
Step 22 , id: 165     ---- 2 move right ---->
Step 23 , id: 166     ---- 4 move up ---->
Step 24 , id: 170     ---- 4 move up ---->
Step 25 , id: 173

42x3
42x3
x005
x005
1168
 79
     ---- 0 move left ---->
Step 26 , id: 174     ---- 3 move left ---->
Step 27 , id: 178     ---- 5 move up ---->
Step 28 , id: 187     ---- 5 move up ---->
Step 29 , id: 191     ---- 0 move right ---->
Step 30 , id: 194

4235
4235
x00x
x00x
1168
 79
     ---- 0 move right ---->
Step 31 , id: 384     ---- 1 move up ---->
Step 32 , id: 386     ---- 1 move up ---->
Step 33 , id: 389     ---- 6 move left ---->
Step 34 , id: 394     ---- 6 move left ---->
Step 35 , id: 396

4235
4235
1100
xx00
6xx8
 79
     ---- 8 move left ---->
Step 36 , id: 405     ---- 8 move left ---->
Step 37 , id: 423     ---- 0 move down ---->
Step 38 , id: 442     ---- 1 move right ---->
Step 39 , id: 445     ---- 1 move right ---->
Step 40 , id: 451

4235
4235
xx11
xx00
6800
 79
     ---- 6 move up ---->
Step 41 , id: 466     ---- 6 move up ---->
Step 42 , id: 495     ---- 8 move left ---->
Step 43 , id: 533     ---- 7 move up ---->
Step 44 , id: 578     ---- 7 move up ---->
Step 45 , id: 620

4235
4235
6x11
x700
8x00
 x9
     ---- 7 move left ---->
Step 46 , id: 660     ---- 9 move left ---->
Step 47 , id: 694     ---- 9 move up ---->
Step 48 , id: 720     ---- 9 move up ---->
Step 49 , id: 736     ---- 9 move up ---->
Step 50 , id: 744

4235
4235
6911
7x00
8x00
 xx
     ---- 0 move left ---->
Step 51 , id: 746     ---- 0 move down ---->
Step 52 , id: 873(Final)

4235
4235
6911
7xxx
800x
 00
Success!
Caculating time: 6 seconds.

python实现华容道游戏(v0.4)--支持游戏自动完成功能相关推荐

  1. Python数字华容道--程序实现的创意数学小游戏

    下载链接:Python数字华容道--程序实现的创意数学小游戏-Python文档类资源-CSDN下载 当前的数学教育环境下,更强调的是数学素养的提升,本程序提供了一个免费的数学益智小游戏的学习和训练平台 ...

  2. Python版基于pygame的玛丽快跑小游戏源代码,玛丽冒险小游戏代码,支持双人模式

    基于pygame的玛丽快跑小游戏源代码,玛丽冒险小游戏代码,支持双人模式 按空格进入单人模式,按't'进入双人模式,双人模式下玛丽1采用空格键上跳,玛丽2采用方向上键上跳. 完整代码下载地址:Pyth ...

  3. Python五子棋小游戏源代码,支持人机对战和局域网对战两模式

    Python五子棋小游戏源代码,支持人机对战和局域网对战两模式,程序运行截图: 核心程序代码 WuZi.py ''' Function:五子棋小游戏-支持人机和局域网对战 Author:Charles ...

  4. 利用python实现简易版的贪吃蛇游戏(面向python小白)

    前言 这篇文章主要给大家介绍了关于如何利用python实现简易版的贪吃蛇游戏的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学 ...

  5. python游戏最简单代码-如何利用Python开发一个简单的猜数字游戏

    前言 本文介绍如何使用Python制作一个简单的猜数字游戏. 游戏规则 玩家将猜测一个数字.如果猜测是正确的,玩家赢.如果不正确,程序会提示玩家所猜的数字与实际数字相比是"大(high)&q ...

  6. python五子棋双人对弈_PyQt5实现五子棋游戏(人机对弈)

    这篇博客主要是为了学习Python和PyQt,因为对棋类游戏比较热衷,所以从规则较简单的五子棋入手,利用PyQt5实现图形界面,做一个可以进行人机对弈的脚本,最后打包成应用程序.AI的算法打算用神经网 ...

  7. php编写猜拳游戏,Python中猜拳游戏与猜筛子游戏的实现方法

    猜拳游戏 import random player_input=input("请输入(0剪刀,1石头,2布):") player=int(player_input) compute ...

  8. python画猫和老鼠_利用python如何实现猫捉老鼠小游戏

    python实现猫捉老鼠小游戏 首界面 开始游戏界面 然后键盘操作小老鼠上下左右移动,猫自己去追,当猫追上老鼠则游戏结束 这里用时3.2秒,最后将游戏时长与猫和老鼠都显示在主页面上 下面我把猫与老鼠的 ...

  9. Python开发过哪些知名网站和游戏?

    我们都知道,Python不仅在数据分析.人工智能方面有着广泛的应用,在网站开发.游戏开发方面更是一枝独秀. 今天达妹就带大家盘点一下,哪些知名的大型公司和网站在用Python开发,以及用Python开 ...

  10. 洗礼灵魂,修炼python(41)--巩固篇—从游戏《绝地求生-大逃杀》中回顾面向对象编程...

    声明:本篇文章仅仅以游戏<绝地求生>作为一个参考话题来介绍面向对象编程,只是作为学术引用,其制作的非常简易的程序也不会作为商业用途,与蓝洞公司无关. <绝地求生>最近很火,笼络 ...

最新文章

  1. 盘点 15 个好用的 API 接口管理神器
  2. 机器学习笔记:牛顿方法
  3. Halcon初学者知识【17】如何将零件提取dxf图
  4. 杭电oj1176,2084java实现
  5. 为WPF和Silverlight的Grid添加边框线
  6. C# 入门之 Hello World
  7. 计算机专业408题目结构,2019考研408计算机组成原理知识:计算机系统层次结构
  8. [Centos 6.2] centos 6.2(64位)网络配置
  9. 我们一起爬爬爬之HTTP原理
  10. python__画图表可参考(转自:寒小阳 逻辑回归应用之Kaggle泰坦尼克之灾)
  11. MySQL 数据库救火:磁盘爆满了,怎么办?
  12. Gensim加载word2vec模型与简易使用
  13. 常用功能-删除功能测试点
  14. javascript的发展(周边插件的由来)
  15. zookeeper 日志查看_zookeeper 安装和集群配置
  16. Android推送方案分析(MQTT/XMPP/GCM)
  17. 使用 Flink Hudi 构建流式数据湖平台
  18. 基于RSA解题时yafu的使用
  19. Sublime Text 一键删除空白行的方法
  20. 关于高通8953开机需要按pwrkey很长时间的问题

热门文章

  1. git代理设置与取消
  2. 噪声,白噪声,加性噪声和乘性噪声
  3. 盛京剑客系列26:极简估值教程——第二讲历史估值的参考与运用
  4. 什么是IPFS?(三)
  5. “你是个成熟的设备了,要学会保护自己”
  6. 如何在开源世界打造自己的明星 Project?
  7. ScreenFlow for mac(最强大的屏幕录像软件)
  8. 英特尔应用PC业真的已经走到了穷途末路?
  9. FAT文件系统介绍以及FatFs的移植
  10. 评测|HPE Nimble AF全闪存系列,诠释真正的高端存储