我穿着睡衣做了一个简单的 TicTacToe,但我 运行 犯了一些错误

Im making a simple TicTacToe in pyjama but I am running into some errors

绘图板函数有一个 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)```

在PyGame坐标系中左上角为(0, 0)。您不必翻转 y 轴或从高度中减去 y 坐标。在 class 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.wait or pygame.time.delay. However, if you want to display a message and then wait some time, you need to update the display beforehand. The display is updated only if either pygame.display.update() or pygame.display.flip() 叫做。此外,在显示更新在 window:
中可见之前,您必须通过 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

另见


完整代码:

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)