需要帮助找到解决Tictatcoe转弯问题的方法吗

2024-10-02 18:25:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理一个tic tac toe游戏。 我不知道如何让XO交换模模糊糊地模仿交换回合。我见过有人像下面的代码那样做,但出于某种原因,我要么出错,要么在我将它连接到我先前存在的代码时它就不工作了

我应该详细说明我计划(尝试)使用极大极小算法,使这个游戏不可能获胜

print("Begin")

global top_left, top_middle, top_right
global middle_left, center, middle_right
global bottem_left, bottem_middle, bottem_right

#these are the variables used to check if someone has put their move their already
#0 = empty
#1 = Circle
#2  = X

top_left = 0
top_middle = 0
top_right = 0

middle_left = 0
center = 0
middle_right = 0

bottem_left = 0
bottem_middle = 0
bottem_right = 0

#code for changing turns
turn = 1
def turn_changer():
    global turn
    if turn == 1:
        turn = 2
    else:
        turn = 1

#board setup
def setup():
    size(600,600)

#this hurt my brain trying to fully understand
#lines dividing board
def draw():
    for y in range(3):
        for x in range(3):
            rect(200*x,200*y,200,200)
    #hope this is not what geomtry is like

    #top left ellipse
    if top_left == 1:
        ellipse(100,100,150,150)

    #top left X
    elif top_left == 2:
        line(0,0,200,200)
        line(200,0,0,200)

    #top middle ellipse
    if top_middle == 1:
        ellipse(300,100,150,150)

    #top middle  X
    elif top_middle == 2:
        line(200,0,400,200)
        line(400,0,200,200)

    #top right ellipse
    if top_right == 1:
        ellipse(500,100,150,150)

    #top right X
    elif top_right == 2:
        line(400,0,600,200)
        line(600,0,400,200)

    #middle left ellipse
    if middle_left == 1:
        ellipse(100,300,150,150)

    #middle left X
    elif middle_left == 2:
        line(0,200,200,400)
        line(200,200,0,400)

    #middle ellipse
    if center == 1:
        ellipse(300,300,150,150)

    #middle X
    elif center == 2:
        line(200,200,400,400)
        line(400,200,200,400)

    #middle right ellipse
    if middle_right == 1:
        ellipse(500,300,150,150)

    #middle right X
    elif middle_right == 2:
        line(400,200,600,400)
        line(600,200,400,400)

    #bottem left ellipse
    if bottem_left == 1:
        ellipse(100,500,150,150)

    #bottem left  X
    elif bottem_left == 2:
        line(0,400,200,600)
        line(200,400,0,600)

    #bottem middle ellipse
    if bottem_middle == 1:
        ellipse(300,500,150,150)

    #bottem middle X
    elif bottem_middle == 2:
        line(200,400,400,600)
        line(400,400,200,600)

    #bottem right ellipse
    if bottem_right == 1:
        ellipse (500,500,150,150)

    #bottem right Xw
    elif bottem_right == 2:
        line(400,400,600,600)
        line(600,400,400,600)


#dectects the quardnates where the mouse clicked and prints them
def mousePressed():
    println( (mouseX, mouseY) )

    #top left square hitbox
    if (mouseX > 0 and mouseX < 200) and (mouseY > 0 and mouseY < 200):
        top_left =+ turn
        turn_changer()
        print("top left")



    #top middle square hitbox 
    elif (mouseX > 200 and mouseX < 400) and (mouseY > 0 and mouseY < 200): 
        top_middle = turn      
        turn_changer()
        print(turn)
        print("top middle")


    #top right square hitbox  
    elif (mouseX > 400 and mouseX < 600) and (mouseY > 0 and mouseY < 200):  
        top_right = turn
        turn_changer()
        print("top right")

    #middle left square hitbox
    elif (mouseX > 0  and mouseX < 200) and (mouseY > 200 and mouseY < 400):  
        middle_left = turn
        turn_changer()
        print("middle left")

    #center square hitbox
    elif (mouseX > 200 and mouseX < 400) and (mouseY > 200 and mouseY < 400):  
        center = turn
        turn_changer()
        print("middle")  

    #middle right square hitbox
    elif (mouseX > 400 and mouseX < 600) and (mouseY > 200 and mouseY < 400):  
        middle_right = turn
        turn_changer()
        print("middle right") 

    #bottem left square hitbox
    elif (mouseX > 0 and mouseX < 200) and (mouseY > 400 and mouseY < 600):  
        bottem_left = turn
        turn_changer()
        print("bottem left")

    #bottem middle square hitbox
    elif (mouseX > 200 and mouseX < 400) and (mouseY > 400 and mouseY < 600):  
        bottem_middle = turn
        turn_changer()
        print("bottem middle")

    #bottem right square hitbox
    elif (mouseX > 400 and mouseX < 600) and (mouseY > 400 and mouseY < 600):  
        bottem_right = turn
        turn_changer()
        print("bottem right")

Tags: andrightmiddleiftoplineleftturn
3条回答

有很多方法可以做到这一点

  1. 你可以翻转一个变量(有点像你刚才展示的那样)。因为只有两个玩家,我可能会在每次回合后翻转一个布尔值:myBoolean = !myBoolean
  2. 您可以计算圈数并使用modulo运算符。然后你们都知道现在是哪个回合,以及当前游戏的总回合数。假设您有一个全局TurnCount变量。如果你这样做TurnCount % 2,结果将是0或1,这是一个确定的方法来知道它是哪个回合。这个操作符非常有用,你应该记住它
  3. 如果玩家1和玩家2之间除了X和O之外在游戏性上没有什么不同,那么您可以在角色“X”和角色“O”之间切换,而不是像代码片段中那样在1和2之间切换。此变量可用于直观显示将放置哪个符号,或直接向上放置一个符号或另一个符号。简单高效

所以,这主要取决于你的代码是怎样的忍者。如果你正在做一个“simpel hot seat”,玩家轮流用同一个鼠标点击,那么方法3非常好。如果您想在游戏结束后显示“统计数据”,方法2将很好地工作。方法1也会起作用,但它更粗糙,即使它很简单。如果需要定制建议,可以添加更多代码

玩得开心

按下按钮时,检查转角是否等于1或2,然后告诉程序显示一个十字或一个圆,而不是执行更改该值的功能

希望这有帮助

我尊重您的自学能力,因此我花了一些时间学习python的基础知识,让您思考一些问题。我还不是python爱好者,所以我可能在某个地方做了一些误导性的操作(因此,如果有一个比我更好的程序员在读这篇文章并发现了一些糟糕的东西,请让我知道),但我相信这大部分是好东西

我使用了class,因为我倾向于在OOP中思考(一段时间后你也会这样)。我看到的不是X和O的网格,而是这样的游戏:

Tic-tac-toe

  1. 一个游戏就是一个目标
  2. 游戏管理:

    网格(也是一个对象)

    轮到谁了(当轮到人工智能时,人工智能应该如何发挥)

    比赛结束时

  3. 网格管理:

    9例(也是实物)

  4. 案例管理:

    它自己画(所以…是坐标之类的)

    如果上面有X或O

    如果已单击它

我完全意识到,当你开始编程时,对象是学习曲线上的一个巨大障碍,但我坚持在这里,因为我在你的代码中看到了很多硬编码,当你扩展你的项目时,这种东西会给你带来问题

硬编码,比如你如何检查哪一个案例被点击,从本质上来说并不坏,但它让一切变得更加困难。这是你有时通过“艰苦的方式”学到的东西的一部分,所以我的建议是:当你忍者编写一些东西(写得很快的短代码片段,不会成为更大的东西的一部分)时,它不是很好,但它确实起到了作用。在任何其他情况下,它必须是出于某种特定的需要,成为一种良好的实践,即使在这种情况下,大多数情况下也可以避免

这里是基于我刚刚写的注释代码。我没有做整个tic-tac-toe游戏,只是在玩家或玩家/人工智能之间切换(我在上面放了一个布尔值,让你在人类对手和人工智能对手之间切换)。缺少的主要是人工智能逻辑(我把一个临时逻辑放在它选择找到的第一个案例的地方)和胜利条件

布尔值当前处于“玩家对玩家”模式。将其更改为True,让AI接管O端

# Player 1 (X) is human and play first
# Player 2 (O) is cpu
# You can change this boolean to play hotseat with a human if you want:
_AIPlayer = False

# Game own a grid, count turns and do any other game-specific concepts
# One "game of tic-tac-toe" would equal one of this object
class Game:
    def __init__(self):
        self.Grid = Grid(self) # creating the grid we'll use
        self.TurnCount = 0 # first turn is turn number zero

    def Render(self):
        # when you draw the game, in fact it asks it's grid to draw itself
        self.Grid.Render()

    def Play(self):
        # if it's the CPU's turn, let him play, else the game will wait for the player before going forward
        # if there is no cpu player, the mouse can be used by player two
        # the difference is that the cpu will do it's turn as a consequence of the player's turn
        # and then add +1 to the turn count, while player 2 is exactly like player one but with O instead of X
        # the game will check X and O to see who win, not a player class (but it could have been designed that way if needed)
        if self.GetCurrentPlayer() == "O" and _AIPlayer:
            self.AITurn()

    def GetCurrentPlayer(self):
        # return which's player is currently playing
        if self.TurnCount % 2 == 0:
            return "X"
        else:
            return "O"

    def AITurn(self):
        # this is a dumb placeholder
        # your AI logic will be used here
        # for now it just put a O on the first available case
        print("AI turn")
        for c in self.Grid.Cases:
            if c.XO == "":
                c.XO = self.GetCurrentPlayer()
                break
        self.TurnCount += 1


# Grid class is the whole grid
class Grid:
    def __init__(self, game):
        # the grid knows the game. I could use the global variable instead, but I dislike
        # this kind of spaghetti. It would have worked, though.
        # It's usually best to make everything you can dynamic, i.e. not hardcoded. 
        # It's easier to maintain and fix bugs that way, and you can upscale more easily too
        # for an example, I could use this code to run several tic-tac-toe games in the
        # same window at the same time with only a few modifications
        self.Game = game
        self.Cases = []
        for i in range(3):
            for j in range(3):
                self.Cases.append(GridCase(i, j))

    def Render(self):
        # when you draw the grid, in fact it ask it's cases to draw themselves
        for c in self.Cases:
            c.Render()

    def CaseClicked(self, xPos, yPos):
        # this checks which case was clicked when it's a player
        # since we don't care about the case's coordinated, we ask them if they have been clicked instead
        for c in self.Cases:
            if c.Clicked(xPos, yPos, self.Game.GetCurrentPlayer()):
                self.Game.TurnCount += 1
                return


# GridCase is each instance of 1 case in the grid
class GridCase:    
    def __init__(self, gridX, gridY):
        # gridX and gridY are useful to know which case is part of which line
        self.gridX = gridX
        self.gridY = gridY
        # I hardcoded the case's width and height, but you could totally make them dynamic
        # and decide "on the fly" how big the grid will be. And it would still work.
        self.w = 200  # width
        self.h = 200  # height
        # these coordinates are in pixels, and are useful to draw the case and for hit detection
        self.x = self.w * gridX # x coordinate of the case
        self.y = self.h * gridY # y coordinate of the case
        # the "content" of the case
        self.XO = ""  # X or O as a character (it could be anything, I choose to stick to these)

    def Render(self):
        # the lines positions are dynamic: they'll be calculated from the case's perspective
        # every case top left corner is in fact: (self.x, self.y)
        rect(self.x, self.y, self.w, self.h)
        # if the case has content, it'll be drawn at the same time than the case
        if self.XO == "X":
            line(self.x , self.y, self.x+self.w, self.y+self.h)
            line(self.x, self.y+self.h, self.x+self.w, self.y)
        elif self.XO == "O":
            ellipse(self.x+(self.w/2),self.y+(self.h/2), self.w*0.75, self.h*0.75)

    def SetXO(self, XO):
        self.XO = XO

    def Clicked(self, xPos, yPos, car):
        # if the case is free and the click was inside it's boundaries, then attribute it to the current player
        # the return True to tell that a sign was just placed
        if self.XO == "" and xPos > self.x and xPos < self.x + self.w and yPos > self.y and yPos < self.y + self.h:
            self.XO = car
            return True
        return False


# globals
_game = Game()

def setup():
    size(600,600)

def draw():
    # background wipes the screen "clean" (here it paints it black)
    # then we can draw the current state of the grid
    # here we could do without but I wanted you to know about it
    background(0)
    # draw the grid, then let the players do their thing
    _game.Render()
    # here you should check for game end conditions (victory or draw)
    _game.Play()

def mouseClicked():
   # listeing to mouse clicks
   _game.Grid.CaseClicked(mouseX, mouseY)

您应该将此代码复制并粘贴到Processing.py IDE中,然后重试。闲逛并阅读评论。如果你尝试,你可以在这里学到很多东西。如果你有问题,请用我的手柄在评论中提问,我会回来帮你

而且。。。玩得开心

相关问题 更多 >