为了账号安全,请及时绑定邮箱和手机立即绑定

使用列表在 Python 矩阵中查找对角线

使用列表在 Python 矩阵中查找对角线

POPMUISE 2021-08-24 18:15:16
我正在尝试编写游戏 connect-4,并且我尝试在 7x6 矩阵中查找代码的一部分,连续 4 个对角线或连续 4 个 2 的对角线。我的这部分代码不起作用,我尝试了我能做的一切。有时它会检测到有 4 个 1s 或 4 个 2s 的对角线而不是。我创建了矩阵,在 6 个零列表的每个位置放置了一个 7 个零列表。我正在尝试仅使用列表函数来执行此操作,我无法使用 numpy 库或类似库。好的,在这部分代码中,我试图找出矩阵的每个可能对角线中是否连续有 4 个零。PD:我只是想找到从左到右 ATM 的对角线。感谢您的帮助,我尽力解释我的问题,因为英语不是我的主要语言。这是我的代码:import randomllista = [0]*6 #when i say llista y mean matrixfor i in range(6):    llista[i]=[0]*7#Here i fill the 7*6 matrix of 0s 1s and 2s randomly so i can see if it works.for i in range(30):    x=random.randrange(-1,-7,-1)    y=random.randrange(0,7,1)    llista[x][y]=1for i in range(30):    x=random.randrange(-1,-7,-1)    y=random.randrange(0,7,1)    llista[x][y]=2#This 2 loops here are too see if it is possible to have a diagonal in the matrece because if you want a diagonal u need at least a one or 2 in the center, the problem is not here.for i in range(-1,-7,-1):    possible = False    if llista[i][3]==1:        possible = True        breakfor i in range(7):    possible2 = False    if llista[-4][i]==1 or llista[-4][i]==1:        possible2=True        breakif possible==True and possible2==True:#The problem starts here. This first loop i use it too find the diagonals that go from left to right. I want to find diagonals of 4 1s or 4 2s.for i in range(len(llista)-3):    for j in range(len(llista[i])-3):        #This if is too see if we have four 1 or 2 togheter in the list, if we have them it prints the sentence below.        if (llista[i][j]==1 and llista[i+1][j+1]==1 and llista[i+2][j+2]==1 and llista[i+3][j+3]==1)  or (llista[i][j]==2 and llista[i+1][j+1]==2 and llista[i+2][j+2]==2 and llista[i+3][j+3]==2 ):            print("There is at least one left to right diagonal")或从右到左对角线。#我不想使用尚未使用的函数,也不想以其他方式使用,因为我必须以这种方式理解。谢谢
查看完整描述

3 回答

?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

如果您考虑“从右到左”循环的逻辑,您实际上只是以相反的顺序执行与“从左到右”循环相同的操作。要真正获得“从右到左”的正确传递,您必须让索引i和j索引向不同的方向移动。


因此,您在本节中的条件语句应如下所示:


if i-3>=0 and j+3<7:

    if (llista[i][j]==1 and llista[i-1][j+1]==1 and llista[i-2][j+2]==1 and llista[i-3][j+3]==1)  or (llista[i][j]==2 and llista[i-1][j+1]==2 and llista[i-2][j+2]==2 and llista[i-3][j+3]==2 ):

        print("There is at least one right to left diagonal")

您可以通过导入像AResem 所示numpy或itertools像 AResem 所示的库来进行大量优化。由于以下原因,该答案并不完全正确。


当你说return True, k你没有对 的值进行任何控制时,k因为它在上面的列表理解中使用过,并且只会拥有它迭代的最后一个项目的值。因此,当您的函数找到对角线时,大约三分之二的时间会报告错误的数字。


这是一个经过编辑的函数,可以给出正确的结果:


def check_diagonals(matrix):

    for offset in range(-2, 4):

        diag = matrix.diagonal(offset=offset)


        # Here you can create a tuple of numbers with the number of times they are repeated. 

        # This allows you to keep your k and g values associated.

        repeat_groups = [(k, sum(1 for _ in g)) for k, g in  groupby(diag)]


        # By using the built-in max function with the 'key' keyword, you can find 

        # the maximum number of repeats and return the number associated with that.

        num, max_repeats = max(repeat_groups, key=lambda item: item[1])

        if max_repeats >= 4:

            return True, num

    return False, None

如果您在print添加语句的情况下运行此函数,您可以获得如下输出:


Matrix: 

[[1 0 2 2 1 0 1]

 [0 2 0 2 1 1 1]

 [2 2 0 0 0 0 1]

 [0 0 2 2 0 2 2]

 [2 1 1 1 1 1 0]

 [2 2 0 2 1 0 2]]


offset -2

diag [2 0 1 2]

repeat_groups [(2, 1), (0, 1), (1, 1), (2, 1)]

num, max_repeats 2 1


offset -1

diag [0 2 2 1 1]

repeat_groups [(0, 1), (2, 2), (1, 2)]

num, max_repeats 2 2


offset 0

diag [1 2 0 2 1 0]

repeat_groups [(1, 1), (2, 1), (0, 1), (2, 1), (1, 1), (0, 1)]

num, max_repeats 1 1


offset 1

diag [0 0 0 0 1 2]

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

num, max_repeats 0 4

(True, 0)

There is at least one left to right diagonal: 0's' # Correct!

如果你想忽略零的对角线,你可以很容易地添加一个额外的条件,例如


if max_repeats >= 4 and num != 0:

    return True, num

如果您愿意,您可以尝试重新创建它而不使用numpy它。


查看完整回答
反对 回复 2021-08-24
?
森栏

TA贡献1810条经验 获得超5个赞

你可以考虑使用 numpy 来解决这个问题。这里有一些代码可以帮助您入门。


import numpy as np

from itertools import groupby


def check_diagonals(matrix):

    for offset in range(-2, 4):

        diag = matrix.diagonal(offset=offset)

        if max([sum(1 for _ in g) for k, g in  groupby(diag)]) >= 4:

            return True, k

    return False, None


# random test matrix

matrix = np.random.randint(0, 3, 6 * 7)

matrix = matrix.reshape(6,7)


# left to right check

resp_tuple = check_diagonals(matrix)

if resp_tuple[0]:

    print("There is at least one left to right diagonal: {}'s'".format(resp_tuple[1]))

else:

    # right to left

    resp_tuple = check_diagonals(np.fliplr(matrix))

    if resp_tuple[0]:

        print("There is at least one right to left diagonal:     {}'s'".format(resp_tuple[1]))

    else:

        # No diagonals

        print('No diagonals')


查看完整回答
反对 回复 2021-08-24
?
冉冉说

TA贡献1877条经验 获得超1个赞

也许由于您解析条件语句的方式,您没有得到正确的答案。你应该有

if cond1 or cond2:
    # do something

括号中包含的条件()。目前只有您的第二个条件包含在括号中。请尝试以下操作:

if (matrix[i][j]==1 and matrix[i+1][j+1]==1 and matrix[i+2][j+2]==1 and matrix[i+3][j+3]==1)  or (matrix[i][j]==2 and matrix[i+1][j+1]==2 and matrix[i+2][j+2]==2 and matrix[i+3][j+3]==2 ):
    print("There is at least one left to right diagonal")


查看完整回答
反对 回复 2021-08-24
  • 3 回答
  • 0 关注
  • 249 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信