井字棋算法在大于 3x3 的棋盘中找到对角线

问题描述 投票:0回答:1

所以我用 python 开发了一个小型 Tic Tac Toe 游戏,它运行得非常好,我确实在这里讨论了它以某种方式改进它。然而,我有一个巧妙的想法,让棋盘变得更大,并且实现得很好 - 除了对角线只能在方形网格上完成并且只能直接穿过中间这一事实之外。然后我添加了一种让用户修改板尺寸的方法,效果很好。这就是路障之前的样子。

import os
base_columns = [chr(x+97) for x in range(26)]
base_rows = [x for x in range(26)]
blank_spot = "-"
player_tracker = 0
player_character = ('X', 'O')
num_wins = {p:0 for p in player_character}
win_type = "Draw"
choice = ("y", "n")
game_running = True

def create_coords(s):
    global coords, columns, rows
    try:
        y = s.index('x')
        rows = base_rows[:int(s[:y])]
        columns = base_columns[:int(s[y+1:])]
        coords = {c:[blank_spot]*len(rows) for c in columns}
    except (IndexError, ValueError):
        create_coords("3x3")
        
def info_checker(s):
    s = s.lower()
    if 'x' in s and len(s) >= 3 and s.count('x') == 1:
        y = s.index('x')
        if y > 0 and s[:y].isnumeric() and s[y+1:].isnumeric():
            return True
    return False
    
def info_input(q, e="Not viable info"):
    x = input(q)
    while not(info_checker(x)):
        print(e)
        x = input(q)
    else:
        create_coords(x.lower())

def intro():
    intro_text = ["Welcome to Tic Tac Toe", "The Goal is to get 3 characters in a row", "Player 1 is 'X'; Player 2 is 'O'","You play the game on a board that's a grid","You have to input coords to place your character", "To input the coord for you charcter (Ex: a0, b2, c1):", "- First, put the letter column you want", "- Second, then put the number row"]
    for text in intro_text:
        print(text, end="\n\n")
    y = choice_input("Want to change the board size (y/n)? ")
    if y == choice[0]:
        board_text = ["Format: (Y)x(Z); Y is rows, Z is columns", "Ex: 3x3, 2x2, 3x2", "Note: If you enter a # greater than 26\nProgram defaluts to 3x3", "You can change this at the end of games"]
        print("")
        for text in board_text:
            print(text, end="\n\n")
        info_input("Input info to change board: ")
    else:
        create_coords("3x3")
    print("")
    input("Press enter to start playing ")
    os.system('clear')

def print_board():
    print("     " + "   ".join([c for c in columns]), end="\n\n")
    rows_formatted = []
    for r in rows:
        row_elements = []
        for c in columns:
            row_elements.append(coords[c][r])
        space = " "*((len(str(r))%2)+1)
        rows_formatted.append(f"{r} {space} {' | '.join(row_elements)}\n")
    seperator = "   " + "----"*len(columns) + "-\n"
    print(seperator.join(rows_formatted))
   
def coord_checker(s):
    try:
        if len(s) == 2 and s[0].lower() in columns and int(s[1]) in rows:
            if coords[s[0].lower()][int(s[1])] == blank_spot:
                return True
            else:
                return False
    except ValueError:
        return False
        
def coord_input(q, e="Not a selectable coord"):
    print(f"It's Player {player_tracker+1}'s  turn ({player_character[player_tracker]})")
    x = input(q)
    while not(coord_checker(x)):
        print(e)
        x = input(q)
    return x
    
def choice_input(q, e=f"Not '{choice[0]}' or '{choice[1]}', expecting 1 of them"):
    x = input(q).lower()
    while not(x in choice):
        print(e)
        x = input(q).lower()
    return x

def place_tac(c):
    global player_tracker
    coords[c[0].lower()][int(c[1])] = player_character[player_tracker]
    player_tracker = (player_tracker+1)%2
    
def someone_won():
    global win_type
    for c in columns:
        if all([coords[c][r] == coords[c][rows[0]] != blank_spot for r in rows]):
            win_type = coords[c][rows[0]]
    for r in rows:
        if all([coords[c][r] == coords[columns[0]][r] != blank_spot for c in columns]):
            win_type = coords[columns[0]][r]
    if len(rows) == len(columns):
        length = len(rows)
        if all([coords[columns[i]][rows[i]] == coords[columns[0]][0] != blank_spot for i in range(length)]):
            win_type = coords[columns[0]][0]
        elif all([coords[columns[0+i]][rows[(length-1)-i]] == coords[columns[0]][length-1] != blank_spot for i in range(length)]):
            win_type = coords[columns[0]][length-1]
    if win_type != "Draw":
        return True
    return False
        
def who_won():
    if win_type == "Draw":
        print(f"It was a draw! {num_wins['X']}-{num_wins['O']}")
    else:
        num_wins[win_type] += 1
        print(f"{win_type} won! {num_wins['X']}-{num_wins['O']}")
    
def game():
    turn_tracker = 0
    while not(someone_won()) and turn_tracker < len(rows)*len(columns):
        print_board()
        c = coord_input("Choose a coord: ")
        place_tac(c)
        os.system('clear')
        turn_tracker += 1
    print_board()
    who_won()
    
def reset():
    global coords, player_tracker, win_type
    coords = {c:[blank_spot]*len(rows) for c in columns}
    if win_type != "Draw":
        player_tracker = (player_character.index(win_type)+1)%2
        win_type = "Draw"
    
def replay():
    global game_running
    x = choice_input("Do you want to keep playing (y/n)? ")
    if x == choice[0]:
        y = choice_input("Change the board size (y/n)? ")
        if y == choice[0]:
            info_input("Input info (Ex: 2x2, 3x3, 3x2) ")
        os.system('clear')
    else:
        print("Thanks for playing")
        game_running = False

intro()
while game_running:
    game()
    reset()
    replay()

然而,在实践中,更大的棋盘会让游戏更难玩,也更难获胜。特别是因为你必须在棋盘的长度或宽度上将字符排成一行。所以一位朋友建议我获胜的方法是连续有 3 个角色 - 除非棋盘小于 3x3。

我自己已经能够完成大部分工作

判断 3 个“tac”是否连续的函数(参数“tics”是布尔列表)

def tic_tac_toe(tics):
    toes = 0
    if len(coords[columns[0]]) >= 3:
        for t in tics:
            if t:
                toes += 1
        if toes >= 3:
            return True
    else:
        return all(tics)
    return False

还有 2 个函数来查找谁赢得了一列或一行胜利

def find_column_tics(c):
    count = 1
    previous = coords[c][rows[0]]
    for r in rows:
        current = coords[c][r]
        if current in player_character:
            if r != rows[0] and previous == current:
                count+=1
            else:
                count = 1
            previous = current
            if count >= 3:
                return current
    
def find_row_tacs(r):
    count = 1
    previous = coords[columns[0]][r]
    for c in columns:
        current = coords[c][r]
        if current in player_character:
            if c != columns[0] and previous == current:
                count+=1
            else:
                count = 1
            previous = current
            if count >= 3:
                return current

在“someone_won()”中,它们看起来都是这样的

def someone_won():
    global win_type
    # For finding a win in columns
    for c in columns:
        for r in rows:
            if tic_tac_toe([coords[c][i] == coords[c][r] != blank_spot for i in rows]):
                    win_type = find_column_tics(c)
    # For finding a win in rows
    for r in rows:
        for c in columns:
            if tic_tac_toe([coords[i][r] == coords[c][r] != blank_spot for i in columns]):
                    win_type = find_row_tacs(r)

这一切都非常有效,但后来我开始尝试解决对角线问题。在 4x4 棋盘中,有 8 种通过对角线取胜的方法,但不知道如何为此创建算法。我尝试了几种方法,但都不起作用。我想自己解决这个问题,但我认为没有经验,我想知道你们是否有任何想法或解决方案。在写这篇文章时,我已经尝试了 3 天找到一种方法来做到这一点,我真的希望这是可能的。

python python-3.x algorithm search tic-tac-toe
1个回答
0
投票

你可以尝试这样的事情:

def check_diagonals(board, color):
    # upper left to bottom right
    for i in range(len(board) - 2):
        for j in range(len(board[0]) - 2):
            if board[i][j] == color and board[i + 1][j + 1] == color and board[i + 2][j + 2] == color:
                return True
    
    # bottom left to top right
    for i in range(2, len(board)):
        for j in range(len(board[0]) - 2):
            print(i, j)
            if board[i][j] == color and board[i - 1][j + 1] == color and board[i - 2][j + 2] == color:
                return True
    
    return False


board = [
    "0001",
    "0010",
    "0100"
]

print(check_diagonals(board, "1"))  # True

因为实际上有两种方向相反的对角线,所以只需检查所有可能的对角线即可。

© www.soinside.com 2019 - 2024. All rights reserved.