通过python递归来解决孔明棋问题

孔明棋大家应该都不陌生。(好吧可能不一定)

简单来讲,是一种规则简单,但是过程并不见得容易,可以一个人玩的棋。

他有还一个有趣的名字:法国跳棋独立钻石。

我上手的是vx某小程序。玩法比最经典的32颗棋子多一些。

(经典玩法如下)

 一颗棋子可以跳过邻近一颗棋子(只包含上下左右,而没有斜向),被跳过的棋子就被拿开。

当然如果,跳过后的空位被占了的话,也是无法跳的。如果一颗棋子上下左右都没有棋子的话那就无法移动。当整个棋盘只剩一个棋子就成功了。

棋子越多自由度就越高,每一步的选择就更多,失败的走法总体上比成功地走法多得多,所以成功不算太容易。

所以为了,为了获得一种解法,或者理论上的所有解法,我决定写这样的一个程序。

简单的思路是先建立一个坐标系,如下:

 然后定义棋子空格,移动规则等等。

同样由于没必要实现全自动操作,所以采用一些麻烦但可以接受的方式输入棋盘数据。

如图操作:

 用0代表空缺,用1来代表棋子,用2来代表棋盘上无法到达的部分。

7*7部分只是为了检验和输入方便,需要的是下面那一行。

运行示例如下:

 为了提高速度,只返回了一种可能的解决方案。

大列表中的小列表代表移动,第一个坐标是被移动的棋子的位置,第二个则是被跳过(取走)的棋子的位置。值得一提的是,再返回结果中为了方便,将原坐标系的横纵坐标加一。

如下:

 代码如下:


class Square():
    def __init__(self,position,num):
        self.position = position #定义位置
        self.num = num

    def __str__(self):
        return '[%s,%s]'% (self.position,self.num)

    def getaline(self):
        linelist = []
        for each in wholepart:
            if each.position[1] == self.position[1]:
                linelist.append(each)
        return linelist

    def getarow(self):
        rowlist = []
        for each in wholepart:
            if each.position[0] == self.position[0]:
                rowlist.append(each)
        return rowlist

def getchance():
    chancelist = []
    for each in wholepart:
        if each.num == [1]:
            try:
                for eacharound in wholepart:
                    if eacharound.num == [1] and \
                    eacharound.position[0] == each.position[0] \
                and abs(eacharound.position[1]-each.position[1])==1:
                        if toplace([each,eacharound]).num == []:
                            chancelist.append([each,eacharound])
                    if eacharound.num == [1] and \
                    eacharound.position[1] == each.position[1] \
                and abs(eacharound.position[0]-each.position[0])==1:
                        if toplace([each,eacharound]).num == []:
                            chancelist.append([each,eacharound])
            except AttributeError:
                pass

    return chancelist

def move(chance):
    square1 = chance[0]
    square2 = chance[1]
    if square1.position[0]==square2.position[0]:
        for each in square1.getarow():
            if each.position[1] == 2*square2.position[1]\
                    -square1.position[1]:
                each.num = [1]
                square1.num = []
                square2.num = []
    elif square1.position[1]==square2.position[1]:
        for each in square1.getaline():
            if each.position[0] == 2*square2.position[0]\
                    -square1.position[0]:
                each.num = [1]
                square1.num = []
                square2.num = []

def unmove(chance):
    square1 = chance[0]
    square2 = chance[1]
    if square1.position[0] == square2.position[0]:
        for each in square1.getarow():
            if each.position[1] == 2 * square2.position[1] \
                    - square1.position[1]:
                each.num = []
                square1.num = [1]
                square2.num = [1]
    elif square1.position[1] == square2.position[1]:
        for each in square1.getaline():
            if each.position[0] == 2 * square2.position[0] \
                    - square1.position[0]:
                each.num = []
                square1.num = [1]
                square2.num = [1]

def toplace(choice):
    square1 = choice[0]
    square2 = choice[1]
    if square1.position[1] == square2.position[1]:
        for each in square1.getaline():
            if each.position[0] == 2 * square2.position[0] \
                    - square1.position[0]:
                return each
    if square1.position[0] == square2.position[0]:
        for each in square1.getarow():
            if each.position[1] == 2 * square2.position[1] \
                    - square1.position[1]:
                return each

# 生成整个棋局
wholepart = []
for row in range(7):
    for line in range(7):
        example = Square((row,line),[])
        wholepart.append(example)

replacelist = []
tolist = []
times = 0
enter = input('please enter:')
for i in enter:
    if i != '0':
        tolist.append(int(i))
        replacelist.append(times)
    times = times + 1

h = dict(zip(replacelist,tolist))
for known,t in h.items():
    wholepart[known].num.append(t)


def main():
    global go
    if not go:
        return
    alist = getchance()
    if alist == []:
        times = 0
        for each in wholepart:
            if each.num == [1]:
                times += 1
        if times != 1:
            return
        elif times == 1:
            print('success')
            for h in testlist2:
                print('[(%s,%s),(%s,%s)]'%(h[0][0]+1,h[0][1]+1\
                                           ,h[1][0]+1,h[1][1]+1),end='')
            print()
            go = False

            return
    for eachway in alist:
        move(eachway)
        testlist2.append([eachway[0].position,eachway[1].position])
        main()
        unmove(eachway)
        testlist2.remove([eachway[0].position, eachway[1].position])




testlist2 = []
go = True
main()

文本如下:

2200022
2201022
0011100
0001000
0001000
2200022
2200022

2200022220102200111000001000000100022000222200022

下面提供几个示例:

please enter:2201022221112201111100001000000100022111222211122
success
[(2,3),(3,3)][(2,5),(3,5)][(7,3),(6,3)][(5,3),(4,3)][(3,3),(3,4)][(1,4),(2,4)][(3,5),(3,4)][(3,2),(3,3)][(4,4),(3,4)][(6,5),(6,4)][(7,5),(7,4)][(7,3),(6,3)][(5,3),(5,4)][(5,5),(4,5)][(3,6),(3,5)][(2,4),(3,4)]

Process finished with exit code 0

please enter:2200022220102200111000111110111111122000222200022
success
[(3,4),(2,4)][(4,3),(3,3)][(4,5),(5,5)][(5,7),(5,6)][(6,5),(5,5)][(4,6),(4,5)][(5,4),(4,4)][(4,4),(3,4)][(1,4),(2,4)][(3,5),(3,4)][(2,3),(3,3)][(4,3),(5,3)][(5,1),(5,2)][(6,3),(5,3)][(4,2),(4,3)]

Process finished with exit code 0

 写在最后:代码有很多不足。对于不同的情况,算法所花的时间差别很大,从几秒到几分钟都可能。可能等我学的更多一些才能优化了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340