Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Cube drawing
#4
As for playing against the computer, what have you tried? You should start with a regular 3x3 tic-tac-toe game.

About game rules: 3 in any row? Even wrapping around a corner? If you can bend around a corner, can you bend diagonally? I tried this and the first player always wins.
import pygame

class Square:
    """I am a square in a tic-tac-toe board in 3D"""
    def __init__(self, side, center=(0, 0, 0)):
        self.color = "white"
        self.points = [
            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.
        rx rotates about the x axis, ry about the y axis, rz about the z axis.
        """
        for degrees, vector in zip(rotation, ((1, 0, 0), (0, 1, 0), (0, 0, 1))):
            if degrees:
                for point in self.points:
                    point.rotate_ip(degrees, vector)

    def move(self, offset):
        """Move square offset (dx, dy, dz) pixels"""
        for point in self.points:
            dx, dy, dz = offset
            point.x += dx
            point.y += dy
            point.z += dz

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

    def draw(self, surface):
        """Draw self"""
        pygame.draw.polygon(surface, self.color, self.projection())

    def contains(self, point):
        """Return True if my xy projection contains point."""
        def t_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 t_contains(a, b, c, p):
            """Return True if triangle ABC contains point p."""
            # Create 3 triangles  that have p as a vertex.  If the sum of the area of these
            # triangles = area of the triangle ABC, then p is inside the triangle
            area = t_area(a, b, c)
            a1 = t_area(a, p, b)
            a2 = t_area(b, p, c)
            a3 = t_area(c, p, a)
            return area >= int(a1 + a2 + a3)  # Compensate for numerical errors

        # Split projected polygon into two triangles.  Test if point is inside either triangle.
        a, b, c, d = self.projection()
        return t_contains(a, b, c, point) or t_contains(a, c, d, point)

class Face:
    def __init__(self, side, center=(0, 0, 0), rotation=(0, 0, 0)):
        side = side / 3
        gap = 8
        self.squares = [
            Square(side-gap, (-side, -side, 0)),
            Square(side-gap, (0, -side, 0)),
            Square(side-gap, (side, -side, 0)),
            Square(side-gap, (-side, 0, 0)),
            Square(side-gap, (0, 0, 0)),
            Square(side-gap, (side, 0, 0)),
            Square(side-gap, (-side, side, 0)),
            Square(side-gap, (0, side, 0)),
            Square(side-gap, (side, side, 0))
        ]
        self.rotate(rotation)
        self.move(center)

    def reset(self):
        """Reset board to empty"""
        self.winner = None
        self.markers = [None] * 9
        for square in self.squares:
            square.color = self.clear_color

    def move(self, offset):
        """Move square offset (dx, dy, dz) pixels"""
        for square in self.squares:
            square.move(offset)

    def rotate(self, rotation):
        """Rotate square (rx, ry, rz) degrees.
        rx rotates about the x axis, ry about the y axis, rz about the z axis.
        """
        for square in self.squares:
            square.rotate(rotation)

class Cube:
    winning_combos = (
        (0, 1, 2), (3, 4, 5), (6, 7, 8),
        (0, 3, 6), (1, 4, 7), (2, 5, 8),
        (0, 4, 8), (2, 4, 6),
        (9, 10, 11), (12, 13, 14), (15, 16, 17),
        (9, 12, 15), (10, 13, 16), (11, 14, 17),
        (9, 13, 17), (11, 13, 15),
        (18, 19, 20), (21, 22, 23), (24, 25, 26),
        (18, 21, 24), (19, 22, 25), (20, 23, 26),
        (18, 22, 26), (24, 22, 20),
        (1, 2, 9), (2, 9, 10), (4, 5, 12), (5, 12, 13), (8, 9, 16), (9, 16, 17),
        (3, 0, 18), (0, 18, 21), (4, 1, 19), (1, 19, 22), (5, 2, 20), (2, 20, 23),
        (12, 9, 20), (9, 20, 19), (13, 10, 23), (10, 23, 22), (14, 11, 26), (11, 26, 25),
        (3, 1, 20), (0, 19, 23), (5, 1, 18), (2, 19, 21),
        (1, 5, 15), (2, 12, 16), (7, 5, 9), (8, 12, 10),
        (19, 23, 11), (20, 10, 14), (25, 22, 9), (26, 10, 12)
    )


    """A tic-tac-toe board plastered on the side of a cube"""
    def __init__(self, side):
        self.clear_color = "white"
        self.colors = ["red", "blue"]
        self.marker = 0
        self.faces = [
            Face(side, (0, 0, -side/2), (0, 0, 0)),
            Face(side, (side/2, 0, 0), (0, 270, 0)),
            Face(side, (0, -side/2, 0), (90, 0, 0))
        ]
        self.squares = []
        for face in self.faces:
            self.squares.extend(face.squares)
        for index, square in enumerate(self.squares):
            square.index = index
            square.marker = None
        self.reset()

    def click(self, point):
        """Find where to place marker"""
        def locate(point):
            for square in self.squares:
                if square.contains(point):
                    return square
            return None

        if self.done:
            self.reset()
            return

        square = locate(point)
        print(square.index)
        if square and square.marker == None:
            square.marker = self.marker
            square.color = self.colors[self.marker]
            self.marker = (self.marker + 1) % 2
            self.check_win(square)

    def check_win(self, square):
        def winner(squares):
            a, b, c = [self.squares[i].marker for i in squares]
            if a == b == c and a is not None:
                return a
            return None

        for combo in self.winning_combos:
            if square.index in combo and winner(combo) is not None:
                self.reset()
                self.done = True
                for index in combo:
                    self.squares[index].color = self.colors[self.marker]
                break

    def reset(self):
        for square in self.squares:
            square.marker = None
            square.color = self.clear_color
        self.done = False

    def rotate(self, rotation):
        """Rotate square (rx, ry, rz) degrees.
        rx rotates about the x axis, ry about the y axis, rz about the z axis.
        """
        for face in self.faces:
            face.rotate(rotation)

    def move(self, move):
        """Move square offset (dx, dy, dz) pixels"""
        for face in self.faces:
            face.move(move)

    def draw(self, surface):
        """Draw all the tic-tac-toe boards."""
        for square in self.squares:
            square.draw(surface)

def main():
    pygame.display.set_caption("Tic-Tac-Toe")
    surface = pygame.display.set_mode((500, 500))

    # Make 3 sides of a cube, and rotate so you can see all three sides
    cube = Cube(300)
    cube.rotate((0, 45, 0))
    cube.rotate((22.5, 0, 0))
    center = surface.get_rect()
    cube.move(pygame.Vector3(center.centerx, center.centery, 0))
    cube.draw(surface)
    pygame.display.flip()

    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                cube.click(pygame.Vector2(event.pos))
                surface.fill("black")
                cube.draw(surface)
                pygame.display.flip()

if __name__ == "__main__":
    pygame.init()
    main()
    pygame.quit()
A variation that might be playable is to play until all squares but 1 are filled (each player gets 13 squares). Then compute the number of winners for each player.
Reply


Messages In This Thread
Cube drawing - by freethrownucleus - Dec-11-2022, 11:49 PM
RE: Cube drawing - by deanhystad - Dec-13-2022, 04:22 AM
RE: Cube drawing - by freethrownucleus - Dec-13-2022, 12:51 PM
RE: Cube drawing - by ClaytonMorrison - Apr-12-2023, 08:04 AM
RE: Cube drawing - by deanhystad - Dec-13-2022, 10:29 PM
RE: Cube drawing - by freethrownucleus - Dec-14-2022, 12:01 AM
RE: Cube drawing - by deanhystad - Dec-14-2022, 05:13 AM
RE: Cube drawing - by freethrownucleus - Dec-14-2022, 11:06 AM
RE: Cube drawing - by deanhystad - Dec-14-2022, 01:14 PM
RE: Cube drawing - by freethrownucleus - Dec-14-2022, 02:09 PM
RE: Cube drawing - by deanhystad - Dec-14-2022, 08:05 PM
RE: Cube drawing - by freethrownucleus - Dec-14-2022, 10:10 PM
RE: Cube drawing - by deanhystad - Dec-14-2022, 11:44 PM
RE: Cube drawing - by freethrownucleus - Dec-16-2022, 07:49 PM
RE: Cube drawing - by deanhystad - Dec-19-2022, 04:54 AM
RE: Cube drawing - by freethrownucleus - Dec-20-2022, 01:18 PM
RE: Cube drawing - by deanhystad - Dec-21-2022, 12:01 AM
RE: Cube drawing - by freethrownucleus - Dec-21-2022, 12:43 PM
RE: Cube drawing - by deanhystad - Jan-01-2023, 04:36 AM
RE: Cube drawing - by freethrownucleus - Jan-01-2023, 10:25 PM
RE: Cube drawing - by deanhystad - Jan-02-2023, 02:17 PM
RE: Cube drawing - by freethrownucleus - Jan-02-2023, 09:39 PM
RE: Cube drawing - by deanhystad - Jan-02-2023, 10:07 PM
RE: Cube drawing - by freethrownucleus - Jan-02-2023, 10:41 PM
RE: Cube drawing - by deanhystad - Jan-03-2023, 04:31 AM
RE: Cube drawing - by freethrownucleus - Jan-03-2023, 04:01 PM
RE: Cube drawing - by deanhystad - Jan-03-2023, 07:21 PM
RE: Cube drawing - by freethrownucleus - Jan-03-2023, 09:18 PM
RE: Cube drawing - by deanhystad - Jan-03-2023, 10:19 PM
RE: Cube drawing - by freethrownucleus - Jan-04-2023, 08:28 PM
RE: Cube drawing - by deanhystad - Jan-04-2023, 08:29 PM
RE: Cube drawing - by freethrownucleus - Jan-04-2023, 08:53 PM
RE: Cube drawing - by deanhystad - Jan-04-2023, 09:15 PM
RE: Cube drawing - by freethrownucleus - Jan-04-2023, 09:20 PM
RE: Cube drawing - by deanhystad - Jan-04-2023, 09:34 PM
RE: Cube drawing - by freethrownucleus - Jan-05-2023, 01:59 PM
RE: Cube drawing - by deanhystad - Jan-05-2023, 06:06 PM
RE: Cube drawing - by freethrownucleus - Jan-05-2023, 06:26 PM
RE: Cube drawing - by deanhystad - Jan-05-2023, 07:35 PM
RE: Cube drawing - by freethrownucleus - Jan-05-2023, 08:32 PM
RE: Cube drawing - by deanhystad - Jan-05-2023, 09:16 PM
RE: Cube drawing - by freethrownucleus - Jan-05-2023, 09:32 PM
RE: Cube drawing - by deanhystad - Jan-05-2023, 10:03 PM
RE: Cube drawing - by freethrownucleus - Jan-05-2023, 10:18 PM
RE: Cube drawing - by deanhystad - Jan-05-2023, 10:23 PM
RE: Cube drawing - by freethrownucleus - Jan-05-2023, 11:24 PM
RE: Cube drawing - by deanhystad - Jan-06-2023, 07:15 PM
RE: Cube drawing - by freethrownucleus - Jan-07-2023, 08:44 PM
RE: Cube drawing - by deanhystad - Jan-07-2023, 11:19 PM
RE: Cube drawing - by freethrownucleus - Jan-08-2023, 12:25 AM
RE: Cube drawing - by deanhystad - Jan-08-2023, 05:11 PM
RE: Cube drawing - by freethrownucleus - Jan-08-2023, 06:29 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Drawing a net of a cube freethrownucleus 26 5,640 May-05-2023, 10:23 PM
Last Post: freethrownucleus
  2D-Cube-Tic-Tac-Toe freethrownucleus 0 1,223 Mar-10-2023, 07:07 PM
Last Post: freethrownucleus
  PyGlet Trouble Drawing Cube. Windspar 3 5,840 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