首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >变板尺寸的Tic-Tac-脚趾(第2部分)

变板尺寸的Tic-Tac-脚趾(第2部分)
EN

Code Review用户
提问于 2019-11-20 11:44:16
回答 1查看 563关注 0票数 2

第一部分:变板尺寸的Tic-Tac-脚趾(第1部分)

我只是重温了我以前的所有问题,发现我没有更新我的Tac脚趾代码。所以,我根据奥斯汀·黑斯廷斯的建议临时编写了我的代码

以下是更新的代码:

代码语言:javascript
复制
import os
from random import randint
from textwrap import dedent

cls = lambda: os.system('CLS')  # Works only in command console.

# Random names
names = [
    'Jacob', 'Michael',
    'Joshua', 'Ethan', 'Matthew', 'Daniel',
    'Christopher', 'Andrew', 'Anthony', 'William',
    'Joseph', 'Alexander', 'David', 'Ryan',
    'Noah', 'James', 'Nicholas', 'Tyler',
    'Logan', 'John', 'Christian', 'Jonathan',
    'Nathan', 'Benjamin', 'Samuel', 'Dylan',
    'Brandon', 'Gabriel', 'Elijah', 'Aiden',
    'Angel', 'Jose', 'Zachary', 'Caleb',
    'Jack', 'Jackson', 'Kevin', 'Gavin',
    'Mason', 'Isaiah', 'Austin', 'Evan',
    'Luke', 'Aidan', 'Justin', 'Jordan',
    'Robert', 'Isaac', 'Landon', 'Jayden',
    'Thomas', 'Cameron', 'Connor', 'Hunter',
    'Jason', 'Diego', 'Aaron', 'Bryan',
    'Owen', 'Lucas', 'Charles', 'Juan',
    'Luis', 'Adrian', 'Adam', 'Julian',
    'Alex', 'Sean', 'Nathaniel', 'Carlos',
    'Jeremiah', 'Brian', 'Hayden', 'Jesus',
    'Carter', 'Sebastian', 'Eric', 'Xavier',
    'Brayden', 'Kyle', 'Ian', 'Wyatt',
    'Chase', 'Cole', 'Dominic', 'Tristan',
    'Carson', 'Jaden', 'Miguel', 'Steven',
    'Caden', 'Kaden', 'Antonio', 'Timothy',
    'Henry', 'Alejandro', 'Blake', 'Liam',
    'Richard', 'Devin', 'Riley', 'Jesse',
    'Seth', 'Victor', 'Brady', 'Cody',
    'Jake', 'Vincent', 'Bryce', 'Patrick',
    'Colin', 'Marcus', 'Cooper', 'Preston',
    'Kaleb', 'Parker', 'Josiah', 'Oscar',
    'Ayden', 'Jorge', 'Ashton', 'Alan',
    'Jeremy', 'Joel', 'Trevor', 'Eduardo',
    'Ivan', 'Kenneth', 'Mark', 'Alexis',
    'Omar', 'Cristian', 'Colton', 'Paul',
    'Levi', 'Damian', 'Jared', 'Garrett',
    'Eli', 'Nicolas', 'Braden', 'Tanner',
    'Edward', 'Conner', 'Nolan', 'Giovanni',
    'Brody', 'Micah', 'Maxwell', 'Malachi',
    'Fernando', 'Ricardo', 'George', 'Peyton',
    'Grant', 'Gage', 'Francisco', 'Edwin',
    'Derek', 'Max', 'Andres', 'Javier',
    'Travis', 'Manuel', 'Stephen', 'Emmanuel',
    'Peter', 'Cesar', 'Shawn', 'Jonah',
    'Edgar', 'Dakota', 'Oliver', 'Erick',
    'Hector', 'Bryson', 'Johnathan', 'Mario',
    'Shane', 'Jeffrey', 'Collin', 'Spencer',
    'Abraham', 'Leonardo', 'Brendan', 'Elias',
    'Jace', 'Bradley', 'Erik', 'Wesley',
    'Jaylen', 'Trenton', 'Josue', 'Raymond',
    'Sergio', 'Damien', 'Devon', 'Donovan',
    'Dalton', 'Martin', 'Landen', 'Miles',
    'Israel', 'Andy', 'Drew', 'Marco',
    'Andre', 'Gregory', 'Roman', 'Ty',
    'Jaxon', 'Avery', 'Cayden', 'Jaiden',
    'Roberto', 'Dominick', 'Rafael', 'Grayson',
    'Pedro', 'Calvin', 'Camden', 'Taylor',
    'Dillon', 'Braxton', 'Keegan', 'Clayton',
    'Ruben', 'Jalen', 'Troy', 'Kayden',
    'Santiago', 'Harrison', 'Dawson', 'Corey',
    'Maddox', 'Leo', 'Johnny', 'Kai',
    'Drake', 'Julio', 'Lukas', 'Kaiden',
    'Zane', 'Aden', 'Frank', 'Simon',
    'Sawyer', 'Marcos', 'Hudson', 'Trey'
]

# Dummy Variable
start = 0

# Essential Variables:
player = 'Player'  # Player name
board_type = 2  # Board Type (1 or 2)

board = [['', '', ''], ['', '', ''], ['', '', '']]  # The TicTacToe board
win_board = [['', '', ''], ['', '', ''], ['', '', '']]  # Traces the win (if any) of 'board'

X = 'X'
O = 'O'

size = 3


def empty_cells():
    empty = []

    for i in range(size):
        for j in range(size):
            if board[i][j] != X and board[i][j] != O:
                empty.append((i, j))

    return empty


def countWins(p):
    """

    Counts the wins possible in the current move for player 'p'

    """

    count = 0

    empty = empty_cells()

    for i, j in empty:
        copy = board[i][j]
        board[i][j] = p

        count += win(p)

        board[i][j] = copy

    return count


def get_insane_AI_move(ai, pl, x=0, name=''):
    """

    ai: ai character
    pl: player character
    x: dummy variable
    name: ai name

    The best AI

    Follows all the tips and checks for moves leading to multiple wins constantly

    """

    empty = empty_cells()
    length = len(empty)

    if length == 1:
        i, j = empty[0]

        if x:
            print(name + ' Moved To Grid', i * size + j + 1)
            return

    for i, j in empty:
        copy = board[i][j]
        board[i][j] = ai

        if win(ai):
            if x:
                print(name + ' Moved To Grid', i * size + j + 1)
            return

        board[i][j] = copy

    for i, j in empty:
        copy = board[i][j]
        board[i][j] = pl

        if win(pl) or length == 1:
            board[i][j] = ai

            if x:
                print(name + ' Moved To Grid', i * size + j + 1)
            return

        board[i][j] = copy

    wins2 = []
    l = 0

    for i, j in empty:
        copy = board[i][j]
        board[i][j] = ai

        if countWins(ai) > 1:
            l += 1
            r = [i, j]
            wins2.append(r)

        board[i][j] = copy

    if l:
        m = wins2[randint(0, 1000) % l]
        board[m[0]][m[1]] = ai

        if x:
            print(name + ' Moved To Grid', m[0] * size + m[1] + 1)
        return

    l = 0

    pos_centers = [[i, j] for i in range(size) for j in range(size)
                   if (i in [0, size - 1]) == (j in [0, size - 1]) == False]

    centers = []

    for i in range(len(pos_centers)):
        x = pos_centers[i][0]
        y = pos_centers[i][1]

        if board[x][y] != ai and board[x][y] != pl:
            centers.append(pos_centers[i])
            l += 1

    if l:
        r = centers[randint(1, 1000) % l]
        board[r[0]][r[1]] = ai

        if x:
            print(name + ' Moved To Grid', r[0] * size + r[1] + 1)

        return

    l1 = l2 = 0

    pos_edges = [[0, 0], [0, size - 1], [size - 1, 0], [size - 1, size - 1]]
    edges = []

    for i in range(len(pos_edges)):
        x = pos_edges[i][0]
        y = pos_edges[i][1]

        if board[x][y] != ai and board[x][y] != pl:
            edges.append(pos_edges[i])
            l1 += 1

    if l1:
        r = edges[randint(1, 1000) % l1]
        board[r[0]][r[1]] = ai

        if x:
            print(name + ' Moved To Grid', r[0] * size + r[1] + 1)

        return

    pos_middles = [[i, j] for i in range(size) for j in range(size)
                   if (i in [0, size - 1]) != (j in [0, size - 1])]

    middles = []

    for i in range(len(pos_middles)):
        x = pos_middles[i][0]
        y = pos_middles[i][1]

        if board[x][y] != ai and board[x][y] != pl:
            middles.append(pos_middles[i])
            l2 += 1

    r = middles[randint(1, 1000) % l2]
    board[r[0]][r[1]] = ai

    if x:
        print(name + ' Moved To Grid', r[0] * size + r[1] + 1)

    return


def get_hard_AI_move(ai, pl, x=0, name=''):
    """

    A medium AI

    Can only look ahead 1 move

    """

    empty = empty_cells()
    length = len(empty)

    if length == 1:
        i, j = empty[0]

        if x:
            print(name + ' Moved To Grid', i * size + j + 1)
            return

    for i, j in empty:
        copy = board[i][j]
        board[i][j] = ai

        if win(ai) == 1:
            if x:
                print(name + ' Moved To Grid', i * size + j + 1)
            return

        board[i][j] = copy

    for i, j in empty:
        copy = board[i][j]
        board[i][j] = pl

        if win(pl) == 1:
            board[i][j] = ai

            if x:
                print(name + ' Moved To Grid', i * size + j + 1)

            return

        board[i][j] = copy

    l = 0

    possible = [[i, j] for i in range(size) for j in range(size)]

    available = []

    for i in range(len(possible)):
        x = possible[i][0]
        y = possible[i][1]

        if board[x][y] != ai and board[x][y] != pl:
            available.append(possible[i])
            l += 1

    r = available[randint(1, 1000) % l]

    board[r[0]][r[1]] = ai

    if x:
        print(name + ' Moved To Grid', r[0] * size + r[1] + 1)

    return


def get_easy_AI_move(ai, pl, x=0, name=''):
    """

    An easy AI

    Moves randomly

    """

    l = 0

    available = []

    for x, y in empty_cells():
        if board[x][y] != ai and board[x][y] != pl:
            available.append((x, y))
            l += 1

    r = available[randint(1, 1000) % l]
    board[r[0]][r[1]] = ai

    if x:
        print(name + ' Moved To Grid', r[0] * size + r[1] + 1)

    return


def get_user_move(p1, p2):
    """ Gets user input and processes it """

    g = int(input(f'Please Enter Grid Number (1 ~ {size * size}): ')) - 1

    x = g // size
    y = g % size

    if x >= size or y >= size or board[x][y] == p1 or board[x][y] == p2:
        print('Please Enter A Valid Move')
        get_user_move(p1, p2)
        return

    print(player + ' Moved To Grid', g + 1)

    board[x][y] = p1
    print()


def get_win(p):
    """ Traces the win into 'win_board' """

    for i in range(size):
        # Rows
        if all(board[i][j] == p for j in range(size)):
            for j in range(size):
                win_board[i][j] = p
            return

        # Columns
        if all(board[j][i] == p for j in range(size)):
            for j in range(size):
                win_board[j][i] = p
            return

    # Diagonals
    if all(board[i][i] == p for i in range(size)):
        for i in range(size):
            win_board[i][i] = p

        return

    if all(board[i][-(i + 1)] == p for i in range(size)):
        for i in range(size):
            win_board[i][-(i + 1)] = p

        return

    ## Returns in every case as multiple wins might be traced out


def printBoard1():
    """ Prints board type 1 """

    for i in range(size - 1):
        print('      ' + '|       ' * (size - 1))
        print(end='  ')

        for j in range(size - 1):
            print(board[i][j], end='   |   ')

        print(board[i][-1])
        print('      ' + '|       ' * (size - 1))
        print('------' + '--------' * (size - 1))
        '      |       '

    print('      ' + '|       ' * (size - 1))
    print(end='  ')

    for j in range(size - 1):
        print(board[-1][j], end='   |   ')

    print(board[-1][-1])
    print('      ' + '|       ' * (size - 1))

    print()


def printBoard2():
    """ Prints board type 2 """

    for i in range(size - 1):
        for j in range(size - 1):
            print(board[i][j], end=' | ')
        print(board[i][-1])
        print('---' * size + '-' * (size - 3))

    for j in range(size - 1):
        print(board[-1][j], end=' | ')

    print(board[-1][-1])
    print()


def printWin(p):
    """ Prints 'win_board' at board type 2"""

    get_win(p)

    for i in range(size - 1):
        for j in range(size - 1):
            print(win_board[i][j], end=' | ')
        print(win_board[i][-1])
        print('---' * size + '-' * (size - 2))

    for j in range(size - 1):
        print(win_board[-1][j], end=' | ')

    print(win_board[-1][-1])
    print()


def getRandomName():
    """ Gets random names from 'names' """

    name = names[randint(1, 1000) % 250]
    return name


def helper():
    """ Help section containing Rules, Tips and Credits """

    print()

    print('B for Back\n')
    print('1. Rules')
    print('2. Tips')
    print('3. Credits')

    option = input('\nPlease Enter Your Option: ').lower()
    print()

    if option == 'b': return
    if option == '1': rules()
    if option == '2': tips()
    if option == '3': about()

    input('Enter To Continue . . . ')
    print()
    helper()


def about():
    print('This Game Of Tic-Tac-Toe Is Created By Srivaths')
    print('If You Are Unfamiliar With This Game, Please Read The Rules And Tips')
    print('Enjoy!!\n')


def changeName():
    """ Changes player name: 'player' """

    global player
    player = input('Please Enter Your Name: ')


def changeBoard():
    """ Changes board type: 'board_type' """

    global board_type

    print()
    print('B for Back\n')
    print('1.')
    printBoard1()
    print('2.\n')
    printBoard2()

    print()

    option = input('\nPlease Enter Your Option: ')

    if option == 'b' or option == 'B':
        return

    if option == '1': board_type = 1
    if option == '2': board_type = 2


def changeCharacters():
    """ Changes characters: 'X', 'O' """

    global X, O

    print()
    X = input('Please Enter Character For Player 1 (currently ' + X + '): ')
    O = input('Please Enter Character For Player 2 (currently ' + O + '): ')


def changeSize():
    """ Changes board size: 'size' """

    global size
    size = int(input('Please Enter Size: '))
    initialize()


def settings():
    """ Settings """

    print()

    print('B for Back\n')
    print('1. Change Name')
    print('2. Change Size')
    print('3. Change Board')
    print('4. Change Characters')
    option = input('\nPlease Enter Your Option: ').lower()

    if option == 'b':
        return

    if option == '1': changeName()
    if option == '2': changeSize()
    if option == '3': changeBoard()
    if option == '4': changeCharacters()

    print()
    settings()


def main_menu():
    """ The main menu """

    global start

    # cls()
    print()

    if start == 0:
        intro()
        start = 1
        main_menu()
        return

    print('Hello ' + player)

    print('\nQ for Quit\n')
    print('1. Help')
    print('2. Settings')
    print('3. Play')
    option = input('\nPlease Enter Your Option: ')

    if option == '1':
        helper()

    if option == '2':
        settings()

    if option == '3':
        initialize()
        play('X', 'O')

    if option == 'q' or option == 'Q':
        print('Thanks For Playing!\n')
        return

    print()
    main_menu()


def rules():
    """ Basic rules """

    print(
        dedent('''
            1. In Tic-Tac-Toe, there are 2 players and their characters are X and O respectively
            2. Any row or column or diagonal filled the same character is a win
            3. A board where there are no moves left is a tie
            4. You are not allowed to place characters over another
            5. The playes must play in alternate turns, starting with X
        ''')
    )


def tips():
    """ Basic tips """

    print(
        dedent(
            '''
                1. Always try and capture the center
                2. Next try to capture the edges
                3. Occupy the edges only if necessary
                4. Be aware of immediate moves
                5. Try the easy bot to get the hang of the game
            '''
        )
    )


def intro():
    """ Introduction """

    global board_type

    initialize()

    print('Hello Player', end=', ')

    changeName()

    print('\nHello ' + player + ', Welcome To The Game Of Tic-Tac-Toe!!')

    know = input('Are You Familiar With The Game? (y / n): ').lower()

    if know == 'n':
        print('\nFirst A Little Introduction To The Rules: \n')
        rules()
        print('\nNext A Few Tips: \n')
        tips()
        print('\nAnd That\'s ALL!!!\n')
        input('Enter To Continue . . . ')
        print('\n')

    print('\nPlease Pick Your Board Preference: \n')

    print('1.')
    printBoard1()
    print('2.\n')
    printBoard2()

    print()

    option = input('Please Enter Your Option: ')

    if option == '1': board_type = 1
    if option == '2': board_type = 2

    print(
        dedent('''
            Change Characters Via [Main Menu -> Settings -> Change Characters]

            Here You Must Try Your Luck Against Three Levels!!

            1. Easy
            2. Hard
            3. Insane

            Can YOU Beat Them ALL????
            Let's See....
        ''')
    )

    input('Enter To Continue . . . ')


def play(p1, p2):
    """

    The play area

    p1: Player 1
    p2: Player 2

    """

    print()
    initialize()

    computer = getRandomName()

    print('1. Easy')
    print('2. Hard')
    print('3. Insane')

    print()

    level = int(input('Please Enter Level: '))

    print()

    while computer == player:
        computer = getRandomName()

    print('\t\t' + player + ' VS ' + computer + '\n\n')

    c = randint(0, 1)

    pl = p1
    ai = p2

    if c == 0:
        ai = p1
        pl = p2

        print('\n' + computer + ' Goes First!\n\n')

    else:
        print('\n' + player + ' Goes First!\n\n')
        if board_type == 1:
            printBoard1()
        else:
            printBoard2()

    d = 0

    while True:
        t = d % 2

        if t == c:
            if level == 1: get_easy_AI_move(ai, pl, 1, computer)
            if level == 2: get_hard_AI_move(ai, pl, 1, computer)
            if level == 3: get_insane_AI_move(ai, pl, 1, computer)

            if board_type == 1:
                printBoard1()
            else:
                printBoard2()

            if win(ai):
                print(computer + ' Wins!\n')
                print('Below Is How ' + computer + ' Won\n\n')
                printWin(ai)
                break

        else:
            get_user_move(pl, ai)

            if board_type == 1:
                printBoard1()
            else:
                printBoard2()

            if win(pl):
                print(player + ' Wins!')
                print('Below Is How ' + player + ' Won\n')
                printWin(pl)
                break

        if len(empty_cells()) == 0:
            print('Tie!')
            break

        d += 1

    play_again(p1, p2)


def initialize():
    """ Resets the board """

    global board, win_board

    board = [[' ' for _ in range(size)] for __ in range(size)]
    win_board = [[' ' for _ in range(size)] for __ in range(size)]


def play_again(p1, p2):
    """ Gets input from the player asking if they want to play again """

    option = input('Would You Like To Play Again? (y(yes) / n(no) / m(Main Menu): ').lower()

    if option == 'y':
        play(p1, p2)
    elif option == 'n':
        return
    elif option == 'm':
        return
    else:
        print('\nPlease Enter a Valid Option')
        play_again(p1, p2)


def win(p):
    """ Checks for win """

    if any(all(board[i][j] == p for j in range(size)) for i in range(size)):
        return True
    if any(all(board[j][i] == p for j in range(size)) for i in range(size)):
        return True
    if all(board[i][i] == p for i in range(size)):
        return True
    if all(board[i][-(i + 1)] == p for i in range(size)):
        return True

    return False


main_menu()

希望奥斯丁·黑斯廷斯也会回答这个问题!

EN

回答 1

Code Review用户

回答已采纳

发布于 2019-11-20 15:41:52

赢下Bug

当董事会处于此阶段时,用户将获得下一步:

代码语言:javascript
复制
      |       |       
  X   |   O   |   X
      |       |       
----------------------
      |       |       
      |   O   |    
      |       |       
----------------------
      |       |       
  O   |   X   |   X
      |       |       

而用户进入5,游戏错误,将让用户再次进入并赢得游戏,而不是AI放置在第4位的X导致平局。

开始游戏Bug

当第一次提示选择困难时,输入一个数字(比如1)。然后它会问你你想做什么。你进入3来玩。然后它又问你有什么困难。我会删除第一个提示的困难,因为这有点奇怪,你问困难之前,看看用户是否想玩。

win

当返回TrueFalse时,90%的时间可以返回将导致这些值的表达式。观察:

代码语言:javascript
复制
def win(p):
    """ Checks for win """

    return any([
        any(all(board[i][j] == p for j in range(size)) for i in range(size)),
        any(all(board[j][i] == p for j in range(size)) for i in range(size)),
        all(board[i][i] == p for i in range(size)),
        all(board[i][-(i + 1)] == p for i in range(size))
    ])

这消除了任何return True语句的需要,因为返回表达式将导致布尔值本身。

三元算子

代码语言:javascript
复制
if board_type == 1:
    printBoard1()
else:
    printBoard2()

可以使用三元算子将其简化为:

代码语言:javascript
复制
printBoard1() if board_type == 1 else printBoard2()

方法命名

方法和变量名都应该是snake_case

代码语言:javascript
复制
printBoard1() -> print_board_one()

我也会用“1”代替"1",但这是个人的喜好。

大名单的名字

是时候跟房间里的大象讲话了。我会将名字放在一个单独的文件中,比如names.txt,然后从那里推断出信息。它从您的代码中清除了大量内容。下面是这个方法的外观:

names.txt

代码语言:javascript
复制
Ben,David,Hannah,Max,Sarah,William
代码语言:javascript
复制
def get_names():
    with open("names.txt", "r") as file:
        return ''.join(file.readlines()).split(",")

它会回来的

代码语言:javascript
复制
["Ben", "David", "Hannah", "Max", "Sarah", "William"]

这样做是读取文件中的每一行,将该列表转换为字符串,然后返回由逗号分隔的每个单词的列表。这是一种从名称文件访问和获取数据的简单方法。它还大大减少了代码中的杂乱。

如果您不想麻烦地将每个名称放入文件中,这是可以理解的。您可以做的是创建另一个python模块names.py,将列表放在该文件中,然后从该文件导入。看一看:

代码语言:javascript
复制
from names import NAMES # NAMES is the list of names

现在您可以对这个NAMES列表进行操作了。

字符串格式

代码语言:javascript
复制
print(name + ' Moved To Grid', r[0] * size + r[1] + 1)

可以写成这样:

代码语言:javascript
复制
print(f"{names} Moved To Grid {r[0] * size + r[1] + 1}")

这些输入语句也是如此

代码语言:javascript
复制
X = input(f"Please Enter Character For Player 1 (currently {X}): ")
O = input(f"Please Enter Character For Player 2 (currently {O}): ")

类型提示

让我们看一下这个方法头:

代码语言:javascript
复制
def play_again(p1, p2):

现在,想一想:

代码语言:javascript
复制
def play_again(p1: str, p2: str) -> None:

这些可以帮助您和使用您的程序的其他人确定要传递给方法的类型,以及可以返回的值。

If语句格式化

代码语言:javascript
复制
if level == 1: get_easy_AI_move(ai, pl, 1, computer)
if level == 2: get_hard_AI_move(ai, pl, 1, computer)
if level == 3: get_insane_AI_move(ai, pl, 1, computer)

真的应该是这个

代码语言:javascript
复制
if level == 1:
    get_easy_AI_move(ai, pl, 1, computer)
if level == 2:
    get_hard_AI_move(ai, pl, 1, computer)
if level == 3:
    get_insane_AI_move(ai, pl, 1, computer)

主护卫

您应该将所有初始化代码封装在主保护程序中。这将允许您在不运行代码的情况下导入此模块。看一看:

代码语言:javascript
复制
if __name__ == '__main__':
    main_menu()

在一行上使用if语句并不是很传统。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/232698

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档