【问题标题】:Im making a simple TicTacToe in pyjama but I am running into some errors我穿着睡衣做了一个简单的井字游戏,但我遇到了一些错误
【发布时间】:2020-12-31 14:47:08
【问题描述】:

draw Board 函数有一个 if 语句来查看它应该绘制哪个色环。但是当单击鼠标按钮时,它会在右侧 x 坐标但在相反的 y 坐标上绘制圆。另外,结尾有点奇怪,我想显示获胜者,然后使用time.wait 等待,但它会等待,然后打印声明一秒钟。如果你能运行它,你就会明白。我也在寻找可以做出的总体改进。

import pygame, sys
import numpy as np
import math

pygame.init()
clock = pygame.time.Clock()

# Colours
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

ROW_COUNT = 3
COLUMN_COUNT = 3
SQUARE_SIZE = 100
RADIUS = int(SQUARE_SIZE/2 - 5)

WIDTH = COLUMN_COUNT * SQUARE_SIZE
HEIGHT = ROW_COUNT * SQUARE_SIZE

myfont = pygame.font.SysFont("monospace", 20)

PLAYER_COUNT = 2
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen.fill(WHITE)


class Player:
    def __init__(self, number):
        self.number = number


players = [Player(i) for i in range(1, PLAYER_COUNT + 1)]


class Board:
    def __init__(self):
        self.board_body = np.zeros((ROW_COUNT, COLUMN_COUNT), dtype=np.uint8)
        self.remaining_spaces = 9
        self.print_board()
        self.draw_board()

    def print_board(self):
        print(np.flip(self.board_body, 0))

    def draw_board(self):
        one_x, one_y, one_end_x, one_end_y, two_x, two_y, two_end_x, two_end_y = 100, 0, 100, 300, 0, 100, 300, 100
        for r in range(ROW_COUNT):
            for c in range(COLUMN_COUNT):
                pygame.draw.line(screen, BLACK, (one_x, one_y), (one_end_x, one_end_y), 3)
                one_x += 100
                one_end_x += 100
            pygame.draw.line(screen, BLACK, (two_x, two_y), (two_end_x, two_end_y), 3)
            two_y += 100
            two_end_y += 100

        for c in range(COLUMN_COUNT):
            for r in range(ROW_COUNT):
                if self.board_body[r][c] == 1:
                    pygame.draw.circle(screen, RED, (int(c * SQUARE_SIZE + SQUARE_SIZE / 2), HEIGHT - int(r * SQUARE_SIZE + SQUARE_SIZE / 2)), RADIUS)
                elif self.board_body[r][c] == 2:
                    pygame.draw.circle(screen, GREEN, (int(c * SQUARE_SIZE + SQUARE_SIZE / 2), HEIGHT - int(r * SQUARE_SIZE + SQUARE_SIZE / 2)), RADIUS)
    pygame.display.update()

    def check_empty_space_and_place(self, row, column, number):
        if self.board_body[row][column] == 0:
            self.board_body[row][column] = number
            self.remaining_spaces -= 1

    def check_winning_move(self, board, piece):
        # Horizontal
        for c in range(COLUMN_COUNT - 1):
            for r in range(ROW_COUNT - 1):
                if board[r - 1][c] == piece and board[r][c] == piece and board[r + 1][c] == piece:
                    return True

        # Vertical
        for c in range(0, COLUMN_COUNT - 1):
            for r in range(0, ROW_COUNT - 1):
                if board[r][c - 1] == piece and board[r][c] == piece and board[r][c + 1] == piece:
                    return True
        # Positively sloped diagonals
        for c in range(0, COLUMN_COUNT - 1):
            for r in range(0, ROW_COUNT - 1):
                if board[r][c] == piece and board[r + 1][c + 1] == piece and board[r + 2][c + 2] == piece:
                    return True

        # Negatively sloped diagonals
        for c in range(COLUMN_COUNT - 1):
            for r in range(ROW_COUNT - 1):
                if board[r + 1][c + 1] == piece and board[r][c] == piece and board[r - 1][c - 1] == piece:
                    return True


def next_player():
    while True:
        for player in players:
            yield player


player_generator = next_player()

board = Board()

run = True

while run:
    if board.remaining_spaces == 0:
        run = False
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.MOUSEBUTTONDOWN:
            pos_of_mouse = pygame.mouse.get_pos()
            posx = pos_of_mouse[0]
            posy = pos_of_mouse[1]
            column = int(posx // SQUARE_SIZE)
            row = int(posy // SQUARE_SIZE)
            p = player_generator.__next__()
            board.check_empty_space_and_place(row, column, p.number)
            board.draw_board()
            if board.check_winning_move(board.board_body, p.number):
                label = myfont.render("Player {} wins!!!!".format(p.number), False, WHITE)
                screen.fill(BLACK)
                screen.blit(label, (20, 50))
                pygame.time.wait(3000)
                run = False

    board.print_board()
    pygame.display.update()
    clock.tick(60)```

【问题讨论】:

    标签: python matrix pygame tic-tac-toe


    【解决方案1】:

    在 PyGame 坐标系中,左上角是 (0, 0)。您不必翻转 y 轴或从高度中减去 y 坐标。去掉Board类的方法draw_board中的HEIGHT - 一词:

    class Board:
        # [...]
    
        def draw_board(self):
            # [...]
    
            for c in range(COLUMN_COUNT):
                for r in range(ROW_COUNT):
                    if self.board_body[r][c] == 1:
                        pygame.draw.circle(screen, RED, (int(c * SQUARE_SIZE + SQUARE_SIZE / 2), int(r * SQUARE_SIZE + SQUARE_SIZE / 2)), RADIUS)
                    elif self.board_body[r][c] == 2:
                        pygame.draw.circle(screen, GREEN, (int(c * SQUARE_SIZE + SQUARE_SIZE / 2), int(r * SQUARE_SIZE + SQUARE_SIZE / 2)), RADIUS)
            
            # [...]
    

    如果您只是等待一段时间,您可以使用pygame.time.waitpygame.time.delay。但是,如果要显示一条消息然后等待一段时间,则需要事先更新显示。仅当 pygame.display.update()pygame.display.flip() 时,才会更新显示 叫做。此外,您必须通过pygame.event.pump() 处理事件,然后才能在窗口中看到显示的更新:
    (见How to wait some time in pygame?

    screen.fill(BLACK)
    screen.blit(label, (20, 50))
    pygame.display.flip()
    pygame.event.pump()
    pygame.time.wait(3000)
    

    此外,在寻找获胜者时也会出现一些错误。哟根本不需要嵌套循环。只有2条对角线。所以对角线不需要任何循环:

    class Board:
        # [...]
    
        def check_winning_move(self, board, piece):
            # Horizontal
            for c in range(COLUMN_COUNT):
                if board[0][c] == piece and board[1][c] == piece and board[2][c] == piece:
                    return True
    
            # Vertical
            for r in range(ROW_COUNT):
                if board[r][0] == piece and board[r][1] == piece and board[r][2] == piece:
                    return True
    
            # Positively sloped diagonals
            if board[0][0] == piece and board[1][1] == piece and board[2][2] == piece:
                return True
    
            # Negatively sloped diagonals
            if board[0][2] == piece and board[1][1] == piece and board[2][0] == piece:
                return True
    

    另见Pygame Tic Tak Toe Logic? How Would I Do It


    完整代码:

    import pygame, sys
    import numpy as np
    import math
    
    pygame.init()
    clock = pygame.time.Clock()
    
    # Colours
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    
    ROW_COUNT = 3
    COLUMN_COUNT = 3
    SQUARE_SIZE = 100
    RADIUS = int(SQUARE_SIZE/2 - 5)
    
    WIDTH = COLUMN_COUNT * SQUARE_SIZE
    HEIGHT = ROW_COUNT * SQUARE_SIZE
    
    myfont = pygame.font.SysFont("monospace", 20)
    
    PLAYER_COUNT = 2
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    screen.fill(WHITE)
    
    
    class Player:
        def __init__(self, number):
            self.number = number
    
    
    players = [Player(i) for i in range(1, PLAYER_COUNT + 1)]
    
    
    class Board:
        def __init__(self):
            self.board_body = np.zeros((ROW_COUNT, COLUMN_COUNT), dtype=np.uint8)
            self.remaining_spaces = 9
            self.print_board()
            self.draw_board()
    
        def print_board(self):
            print(np.flip(self.board_body, 0))
    
        def draw_board(self):
            one_x, one_y, one_end_x, one_end_y, two_x, two_y, two_end_x, two_end_y = 100, 0, 100, 300, 0, 100, 300, 100
            for r in range(ROW_COUNT):
                for c in range(COLUMN_COUNT):
                    pygame.draw.line(screen, BLACK, (one_x, one_y), (one_end_x, one_end_y), 3)
                    one_x += 100
                    one_end_x += 100
                pygame.draw.line(screen, BLACK, (two_x, two_y), (two_end_x, two_end_y), 3)
                two_y += 100
                two_end_y += 100
    
            for c in range(COLUMN_COUNT):
                for r in range(ROW_COUNT):
                    if self.board_body[r][c] == 1:
                        pygame.draw.circle(screen, RED, (int(c * SQUARE_SIZE + SQUARE_SIZE / 2), int(r * SQUARE_SIZE + SQUARE_SIZE / 2)), RADIUS)
                    elif self.board_body[r][c] == 2:
                        pygame.draw.circle(screen, GREEN, (int(c * SQUARE_SIZE + SQUARE_SIZE / 2), int(r * SQUARE_SIZE + SQUARE_SIZE / 2)), RADIUS)
        pygame.display.update()
    
        def check_empty_space_and_place(self, row, column, number):
            if self.board_body[row][column] == 0:
                self.board_body[row][column] = number
                self.remaining_spaces -= 1
    
        def check_winning_move(self, board, piece):
            # Horizontal
            for c in range(COLUMN_COUNT):
                if board[0][c] == piece and board[1][c] == piece and board[2][c] == piece:
                    return True
    
            # Vertical
            for r in range(ROW_COUNT):
                if board[r][0] == piece and board[r][1] == piece and board[r][2] == piece:
                    return True
    
            # Positively sloped diagonals
            if board[0][0] == piece and board[1][1] == piece and board[2][2] == piece:
                return True
    
            # Negatively sloped diagonals
            if board[0][2] == piece and board[1][1] == piece and board[2][0] == piece:
                return True
    
    
    def next_player():
        while True:
            for player in players:
                yield player
    
    
    player_generator = next_player()
    
    board = Board()
    
    run = True
    
    while run:
        if board.remaining_spaces == 0:
            run = False
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
    
            if event.type == pygame.MOUSEBUTTONDOWN:
                pos_of_mouse = pygame.mouse.get_pos()
                posx = pos_of_mouse[0]
                posy = pos_of_mouse[1]
                column = int(posx // SQUARE_SIZE)
                row = int(posy // SQUARE_SIZE)
                p = player_generator.__next__()
                board.check_empty_space_and_place(row, column, p.number)
                board.draw_board()
                if board.check_winning_move(board.board_body, p.number):
                    label = myfont.render("Player {} wins!!!!".format(p.number), False, WHITE)
                    screen.fill(BLACK)
                    screen.blit(label, (20, 50))
                    pygame.display.flip()
                    pygame.event.pump()
                    pygame.time.wait(3000)
    
                    run = False
    
        board.print_board()
        pygame.display.update()
        clock.tick(60)
    

    【讨论】:

    • 谢谢,你能帮忙解决一些其他问题吗
    • 如果我在任何我按的地方拿掉负1,它就会说索引超出范围
    • 您在最后问题上修复了屏幕,但更大的问题是我按下内部表示的任何位置,并且图形表示具有相反的 y 坐标,例如,如果我要在底行中间放置一个圆圈列它将被放置在内部和图形的顶行中间列
    • 在内部发生这种情况是因为我在 print_board 函数中使用 lumpy.flip 垂直翻转它
    • 好的我现在看到了答案 check_winning_move 方法应该如何
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    • 2020-02-03
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 2021-11-12
    相关资源
    最近更新 更多