如何避免多个`elif`语句?

时间:2019-09-14 06:32:31

标签: python python-3.x

所以,我试图用python制作一个基本的井字游戏,然后我创建了一个效果很好的游戏,但是我的代码并不好,因为它有很多代码可以检查列表索引(游戏胜利者),这让我很烦。那么,如何避免使用左索引来检查游戏的获胜者?

我的代码:

board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']


def show_board():# for showing the tic-tac-toe board
    print(' | ' + str(board[0]) + ' | ' +
          str(board[1]) + ' | ' + str(board[2]) + ' | ')
    print(' | ' + str(board[3]) + ' | ' +
          str(board[4]) + ' | ' + str(board[5]) + ' | ')
    print(' | ' + str(board[6]) + ' | ' +
          str(board[7]) + ' | ' + str(board[8]) + ' | ')


def main():
    one = 1
    flag = 1

    show_board()
    while one == 1:
        if flag == 1:
            x_o = 'X'
        if flag == 2:
            x_o = 'O'
        pos = int(input('Player "' + x_o + '" Turn: '))

        if x_o == 'o':
            x_o = 'O'
        if x_o == 'x':
            x_o = 'X'
        if board[pos - 1] == 'O' or board[pos - 1] == 'O':
            print('That Place Is Already Filled By Player "0"')

        if board[pos - 1] == 'X' or board[pos - 1] == 'X':
            print('That Place Is Already Filled By Player "X"')

        else:
            try:
                board[pos - 1] = x_o
            except IndexError:
                print('Type Numbers Between Only 1 And 9')

            if flag == 1:
                flag = 2
            elif flag == 2:
                flag = 1

            show_board()

            # Checking The Winner Of The Game

            # for horizontal X
            if board[0] == board[1] == board[2] == 'X':
                one = 2
                print('The Winner Is Player "X"!')

            elif board[3] == board[4] == board[5] == 'X':
                one = 2
                print('The Winner Is Player "X"!')

            elif board[6] == board[7] == board[8] == 'X':
                one = 2
                print('The Winner Is Player "X"!')

            # for Daigonal X
            elif board[0] == board[4] == board[8] == 'X':
                one = 2
                print('The Winner Is Player "X"!')

            elif board[2] == board[4] == board[6] == 'X':
                one = 2
                print('The Winner Is Player "X"!')

            # for Vertical X
            elif board[1] == board[4] == board[7] == 'X':
                one = 2
                print('The Winner Is Player "X"!')

            elif board[2] == board[5] == board[8] == 'X':
                one = 2
                print('The Winner Is Player "X"!')

            elif board[0] == board[3] == board[6] == 'X':
                one = 2
                print('The Winner Is Player "X"!')

            # for horizontal O
            elif board[0] == board[1] == board[2] == 'O':
                one = 2
                print('The Winner Is Player "O"!')

            elif board[3] == board[4] == board[5] == 'O':
                one = 2
                print('The Winner Is Player "O"!')

            elif board[6] == board[7] == board[8] == 'O':
                one = 2
                print('The Winner Is Player "O"!')

            # for Diagonal O
            elif board[0] == board[4] == board[8] == 'O':
                one = 2
                print('The Winner Is Player "O"!')

            elif board[2] == board[4] == board[6] == 'O':
                one = 2
                print('The Winner Is Player "O"!')

            # for Vertical 0
            elif board[1] == board[4] == board[7] == 'O':
                one = 2
                print('The Winner Is Player "O"!')

            elif board[2] == board[5] == board[8] == 'O':
                one = 2
                print('The Winner Is Player "O"!')

            elif board[0] == board[3] == board[6] == 'O':
                one = 2
                print('The Winner Is Player "O"!')

            elif board[0] != ' ' and board[1] != ' ' and board[2] != ' ' and board[3] != ' ' and board[4] != ' ' and board[5] != ' ' and board[6] != ' ' and board[7] != ' ' and board[8] != ' ':
                print('The Match Is A Tie!')
                one = 2


main()

因此,如您所见,我使用了大量的if语句来检查游戏的获胜者。如何避免这种情况并减少行数。

5 个答案:

答案 0 :(得分:3)

您可以将它们替换为一些循环,例如:

board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']


def show_board():# for showing the tic-tac-toe board
    print(' | ' + str(board[0]) + ' | ' +
          str(board[1]) + ' | ' + str(board[2]) + ' | ')
    print(' | ' + str(board[3]) + ' | ' +
          str(board[4]) + ' | ' + str(board[5]) + ' | ')
    print(' | ' + str(board[6]) + ' | ' +
          str(board[7]) + ' | ' + str(board[8]) + ' | ')


def main():
    one = 1
    flag = 1

    show_board()
    while one == 1:
        if flag == 1:
            x_o = 'X'
        if flag == 2:
            x_o = 'O'
        pos = int(input('Player "' + x_o + '" Turn: '))

        if x_o == 'o':
            x_o = 'O'
        if x_o == 'x':
            x_o = 'X'
        if board[pos - 1] == 'O' or board[pos - 1] == 'O':
            print('That Place Is Already Filled By Player "0"')

        if board[pos - 1] == 'X' or board[pos - 1] == 'X':
            print('That Place Is Already Filled By Player "X"')

        else:
            try:
                board[pos - 1] = x_o
            except IndexError:
                print('Type Numbers Between Only 1 And 9')

            if flag == 1:
                flag = 2
            elif flag == 2:
                flag = 1

            show_board()

            # Checking The Winner Of The Game
            won = False
            for turn in ('X', 'O'):
                # horizontal
                if not won:
                    for i in (0, 3, 6):
                        if all(board[i + k] == turn for k in range(3)):
                            won = True
                            break
                # vertical
                if not won:       
                    for i in range(3):
                        if all(board[i + k] == turn for k in (0, 3, 6)):
                            won = True
                            break
                # diagonal
                if not won:
                    if all(board[k] == turn for k in (0, 4, 8)) or \
                            all(board[k] == turn for k in (2, 4, 6)):
                        won = True
                # handle winning
                if won:
                    one = 2
                    print(f'The Winner Is Player "{turn}"!')
                    break
            # handle a tie
            if not won and all(square != ' ' for square in board):
                one = 2
                print('The Match Is A Tie!')


main()

(您可能还可以对其他代码进行很多改进/简化)


编辑

以下是一些类似的代码,简化/完善/扩展为:

  • 处理任意大小的板子
  • 正确处理非数字输入
  • 使用更多功能
  • 摆脱冗余变量
NUM_ROWS = 3
NUM_COLS = 3
NUM_WIN = 3
BOARD_SIZE = NUM_ROWS * NUM_COLS

EMPTY = ' '
BOARD = [EMPTY] * BOARD_SIZE
TURNS = 'X', 'O'


def show_board(board):
    """Show the tic-tac-toe board."""
    for i in range(0, BOARD_SIZE, NUM_COLS):
        print(' | ' + ' | '.join(board[i:i + NUM_COLS]) + ' | ')


def ij(i, j):
    """Convert (row, col) to board index."""
    return i + NUM_COLS * j


def check_winner(board, turn):
    """Check if there is a winner."""
    # horizontal
    for i in range(NUM_ROWS):
        for j in range(NUM_COLS - NUM_WIN + 1):
            if all(board[ij(i, j + k)] == turn for k in range(NUM_WIN)):
                return True
    # vertical
    for i in range(NUM_ROWS - NUM_WIN + 1):
        for j in range(NUM_COLS):
            if all(board[ij(i + k, j)] == turn for k in range(NUM_WIN)):
                return True
    # diagonal
    for i in range(NUM_ROWS - NUM_WIN + 1):
        for j in range(NUM_COLS - NUM_WIN + 1):
            K = NUM_WIN
            if all(board[ij(i + k, j + k)] == turn for k in range(NUM_WIN)):
                return True
            if all(board[ij(i + NUM_WIN - k - 1, j + k)] == turn
                   for k in range(NUM_WIN)):
                return True


def check_tie(board):
    """Check if tie."""
    return all(square != EMPTY for square in board)


def next_turn(turn):
    """Advance to next turn."""
    return TURNS[(TURNS.index(turn) + 1) % 2]


def main():
    """Tic-tac-toe game."""
    turn = TURNS[0]
    show_board(BOARD)
    while True:
        valid_input = False
        while not valid_input:
            try:
                choice = int(input(f'Player `{turn}` turn: '))
                valid_input = (1 <= choice <= BOARD_SIZE)
                if not valid_input:
                    raise ValueError
            except ValueError:
                print(f'Type numbers between 1 and {BOARD_SIZE} only.')
            else:
                idx = choice - 1
                if BOARD[idx] != EMPTY:
                    print(f'Position `{idx}` already taken by `{BOARD[idx]}`')
                else:
                    BOARD[idx] = turn

        show_board(BOARD)
        won = check_winner(BOARD, turn)
        if won:
            print(f'The winner is player `{turn}`!')
            break
        # handle a tie
        if not won and check_tie(BOARD):
            print('The match is a tie!')
            break
        turn = next_turn(turn)


if __name__ == '__main__':
    main()

请使用NumPy和类(尤其是Board.py)检查mnk-gamesource code以获得类似的实现。免责声明:我是包裹的作者。


编辑2

请注意,仅对于井字游戏,可以使用类似于@ rusu_ro1 proposed的方法来缩短check_winner()

WIN_CASES = [
    [0, 1, 2], [3, 4, 5], [6, 7, 8],  # horizontal
    [0, 3, 6], [1, 4, 7], [2, 5, 8],  # vertical
    [0, 4, 8], [2, 4, 6],  # diagonal
]


def check_winner(board, turn, win_cases=WIN_CASES):
    """Check if there is a winner."""
    for win_case in win_cases:
        if all(board[i] == turn for i in win_case):
            return True

答案 1 :(得分:1)

import random as rnd
size = 3

## random board to test
board = [[rnd.choice(["X", "O"]) for _ in range(size)] for _ in range(size)]
print(board)

def check_winner(board):
    for mark in ["X", "O"]:
        ## count mark in all rows
        count_in_rows = [row.count(mark) for row in board]
        ## count mark in all columns
        count_in_columns = [ [board[row_n][col_n] for row_n in range(size)].count(mark) for col_n in range(size)]
        ## count mark in fwd diagonal
        count_in_diag = [[board[i][i] for i in range(size)].count(mark)]
        ## count in backward diagonal
        count_in_diag.append([board[i][size-i-1] for i in range(size)].count(mark))

        print((count_in_rows + count_in_columns + count_in_diag))

        ## if there is 3 count of mark in any rows, columns or diagonal
        if 3 in (count_in_rows + count_in_columns + [count_in_diag]):
            print(f"winner is {mark}")
            return mark

        return

check_winner(board)  

答案 2 :(得分:1)

您可以定义o_list = ['o','o','o']和x_list = ['x','x','x'] 然后像这样比较它们:

#l = board
if(l[0:3] == o_list or l[3:6] == o_list or l[6:9] == o_list or l[0:9:3] == o_list or l[1:9:3] == o_list or l[8:0:-3] == o_list):
   print('The Winner Is Player "O"!')

与x_list相同。 ;)

o_list =['o', 'o', 'o']
x_list =['x', 'x', 'x']

board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']


def show_board():# for showing the tic-tac-toe board
    print(' | ' + str(board[0]) + ' | ' +
          str(board[1]) + ' | ' + str(board[2]) + ' | ')
    print(' | ' + str(board[3]) + ' | ' +
          str(board[4]) + ' | ' + str(board[5]) + ' | ')
    print(' | ' + str(board[6]) + ' | ' +
          str(board[7]) + ' | ' + str(board[8]) + ' | ')


def main():
    one = 1
    flag = 1
    o_list =['o', 'o', 'o']
    x_list =['x', 'x', 'x']
    show_board()
    while one == 1:
        if flag == 1:
            x_o = 'X'
        if flag == 2:
            x_o = 'O'
        pos = int(input('Player "' + x_o + '" Turn: '))

        if x_o == 'o':
            x_o = 'O'
        if x_o == 'x':
            x_o = 'X'
        if board[pos - 1] == 'O' or board[pos - 1] == 'O':
            print('That Place Is Already Filled By Player "0"')

        if board[pos - 1] == 'X' or board[pos - 1] == 'X':
            print('That Place Is Already Filled By Player "X"')

        else:
            try:
                board[pos - 1] = x_o
            except IndexError:
                print('Type Numbers Between Only 1 And 9')

            if flag == 1:
                flag = 2
            elif flag == 2:
                flag = 1

            show_board()

            # Checking The Winner Of The Game

            # for horizontal X
            if(board[0:3] == x_list or board[3:6] == x_list or board[6:9] == x_list or board[0:9:3] == x_list or board[1:9:3] == x_list or board[8:0:-3] == x_list):
                one = 2
                print('The Winner Is Player "X"!')

            if(board[0:3] == o_list or board[3:6] == o_list or board[6:9] == o_list or board[0:9:3] == o_list or board[1:9:3] == o_list or board[8:0:-3] == o_list):
                one = 2
                print('The Winner Is Player "O"!')

            elif board[0] != ' ' and board[1] != ' ' and board[2] != ' ' and board[3] != ' ' and board[4] != ' ' and board[5] != ' ' and board[6] != ' ' and board[7] != ' ' and board[8] != ' ':
                print('The Match Is A Tie!')
                one = 2


main()

答案 3 :(得分:0)

您可以使用以下功能(输入:板子和玩家的字母,输出:如果该玩家赢了,则为True):

def isWinner(board, letter):
    return (
        (board[1] == board[2] ==  board[3] == letter) or
        (board[4] == board[5] ==  board[6] == letter) or
        (board[7] == board[8] ==  board[9] == letter) or
        (board[7] == board[4] ==  board[1] == letter) or
        (board[8] == board[5] ==  board[2] == letter) or
        (board[9] == board[6] ==  board[3] == letter) or
        (board[7] == board[5] ==  board[3] == letter) or
        (board[9] == board[5] ==  board[1] == letter))

答案 4 :(得分:0)

要检查获胜者,您可以使用:

from operator import itemgetter
from itertools import chain 

winning_cases = {'diags' : [[0, 4, 8], [2, 4, 6]],
                 'rows': [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
                 'cols': [[0, 3, 6], [1, 4, 7], [2, 5, 8]]}


def check_winner(board=board):
    for case in chain(*winning_cases.values()):
        candidates = set(itemgetter(*case)(board))
        if len(candidates) == 1 and '' not in candidates: # check if a diag, row or col has only one charcter
            winner, = candidates
            return winner


    return None 

例如:

board = ['X', 'X', 'O', 'X', 'O','O', 'X', 'O', 'X']
check_winner(board)

输出:

 X

如果有一个,check_winner方法将返回赢家,否则返回无