查找具有相同值的网格中的相邻像元。如何改善此功能的想法? [英] Finding neighbor cells in a grid with the same value. Ideas how to improve this function?

查看:92
本文介绍了查找具有相同值的网格中的相邻像元。如何改善此功能的想法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Python的新手(学习了1个月多一点),然后尝试创建Tic Tac Toe。但是,一旦完成,我决定将板子扩展(从3x3扩展到9x9,具体取决于客户的输入),并通过在板子的任何位置连续,以列或对角线连接4个来赢得胜利。



因此,我需要一个功能,该功能可以根据客户的输入在板子的各个方向上搜索,而不必落水,而是搜索3个具有相同标记的连接单元。



然后我意识到实际上我需要同时从标记的两个相反的方向进行检查,因为当前放置的标记可能会连接同一标记的其他组并以此来获胜。

下面您可以找到我对上述获胜条件的解决方案,该方案正在起作用,但是它看起来并不漂亮,因为循环有很多重复的几乎相同的内容。但是我不知道如何将它们组合在一起。



有8个循环(因为有8个方向),分为4组相反的方向,每个循环检查是否下一个单元格具有与客户当前放置的单元格相同的值(标记)( O或 X)。如果是,则将计数变量加1。否则,循环中断。然后,我要检查两个相反方向的循环是否成功使count ==4。如果是,则有赢家。如果不是,请转到下一对。



我相信应该更容易维护代码,但我想不到。



谢谢您的帮助!



PS如果有需要,我将从我的代码中发布更多信息

  def do_we_have_a_winner(位置,current_mark):
全球game_board
connect = 4
#打开当前位置的坐标
x,y =坐标[位置]

长度= len(game_board)

count = 0

对于i在范围(0,连接):
如果(xi在范围(0,长度))和(y + i在范围(0,长度) ):
如果game_board [xi] [y + i]!= current_mark:
打破
否则:
count + = 1

for i in范围(1,连接):
如果(x + i在范围(0,长度))和(yi在范围(0,长度)):
如果game_board [x + i] [yi] != current_mark:
中断
其他:
计数+ = 1

如果count == connect:
打印(我们有赢家! )
返回真

count = 0

for in in r ange(0,connect):
如果(x + i在范围(0,长度))和(y + i范围在(0,长度)):
如果game_board [x + i] [ y + i]!= current_mark:
中断
否则:
count + = 1

for i在范围(1,连接):
如果(xi in range(0,length))和(yi in range(0,length)):
如果game_board [xi] [yi]!= current_mark:
打破
否则:
count + = 1

如果count == connect:
print(我们有赢家!)
返回True

count = 0对于i in range(0,connect):
if(y + i in range(0,length)):
if game_board [x] [y + i]!= current_mark:
中断
其他:
计数+ = 1

for i在范围(1,连接):
if(yi范围(0,长度)):
如果game_board [x] [yi]!= current_mark:
打破
否则:
计数+ = 1

如果计数==连接:
print(我们有赢家!)
返回True

计数= 0

对于范围内的i(0,连接):
如果(范围内的x + i(0,长度)):
如果game_board [x + i] [y]!= current_mark:
break
else:
count + = 1

for i在范围内(1,连接) :
if(xi in range(0,length)):
if game_board [xi] [y]!= current_mark:
break
else:
count + = 1

如果计数==连接:
print(我们有赢家!)
返回True

return False


解决方案

这是一种涉及较少复制和粘贴的方法-希望它能为您提供关于如何将事物分解为最少数量的最可重复使用的碎片的一些想法看起来:)



这里的总体思路是提出一种表达方式,即以一种可以跨不同方向扫描一条线的概念,表示方向,然后不管方向是什么,都让相同的代码块处理扫描。

 通过输入import List,可选,元组


def do_we_have_a_winner(board:List [List [Optional [str]]],长度:int)->可选[str]:
返回给定长度的玩家的标记。
width = range(len(board))
height = range(len(board [0]))
#进行四次全面扫描-右,下和对角线。 dx,dy in [(0,1),(1,0),(1,1),(1,-1)]的

edges:List [Tuple [int,int] ] = []
(如果dx> 0:
#向右扫描,从左边缘开始
边缘+ = [(0,y)for y y]
如果dy> 0:
#向下扫描,从顶部边缘
边缘开始+ = [(x,0)for width in x]如果dy<
0:
#向上扫描,从底部边缘
边缘开始+ = [(x,height [-1])表示x的宽度]
表示ex,ey的边缘:
标记:可选[str] =无
行= 0
x,y = ex,ey
而x的宽度和y的高度:
如果board [x] [y ] ==标记:
行+ = 1
否则:
标记= board [x] [y]
行= 1
(如果标记不是None且行) > =长度:
返回标记
x,y = x + dx,y + dy
返回None


print(do_we_have_a_winner([
['X','O','O'],
['O','X','O'],
['O','O','X' ],
],3))#X

请注意,此函数最多假设一个获胜者,因此,如果有多个获胜者,它将只返回其中一位-我将其留作练习,供读者理解如何更改它以更好地处理这种情况。 :)


I am new to Python (learning it for a little over 1 month) and I tried creating Tic Tac Toe. However once I finished it, I decide to expand the board (from 3x3 to 9x9 depending from the customer input) and allow a win by connecting 4 in a row, column or diagonal anywhere in the board.

Therefore I needed a function that search - depending from the customer input - in every directions on the board, without going overboard, for 3 connected cells with the same mark.

Then I realize that actually I need to check simultaneously in both opposite direction from the mark, as there is a possibility that the currently placed mark can connect other groups of the same mark and winning by doing this.

Below you can find my solution of the above winning condition, which is working, however it does not look pretty as there is a lot of repetitive almost identical for loops. But I have zero clue how to combine them.

There are 8 loops (as there are 8 directions), in 4 groups of opposite directions, and each loop check if the next cell is with the same value (mark) as the one that is currently placed by the customer (either 'O' or 'X').If it is the count variable is increased by 1. If not - the loop breaks. Then I am checking if the two opposite direction loops managed to made count == 4. If yes - we have a winner. If not - we go to the next pair.

I am sure there should be easier to maintain code, but I am not able to think of any.

Thank you for your help!

P.S. if there is a need I will post more from my code

def do_we_have_a_winner(position, current_mark):
    global game_board
    connect = 4
    # unpacking the coordinates of the current position
    x, y = coordinates[position]

    length = len(game_board)

    count = 0

    for i in range(0, connect):
        if (x-i in range(0, length)) and (y+i in range(0, length)):
            if game_board[x-i][y+i] != current_mark:
                break
            else:
                count += 1

    for i in range(1, connect):
        if (x+i in range(0, length)) and (y-i in range(0, length)):
            if game_board[x+i][y-i] != current_mark:
                break
            else:
                count += 1

    if count == connect:
        print("We have a winner!")
        return True

    count = 0

    for i in range(0, connect):
        if (x+i in range(0, length)) and (y+i in range(0, length)):
            if game_board[x+i][y+i] != current_mark:
                break
            else:
                count += 1

    for i in range(1, connect):
        if (x-i in range(0, length)) and (y-i in range(0, length)):
            if game_board[x-i][y-i] != current_mark:
                break
            else:
                count += 1

    if count == connect:
        print("We have a winner!")
        return True

    count = 0

    for i in range(0, connect):
        if (y+i in range(0, length)):
            if game_board[x][y+i] != current_mark:
                break
            else:
                count += 1

    for i in range(1, connect):
        if (y-i in range(0, length)):
            if game_board[x][y-i] != current_mark:
                break
            else:
                count += 1

    if count == connect:
        print("We have a winner!")
        return True

    count = 0

    for i in range(0, connect):
        if (x+i in range(0, length)):
            if game_board[x+i][y] != current_mark:
                break
            else:
                count += 1

    for i in range(1, connect):
        if (x-i in range(0, length)):
            if game_board[x-i][y] != current_mark:
                break
            else:
                count += 1

    if count == connect:
        print("We have a winner!")
        return True

    return False

解决方案

Here's an approach that involves less copying and pasting -- hopefully it gives you some idea of how to break things down into the smallest number of the most reusable pieces possible. :)

The general idea here is to come up with a way of expressing the concept of scanning a line across the board in different directions in such a way that you can just express the direction and then let the same block of code handle the scan regardless of what the direction is.

from typing import List, Optional, Tuple


def do_we_have_a_winner(board: List[List[Optional[str]]], length: int) -> Optional[str]:
    """Returns the 'mark' of the player with a row of the given length."""
    width = range(len(board))
    height = range(len(board[0]))
    # Do four scans across the board -- right, down, and diagonals.
    for dx, dy in [(0, 1), (1, 0), (1, 1), (1, -1)]:
        edges: List[Tuple[int, int]] = []
        if dx > 0:
            # scanning right, start from left edge
            edges += [(0, y) for y in height]
        if dy > 0:
            # scanning down, start from top edge
            edges += [(x, 0) for x in width]
        if dy < 0:
            # scanning up, start from bottom edge
            edges += [(x, height[-1]) for x in width]
        for ex, ey in edges:
            mark: Optional[str] = None
            row = 0
            x, y = ex, ey
            while x in width and y in height:
                if board[x][y] == mark:
                    row += 1
                else:
                    mark = board[x][y]
                    row = 1
                if mark is not None and row >= length:
                    return mark
                x, y = x + dx, y + dy
    return None


print(do_we_have_a_winner([
    ['X', 'O', 'O'],
    ['O', 'X', 'O'],
    ['O', 'O', 'X'],
], 3))  # X

Note that this function assumes one at most winner, so if there are multiple winners, it will only return one of them -- I'll leave it as an exercise for the reader to figure out how to change it to handle that situation better. :)

这篇关于查找具有相同值的网格中的相邻像元。如何改善此功能的想法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆