Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Cube drawing
#21
Now it's a great solution! Thanks again!

Do you know maybe how can I set some time between my turn and computer's turn (I want to make the computer playing its move 1 second after me (for example))? I tried "time.wait(1000)" either in robot.play() function or in while loop in the main() function but nothing worked. I just succeeded to make it a second before both turns together.

Also, I wanted to print the winner under the board (for example: "You win!", "Computer wins"), tried with winner = font.render(...) and winner.get_rect() but I just keep getting errors.
Reply
#22
You need to draw the cube, wait, make robot play, draw the cube. I think I posted a version that had the extra draw, back when the robot player was slow. The idea of waiting on purpose is bizarre.

Drawing text is easy. There are tons of examples on the internet.
Reply
#23
No no, I didn't mean to make it look like the computer's thinking, I thought it would be better if a second passes by (or even a couple of miliseconds), visually it would be better because now it looks like you click it twice, even though if you know that you clicked only once.
Reply
#24
If all you want is enough delay that you can see two drawing events, draw the cube just before having the robot make a move.
                if cube.mark == ROBOT and not cube.done():
                    cube.draw(surface)    # Add this line
                    cube.play(robot.play(), "O")
Reply
#25
Yeah, makes sense, thanks.

And for text that you said, I searched for some examples all over the internet (in my case how to display "you win" and "computer wins"), copied and mixed some parts (which are repeating almost all the time) but can't make it work.

I tried to display "game over" just to see if it works but nothing, I suppose because of an infinite loop until I exit the window.

running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if cube.done():
                    text = font.render("Game Over", True, (255,255,255))
                    text_rect = text.get_rect()
                    text_x = surface.get_width() / 2 - text_rect.width / 2
                    text_y = surface.get_height() / 2 - text_rect.height / 2
                    surface.blit(text, [text_x, text_y])
                    cube.reset()
                else:
                    cube.click(pygame.Vector2(event.pos))
                    pygame.event.clear()
                if cube.mark == ROBOT and not cube.done():
                    cube.draw(surface)
                    cube.play(robot.play(), "O")
                cube.draw(surface)
Reply
#26
Do you think about what you are doing first, or do you immediately start coding? This is an easy problem to solve if you think about what it means to refresh the pygame screen.

You can think of pygame as having two screens. The one you see and the one you draw on. I'll call the screen you draw on as the "backing screen" and the one you can see the "visible screen". After drawing to the backing screen you call display.flip() (or display.update()) to draw the backing screen to the visible screen.

To normal way to refresh the screen in pygame starts with erasing the backing screen or drawing a full screen background. Next you draw all the objects you want to appear on the visible screen. After everything is drawn on the backing screen you flip the visible screen to display the backing screen. This is how cube.draw(surface) works. Every time cube.draw(surface) is called, anything previously drawn to the backing screen gets erased.

Your code has two problems. The first problem is you are not drawing the text when the game is over. You draw your message when the player resets the board. This is when the board gets reset and the cube is redrawn. What you should do is check cube.done() after calling cube.play(). If the cube is done you know it is the result of the last play.

The second problem is that you refresh the screen immediately after you draw the text. cube.draw(surface) is called each time there is a MOUSEBUTTONDOWN event. This erases your text before anyone has a chance to see it. If you want text to remain on the screen you need to draw the text after the screen is refreshed or add drawing text to the refresh function. Either will work, but I prefer the latter. I like keeping all the screen drawing code in one place instead of sprinkling it around throughout the program. It makes it easier to control the drawing order. You want to draw the message after drawing the cube. You want to draw the cube after drawing the background.
Reply
#27
I got your point. But why can't I do it this way, just need to remove one extra click when the game's done. Maybe try to remove "if cube.done()" condition and somehow combine it with the others.

I'm not trying to act smart, just presenting how I'm thinking and trying to understand this.

    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if cube.done():
                    text = font.render("Game Over", True, (255,255,255))
                    text_rect = text.get_rect()
                    text_x = surface.get_width() / 2 - text_rect.width / 2
                    text_y = surface.get_height() / 2 - text_rect.height / 2
                    surface.blit(text, [text_x, text_y])
                    pygame.display.flip()
                    cube.reset()
                    break
                else:
                    cube.click(pygame.Vector2(event.pos))
                    pygame.event.clear()
                if cube.mark == ROBOT and not cube.done():
                    cube.draw(surface)
                    cube.play(robot.play(), "O")
                cube.draw(surface)
Reply
#28
Your if cube.done() is in the wrong place. The game ends and the screen doesn't show a message until you click the mouse. Then you have to click again to start a new game.

And the code is ugly. if you keep the pygame event loop small it is fairly easy to understand the game logic. I've seen pygame code were everything is in the main loop and it is impossible to follow what's happening. You cannot control that the code required to draw a simple message in pygame is ugly, but you can control where you put that code. I would remove the cube.draw() method and make a refresh() function. The refresh() function would do all the screen drawing, including displaying a message. If you wanted to add a scoreboard or a title, or anything, it will be much easier if you have all the code for drawing that stuff located in one place.
def refresh(surface, cube, msg=None):
    """Draw all the tic-tac-toe boards."""
    surface.fill("white")
    for square in cube.squares:
        square.draw(surface)
    if msg:
        text = pygame.font.Font(None, 100).render(text, True, 'white')
        rect = text.get_rect()
        pos = ((surface.get_width() - rect.width) / 2, (surface.get_height() - rect.height) / 2)
        surface.blit(text, pos)
    pygame.display.flip()
Still ugly, but isolated.

Now the main loop can be tight again.
    refresh(surface, cube)
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if cube.done():
                    # Game over.  Start a new game
                    cube.reset()
                    if cube.mark == ROBOT:
                        cube.play(robot.play(), ROBOT)
                    refresh(surface, cube)
                else:
                    if cube.click(pygame.Vector2(event.pos)):
                        # Player selected square.  Robot's turn,
                        if not cube.done():
                            refresh(surface, cube)
                            cube.play(robot.play(), ROBOT)
                        # Is the game over?
                        refresh(surface, cube, "Game Over" if cube.done() else None)
                        pygame.event.clear()
Reply
#29
Could you please implement that in the whole code? I tried it now, made text a global variable in the refresh() function because of "UnboundLocalError: local variable 'text' referenced before assignment" but still can't make it work. I don't get all the logic ...

"""A tic-tac-toe game"""
import pygame
import random

PLAYER = 'X'
ROBOT = 'O'
colors = {None: 'gray30', ROBOT: 'red', PLAYER: 'green'}
 

class Robot:
    """Computer tic-tac-toe player"""
    def __init__(self, cube):
        self.boards = cube.boards
 
    def get_scores(self, board):
        """Get scores for all open squares on a board"""
 
        def minimax(mark, square, alpha=-1000, beta=1000, depth=0):
            """Compute a score for the square.  Uses using minimax
            algorithm with alpha/beta pruning.
            """
            # Place the marker and compute a score for the square.
            # Score is a win, a loss, a draw, or the score from
            # the next play.
            square.mark = mark
            if square.check_win():
                # Give extra weight to earlier wins/losses
                score = 10 - depth if mark == ROBOT else depth - 10
                board.depth = min(board.depth, depth)
            else:
                empty_squares = board.empty_squares()
                if not empty_squares:
                    score = 0  # Draw
                elif mark == PLAYER:
                    # Pick best move for robot
                    score = -1000
                    for s in empty_squares:
                        score = max(score, minimax(ROBOT, s, alpha, beta, depth+1))
                        alpha = max(alpha, score)
                        if alpha > beta:
                            break
                else:
                    # Guess what move we think player will make
                    score = 1000
                    for s in empty_squares:
                        score = min(score, minimax(PLAYER, s, alpha, beta, depth+1))
                        beta = min(beta, score)
                        if alpha > beta:
                            break
            # Undo play and return score
            square.mark = None
            return score
 
        # Collect scores for empty squares.  If board is empty,
        # minimax will return 0 for all squares
        board.depth = 10
        empty_squares = board.empty_squares()
        if len(empty_squares) == 9:
            board.scores = [[0, s] for s in empty_squares]
        else:
            # Calling minimax twice.  The first is to find the square
            # giving us best chance to win board.  Second is to prevent
            # abandoning board early and giving player an easy win.
            board.scores = [[minimax("O", s), s] for s in empty_squares]
            [minimax("X", s, depth=1) for s in empty_squares]
 
    def play(self):
        """Place robot mark."""
        # Get scores for all empty squares
        pygame.time.wait(1000)
        depth = 10
        for board in self.boards:
            self.get_scores(board)
            depth = min(depth, board.depth)
 
        # Select board(s) with minimum depth.  This is the board(s) that
        # will win/lose in the least number of moves.
        scores = []
        for board in self.boards:
            if board.depth <= depth:
                scores.extend(board.scores)
 
        # Randomly select from best scores on the selected board(s).
        max_score = max(score[0] for score in scores)
        squares = [score[1] for score in scores if score[0] >= max_score]
        return random.choice(squares)
 
 
class Square:
    """I am a square in a tic-tac-toe board in 3D"""
    def __init__(self, board, index, side, center=(0, 0, 0)):
        self.board = board
        self.index = index
        self.mark = None
        self.corners = [
            pygame.Vector3(-1, -1, 0) * side / 2,
            pygame.Vector3(1, -1, 0) * side / 2,
            pygame.Vector3(1, 1, 0) * side / 2,
            pygame.Vector3(-1, 1, 0) * side / 2
        ]
        self.move(center)
 
    def rotate(self, rotation):
        """Rotate square (rx, ry, rz) degrees"""
        for deg, axis in zip(rotation, ((1, 0, 0), (0, 1, 0), (0, 0, 1))):
            if deg:
                for corner in self.corners:
                    corner.rotate_ip(deg, axis)
 
    def move(self, offset):
        """Move square offset (x, y, z) pixels"""
        x, y, z = offset
        for corner in self.corners:
            corner.x += x
            corner.y += y
            corner.z += z
 
    def projection(self):
        """Return corners projected on xy plane"""
        return [pygame.Vector2(p.x, p.y) for p in self.corners]
 
    def draw(self, surface):
        """Draw projection of square on xy plane"""
        pygame.draw.polygon(surface, colors[self.mark], self.projection())
 
    def contains(self, point):
        """Return True if projection contains point."""
        def area(a, b, c):
            """Compute area of triangle"""
            return abs((a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)) / 2.0)
 
        def has_point(a, b, c, p):
            """Return True if triange ABC contains point p."""
            return area(a, b, c) >= int(area(a, p, b) + area(b, p, c) + area(c, p, a))
 
        a, b, c, d = self.projection()
        return has_point(a, b, c, point) or has_point(a, c, d, point)
 
    def check_win(self):
        return self.board.check_win(self)
 
 
class Board:
    """A 3x3 tic-tac-toe board"""
    winning_combos = (
        (0, 2, 4, 6, 8), (1, 3, 5, 7), (0, 1, 2), (3, 4, 5),
        (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8)
    )
 
    def __init__(self, side):
        dx = side / 3
        self.squares = []
        for index in range(9):
            x = (index % 3 - 1) * dx
            y = (index // 3 - 1) * dx
            self.squares.append(Square(self, index, dx - 3, (x, y, 0)))
        self.scores = None
        self.depth = 10
 
    def empty_squares(self):
        """Return list of empty squares"""
        return [s for s in self.squares if s.mark is None]
 
    def check_win(self, square):
        """Return winning combination from last move, else None"""
        for combo in self.winning_combos:
            if square.index in combo:
                squares = [self.squares[i] for i in combo]
                if all(square.mark == s.mark for s in squares):
                    return squares
        return None
 
 
class Cube:
    """Three tic-tac-toe boards plastered on the sides of a cube"""
    def __init__(self, side):
        def make_board(center, rotation):
            board = Board(side)
            for square in board.squares:
                square.rotate(rotation)
                square.move(center)
            return board
 
        self.boards = [
            make_board((0, 0, -side/2), (0, 0, 0)),
            make_board((side/2, 0, 0), (0, 270, 0)),
            make_board((0, -side/2, 0), (90, 0, 0))
        ]
        self.squares = [s for b in self.boards for s in b.squares]
        self.winner = None
        self.mark = PLAYER
        self.reset()
 
    def click(self, point):
        """Try to place mark in clicked square."""
        if self.mark == PLAYER:
            for square in self.squares:
                if square.contains(point):
                    if square.mark is None:
                        self.play(square, self.mark)
                        return square
                    break
        return None
 
    def play(self, square, mark):
        """Place mark in square.  Test if is a winning move"""
        square.mark = mark
        self.mark_count += 1
        if winner := square.check_win():
            self.winner = winner
            for square in self.squares:
                if square not in winner:
                    square.mark = None
        self.mark = PLAYER if mark == ROBOT else ROBOT
 
    def done(self):
        """Return True if there is a winner or draw"""
        return self.winner or self.mark_count >= 27
 
    def reset(self):
        """Reset all boards to empty"""
        self.mark_count = 0
        self.winner = None
        for square in self.squares:
            square.mark = None
 
    def draw(self, surface):
        """Draw all the tic-tac-toe boards."""
        surface.fill("gray95")
        for square in self.squares:
            square.draw(surface)
        pygame.display.flip()
 

def refresh(surface, cube, msg=None):
    """Draw all the tic-tac-toe boards."""
    global text
    surface.fill("white")
    for square in cube.squares:
        square.draw(surface)
    if msg:
        text = pygame.font.Font(None, 100).render(text, True, 'white')
        rect = text.get_rect()
        pos = ((surface.get_width() - rect.width) / 2, (surface.get_height() - rect.height) / 2)
        surface.blit(text, pos)
    pygame.display.flip()
 
def main():
    """Play tic-tac-toe"""
    pygame.display.set_caption("Tic-Tac-Toe")
    surface = pygame.display.set_mode((750, 750))
    cube = Cube(300)
    center = surface.get_rect()
    font = pygame.font.SysFont('Times New Roman', 40)
    for square in cube.squares:
        square.rotate((0, 45, 0))
        square.rotate((30, 0, 0))
        square.move((center.centerx, center.centery, 0))
    robot = Robot(cube)
    cube.draw(surface)

    refresh(surface, cube)
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if cube.done():
                    # Game over.  Start a new game
                    cube.reset()
                    if cube.mark == ROBOT:
                        cube.play(robot.play(), ROBOT)
                    refresh(surface, cube)
                else:
                    if cube.click(pygame.Vector2(event.pos)):
                        # Player selected square.  Robot's turn,
                        if not cube.done():
                            refresh(surface, cube)
                            cube.play(robot.play(), ROBOT)
                        # Is the game over?
                        refresh(surface, cube, "Game Over" if cube.done() else None)
                        pygame.event.clear()
 
if __name__ == "__main__":
    pygame.init()
    main()
    pygame.quit()
Also, is there any similar logic by which, during the game, I can display for example "your turn" and "computer's turn" so that I don't have to make a new function?
Reply
#30
Sorry about that. I was in mid-edit, cleaning up the code.
    if msg:
        text = pygame.font.Font(None, 100).render(msg, True, 'white')
Are you learning anything from this, or do you just want a tic-tac-toe game? This last error was very obvious. That you didn't catch it immediately makes me think that you are so overwhelmed by other parts of the code that your brain switches off. If you have questions, ask. I'll answer questions if it is obvious that you put some effort into formulating good questions.

If you just want a tic-tac-toe game, here it is. I cleaned up the screen refresh some more, making it an enclosed function of main() so it knows about cube and surface. I moved constants to the top of the file where they are easier to find and modify. I made sure ROBOT and PLAYER were used consistently instead of sometimes use "X" and "O". I removed unnecessary or limited value class methods, wrote better comments, improved formatting, etc... Basically just cleaned out the gunk that accumulates in programs that grow organically.
"""Tic-tac-toe with a computer opponent.  Three boards played simultaneously"""
import pygame
import random

PLAYER = 'X'
ROBOT = 'O'
EMPTY = ' '
background = "white"
msg_color = "white"
colors = {EMPTY: 'dodger blue', PLAYER: 'red', ROBOT: 'black'}


class Robot:
    """Computer tic-tac-toe player.  Uses minimax algorithm with
    alpha/beta pruning and some additional heuristics to provide
    a challenging, but beatable opponent.
    """
    def __init__(self, cube):
        self.boards = cube.boards

    def get_scores(self, board):
        """Get scores for all open squares on a board"""

        def minimax(mark, square, alpha=-1000, beta=1000, depth=0):
            """minimax algorithm with alpha/beta pruning"""
            # Place the mark and check for a win
            square.mark = mark
            if square.check_win():
                # Give extra weight to earlier wins/losses
                score = 10 - depth if mark is ROBOT else depth - 10
                board.depth = min(board.depth, depth)
            elif len(empty_squares := board.empty_squares()) == 0:
                # No plays left.  Draw.
                score = 0
            elif mark is PLAYER:
                # Pick best move for robot
                score = -1000
                for s in empty_squares:
                    score = max(score, minimax(ROBOT, s, alpha, beta, depth+1))
                    alpha = max(alpha, score)
                    if alpha > beta:
                        break
            else:
                # Guess what move player will make
                score = 1000
                for s in empty_squares:
                    score = min(score, minimax(PLAYER, s, alpha, beta, depth+1))
                    beta = min(beta, score)
                    if alpha > beta:
                        break

            # Remove mark and return score for the square
            square.mark = EMPTY
            return score

        # Collect scores for empty squares.  If board is empty,
        # minimax will return 0 for all squares
        board.depth = 10
        empty_squares = board.empty_squares()
        if len(empty_squares) == 9:
            board.scores = [[0, s] for s in empty_squares]
        else:
            # Calling minimax twice.  The first is to find the square
            # giving us best chance to win board.  Second is to prevent
            # abandoning board early and giving player an easy win.
            board.scores = [[minimax("O", s), s] for s in empty_squares]
            [minimax("X", s, depth=1) for s in empty_squares]

    def play(self):
        """Place robot mark."""
        # Get scores for all empty squares
        depth = 10
        for board in self.boards:
            self.get_scores(board)
            depth = min(depth, board.depth)

        # Select board with minimum depth.  This is the board that
        # will win/lose in the least number of moves.
        scores = []
        for board in self.boards:
            if board.depth <= depth:
                scores.extend(board.scores)

        # Randomly select from best scores on the selected board.
        max_score = max(score[0] for score in scores)
        squares = [score[1] for score in scores if score[0] >= max_score]
        return random.choice(squares)


class Square:
    """A 3D square in a tic-tac-toe board"""
    def __init__(self, board, index, side, center=(0, 0, 0)):
        self.board = board
        self.index = index
        self.mark = EMPTY
        self.corners = [
            pygame.Vector3(-1, -1, 0) * side / 2,
            pygame.Vector3(1, -1, 0) * side / 2,
            pygame.Vector3(1, 1, 0) * side / 2,
            pygame.Vector3(-1, 1, 0) * side / 2
        ]
        self.move(center)

    def rotate(self, rotation):
        """Rotate square (rx, ry, rz) degrees"""
        for deg, axis in zip(rotation, ((1, 0, 0), (0, 1, 0), (0, 0, 1))):
            if deg:
                for corner in self.corners:
                    corner.rotate_ip(deg, axis)
        return self

    def move(self, offset):
        """Move square offset (x, y, z) pixels"""
        x, y, z = offset
        for corner in self.corners:
            corner.x += x
            corner.y += y
            corner.z += z
        return self

    def projection(self):
        """Return corners projected on xy plane"""
        return [pygame.Vector2(p.x, p.y) for p in self.corners]

    def draw(self, surface):
        """Draw projection of square on xy plane"""
        pygame.draw.polygon(surface, colors[self.mark], self.projection())

    def contains(self, point):
        """Return True if projection contains point."""
        def area(a, b, c):
            """Compute area of triangle"""
            return abs((a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)) / 2.0)

        def has_point(a, b, c, p):
            """Return True if triange ABC contains point p."""
            return area(a, b, c) >= int(area(a, p, b) + area(b, p, c) + area(c, p, a))

        a, b, c, d = self.projection()
        return has_point(a, b, c, point) or has_point(a, c, d, point)

    def check_win(self):
        return self.board.check_win(self)


class Board:
    """A tic-tac-toe board"""
    winning_combos = (
        (0, 2, 4, 6, 8), (1, 3, 5, 7), (0, 1, 2), (3, 4, 5), (6, 7, 8),
        (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)
    )

    def __init__(self, side):
        dx = side / 3
        self.squares = []
        for index in range(9):
            x = (index % 3 - 1) * dx
            y = (index // 3 - 1) * dx
            self.squares.append(Square(self, index, dx-6, (x, y, 0)))
        self.scores = None
        self.depth = 10

    def empty_squares(self):
        """Return list of empty squares"""
        return [s for s in self.squares if s.mark is EMPTY]

    def check_win(self, square):
        """Return winning squares from last move, else None"""
        for combo in self.winning_combos:
            if square.index in combo:
                squares = [self.squares[i] for i in combo]
                if all(square.mark == s.mark for s in squares):
                    return squares
        return None


class Cube:
    """Three tic-tac-toe boards plastered on the faces of a cube"""
    def __init__(self, side):
        def make_board(center, rotation):
            board = Board(side)
            for square in board.squares:
                square.rotate(rotation).move(center)
            return board

        self.boards = [
            make_board((0, 0, -side/2), (0, 0, 0)),
            make_board((side/2, 0, 0), (0, 270, 0)),
            make_board((0, -side/2, 0), (90, 0, 0))
        ]
        self.squares = [s for b in self.boards for s in b.squares]
        self.winner = None
        self.mark = PLAYER
        self.reset()

    def click(self, point):
        """Try to place player's mark in clicked square."""
        if self.mark is PLAYER:
            for square in self.squares:
                if square.contains(point):
                    if square.mark is EMPTY:
                        self.play(square, self.mark)
                        return square
                    break
        return None

    def play(self, square, mark):
        """Place mark in square.  Test if is a winning move"""
        square.mark = mark
        self.mark_count += 1
        if winner := square.check_win():
            self.winner = winner
            for square in self.squares:
                if square not in winner:
                    square.mark = EMPTY
        self.mark = PLAYER if mark is ROBOT else ROBOT

    def done(self):
        """Return True if there is a winner or draw"""
        return self.winner or self.mark_count >= 27

    def reset(self):
        """Reset all boards to empty"""
        self.mark_count = 0
        self.winner = None
        for square in self.squares:
            square.mark = EMPTY


def main():
    """Play tic-tac-toe"""

    def refresh_screen(msg=None):
        """Draw the cube and an optional message"""
        surface.fill(background)
        for square in cube.squares:
            square.draw(surface)
        if msg:
            text = pygame.font.Font(None, 100).render(msg, True, msg_color)
            surface.blit(text, (center.x - text.get_width() / 2, center.y))
        pygame.display.flip()

    pygame.display.set_caption("Tic-Tac-Toe")
    surface = pygame.display.set_mode((500, 500))
    center = pygame.Vector3(250, 250, 0)

    # Move cube for pretty orthogonal view at center of screen
    cube = Cube(300)
    for square in cube.squares:
        square.rotate((0, 45, 0)).rotate((22.5, 0, 0)).move(center)
    robot = Robot(cube)
    refresh_screen()

    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if cube.done():
                    # Start a new game
                    cube.reset()
                    if cube.mark is ROBOT:
                        cube.play(robot.play(), ROBOT)
                    refresh_screen()
                elif cube.click(pygame.Vector2(event.pos)):
                    # Player selected square.  Robot's turn,
                    if not cube.done():
                        refresh_screen()
                        cube.play(robot.play(), ROBOT)
                    # Is the game over?
                    refresh_screen("Game Over" if cube.done() else None)
                    pygame.event.clear()


if __name__ == "__main__":
    pygame.init()
    main()
    pygame.quit()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Drawing a net of a cube freethrownucleus 26 5,116 May-05-2023, 10:23 PM
Last Post: freethrownucleus
  2D-Cube-Tic-Tac-Toe freethrownucleus 0 1,158 Mar-10-2023, 07:07 PM
Last Post: freethrownucleus
  PyGlet Trouble Drawing Cube. Windspar 3 5,744 Jan-02-2018, 06:37 PM
Last Post: Windspar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020