在Python中的井字游戏

在Python中的井字游戏

在以下教程中,我们将使用Python编程语言从头开始创建一个名为井字游戏的游戏。为了更好地理解,我们将整个程序分为多个步骤。但在进入过程之前,让我们先了解一下这个游戏。

什么是井字游戏

井字游戏 是在一个 3 x 3的方格中 进行的两个玩家之间的游戏。每个玩家都在自己的回合中占据一个方格,目标是在垂直、水平或对角线上放置三个相同的标记。第一个玩家使用 X形 作为标记,而另一个玩家使用 圆圈形 O形

现在,让我们了解一下井字游戏的设计。

井字游戏的设计

我们将使用命令提示符来玩井字游戏。因此,构建井字游戏的设计是主要目标。

目标: 如果玩家需要标记一个特定的方块,他/她必须输入网格中显示的相应数字。例如,如果我们想要占据右上方的方块,则必须在终端中输入数字3。

让我们了解一下生成网格的代码片段。

程序:

# Function to print the Tic-Tac-Toe Design
def mytictactoe(val):
    print("\n")
    print("\t     |     |")
    print("\t  {}  |  {}  |  {}".format(val[0], val[1], val[2]))
    print('\t_____|_____|_____')

    print("\t     |     |")
    print("\t  {}  |  {}  |  {}".format(val[3], val[4], val[5]))
    print('\t_____|_____|_____')

    print("\t     |     |")

    print("\t  {}  |  {}  |  {}".format(val[6], val[7], val[8]))
    print("\t     |     |")
    print("\n")

解释:

在上面的代码片段中,我们定义了一个用于井字游戏的函数,该函数接受值作为参数。在这里, val 参数是一个列表,包含网格中每个单元格的状态。在函数内部,我们打印了井字游戏网格的设计。

现在,下一步是使用数据结构来存储数据。

使用数据结构存储数据

任何游戏的原则都依赖于游戏背后的机制。由于我们正在创建一个相对简单和易于玩的游戏,所以所采用的机制也很简单。

任何时刻都需要两个关键的信息:

  1. 网格状态: 我们需要创建一个数据结构来包含每个单元格的状态。状态可以是占用或空闲的。
  2. 每个玩家的移动: 需要知道每个玩家过去和现在的移动,即’X’和’O’所占据的位置。

注意:上述数据可以通过网格状态来访问。然而,每次想要获取玩家位置时,都需要遍历这些信息。这可以被称为时间复杂度与空间复杂度的权衡。这是一种保留时间的常规技术。

下面是相同操作的语法:

代码片段:

# Function for a single game of Tic-Tac-Toe
def singlegame(curplayer):
    # Representing the Tic-Tac-Toe
    val = [' ' for i in range(9)]

    # Storing the positions occupied by X and O
    playerpos = {'X' : [], 'O' : []}

说明:

在上面的代码片段中,我们定义了一个用于井字棋单局游戏的函数,其中 val 表示上一个函数的参数, playerpos 存储着 交叉(X)圈(O) 所占据的方块的位置。

通常情况下,在管理网格状态的字符列表中有三个值:

  1. ‘ ‘ - 这个字符表示空位或者空格。
  2. ‘X’ - 这个字符表示一个单元格被X玩家占据。
  3. ‘O’ - 这个字符表示一个单元格被O玩家占据。

每个玩家的移动都以整数列表的形式存储在字典中,其中键以 ‘X’‘O’ 表示对应的玩家。他们各自的列表包含了他们所占据的网格中的方格的数字。

注意:curplayer变量存储当前进行移动的玩家,如’X’或’O’。

理解游戏循环

每个游戏都包含一种游戏循环,允许玩家进行游戏直到某个玩家获胜或游戏为平局。在井字棋游戏中,每次循环迭代表示玩家的一次移动。

让我们考虑以下代码片段以设计游戏循环。

语法:

# Loop of Game for a single game of Tic-Tac-Toe
while True:
    mytictactoe(val)

解释:

正如我们所观察到的,我们使用了while循环来打印函数 mytictactoe() 的值,为一个井字棋的单个游戏生成了一个游戏循环。

处理玩家的输入

在游戏的每次迭代中,玩家必须提供他的移动输入。让我们考虑以下语法来处理玩家的输入。

语法:

# Try-Exception block for CHANCE input
try:
    print("Player ", curplayer, " turn. Choose your Block : ", end="")
    chance = int(input())
except ValueError:
    print("Invalid Input!!! Try Again")
    continue

# Sanity check for CHANCE input
if chance < 1 or chance > 9:
    print("Invalid Input!!! Try Again")
    continue

# Checking if the block is not occupied already
if val[chance - 1] != ' ':
    print("Oops! The Place is already occupied. Try again!!")
    continue

解释:

在上面的代码片段中,我们创建了一个try块来处理players的意外值。然后我们处理了ValueError异常,以便游戏不会停止。之后我们进行了一些健全性检查,例如输入的值是否为有效位置,如果是有效位置,是否已经填充了?

现在,让我们进入下一步。

更新游戏信息

根据玩家提供的输入,我们必须更新游戏信息,以确保游戏的顺利进行。我们可以通过将以下代码片段添加到主项目中来更新游戏信息。

语法:

# Updating the game information

# Update the status of the grid
val[chance - 1] = curplayer

# Update the positions of the player
playerpos[curplayer].append(chance)

解释:

在上面的代码片段中,我们通过更新网格的状态和玩家的位置来更新游戏信息。 val 列表将根据当前玩家更新填充的单元格。玩家的位置将添加刚被当前玩家占据的位置。

一旦 val 列表被更新,我们将调用 mytictactoe() 函数,网格将如下所示:

输出:

             |     |
          1  |  2  |  3
        _____|_____|_____
             |     |
          4  |  5  |  6
        _____|_____|_____
             |     |
          7  |  8  |  9
             |     |

检查胜负或平局

在每次移动后,我们需要检查是否有玩家赢得了比赛或比赛已经是平局。我们可以使用下面给出的语法进行检查:

语法:

# Calling Function to check Victory
if check_Victory(playerpos, curplayer):
    mytictactoe(val)
    print("Congratulations! Player ", curplayer, " has won the game!")     
    print("\n")
    return curplayer

# Calling Function to check Tie
if check_Tie(playerpos):
    mytictactoe(val)
    print("Oh! Game Tied")
    print("\n")
    return 'D'

说明:

在上述语法中,我们使用了 if 语句来检查胜利或平局。如果 singlegame() 函数返回当前玩家,则表示该玩家赢得了比赛。否则,游戏是平局,会返回 ‘D’

让我们考虑一下检查是否有任何玩家赢得比赛的函数。

语法:

# Defining Function to check Victory
def check_Victory(playerpos, curplayer):

    # All probable winning combinations
    solution = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]]

    # Loop to check whether any winning combination is satisfied or not
    for i in solution:
        if all(j in playerpos[curplayer] for j in i):

            # Return True if any winning combination is satisfied
            return True
    # Return False if no combination is satisfied 
    return False       

# Defining Function to check if the game is Tied
def check_Tie(playerpos):
    if len(playerpos['X']) + len(playerpos['O']) == 9:
        return True
    return False   

解释:

在上面的代码片段中,我们定义了检查胜利或平局的函数。这些函数分别是 check_Victory()check_Tie()

  1. check_Victory(): 它存储了所有赢得游戏的组合。该函数检查当前玩家的位置是否满足任何获胜的组合。如果满足条件,它将返回TRUE;否则,它将返回FALSE。
  2. check_Tie(): 这是非常简单的,它检查是否所有的“九”个位置都被占用,游戏平局。

切换当前玩家

每个玩家每次只有一次机会。因此,在每次成功移动后,当前玩家将被交换。让我们考虑以下代码片段:

语法:

# Switching moves of the player
if curplayer == 'X':
    curplayer = 'O'
else:
    curplayer = 'X'

解释:

在下面的代码片段中,我们使用了 if-else 语句来切换玩家的移动方式,如果当前玩家标记了一个位置,则当前玩家将被更换,另一个玩家将标记他们的移动。

这些是制作单个游戏时需要关注的一些步骤。然而,我们将创建一个记分板系统来跟踪想要玩多个游戏的玩家。

输入玩家的姓名

由于我们正在创建记分板,我们有必要显示每个玩家的姓名。

下面是相同的语法示例:

语法:

if __name__ == "__main__":

    print("First Player")
    FirstPlayer = input("Specify the Name: ")
    print("\n")

    print("Second Player")
    SecondPlayer = input("Specify the Name: ")
    print("\n")

解释:

正如我们所观察到的,我们使用了特殊变量 __name__ 来获取值 “__main__” 。然后我们分别为第一个和第二个玩家提供了姓名的输入。这将成为程序的入口点,在执行程序时首先会要求输入姓名。

存储关于游戏的信息

我们需要存储诸如当前玩家、玩家选择(即X或O)、可选选择(X或O)和记分板等信息。

语法:

# Storing the player who chooses X and O
curplayer = FirstPlayer

# Storing the Players' choice
playerchoice = {'X' : "", 'O' : ""}

# Storing the options
opt = ['X', 'O']

# Storing the scoreboard
scoreboard = {FirstPlayer: 0, SecondPlayer: 0}
myscoreboard(scoreboard)

解释:

在上面的代码片段中,我们将当前玩家设置为第一个玩家。我们还存储了玩家的选择、可用选项和记分牌。

设计记分牌

我们将使用字典数据结构设计一个记分牌。对于这个记分牌,玩家的姓名将作为键,他们的总胜利次数将作为值。让我们考虑以下代码片段来设计井字游戏的记分牌。

语法:

def myscoreboard(scoreboard):
    print("\t--------------------------------")
    print("\t         SCORE BOARD       ")
    print("\t--------------------------------")

    listofplayers = list(scoreboard.keys())
    print("\t   ", listofplayers[0], "\t    ", scoreboard[listofplayers[0]])
    print("\t   ", listofplayers[1], "\t    ", scoreboard[listofplayers[1]])

    print("\t--------------------------------\n")

解释:

在上面的代码段中,我们定义了一个名为 myscoreboard 的函数,它以 scoreboard 作为参数。然后我们打印了计分板的设计。我们通过使用 .keys() 函数将玩家的姓名存储为列表的变量。然后我们从计分板中索引它们并显示分数。

创建一个外部游戏循环

为了保持多个井字游戏的比赛,我们需要为游戏添加另一个循环。当前玩家将为每个比赛选择标记。在游戏的每次迭代中,都应显示选择菜单。

让我们考虑以下语法来创建外部游戏循环。

语法:

# Loop for a series of Tic-Tac-Toe game
# The loop executes until the players quit
while True:

     # Main Menu for Players
     print(curplayer, "will make the choice:")
     print("Press 1 for X")
     print("Press 2 for O")
     print("Press 3 to Quit")

说明:

在上面的代码片段中,我们创建了一个 while 循环,用于为玩家显示主菜单,当前玩家可以在标记(十字形“X”或圆圈形“O”)之间进行选择,或者选择退出游戏。

输出:

First Player
Specify the Name: Andy


Second Player
Specify the Name: Carlo


        --------------------------------
                 SCORE BOARD       
        --------------------------------
            Andy             0
            Carlo            0
        --------------------------------

Andy will make the choice:
Press 1 for X
Press 2 for O
Press 3 to Quit

处理和分配玩家的选择

我们需要处理和存储当前玩家在每次迭代中的选择。让我们考虑以下相应代码片段。

语法:

# Try exception for THE_CHOICE input
try:
    the_choice = int(input())   
  except ValueError:
    print("Invalid Input!!! Try Again\n")
    continue

# Conditions for player choice  
if the_choice == 1:
    playerchoice['X'] = curplayer
    if curplayer == FirstPlayer:
        playerchoice['O'] = SecondPlayer
    else:
        playerchoice['O'] = FirstPlayer

elif the_choice == 2:
     playerchoice['O'] = curplayer
     if curplayer == FirstPlayer:
         playerchoice['X'] = SecondPlayer
     else:
         playerchoice['X'] = FirstPlayer

elif the_choice == 3:
     print("The Final Scores")
     myscoreboard(scoreboard)
     break  

else:
     print("Invalid Selection!! Try Again\n")

解释:

在上面的代码片段中,我们使用了try-exception块来处理the_choice输入的任何异常。然后,我们使用了if-else语句来为当前玩家创建选择菜单。

根据玩家的选择,数据将被存储。这很重要,因为它将告诉我们每场比赛后哪个玩家获胜。

执行游戏

一旦所有必需的信息都被存储,我们就可以执行一场独立的比赛并记录胜利标记。

相同的语法如下所示。

语法:

# Storing the winner in a single game of Tic-Tac-Toe
win = singlegame(opt[the_choice - 1])

解释:

在以上代码片段中,我们存储了一场井字游戏的获胜者详细信息。

更新记分牌

我们必须在每场井字游戏之后更新记分牌。

让我们考虑以下代码片段来更新记分牌。

语法:

# Updation of the scoreboard as per the winner
if win != 'D' :
    playerWon = playerchoice[win]
    scoreboard[playerWon] = scoreboard[playerWon] + 1

myscoreboard(scoreboard)

说明:

在上面的代码片段中,我们使用 if 语句来检查比赛是否不是平局。一旦比赛不是平局,计分板将会被更新。

选择玩家的交换

在玩游戏时,切换选择标记的机会变得必要。因此,让我们考虑以下语法来理解交换。

语法:

# Switching player who chooses X or O
if curplayer == FirstPlayer:
    curplayer = SecondPlayer
else:
    curplayer = FirstPlayer

解释:

在上面的代码片段中,我们再次使用了if-else语句来在玩家之间切换选择标记(叉或圈)。

因此,我们成功地构建了我们自己的井字棋游戏。

下载代码

可以从以下链接下载游戏的代码: 点击此处下载

游戏时间

由于所有步骤最终都完成了,这里是游戏的最终输出。

输出:

First Player
Specify the Name: Andy


Second Player
Specify the Name: Carlo


        --------------------------------
                 SCORE BOARD       
        --------------------------------
            Andy             0
            Carlo            0
        --------------------------------

Andy will make the choice:
Press 1 for X
Press 2 for O
Press 3 to Quit
1


             |     |
             |     |
        _____|_____|_____
             |     |
             |     |
        _____|_____|_____
             |     |
             |     |
             |     |


Player  X  turn. Choose your Block : 5


             |     |
             |     |   
        _____|_____|_____
             |     |
             |  X  |   
        _____|_____|_____
             |     |
             |     |   
             |     |


Player  O  turn. Choose your Block : 3


             |     |
             |     |  O
        _____|_____|_____
             |     |
             |  X  |   
        _____|_____|_____
             |     |
             |     |   
             |     |


Player  X  turn. Choose your Block : 1


             |     |
          X  |     |  O
        _____|_____|_____
             |     |
             |  X  |   
        _____|_____|_____
             |     |
             |     |   
             |     |


Player  O  turn. Choose your Block : 9


             |     |
          X  |     |  O
        _____|_____|_____
             |     |
             |  X  |   
        _____|_____|_____
             |     |
             |     |  O
             |     |


Player  X  turn. Choose your Block : 6


             |     |
          X  |     |  O
        _____|_____|_____
             |     |
             |  X  |  X
        _____|_____|_____
             |     |
             |     |  O
             |     |


Player  O  turn. Choose your Block : 4


             |     |
          X  |     |  O
        _____|_____|_____
             |     |
          O  |  X  |  X
        _____|_____|_____
             |     |
             |     |  O
             |     |


Player  X  turn. Choose your Block : 2


             |     |
          X  |  X  |  O
        _____|_____|_____
             |     |
          O  |  X  |  X
        _____|_____|_____
             |     |
             |     |  O
             |     |


Player  O  turn. Choose your Block : 8


             |     |
          X  |  X  |  O
        _____|_____|_____
             |     |
          O  |  X  |  X
        _____|_____|_____
             |     |
             |  O  |  O
             |     |


Player  X  turn. Choose your Block : 7


             |     |
          X  |  X  |  O
        _____|_____|_____
             |     |
          O  |  X  |  X
        _____|_____|_____
             |     |
          X  |  O  |  O
             |     |


Game Tied


        --------------------------------
                 SCORE BOARD       
        --------------------------------
            Andy             0
            Carlo            0
        --------------------------------

Carlo will make the choice:
Press 1 for X
Press 2 for O
Press 3 to Quit
3
The Final Scores
        --------------------------------
                 SCORE BOARD
        --------------------------------
            Andy             0
            Carlo            0
        --------------------------------

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程