一个趣味小游戏

本文介绍了如何使用Python编程语言,结合暴力穷举和递归方法解决一笔连黑子游戏问题,包括将游戏图转换为列表,判断两点间的斜连,以及利用turtle库进行可视化展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        最近在抖音看到有意思的小游戏,如图:

        当然,这很简单。但我想的是用python来解决这个问题,且用最暴力的穷举法来解决。

思路如下:

  1.     先将上图转化为一个列表。黑点用1表示,白点用0表示。并一行一行的取黑点坐标。
    dots = [
        [1, 1, 1, 1],
        [1, 1, 0, 1],
        [0, 1, 1, 1],
        [1, 1, 1, 1],
        [0, 1, 1, 0]
    ]
    black_dots = []  # 黑点坐标列表
    for i in range(5):
        for j in range(4):
            point = dots[i][j]
            if point == 1:
                black_dots.append((i, j))
  2.  根据游戏规则,一笔连完所有黑子,不能连白子,不能斜连,其实就是当选定一个起点后,从这个起点的坐标来看,后一个黑子的位置就是只能是x坐标相差1或者y坐标相差1的黑子。即设起点坐标为(x_1,y_1),第二个黑子的坐标为(x_2,y_2),因此有:
    |x_1-x_2|=1,|y_1-y_2|=0;
    或者:
    |x_1-x_2|=0,|y_1-y_2|=1;
    后面第三个黑子又和第二个满足如上条件,一直到最后一颗黑子,表示全部黑子被一笔连完。
    # 先定义判断两坐标代表的黑子有没有斜连的函数
    def isdirect(_p1, _p2):
        _x = abs(_p1[0] - _p2[0])
        _y = abs(_p1[1] - _p2[1])
        if (_x == 1 and _y == 0) or (_x == 0 and _y == 1):
            return True
        else: 
            return False
    
    """
        1.根据规则,先从黑点里选一个当作起点.
        2.再在剩下的选第二个点,判断第一,第二个点是否满足要求。
        3.再在剩下里选第三个点,判断第二,第三个点是否满足要求。
        4.重复第二步和第三步,一直到最后一个。
    """
    """
    for d1 in black_dots:  # 选择起点
        ds1 = [_ for _ in black_dots if _ != d1]  # 去掉起点
        for d2 in ds1:  # 选择第二个点
            ds2 = [_ for _ in ds1 if _ != d2]  # 去掉第二个点
            if isdirect(d1, d2):  # 判断起点和第二个点是否斜连
                for d3 in ds2:  # 选择第三个点
                    ds3 = [_ for _ in ds2 if _ != d3]  # 去掉第三个点
                    if isdirect(d2, d3):  # 判断第二个点和第三个点是否斜连
                        ...  # 重复
    """
    
    
    # 通过观察发现,用递归函数的方法要更清晰一些。
    def link(_ds, _d, _r, *args):
        """
            _ds: 点列表。
            _d: 上一个点坐标。
            _r: 结果列表。
            args: _p的记录。
        """
        args = list(args)
        args.append(_d)
        for __d in _ds:
            __ds = [_ for _ in _ds if _ != __d]
            if isdirect(_d, __d):
                if __ds:
                    link(__ds, __d, _r, args)
                else:
                    args.append(__d)
                    _r.append(args)
            else:
                continue
        
    
    # 获取递归结果
    result = []
    for d1 in black_dots:
        ds1 = [_ for _ in black_dots if _ != d1]
        link(ds1, d1, result)
    for i in result:
        print(i)
    运行结果为:
    [[[[[[[[[[[[[[[(1, 3)], (0, 3)], (0, 2)], (0, 1)], (0, 0)], (1, 0)], (1, 1)], (2, 1)], (2, 2)], (2, 3)], (3, 3)], (3, 2)], (4, 2)], (4, 1)], (3, 1), (3, 0)]
    [[[[[[[[[[[[[[[(2, 2)], (2, 1)], (1, 1)], (1, 0)], (0, 0)], (0, 1)], (0, 2)], (0, 3)], (1, 3)], (2, 3)], (3, 3)], (3, 2)], (4, 2)], (4, 1)], (3, 1), (3, 0)]
    [[[[[[[[[[[[[[[(3, 0)], (3, 1)], (4, 1)], (4, 2)], (3, 2)], (2, 2)], (2, 1)], (1, 1)], (1, 0)], (0, 0)], (0, 1)], (0, 2)], (0, 3)], (1, 3)], (2, 3), (3, 3)]
    [[[[[[[[[[[[[[[(3, 0)], (3, 1)], (4, 1)], (4, 2)], (3, 2)], (3, 3)], (2, 3)], (1, 3)], (0, 3)], (0, 2)], (0, 1)], (0, 0)], (1, 0)], (1, 1)], (2, 1), (2, 2)]
    [[[[[[[[[[[[[[[(3, 0)], (3, 1)], (4, 1)], (4, 2)], (3, 2)], (3, 3)], (2, 3)], (2, 2)], (2, 1)], (1, 1)], (1, 0)], (0, 0)], (0, 1)], (0, 2)], (0, 3), (1, 3)]
    [[[[[[[[[[[[[[[(3, 3)], (2, 3)], (1, 3)], (0, 3)], (0, 2)], (0, 1)], (0, 0)], (1, 0)], (1, 1)], (2, 1)], (2, 2)], (3, 2)], (4, 2)], (4, 1)], (3, 1), (3, 0)]
    
  3. 发现结果是多维列表,因此对结果进行清理。
    # 对结果进行清理的函数
    def process(_r):
        _rs = []
        for _d in _r:
            if isinstance(_d, list):
                _rs += process(_d)
            else:
                _rs.append(_d)
        return _rs
    
    
    result = []
    for d1 in black_dots:
        ds1 = [_ for _ in black_dots if _ != d1]
        link(ds1, d1, result)
    for i in result:
        print(process(i))

    此时运行结果为:

[(1, 3), (0, 3), (0, 2), (0, 1), (0, 0), (1, 0), (1, 1), (2, 1), (2, 2), (2, 3), (3, 3), (3, 2), (4, 2), (4, 1), (3, 1), (3, 0)]
[(2, 2), (2, 1), (1, 1), (1, 0), (0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (3, 3), (3, 2), (4, 2), (4, 1), (3, 1), (3, 0)]
[(3, 0), (3, 1), (4, 1), (4, 2), (3, 2), (2, 2), (2, 1), (1, 1), (1, 0), (0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (3, 3)]
[(3, 0), (3, 1), (4, 1), (4, 2), (3, 2), (3, 3), (2, 3), (1, 3), (0, 3), (0, 2), (0, 1), (0, 0), (1, 0), (1, 1), (2, 1), (2, 2)]
[(3, 0), (3, 1), (4, 1), (4, 2), (3, 2), (3, 3), (2, 3), (2, 2), (2, 1), (1, 1), (1, 0), (0, 0), (0, 1), (0, 2), (0, 3), (1, 3)]
[(3, 3), (2, 3), (1, 3), (0, 3), (0, 2), (0, 1), (0, 0), (1, 0), (1, 1), (2, 1), (2, 2), (3, 2), (4, 2), (4, 1), (3, 1), (3, 0)]

到此,完成一笔连黑子的画法计算。现在利用turtle库来进行可视化。

import turtle as te


row = len(dots)  # 行
column = len(dots[0])  # 列
te.setup(1.0, 1.0)  # 画布大小
te.colormode(255)  # 颜色模式
te.bgcolor((245, 230, 205))  # 画布背景色
te.hideturtle()  # 隐藏箭头
dotSize = 20  # 点大小
penSize = 3  # 画笔大小
x_scale = 50  # x缩放比例
y_scale = 50  # y缩放比例
x_bias = -x_scale * column / 2  # x偏置
y_bias = row * y_scale / 2  # y偏置

dot0Color = (255, 255, 255)  # 白点
dot1Color = (0, 0, 0)  # 黑点
penColor = (255, 0, 0)  # 画笔颜色(红色)

for i in range(row):
    for j in range(column):
        x = x_scale * j + x_bias
        y = -y_scale * i + y_bias
        if dots[i][j] == 1:
            te.penup()
            te.setpos(x, y)
            te.pendown()
            te.dot(dotSize, dot1Color)
        elif dots[i][j] == 0:
            te.penup()
            te.setpos(x, y)
            te.pendown()
            te.dot(dotSize, dot0Color)

# 画出第一条路径
n = 0
x = result[n][0][1] * x_scale + x_bias
y = -result[n][0][0] * y_scale + y_bias
te.penup()
te.setpos(x, y)
te.pendown()
for p1 in result[n]:
    x = p1[1] * x_scale + x_bias
    y = -p1[0] * y_scale + y_bias
    te.pencolor(penColor)
    te.pensize(penSize)
    te.goto(x, y)
te.done()

绘图结果:

源代码:

 

import turtle as te

dots = [
    [1, 1, 1, 1],
    [1, 1, 0, 1],
    [0, 1, 1, 1],
    [1, 1, 1, 1],
    [0, 1, 1, 0]
]
black_dots = []  # 黑点坐标列表
for i in range(5):
    for j in range(4):
        point = dots[i][j]
        if point == 1:
            black_dots.append((i, j))


# 先定义判断两坐标代表的黑子有没有斜连的函数
def isdirect(_p1, _p2):
    _x = abs(_p1[0] - _p2[0])
    _y = abs(_p1[1] - _p2[1])
    if (_x == 1 and _y == 0) or (_x == 0 and _y == 1):
        return True
    else:
        return False


"""
    1.根据规则,先从黑点里选一个当作起点.
    2.再在剩下的选第二个点,判断第一,第二个点是否满足要求。
    3.再在剩下里选第三个点,判断第二,第三个点是否满足要求。
    4.重复第二步和第三步,一直到最后一个。
"""
"""
for d1 in black_dots:  # 选择起点
    ds1 = [_ for _ in black_dots if _ != d1]  # 去掉起点
    for d2 in ds1:  # 选择第二个点
        ds2 = [_ for _ in ds1 if _ != d2]  # 去掉第二个点
        if isdirect(d1, d2):  # 判断起点和第二个点是否斜连
            for d3 in ds2:  # 选择第三个点
                ds3 = [_ for _ in ds2 if _ != d3]  # 去掉第三个点
                if isdirect(d2, d3):  # 判断第二个点和第三个点是否斜连
                    ...  # 重复
"""


# 通过观察发现,用递归函数的方法要更清晰一些。
def link(_ds, _d, _r, *args):
    """
        _ds: 点列表。
        _d: 上一个点坐标。
        _r: 结果列表。
        args: _p的记录。
    """
    args = list(args)
    args.append(_d)
    for __d in _ds:
        __ds = [_ for _ in _ds if _ != __d]
        if isdirect(_d, __d):
            if __ds:
                link(__ds, __d, _r, args)
            else:
                args.append(__d)
                _r.append(args)
        else:
            continue


def process(_r):
    _rs = []
    for _d in _r:
        if isinstance(_d, list):
            _rs += process(_d)
        else:
            _rs.append(_d)
    return _rs


result = []
for d1 in black_dots:
    ds1 = [_ for _ in black_dots if _ != d1]
    link(ds1, d1, result)
for i in result:
    result = [process(r) for r in result]


row = len(dots)  # 行
column = len(dots[0])  # 列
te.setup(1.0, 1.0)  # 画布大小
te.colormode(255)  # 颜色模式
te.bgcolor((245, 230, 205))  # 画布背景色
te.hideturtle()  # 隐藏箭头
dotSize = 20  # 点大小
penSize = 3  # 画笔大小
x_scale = 50  # x缩放比例
y_scale = 50  # y缩放比例
x_bias = -x_scale * column / 2  # x偏置
y_bias = row * y_scale / 2  # y偏置

dot0Color = (255, 255, 255)  # 白点
dot1Color = (0, 0, 0)  # 黑点
penColor = (255, 0, 0)  # 画笔颜色(红色)
for i in range(row):
    for j in range(column):
        x = x_scale * j + x_bias
        y = -y_scale * i + y_bias
        if dots[i][j] == 1:
            te.penup()
            te.setpos(x, y)
            te.pendown()
            te.dot(dotSize, dot1Color)
        elif dots[i][j] == 0:
            te.penup()
            te.setpos(x, y)
            te.pendown()
            te.dot(dotSize, dot0Color)
# 画出第一条路径
n = 0
x = result[n][0][1] * x_scale + x_bias
y = -result[n][0][0] * y_scale + y_bias
te.penup()
te.setpos(x, y)
te.pendown()
for p1 in result[n]:
    x = p1[1] * x_scale + x_bias
    y = -p1[0] * y_scale + y_bias
    te.pencolor(penColor)
    te.pensize(penSize)
    te.goto(x, y)
te.done()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值