python华容道最短路径_Python方法生成华容道所有开局

2024-02-18 15:30

本文主要是介绍python华容道最短路径_Python方法生成华容道所有开局,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

玩蛇网本文是关于Python语言解决游戏算法的相关文章。Python方法生成华容道所有求解的开局,其中含镜像263977种,不含镜像132156种。

e43190099429d78acfc194edbf5575d6.png

华容道所有开局求解的思路是:

1. 生成所有终局

2. 广度优先推出所有开局,形成一个树

3. 树中所有的节点都是开局,可以根据Level进行排序

#! /usr/bin/env python

# -*- coding: utf-8 -*-

#-----------www.iplaypy.com----------------------------

# Definitions

# B(4): Box, 2x2

# V(2): Vertical Bar, 1x2

# H(3): Horizontal Bar, 2x1

# D(1): Dot, 1x1

# E(0): the empty 1x1(or space)

# U(7): undefined, or (?)

Empty,Dot,Vbar,Hbar,Box,Undef = 0,1,2,3,4,7

row, col = 5, 4

#---------------------------------------------------------------

# Generates all the valid end matrix

#

C72 = ((0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6),

(1, 2), (1, 3), (1, 4), (1, 5), (1, 6),

(2, 3), (2, 4), (2, 5), (2, 6),

(3, 4), (3, 5), (3, 6),

(4, 5), (4, 6),

(5, 6))

#Possible endings(mirror ending is not included)

# Ending 1: ???? Ending 2: ????

# ???? ????

# ???? ?EE?

# EBB? ?BB?

# EBB? ?BB?

endings = ([7,7,7,7, 7,7,7,7, 7,7,7,7, 0,4,4,7, 0,4,4,7],

[7,7,7,7, 7,7,7,7, 7,0,0,7, 7,4,4,7, 7,4,4,7])

def print_matrix(m):

for i in range(5):

for j in range(4):

print m[4*i + j],

print

print

def all_ending_layouts():

"""Check all possible configurations when CaoCao is at the exit."""

values = {}

for end in endings:

#14 undefined cells, red & black, select 4, 2 red & 2 black

slot = [i for i in range(20) if Undef == end[i]]

red = [slot[i] for i in range(14) if (slot[i] % col + slot[i] / col) % 2 == 0]

black = [slot[i] for i in range(14) if (slot[i] % col + slot[i] / col) % 2]

# 21 = C(7,2)

for c1 in C72:

for c2 in C72:

matrix = end[:]

matrix[red[c1[0]]] = Dot

matrix[red[c1[1]]] = Dot

matrix[black[c2[0]]] = Dot

matrix[black[c2[1]]] = Dot

for layout in tile(matrix):

value = 0L

for t in layout:

value = value << 3 | t

if not values.has_key(value):

rvalue = 0L

for i in range(5):

for j in range(4):

rvalue = rvalue << 3 | layout[i*4 + 4-j-1]

values[value] = True

values[rvalue] = True

yield layout

def is_neighbor(slot, i, j):

xi, yi = slot[i] % col, slot[i] / col

xj, yj = slot[j] % col, slot[j] / col

if xj==xi and yj==yi+1:

return 2

if xj==xi+1 and yj==yi:

return 3

return 0

def tile(matrix):

"""return the valid layout to tile five 1x2/2x1 in 10 slots"""

matrix_list = [matrix]

index = 0

while index < len(matrix_list):

matrix = matrix_list[index]

slot = [i for i in range(20) if Undef == matrix[i]]

n = len(slot)

if n == 0:

return matrix_list[index:]

#for each undefined block, look up its adjacent undefined block's

p = [[] for i in range(n)]

min_p, k = n, -1

for i in range(n):

for j in range(i+1, n):

ret = is_neighbor(slot, i, j)

if ret:

p[i].append((j, ret))

p[j].append((i, ret))

if not p[i]:

k = -1

break #an isolated block is detected

if len(p[i]) < min_p:

min_p, k = len(p[i]), i

if k != -1:

#start with the position with the least adjacent undefined slots, enumerate all

# possible configurations after filling this position

for neighbor in p[k]:

new_matrix = matrix[:]

new_matrix[slot[k]] = neighbor[1]

new_matrix[slot[neighbor[0]]] = neighbor[1]

matrix_list.append(new_matrix)

#process next matrix

index += 1

return []

#---------------------------------------------------------------

# spawn all the layouts to be solved

#convert 4*5 DHVB into block layouts(totally 10 blocks)

def convert(matrix):

b = [0, 0, 0, 0]

c,d = 0,0

result = []

for i in range(20):

x = i % 4

y = i / 4

n = matrix[i]

if n == Dot:

result += [1, x, y]

elif n == Vbar:

if y == 0 or b[x] == 0:

b[x] = 2

result += [2, x, y]

else:

b[x] = 0

elif n == Hbar:

if c == 0:

result += [3, x, y]

c = 3

else:

c = 0

elif n == Box:

if d % 4 == 0:

result += [4, x, y]

d = 1

else:

d += 1

return result

from copy import deepcopy

class Board:

def __init__(self, layout):

#the moved index to generate this board

self.moved = -1

#init the matrix and items

self.items = [()] * 10 #BIT:type:3,x:2,y:3), x,y is zero-based

self.empty = [(0,0), (0,0)] #2 empty slot's position in matrix, (col, row)

#-1 mean's boundary

f = -1

#[1+5+1][1+4+1] of byte, each byte is the (index+1) in items

# the extra 1s is for the boundary

self.matrix = [ [f, f, f, f, f, f],

[f, 0, 0, 0, 0, f],

[f, 0, 0, 0, 0, f],

[f, 0, 0, 0, 0, f],

[f, 0, 0, 0, 0, f],

[f, 0, 0, 0, 0, f],

[f, f, f, f, f, f] ]

#calculate the items into cell-matrix

type, x, y = 0, 0, 0

for i in range(10):

type = layout[i*3]

x = layout[i*3+1]

y = layout[i*3+2]

self.items[i] = (type, x, y)

self.matrix[y+1][x+1] = i+1

if type == Vbar:

self.matrix[y+2][x+1] = i+1

elif type == Hbar:

self.matrix[y+1][x+2] = i+1

elif type == Box:

self.matrix[y+1][x+2] = i+1

self.matrix[y+2][x+1] = i+1

self.matrix[y+2][x+2] = i+1

#find out the empty blocks

count = 0

for i in range(7):

for j in range(6):

if not self.matrix[i][j]:

self.empty[count] = (j, i)

if not count: count += 1

else: return

def getValue(self):

val, bt = 0L, 0

for i in range(1, 6):

for k in range(1, 5):

index = self.matrix[i][k] - 1

if index < 0: bt = 0

else: bt = self.items[index][0]

val = val << 3 | bt

return val

def getRValue(self):

val, bt = 0L, 0

for i in range(1, 6):

for k in range(4, 0, -1):

index = self.matrix[i][k] - 1

if index < 0: bt = 0

else: bt = self.items[index][0]

val = val << 3 | bt

return val

#spawn new Board by moving the cells around empty cells

# changes global variable: g_values

def spawn(self):

global g_values

new_boards = []

#collect the cells around empty cells

around = [0] * 8

#DO NOT change the order of ulrd, it's been depended

# ulrd: Up/Left/Right/Down

ulrd = ((0,-1), (-1,0), (1,0), (0,1))

for e in self.empty: #two empty blocks, always 2

x, y = e

for k in range(4):

dir = ulrd[k]

nx = x + dir[0]

ny = y + dir[1]

1c40

index = self.matrix[ny][nx] - 1

if index >= 0:

newb = deepcopy(self)

newb.moved = index

if newb.tryAndMove(index, -dir[0], -dir[1]):

value = newb.getValue()

if not g_values.has_key(value):

if len(g_values) % 1000 == 0:

print len(g_values)

rvalue = newb.getRValue()

g_values[value] = rvalue

g_values[rvalue] = value

new_boards.append(newb)

return new_boards

def tryAndMove(self, index, dx, dy):

item = self.items[index]

type, x, y = item

ret = False

#ci is short for cell index

ci1 = ci2 = ci3 = ci4 = 0

if type == Dot:

ci1 = self.matrix[y+dy+1][x+dx+1]

ret = not ci1 or ci1 == index+1

if ret:

self.matrix[y+1][x+1] = 0

self.matrix[y+dy+1][x+dx+1] = index + 1

self.items[index] = (type, x+dx, y+dy)

self.setEmpty(x+1, y+1)

elif type == Vbar:

ci1 = self.matrix[y+dy+1][x+dx+1]

ci2 = self.matrix[y+dy+2][x+dx+1]

ret = (not ci1 or ci1==index+1) and (not ci2 or ci2==index+1)

if ret:

self.matrix[y+1][x+1] = 0

self.matrix[y+2][x+1] = 0

self.matrix[y+dy+1][x+dx+1] = index + 1

self.matrix[y+dy+2][x+dx+1] = index + 1

self.items[index] = (type, x+dx, y+dy)

if self.matrix[y+1][x+1] == 0: self.setEmpty(x+1, y+1)

if self.matrix[y+2][x+1] == 0: self.setEmpty(x+1, y+2)

elif type == Hbar:

ci1 = self.matrix[y+dy+1][x+dx+1]

ci2 = self.matrix[y+dy+1][x+dx+2]

ret = (not ci1 or ci1==index+1) and (not ci2 or ci2==index+1)

if ret:

self.matrix[y+1][x+1] = 0

self.matrix[y+1][x+2] = 0

self.matrix[y+dy+1][x+dx+1] = index + 1

self.matrix[y+dy+1][x+dx+2] = index + 1

self.items[index] = (type, x+dx, y+dy)

if self.matrix[y+1][x+1] == 0: self.setEmpty(x+1, y+1)

if self.matrix[y+1][x+2] == 0: self.setEmpty(x+2, y+1)

elif type == Box:

ci1 = self.matrix[y+dy+1][x+dx+1]

ci2 = self.matrix[y+dy+1][x+dx+2]

ci3 = self.matrix[y+dy+2][x+dx+1]

ci4 = self.matrix[y+dy+2][x+dx+2]

ret = (not ci1 or ci1==index+1) and (not ci2 or ci2==index+1) and \

(not ci3 or ci3==index+1) and (not ci4 or ci4==index+1)

if ret:

self.matrix[y+1][x+1] = 0

self.matrix[y+1][x+2] = 0

self.matrix[y+2][x+1] = 0

self.matrix[y+2][x+2] = 0

self.matrix[y+dy+1][x+dx+1] = index+1

self.matrix[y+dy+1][x+dx+2] = index+1

self.matrix[y+dy+2][x+dx+1] = index+1

self.matrix[y+dy+2][x+dx+2] = index+1

self.items[index] = (type, x+dx, y+dy)

if self.matrix[y+1][x+1] == 0: self.setEmpty(x+1, y+1)

if self.matrix[y+1][x+2] == 0: self.setEmpty(x+2, y+1)

if self.matrix[y+2][x+1] == 0: self.setEmpty(x+1, y+2)

if self.matrix[y+2][x+2] == 0: self.setEmpty(x+2, y+2)

return ret

def setEmpty(self, ex, ey):

x, y = self.empty[0]

if (self.matrix[y][x]):

self.empty[0] = (ex, ey)

else:

self.empty[1] = (ex, ey)

#-----------------------------------------

#global variables

#all end matrix

#all non-end matrix

#values for all end and non-end matrix

g_values = {}

#print ending count

end_count = 0

for matrix in all_ending_layouts():

end_count += 1

#check if this board has been touched

value = 0L

for t in matrix:

value = value << 3 | t

if g_values.has_key(value):

continue

rvalue = 0L

for i in range(5):

for j in range(4):

rvalue = rvalue << 3 | matrix[i*4 + 4-j-1]

layout = convert(matrix)

g_values[value] = rvalue

g_values[rvalue] = value

#start spawn

board = Board(layout)

board_pool = [board]

index = 0

while index < len(board_pool):

board_pool += board_pool[index].spawn()

index += 1

print len(g_values)

print "Total Endings count:", end_count

print "Total Layouts count:", len(g_values)

def solve_all_layouts():

g_nondups = {}

count = 0

from os import popen

outfile = open("input.log", "w+")

for value in g_values:

if count % 1000 == 0:

print count

if g_nondups.has_key(value):

continue

count += 1

rvalue = g_values[value]

g_nondups[value] = True

g_nondups[rvalue] = True

matrix = [0] * 20

val = value

for i in range(20):

matrix[20-i-1] = val & 7

val = val >> 3

layout = convert(matrix)

layout_str = "".join([str(i) for i in layout])

print >>outfile, layout_str, value, rvalue, layout

return count

count = solve_all_layouts()

print "Total Layouts count(no mirror):", count

print "Everything is over, see result.log for detailed result"

玩蛇网文章,转载请注明出处和文章网址:https://www.iplaypy.com/code/game/g2611.html

相关文章 Recommend

这篇关于python华容道最短路径_Python方法生成华容道所有开局的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/721600

相关文章

基于Python编写一个git自动上传的脚本(打包成exe)

《基于Python编写一个git自动上传的脚本(打包成exe)》这篇文章主要为大家详细介绍了如何基于Python编写一个git自动上传的脚本并打包成exe,文中的示例代码讲解详细,感兴趣的小伙伴可以跟... 目录前言效果如下源码实现利用pyinstaller打包成exe利用ResourceHacker修改e

Python在二进制文件中进行数据搜索的实战指南

《Python在二进制文件中进行数据搜索的实战指南》在二进制文件中搜索特定数据是编程中常见的任务,尤其在日志分析、程序调试和二进制数据处理中尤为重要,下面我们就来看看如何使用Python实现这一功能吧... 目录简介1. 二进制文件搜索概述2. python二进制模式文件读取(rb)2.1 二进制模式与文本

Python中Tkinter GUI编程详细教程

《Python中TkinterGUI编程详细教程》Tkinter作为Python编程语言中构建GUI的一个重要组件,其教程对于任何希望将Python应用到实际编程中的开发者来说都是宝贵的资源,这篇文... 目录前言1. Tkinter 简介2. 第一个 Tkinter 程序3. 窗口和基础组件3.1 创建窗

Django调用外部Python程序的完整项目实战

《Django调用外部Python程序的完整项目实战》Django是一个强大的PythonWeb框架,它的设计理念简洁优雅,:本文主要介绍Django调用外部Python程序的完整项目实战,文中通... 目录一、为什么 Django 需要调用外部 python 程序二、三种常见的调用方式方式 1:直接 im

Python字符串处理方法超全攻略

《Python字符串处理方法超全攻略》字符串可以看作多个字符的按照先后顺序组合,相当于就是序列结构,意味着可以对它进行遍历、切片,:本文主要介绍Python字符串处理方法的相关资料,文中通过代码介... 目录一、基础知识:字符串的“不可变”特性与创建方式二、常用操作:80%场景的“万能工具箱”三、格式化方法

springboot+redis实现订单过期(超时取消)功能的方法详解

《springboot+redis实现订单过期(超时取消)功能的方法详解》在SpringBoot中使用Redis实现订单过期(超时取消)功能,有多种成熟方案,本文为大家整理了几个详细方法,文中的示例代... 目录一、Redis键过期回调方案(推荐)1. 配置Redis监听器2. 监听键过期事件3. Redi

基于SpringBoot实现分布式锁的三种方法

《基于SpringBoot实现分布式锁的三种方法》这篇文章主要为大家详细介绍了基于SpringBoot实现分布式锁的三种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、基于Redis原生命令实现分布式锁1. 基础版Redis分布式锁2. 可重入锁实现二、使用Redisso

浅析python如何去掉字符串中最后一个字符

《浅析python如何去掉字符串中最后一个字符》在Python中,字符串是不可变对象,因此无法直接修改原字符串,但可以通过生成新字符串的方式去掉最后一个字符,本文整理了三种高效方法,希望对大家有所帮助... 目录方法1:切片操作(最推荐)方法2:长度计算索引方法3:拼接剩余字符(不推荐,仅作演示)关键注意事

自定义注解SpringBoot防重复提交AOP方法详解

《自定义注解SpringBoot防重复提交AOP方法详解》该文章描述了一个防止重复提交的流程,通过HttpServletRequest对象获取请求信息,生成唯一标识,使用Redis分布式锁判断请求是否... 目录防重复提交流程引入依赖properties配置自定义注解切面Redis工具类controller

python版本切换工具pyenv的安装及用法

《python版本切换工具pyenv的安装及用法》Pyenv是管理Python版本的最佳工具之一,特别适合开发者和需要切换多个Python版本的用户,:本文主要介绍python版本切换工具pyen... 目录Pyenv 是什么?安装 Pyenv(MACOS)使用 Homebrew:配置 shell(zsh