Drawing a net of a cube - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Game Development (https://python-forum.io/forum-11.html) +--- Thread: Drawing a net of a cube (/thread-39679.html) |
Drawing a net of a cube - freethrownucleus - Mar-25-2023 I need to draw a net of a cube. Each of squares of a cube will present a tic-tac-toe board. I tried this but I can do nothing with it (making anything more than a drawing). If anyone could help ... import pygame # Define some colors BLACK = (0, 0, 0) WHITE = (255, 255, 255) # Initialize Pygame pygame.init() # Set the dimensions of the screen size = (400, 400) screen = pygame.display.set_mode(size) # Load the images for each face of the cube front = pygame.image.load("cube_model.png").convert() back = pygame.image.load("cube_model.png").convert() left = pygame.image.load("cube_model.png").convert() right = pygame.image.load("cube_model.png").convert() top = pygame.image.load("cube_model.png").convert() bottom = pygame.image.load("cube_model.png").convert() # Create a list of Rect objects for each face of the cube faces = [ pygame.Rect(100, 100, 100, 100), pygame.Rect(200, 100, 100, 100), pygame.Rect(0, 100, 100, 100), pygame.Rect(300, 100, 100, 100), pygame.Rect(100, 0, 100, 100), pygame.Rect(100, 200, 100, 100), ] # Draw each face of the cube on the screen screen.blit(front, faces[0]) screen.blit(back, faces[1]) screen.blit(left, faces[2]) screen.blit(right, faces[3]) screen.blit(top, faces[4]) screen.blit(bottom, faces[5]) # Update the screen pygame.display.flip() # Wait for the user to close the window done = False while not done: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True # Quit Pygame pygame.quit() RE: Drawing a net of a cube - deanhystad - Mar-25-2023 Squares are places you can place an x or o. A tic-tac-toe board has 9 squares. Your board will have 54 squares. This would be easier with tkinter using buttons for the squares If you want to continue with pygame you need a sprite for each square. Using sprites will help detect where the mouse was clicked and you can change the sprite image to blank, x or o. You should start with a 3x3 board to iyon out the details. RE: Drawing a net of a cube - freethrownucleus - Mar-25-2023 Yes, I need to have 6 boards with 9 places (in general 54 places). Hmm, maybe it would be easier and better with tkinter but I think I would have the same problem if I used tkinter. I would only know to draw the net which isn't useful for making the game. RE: Drawing a net of a cube - deanhystad - Mar-25-2023 In tkinter there would be no drawing. This is one of the first programs I wrote in Python. """tkinter tic-tac-toe game""" import tkinter as tk class Square(tk.Button): """Special button for playing tic-tac-toe.""" colors = {"O": "blue", "X": "red"} def __init__(self, parent, index): super().__init__(parent, width=3, font=('Comic Sans MS', 64, 'bold')) self.index = index self._mark = None @property def mark(self): """What marker appears in square.""" return self._mark @mark.setter def mark(self, mark): self._mark = mark self["fg"] = self.colors.get(mark, 'black') self["text"] = '' if mark is None else mark class TicTacToe(tk.Tk): """Play tic-tac-toe. Players take turn clicking on empty buttons to place their marker. The first player to get three markers in a row, up/down, sideways or diagonally, wins """ # All possible winning conbinations wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (6, 4, 2)) def __init__(self): super().__init__() self.title('Tic Tac Toe') self.squares = [Square(self, i) for i in range(9)] for square in self.squares: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg)) self.message = tk.Label(self, text=' ', width=30) self.message.grid(row=4, column=0, columnspan=3) self.new_game = False self.player = "X" self.reset() def reset(self): """Reset board to empty""" self.open_squares = 9 self.new_game = False for square in self.squares: square.mark = None self.message['text'] = f"{self.player}'s turn" def play(self, square): """Put player marker in slot if open. Check for win or tie""" if self.new_game: self.reset() elif square.mark is not None: self.message['text'] = 'That space is already taken' else: square.mark = self.player self.open_squares -= 1 self.new_game = self.game_over() self.player = "X" if self.player == "O" else "O" if not self.new_game: self.message['text'] = f"{self.player}'s turn" def game_over(self): '''Check for winner or tie''' # Check all winning combinations for win in self.wins: if all(self.player == self.squares[i].mark for i in win): for i in win: self.squares[i]['fg'] = 'green' self.message['text'] = f'{self.player} wins!' return True # Check for a tie if self.open_squares <= 0: self.message['text'] = 'Game ends in a tie' return True return False TicTacToe().mainloop() RE: Drawing a net of a cube - freethrownucleus - Mar-26-2023 Nice game but you didn't understand me well. I need this shape for my game. Something like a cross of 6 squares and each square contains a tic-tac-toe board: https://mega.nz/file/zNgRlRoJ#vXbnAswpwAuV3mjuq3c57hpAgY_Y-ZySR4auU_Vsq5o . That's why I tried pygame at first. RE: Drawing a net of a cube - deanhystad - Mar-26-2023 I understand you just fine. I provided an example of how to write a tic-tac-toe game using the grid layout in tkinter. It has 9 squares. Repeat 5 more times, adjusting the row and column values in the .grid() layout calls. """tkinter tic-tac-toe game""" import tkinter as tk import tkinter.ttk as ttk from functools import partial class Square(ttk.Button): """Special button for playing tic-tac-toe.""" styles = {"X": "X.TButton", "O": "O.TButton", None: "X.TButton"} def __init__(self, parent, board, index): super().__init__(parent, width=3, style='X.TButton') self.board = board self.index = index self._mark = None @property def mark(self): """What marker appears in square.""" return self._mark @mark.setter def mark(self, mark): self._mark = mark self.configure(style=self.styles[mark]) self["text"] = '' if mark is None else mark class Board(tk.Frame): """A tic-tac-toe board.""" wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (6, 4, 2)) def __init__(self, parent, bg="black"): super().__init__(parent, bg=bg) self.squares = [Square(self, self, i) for i in range(9)] for s in self.squares: r = s.index // 3 c = s.index % 3 s.grid(row=r, column=c, padx=2, pady=2) self.new_game = False self.open_squares = 9 def reset(self): """Reset board to empty""" self.open_squares = 9 self.new_game = False for square in self.squares: square.mark = None def play(self, square, player): """Put player marker in slot if open. Check for win or tie""" square.mark = player self.open_squares -= 1 self.game_over(player) def game_over(self, player): '''Check for winner or tie''' # Check all winning combinations for win in self.wins: if all(player == self.squares[i].mark for i in win): for i in win: self.squares[i].configure(style="win.TButton") self.new_game = True break else: self.new_game = self.open_squares <= 0 class TicTacToe(tk.Tk): """Multi-board tic-tac-toe game.""" def __init__(self): super().__init__() # Define styles used by squares. style = ttk.Style(self) style.configure('X.TButton', padding=-10, font=('Comic Sans MS', 32, 'bold'), foreground="red") style.configure('O.TButton', padding=-10, font=('Comic Sans MS', 32, 'bold'), foreground="blue") style.configure('win.TButton', padding=-10, font=('Comic Sans MS', 32, 'bold'), foreground="green") self.title('Tic Tac Toe') self.player = "X" # Make the tic-tac-toe boards. Bind squares command to self.play frame = tk.Frame(self, bg="black") frame.pack(side=tk.TOP) self.boards = [Board(frame, color) for color in ('red', 'green', 'blue')] for index, board in enumerate(self.boards): for square in board.squares: square.configure(command=partial(self.play, square)) board.grid(row=index, column=index) self.message = tk.Label(self, text=f"{self.player}'s turn", font=("Comic Sans MS", 20)) self.message.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5) def play(self, square): """Put player mark in square if open""" if square.board.new_game: square.board.reset() elif square.mark is None: square.board.play(square, self.player) self.player = "X" if self.player == "O" else "O" self.message['text'] = f"{self.player}'s turn" TicTacToe().mainloop()You don't expect somebody to write all the code do you? You can write the game in pygame, as you have already done with a different layout. It is just more difficult. Unlike tkinter you have to do all the layout and monitor for button clicks. The only advantage I can see to pygame is you have total control over the presentation. But total control also means you have to write all the code that updates the screen. RE: Drawing a net of a cube - freethrownucleus - Mar-27-2023 No, I don't expect anyone to write the whole code ... I just ask what I have problem with or don't understand. I don't get exactly what you did with the new code. I think I managed to modify your first code to get what I wanted. But how can I modify the code in this case so I can set the winning combinations over all 6 boards, not over each for itself? import tkinter as tk class Square(tk.Button): """Special button for playing tic-tac-toe.""" colors = {"O": "blue", "X": "red"} def __init__(self, parent, index): super().__init__(parent, width=3, font=('Comic Sans MS', 20, 'bold')) self.index = index self._mark = None @property def mark(self): """What marker appears in square.""" return self._mark @mark.setter def mark(self, mark): self._mark = mark self["fg"] = self.colors.get(mark, 'black') self["text"] = '' if mark is None else mark class TicTacToe(tk.Tk): """Play tic-tac-toe. Players take turn clicking on empty buttons to place their marker. The first player to get three markers in a row, up/down, sideways or diagonally, wins """ # All possible winning conbinations wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (6, 4, 2)) def __init__(self): super().__init__() self.title('Tic Tac Toe') # create a frame to hold all four boards self.boards_frame = tk.Frame(self) self.boards_frame.pack(side="top", padx=5, pady=5) # create the left board self.frame1 = tk.Frame(self.boards_frame) self.frame1.pack(side="left") self.squares1 = [Square(self.frame1, i) for i in range(9)] for square in self.squares1: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares1, self.squares2, self.squares3, self.squares4, self.squares5, self.squares6)) # create the middle-left board self.frame2 = tk.Frame(self.boards_frame) self.frame2.pack(side="left") self.squares2 = [Square(self.frame2, i) for i in range(9)] for square in self.squares2: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares2, self.squares1, self.squares3, self.squares4, self.squares5, self.squares6)) # create the middle-right board self.frame3 = tk.Frame(self.boards_frame) self.frame3.pack(side="left") self.squares3 = [Square(self.frame3, i) for i in range(9)] for square in self.squares3: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares3, self.squares1, self.squares2, self.squares4, self.squares5, self.squares6)) self.frame5 = tk.Frame(self.boards_frame) self.frame5.pack(side="left") self.squares5 = [Square(self.frame5, i) for i in range(9)] for square in self.squares5: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares5, self.squares1, self.squares2, self.squares3, self.squares4, self.squares6)) self.frame4 = tk.Frame(self.boards_frame) self.frame4.pack(side="left") self.squares4 = [Square(self.frame4, i) for i in range(9)] for square in self.squares4: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares4, self.squares1, self.squares2, self.squares3, self.squares5, self.squares6)) self.frame1.pack(side="bottom") self.frame2.pack(side="top") self.frame6 = tk.Frame(self.boards_frame) self.frame6.pack(side="left") self.squares6 = [Square(self.frame6, i) for i in range(9)] for square in self.squares6: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares6, self.squares1, self.squares2, self.squares3, self.squares4, self.squares5)) self.frame3.pack(side="bottom") self.message = tk.Label(self, text=' ', width=30) self.message.pack(side="bottom") self.new_game = False self.player = "X" self.reset(self.squares1, self.squares2, self.squares3, self.squares4, self.squares5, self.squares6) def reset(self, squares1, squares2, squares3, squares4, squares5, squares6): """Reset board to empty""" self.open_squares = 54 self.new_game = False for square in squares1: square.mark = None for square in squares2: square.mark = None for square in squares3: square.mark = None for square in squares4: square.mark = None for square in squares5: square.mark = None for square in squares6: square.mark = None self.message['text'] = f"{self.player}'s turn" def play(self, square, squares1, squares2, squares3, squares4, squares5, squares6): """Put player marker in slot if open. Check for win or tie""" if self.new_game: return if square.mark is not None: self.message['text'] = "Invalid move" return square.mark = self.player self.open_squares -= 1 # check for a win for win in self.wins: if all(squares1[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares2[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares3[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares4[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares5[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares6[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return # check for a tie if self.open_squares == 0: self.message['text'] = "Tie game" self.new_game = True return # switch players self.player = "O" if self.player == "X" else "X" self.message['text'] = f"{self.player}'s turn" def game_over(self, squares1, squares2, squares3, squares4, squares5, squares6): """Check for winner or tie""" # Check all winning combinations for win in self.wins: if all(squares1[i].mark == self.player for i in win): for i in win: squares1[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares2[i].mark == self.player for i in win): for i in win: squares2[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares3[i].mark == self.player for i in win): for i in win: squares3[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares4[i].mark == self.player for i in win): for i in win: squares4[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares5[i].mark == self.player for i in win): for i in win: squares5[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares6[i].mark == self.player for i in win): for i in win: squares6[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True # Check for a tie if self.open_squares <= 0: self.message["text"] = "Game ends in a tie" return True return False TicTacToe().mainloop()I tried next logic: not drawing 6 boards, but drawing all the squares together but I can't get the shape I need. import tkinter as tk class Square(tk.Button): """Special button for playing tic-tac-toe.""" colors = {"O": "blue", "X": "red"} def __init__(self, parent, index): super().__init__(parent, width=3, font=('Comic Sans MS', 20, 'bold')) self.index = index self._mark = None @property def mark(self): """What marker appears in square.""" return self._mark @mark.setter def mark(self, mark): self._mark = mark self["fg"] = self.colors.get(mark, 'black') self["text"] = '' if mark is None else mark class TicTacToe(tk.Tk): """Play tic-tac-toe. Players take turn clicking on empty buttons to place their marker. The first player to get three markers in a row, up/down, sideways or diagonally, wins """ # All possible winning conbinations wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (6, 4, 2), (4, 8, 12, 22)) def __init__(self): super().__init__() self.title('Tic Tac Toe') # create a frame to hold all four boards self.boards_frame = tk.Frame(self) self.boards_frame.pack(side="top", padx=5, pady=5) # create the left board self.frame1 = tk.Frame(self.boards_frame) self.frame1.pack(side="top") self.squares1 = [Square(self.frame1, i) for i in range(54)] for square in self.squares1: if square.index >= 9 and square.index <= 17: row = 3 column = square.index % 9 elif square.index >= 18 and square.index <= 26: row = 4 column = square.index % 9 elif square.index >= 27 and square.index <= 35: row = 5 column = square.index % 9 else: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares1)) ''' # create the middle-left board self.frame2 = tk.Frame(self.boards_frame) self.frame2.pack(side="left") self.squares2 = [Square(self.frame2, i) for i in range(9)] for square in self.squares2: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares2, self.squares1)) # create the middle-right board self.frame3 = tk.Frame(self.boards_frame) self.frame3.pack(side="left") self.squares3 = [Square(self.frame3, i) for i in range(9)] for square in self.squares3: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares3, self.squares1, self.squares2, self.squares4, self.squares5, self.squares6)) self.frame4 = tk.Frame(self.boards_frame) self.frame4.pack(side="left") self.squares4 = [Square(self.frame4, i) for i in range(9)] for square in self.squares4: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares4, self.squares1, self.squares2, self.squares3, self.squares5, self.squares6)) self.frame5 = tk.Frame(self.boards_frame) self.frame5.pack(side="left") self.squares5 = [Square(self.frame5, i) for i in range(9)] for square in self.squares5: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares5, self.squares1, self.squares2, self.squares3, self.squares4, self.squares6)) self.frame1.pack(side="bottom") self.frame2.pack(side="top") self.frame6 = tk.Frame(self.boards_frame) self.frame6.pack(side="left") self.squares6 = [Square(self.frame6, i) for i in range(9)] for square in self.squares6: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares6, self.squares1, self.squares2, self.squares3, self.squares4, self.squares5)) self.frame3.pack(side="bottom") ''' self.message = tk.Label(self, text=' ', width=30) self.message.pack(side="bottom") self.new_game = False self.player = "X" self.reset(self.squares1) def reset(self, squares1): """Reset board to empty""" self.open_squares = 18 self.new_game = False for square in squares1: square.mark = None ''' for square in squares2: square.mark = None for square in squares3: square.mark = None for square in squares4: square.mark = None for square in squares5: square.mark = None for square in squares6: square.mark = None ''' self.message['text'] = f"{self.player}'s turn" def play(self, square, squares1): """Put player marker in slot if open. Check for win or tie""" if self.new_game: return if square.mark is not None: self.message['text'] = "Invalid move" return square.mark = self.player self.open_squares -= 1 # check for a win for win in self.wins: if all(squares1[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return ''' if all(squares2[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares3[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares4[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares5[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares6[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return ''' # check for a tie if self.open_squares == 0: self.message['text'] = "Tie game" self.new_game = True return # switch players self.player = "O" if self.player == "X" else "X" self.message['text'] = f"{self.player}'s turn" def game_over(self, squares1): """Check for winner or tie""" # Check all winning combinations for win in self.wins: if all(squares1[i].mark == self.player for i in win): for i in win: squares1[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True ''' if all(squares2[i].mark == self.player for i in win): for i in win: squares2[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares3[i].mark == self.player for i in win): for i in win: squares3[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares4[i].mark == self.player for i in win): for i in win: squares4[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares5[i].mark == self.player for i in win): for i in win: squares5[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares6[i].mark == self.player for i in win): for i in win: squares6[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True ''' # Check for a tie if self.open_squares <= 0: self.message["text"] = "Game ends in a tie" return True return False TicTacToe().mainloop() RE: Drawing a net of a cube - deanhystad - Mar-27-2023 You should not have squares1, squares2...squares6. You should have squares[] (or preferrably boards[]). If you have two things that are similar you should put them in a list or tuple. If you have 6 things that are similar you should most definitely put them in a list or tuple. Do not use individual attributes when you can make a collection. You only ever have to check for winning combinations involving the last square played. That means you only have to check for a win on the board that contains the last square played. If you want to reset all boards after there is a winner on any board, the logic, and code, might actually be simpler. """tkinter tic-tac-toe game""" import tkinter as tk import tkinter.ttk as ttk from functools import partial class Square(ttk.Button): """Special button for playing tic-tac-toe.""" styles = {"X": "X.TButton", "O": "O.TButton", None: "X.TButton"} def __init__(self, parent, board, index): super().__init__(parent, width=3, style="X.TButton") self.board = board self.index = index self._mark = None @property def mark(self): """What marker appears in square.""" return self._mark @mark.setter def mark(self, mark): self._mark = mark self.configure(style=self.styles[mark]) self["text"] = "" if mark is None else mark class Board(tk.Frame): """A tic-tac-toe board.""" wins = ( (0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (6, 4, 2), ) def __init__(self, parent, bg="black"): super().__init__(parent, bg=bg) self.squares = [Square(self, self, i) for i in range(9)] for s in self.squares: r = s.index // 3 c = s.index % 3 s.grid(row=r, column=c, padx=2, pady=2) self.new_game = False def reset(self): """Reset board to empty""" self.new_game = False for square in self.squares: square.mark = None def play(self, square, player): """Put player marker in slot if open. Check for win or tie""" square.mark = player for win in self.wins: if all(player == self.squares[i].mark for i in win): for i in win: self.squares[i].configure(style="win.TButton") self.new_game = True break class TicTacToe(tk.Tk): """Multi-board tic-tac-toe game.""" def __init__(self): super().__init__() # Define styles used by squares. style = ttk.Style(self) style.configure( "X.TButton", padding=-10, font=("Comic Sans MS", 32, "bold"), foreground="red", ) style.configure( "O.TButton", padding=-10, font=("Comic Sans MS", 32, "bold"), foreground="blue", ) style.configure( "win.TButton", padding=-10, font=("Comic Sans MS", 32, "bold"), foreground="green", ) self.title("Tic Tac Toe") self.player = "X" self.new_game = False self.open_squares = 0 # Make the tic-tac-toe boards. frame = tk.Frame(self, bg="black") frame.pack(side=tk.TOP) self.boards = [ Board(frame, color) for color in ("red", "green", "blue", "orange", "yellow") ] # Bind squares to call self.play() for board in self.boards: for square in board.squares: square.configure(command=partial(self.play, square)) # Arrange the boards in the grid self.boards[0].grid(row=0, column=0) self.boards[1].grid(row=0, column=2) self.boards[2].grid(row=1, column=1) self.boards[3].grid(row=2, column=0) self.boards[4].grid(row=2, column=2) self.message = tk.Label( self, text=f"{self.player}'s turn", font=("Comic Sans MS", 20) ) self.message.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5) self.reset() def play(self, square): """Put player mark in square if open""" board = square.board if self.new_game: self.reset() elif square.mark is None: board.play(square, self.player) self.open_squares -= 1 self.new_game = board.new_game or self.open_squares <= 0 self.player = "X" if self.player == "O" else "O" self.message["text"] = f"{self.player}'s turn" def reset(self): """Reset all the boards""" for board in self.boards: board.reset() self.new_game = False self.open_squares = len(self.boards) * 9 TicTacToe().mainloop() RE: Drawing a net of a cube - freethrownucleus - Mar-27-2023 I don't know if you understand me well, sorry. This is what I meant by combining more boards (2 or even more) for winning combinations: https://mega.nz/file/uJw0VBRR#vbKjX5l_cKIDKK-7hZzbcGBso_1MItCVf2Nso9H2rlM . That's why I tried drawing all 54 squares at once as you can see in my last reply (I believe I could easily add borders if I wanted those 6 boards separately). These 3 boards that are horizontal: I treat them as 3 rows in the for loop (rows 3, 4 and 5 (index)). But I can't get the shape that I want. The best I got is this: https://mega.nz/file/XVhyhY7I#PDp0KtlqMrYeMp5623Q8BihhDtaVcEIsUnjY1o1UbRM . Firstly I saw the old version of the code that you sent so I tried to modify that one in the beginning. For the new version of the code, I only understand the part with a list or tuple. EDIT: Okay I think I got it (the idea with all 54 squares at once). If you think of some flaws here, feel free to say! import tkinter as tk class Square(tk.Button): """Special button for playing tic-tac-toe.""" colors = {"O": "blue", "X": "red"} def __init__(self, parent, index): super().__init__(parent, width=3, font=('Comic Sans MS', 20, 'bold')) self.index = index self._mark = None @property def mark(self): """What marker appears in square.""" return self._mark @mark.setter def mark(self, mark): self._mark = mark self["fg"] = self.colors.get(mark, 'black') self["text"] = '' if mark is None else mark class TicTacToe(tk.Tk): """Play tic-tac-toe. Players take turn clicking on empty buttons to place their marker. The first player to get three markers in a row, up/down, sideways or diagonally, wins """ # All possible winning conbinations wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (6, 4, 2), (4, 8, 27, 31)) #last one example of a diagonal combo over 2 boards def __init__(self): super().__init__() self.title('Tic Tac Toe') # create a frame to hold all four boards self.boards_frame = tk.Frame(self) self.boards_frame.pack(side="top", padx=5, pady=5) # create the left board self.frame1 = tk.Frame(self.boards_frame) self.frame1.pack(side="left") self.squares1 = [] for i in range(9): self.squares1.append(Square(self.frame1, i)) for square in self.squares1: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares1)) self.frame1.pack(side="top") self.frame2 = tk.Frame(self.boards_frame) self.frame2.pack(side="left") for i in range(9, 18): self.squares1.append(Square(self.frame2, i)) for square in self.squares1: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares1)) self.frame3 = tk.Frame(self.boards_frame) self.frame3.pack(side="left") for i in range(18, 27): self.squares1.append(Square(self.frame3, i)) for square in self.squares1: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares1)) self.frame4 = tk.Frame(self.boards_frame) self.frame4.pack(side="left") for i in range(27, 36): self.squares1.append(Square(self.frame4, i)) for square in self.squares1: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares1)) self.frame5 = tk.Frame(self.boards_frame) self.frame5.pack(side="left") for i in range(36, 45): self.squares1.append(Square(self.frame5, i)) for square in self.squares1: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares1)) self.frame2.pack(side="bottom") self.frame6 = tk.Frame(self.boards_frame) self.frame6.pack(side="left") for i in range(45, 54): self.squares1.append(Square(self.frame6, i)) for square in self.squares1: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares1)) self.frame3.pack(side="bottom") ''' # create the middle-left board self.frame2 = tk.Frame(self.boards_frame) self.frame2.pack(side="left") self.squares2 = [Square(self.frame2, i) for i in range(9)] for square in self.squares2: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares2, self.squares1)) # create the middle-right board self.frame3 = tk.Frame(self.boards_frame) self.frame3.pack(side="left") self.squares3 = [Square(self.frame3, i) for i in range(9)] for square in self.squares3: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares3, self.squares1, self.squares2, self.squares4, self.squares5, self.squares6)) self.frame4 = tk.Frame(self.boards_frame) self.frame4.pack(side="left") self.squares4 = [Square(self.frame4, i) for i in range(9)] for square in self.squares4: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares4, self.squares1, self.squares2, self.squares3, self.squares5, self.squares6)) self.frame5 = tk.Frame(self.boards_frame) self.frame5.pack(side="left") self.squares5 = [Square(self.frame5, i) for i in range(9)] for square in self.squares5: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares5, self.squares1, self.squares2, self.squares3, self.squares4, self.squares6)) self.frame1.pack(side="bottom") self.frame2.pack(side="top") self.frame6 = tk.Frame(self.boards_frame) self.frame6.pack(side="left") self.squares6 = [Square(self.frame6, i) for i in range(9)] for square in self.squares6: row = square.index // 3 column = square.index % 3 square.grid(row=row, column=column, padx=5, pady=5) square.configure(command=lambda arg=square: self.play(arg, self.squares6, self.squares1, self.squares2, self.squares3, self.squares4, self.squares5)) self.frame3.pack(side="bottom") ''' self.message = tk.Label(self, text=' ', width=30) self.message.pack(side="bottom") self.new_game = False self.player = "X" self.reset(self.squares1) def reset(self, squares1): """Reset board to empty""" self.open_squares = 18 self.new_game = False for square in squares1: square.mark = None ''' for square in squares2: square.mark = None for square in squares3: square.mark = None for square in squares4: square.mark = None for square in squares5: square.mark = None for square in squares6: square.mark = None ''' self.message['text'] = f"{self.player}'s turn" def play(self, square, squares1): """Put player marker in slot if open. Check for win or tie""" if self.new_game: return if square.mark is not None: self.message['text'] = "Invalid move" return square.mark = self.player self.open_squares -= 1 # check for a win for win in self.wins: if all(squares1[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return ''' if all(squares2[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares3[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares4[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares5[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return if all(squares6[i].mark == self.player for i in win): self.message['text'] = f"{self.player} wins!" self.new_game = True return ''' # check for a tie if self.open_squares == 0: self.message['text'] = "Tie game" self.new_game = True return # switch players self.player = "O" if self.player == "X" else "X" self.message['text'] = f"{self.player}'s turn" def game_over(self, squares1): """Check for winner or tie""" # Check all winning combinations for win in self.wins: if all(squares1[i].mark == self.player for i in win): for i in win: squares1[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True ''' if all(squares2[i].mark == self.player for i in win): for i in win: squares2[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares3[i].mark == self.player for i in win): for i in win: squares3[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares4[i].mark == self.player for i in win): for i in win: squares4[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares5[i].mark == self.player for i in win): for i in win: squares5[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True if all(squares6[i].mark == self.player for i in win): for i in win: squares6[i]["fg"] = "green" self.message["text"] = f"{self.player} wins!" return True ''' # Check for a tie if self.open_squares <= 0: self.message["text"] = "Game ends in a tie" return True return False TicTacToe().mainloop()According to this code, the last winning combo will be this one (randomly chosen, just wanted to make a win over 2 or more boards possible): https://mega.nz/file/nZhUABAI#S-NVm_a_TcAt7_-cdj3vyrVLk5RKZDA6EtAqDb6QS6A . RE: Drawing a net of a cube - deanhystad - Mar-28-2023 This is a different approach. It uses a map to define the board. Kind of like using a map to lay out tiles in pygame. """tkinter tic-tac-toe game""" import tkinter as tk import tkinter.ttk as ttk from functools import partial def find_wins(map_): """Compute 3 in a row combinations in map_.""" def combo(row, column, irow, icolumn, length=3): """Return index list of winning combination starting at row, column and advancing in irow, icolumn direction. Return None if streak of consecutive squares is less than "length" long. """ try: combo = [grid[row+irow*x][column+icolumn*x] for x in range(length)] if None not in combo: return combo except IndexError: pass return None columns = max(len(row) for row in map_) grid = [[None] * columns for _ in map_] index = 0 for r, row in enumerate(map_): for c, key in enumerate(row): if key == "S": grid[r][c] = index index += 1 wins = [] for r, row in enumerate(map_): for c, key in enumerate(row): for irow, icolumn in ((1, 0), (-1, 1), (0, 1), (1, 1)): if win := combo(r, c, irow, icolumn): wins.append(win) return wins class Square(ttk.Button): """Special button for playing tic-tac-toe.""" styles = {"X": "X.TButton", "O": "O.TButton", None: "X.TButton"} def __init__(self, parent, index): super().__init__(parent, width=3, style="X.TButton") self.index = index self._mark = None @property def mark(self): """What marker appears in square.""" return self._mark @mark.setter def mark(self, mark): self._mark = mark self.configure(style=self.styles[mark]) self["text"] = "" if mark is None else mark class Board(tk.Frame): """A funky TicTacToe board. Use map to make any shape you want.""" def __init__(self, map_, *args, **kwargs): super().__init__(*args, **kwargs) self.squares = [] for r, row in enumerate(map_): for c, key in enumerate(row): if key == "S": square = Square(self, len(self.squares)) square.grid(row=r, column=c) self.squares.append(square) # Convert win combos from numbers to squares self.wins = [[self.squares[i] for i in win] for win in find_wins(map_)] def play(self, square, player): """Put player marker in slot. Check for win""" square.mark = player for win in self.wins: if square in win and all(player == s.mark for s in win): for s in win: s.configure(style="win.TButton") self.new_game = True break def reset(self): """Reset board to empty""" self.new_game = False for square in self.squares: square.mark = None class TicTacToe(tk.Tk): """A funky TicTacToe game. Use map to make any shape board you want.""" def __init__(self, map_): super().__init__() # Define styles used by squares. style = ttk.Style(self) style.configure( "X.TButton", padding=-10, font=("Comic Sans MS", 32, "bold"), foreground="red", ) style.configure( "O.TButton", padding=-10, font=("Comic Sans MS", 32, "bold"), foreground="blue", ) style.configure( "win.TButton", padding=-10, font=("Comic Sans MS", 32, "bold"), foreground="green", ) self.title("Tic Tac Toe") self.player = "X" self.open_squares = 0 self.board = Board(map_, self) for square in self.board.squares: square.configure(command=partial(self.play, square)) self.board.pack(side=tk.TOP) self.message = tk.Label( self, text=f"{self.player}'s turn", font=("Comic Sans MS", 20) ) self.message.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5) self.reset() def play(self, square): """Put player mark in square if open""" if self.new_game: self.reset() elif square.mark is None: self.board.play(square, self.player) self.open_squares -= 1 self.new_game = self.board.new_game or self.open_squares <= 0 self.player = "X" if self.player == "O" else "O" self.message["text"] = f"{self.player}'s turn" def reset(self): """Reset all the boards""" self.board.reset() self.new_game = False self.open_squares = len(self.board.squares) board = ("BSSSBSSSB", "SSSSSSSSS", "BSSSBSSSB") # B = Blank, S = Square TicTacToe(board).mainloop()Other than the way the squares get placed in the grid, the code is very similar to a 3x3 tic-tac-toe game. On your 54 square board there are going to be many winning combinations. Using a map, you can write a function to find all the winning combinations instead of doing it by hand. With all the combinations you might need to make to modify the rules to require 4 consecutive marks to win to have the game be challenging. |