不确定tic_tac_toe更衣板

时间:2019-01-11 21:27:04

标签: python-3.x for-loop tic-tac-toe

我正在用Python 3编写井字游戏。我将木板制作成2D阵列,并具有将木板打印为网格,教程以及获取和放置输入的功能。

它具有基本的功能,可以正确显示板子,处理输入以及处理,但是我的算法有两个主要问题。他们是:

  1. 确定胜利是否发生。 (此后,它应询问玩家是否要再次玩,并采取相应的行动。) 2.(可选,但值得赞赏)如何创建一个可与单个播放器一起播放的CPU。

我有一个粗略的概念,即在转弯开关和博弈机制中使用“ for循环”,但是如果不平局,游戏可能会中断。

如果任何人对以下问题或一般建议有任何解决方案, 请在这里发布。

    from array import *
    class board:
        def __init__(self, row_1, row_2, row_3):
            self.row_1 = row_1
            self.row_2 = row_2
            self.row_3 = row_3
            # full_board is two-dimensional array
            self.full_board = row_1, row_2, row_3
    dash = "-"
    main_board = board([dash, dash, dash], [dash, dash, dash], [dash, dash, 
    dash,])
    def board_print(board):
        for row in board:
            for item in row:
                print(item, end = " ")
            print()

    def take_input():
        player = input("What space would you like to mark?(From 1 through 9):")
        input_process(player)

# Algorithm for player input
# Make a dictionary of player inputs as keys, and 2d array coordinates as values
# if player's input equals a dictionary value:
#   take the string and split it at ":"
#   assign the two numbers of the 2d dictionary value as part_1 and part_2
#   change the value of the matching coordinate to a "X" or "O", on the player(sorry, I can't make good CPU.)
# else:
#   print a notification that their input was invalid and recall the function
def input_process(pl_choice):
    possible_inputs = {"1" : "0:0", "2" : "0:1", "3" : "0:2", "4" : "1:0", "5" : "1:1", "6" : "1:2", "7": "2:0", "8" : "2:1", "9" : "2:2"}
    if pl_choice in possible_inputs:
        confirm = input("Are you sure you want to select %s? y/n: "%pl_choice)
        if confirm == "y":
            choice = possible_inputs[pl_choice].split(":")
            answer_p1 = choice[0]
            answer_p2 = choice[1]
            choice_parts = [answer_p1, answer_p2]
        elif confirm == "n":
            print("Oh. Well you can try again.\n")
            take_input()
    elif pl_choice not in possible_inputs or not pl_choice.isdigit():
        print("Your choice was invalid. Please try again.")
        take_input()

def change_board(play_board, player_id, input_p1, input_p2):
        if player_id == 1:
            play_board[input_p1][input_p2] = "X"
        elif player_id == 2:
            play_board[input_p1][input_p2] = "O" 

def tutorial():
        print("Welcome to the Tic-Tac-Toe tutorial.\n")
        print("This version of Tic-Tac-Toe is two-player only, although CPU may be added in the future. To play, \nYou input a number, 1-9. The numbers bind like so: ")
        tutorial_board = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
        print(board_print(tutorial_board))
        print("Otherwise, this plays like on paper; get 3 in a row vertically, horizontally, or diagonally before your opponent, and you win.")
        # Placeholder for main game

    def main_game():
        print("Hello, and welcome to Tic-Tac-Toe.\nWould you like to see the tutorial? y/n:")
        tutorial_needed = input
        if tutorial_needed == "y":
            tutorial()
        elif tutorial_needed == "n":
            print("Okay. Let's start!")
            game_end = False
            actual_board = main_board.full_board
            board_print(actual_board)
            take_input()

1 个答案:

答案 0 :(得分:0)

1。检测是否已经赢了。

我们为玩家X定义了一个“胜利”,条件是以下情况之一为“真”:

  • 一行包含X
  • 一列包含X
  • 左上角到右下角对角线由X组成
  • 左下角到右上角对角线由X组成

我们如何将其翻译成Python?

行只是元组中的子列表(这是您使用的类型),因此我们只需编写board[row]即可获得一行。要检查any (注意代码格式)行是否包含“ X”,我们必须检查all的值是否等于“ X”。因此,我们可以写any(all(field == 'X' for field in row) for row in board)

列更加复杂,因为我们必须使用索引。但是,基本上,这是同一回事,反之亦然:any列中有all个字段“ X”: any(all(board[row][column] == 'X' for row in range(3)) for column in range(3))

对角线:我们每个只有一条线,所以我们只需要一个循环。
对于TL-> BR,两个索引相等。因此,我们希望索引相等的字段all等于“ X”。 all(board[i][i] == 'X' for i in range(3))
对于BL-> TR,一个索引为2-other_index不是 3,因为序列是零索引的)。我们希望具有两个索引的all字段等于“ X” all(board[i][2-i] for i in range(3))问题:如果将i2-i取反会发生什么?如果您不知道,请打印出来。

您可能想编写一个check_win(board, player)函数来为通用player做以上所有操作-在这里是“ X”或“ O”,但是,如果您决定在其中包含三个播放器稍后再放一个更大的板子...

2。创建 CPU AI:

如果您确实要创建CPU,那么这是个错误的提出问题的地方。 如果要创建(简单的)AI,请继续阅读。如果您想使其复杂,请提出一个新问题。

考虑它应该做什么:

  • 是否应该因为某些位置而偏爱某些领域?
  • 它应该尝试快速阻止对手吗?
  • 它应该尝试创造多种获胜机会还是专注于一个?
  • 应该...吗?

虽然在这种情况下,仅模拟几个转弯并选择最有可能获胜的转弯,问自己上面的问题,并编写适用于(很多)更大的板子的东西可能会更简单,有趣。

3。开关转弯。

一种可能性是:

您有一个播放器序列(str,list或tuple),例如:"XO"和一个round_counter变量,该变量总是增加的。然后,您使用PLAYERS[round_counter % len(PLAYERS)]获取当前玩家。使用模数运算符%始终可获得有效的索引。

替代:

使用itertools.cycle

  

cycle('ABCD')-> A B C D A B C D A B C D ...

这很容易(for current_player in itertools.cycle("XO"):),但是使用第一种方法时,您可以受益于拨打号码的enumerate(itertools.cycle("XO")),并且可以限制库的使用(如果此代码显示为某人,您可能想解释一下它的工作原理。

4。如何检测平局:

all字段为not为空(在您的情况下为!=短划线)时,将发生抽奖;这等效于说not any字段带有破折号。 请参见list comprehension来展平木板:

  

>>> # flatten a list using a listcomp with two 'for'
   >>> vec = [[1,2,3], [4,5,6], [7,8,9]]
   >>> [num for elem in vec for num in elem]
   [1, 2, 3, 4, 5, 6, 7, 8, 9]

-倒数第二个示例