moomoomoo309

TicTacToeBoardTurtle

Dec 9th, 2016
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 22.09 KB | None | 0 0
  1. from numbers import Number
  2. from turtle import Turtle
  3.  
  4. from TicTacToe import TicTacToeBoardBase
  5.  
  6. win = TicTacToeBoardBase.winCase
  7.  
  8.  
  9. class BoardSpaceOccupied(Exception):
  10.     pass
  11.  
  12.  
  13. class TicTacToeBoard:
  14.     """The board for Tic-Tac-Toe. Can only store TicTacToeBoard.X, TicTacToeBoard.O, and TicTacToeBoard.Empty."""
  15.  
  16.     # Don't change these. It is expected behavior that Empty is falsey, X and O are truthy and that Empty, X, and O can
  17.     # all be stored in a bytearray. To fit these conditions, Empty MUST be 0. X and O can be any number from 1-255 as
  18.     # long as they are not the same.middle
  19.     Empty = 0
  20.     X = 1
  21.     O = 2
  22.  
  23.     NamesX = {0: "left", 1: "middle", 2: "right"}
  24.     NamesY = {0: "top", 1: "center", 2: "bottom"}
  25.  
  26.     def _getBoard(self):
  27.         return self._board
  28.  
  29.     def _setBoard(self, board):
  30.         if self._board and len(self._board) != 9:
  31.             raise ValueError("You cannot add or remove elements from the board!")
  32.         self._board = board
  33.  
  34.     board = property(_getBoard, _setBoard, doc="The bytearray containing the actual board items.")
  35.  
  36.     def __init__(self):
  37.         self._board = bytearray(self.Empty for _ in range(9))  # Initialize the board with self.Empty.
  38.  
  39.     def won(self):
  40.         """Returns which player won (Board.X or Board.O) or False if neither player won."""
  41.         b = self._board  # This is going to be really long...
  42.         won = b[0] == b[3] == b[6] != self.Empty and (b[0], win.vertLeft) or \
  43.               b[1] == b[4] == b[7] != self.Empty and (b[1], win.vertMiddle) or \
  44.               b[2] == b[5] == b[8] != self.Empty and (b[2], win.vertRight) or \
  45.               b[0] == b[1] == b[2] != self.Empty and (b[0], win.horizTop) or \
  46.               b[3] == b[4] == b[5] != self.Empty and (b[3], win.horizMiddle) or \
  47.               b[6] == b[7] == b[8] != self.Empty and (b[6], win.horizBottom) or \
  48.               b[0] == b[4] == b[8] != self.Empty and (b[0], win.diagonalTopLeft) or \
  49.               b[2] == b[4] == b[6] != self.Empty and (b[2], win.diagonalTopRight)
  50.         if won:
  51.             return won
  52.         elif self.isTie():
  53.             return None
  54.         return False
  55.         # Yes, the above will work the way it should. b is there for code cleanup and cutting down on lookups.
  56.  
  57.     def isTie(self):
  58.         """Returns if the board has a tie."""
  59.         for line in ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)):
  60.             totalScore = 0
  61.             for space in line:
  62.                 if self.getSpace(space % 3, space // 3) != self.Empty:
  63.                     totalScore += 10 ^ (self.getSpace(space % 3, space // 3) - 1)
  64.             if totalScore <= 10 or totalScore % 10 == 0:
  65.                 return False
  66.         return True
  67.  
  68.     @staticmethod
  69.     def _checkIndices(xIndex, yIndex):
  70.         """Throws an exception if invalid board indices are passed to it."""
  71.         if 0 >= xIndex > 2 or 0 >= yIndex > 2:
  72.             raise IndexError("Board indices must be between 0 and 2.")
  73.         elif not isinstance(xIndex, int) or not isinstance(yIndex, int):
  74.             raise ValueError("Board indices can only be ints!")
  75.  
  76.     def _setBoardItem(self, xIndex, yIndex, val):
  77.         """Makes sure the board is set properly. Throws an error otherwise."""
  78.         self._checkIndices(xIndex, yIndex)
  79.         if val != self.X and val != self.O and val != self.Empty:
  80.             raise ValueError("The board can only store Empty, X, or O!")
  81.         elif self._board[int(3 * yIndex + xIndex)]:
  82.             raise BoardSpaceOccupied("The {} {} space is already occupied by an {}!".format(self.NamesX[xIndex],
  83.                 self.NamesY[yIndex], self._board[3 * yIndex + xIndex] == self.X and "X" or "O"))
  84.         self._board[int(3 * yIndex + xIndex)] = val
  85.  
  86.     def putX(self, xIndex, yIndex):
  87.         """Puts an X at the given X index and Y index, or errors if something is already there."""
  88.         self._setBoardItem(xIndex, yIndex, self.X)
  89.  
  90.     def putO(self, xIndex, yIndex):
  91.         """Puts an O at the given X index and Y index, or errors if something is already there."""
  92.         self._setBoardItem(xIndex, yIndex, self.O)
  93.  
  94.     def clearSpace(self, xIndex, yIndex):
  95.         """Clears the space at the given X index and Y index."""
  96.         self._setBoardItem(xIndex, yIndex, self.Empty)
  97.  
  98.     def getSpace(self, xIndex, yIndex):
  99.         """Gets what is at the space with the provided xIndex and yIndex."""
  100.         self._checkIndices(xIndex, yIndex)
  101.         return self._board[3 * yIndex + xIndex]
  102.  
  103.     def getNameForSpace(self, xIndex, yIndex):
  104.         """Gets the name for the given space, like bottom right or top left."""
  105.         self._checkIndices(xIndex, yIndex)
  106.         return "{} {}".format(self.NamesX[xIndex], self.NamesY[yIndex])
  107.  
  108.     # Aliases, in case you prefer these names.
  109.     setX = putX
  110.     setO = putO
  111.     setEmpty = clearSpace
  112.  
  113.  
  114. class TicTacToeBoardTurtle(TicTacToeBoardBase):
  115.     """The component of Tic-Tac-Toe used to draw the board, implemented with Python's Turtle API."""
  116.  
  117.     def _getBoard(self):
  118.         """The getter, in case you need to run something when this value is accessed."""
  119.         return self._board
  120.  
  121.     def _setBoard(self, board):
  122.         if self._board:
  123.             raise ValueError("You can't change the board once it's been initialized! Use the board class methods!")
  124.         self._board = board
  125.  
  126.     board = property(_getBoard, _setBoard,
  127.         doc="The board, stored as a 1D array of length 9. Can only store Board.X, Board.O, and Board.Empty.")
  128.  
  129.     def getSpace(self, xIndex, yIndex):
  130.         if xIndex > 2 or yIndex > 2:
  131.             raise IndexError("Board indices must be between 0-2.")
  132.         return self.board.getSpace(int(xIndex), int(yIndex))
  133.  
  134.     def getBoardPosition(self):
  135.         """The getter, in case you need to run something when this value is accessed."""
  136.         return self._boardPosition
  137.  
  138.     def _setBoardPosition(self, boardPosition):
  139.         if len(boardPosition) != 2:
  140.             raise ValueError("The board position must only contain two numbers!")
  141.         elif not isinstance(boardPosition[0], Number) or isinstance(boardPosition[1], Number):
  142.             raise ValueError("The board positions must only be numbers!")
  143.         oldPos = self._boardPosition
  144.         self._boardPosition = boardPosition
  145.         if oldPos and oldPos != boardPosition:  # If it's initializing, don't keep redrawing!
  146.             self.redrawBoard()
  147.  
  148.     boardPosition = property(getBoardPosition, _setBoardPosition,
  149.         doc="The position of the board, stored as a tuple.")
  150.  
  151.     def getX(self):
  152.         return self._boardPosition[0]
  153.  
  154.     def setX(self, x):
  155.         """Set the X coordinate of the board."""
  156.         if not isinstance(x, Number):
  157.             raise ValueError("X must be a number!")
  158.         self._boardPosition[0] = x
  159.  
  160.     x = property(getX, setX)
  161.  
  162.     def getY(self):
  163.         return self._boardPosition[1]
  164.  
  165.     def setY(self, y):
  166.         """Set the Y coordinate of the board."""
  167.         if not isinstance(y, Number):
  168.             raise ValueError("Y must be a number!")
  169.         self._boardPosition[1] = y
  170.  
  171.     y = property(getY, setY)
  172.  
  173.     def getBoardColor(self):
  174.         """The getter, in case you need to run something when this value is accessed."""
  175.         return self._boardColor
  176.  
  177.     def _setBoardColor(self, boardColor):
  178.         if isinstance(self._boardColor, (tuple, set, list)):
  179.             if 3 >= len(self._boardColor) >= 4:
  180.                 for i in self._boardColor:
  181.                     if not isinstance(i, Number):
  182.                         raise ValueError("The board color must have only numbers in it!")
  183.                 oldColor = self._boardColor
  184.                 self._boardColor = boardColor
  185.             else:
  186.                 raise ValueError("The board color must be of length 3 or 4.")
  187.         else:
  188.             raise ValueError("The board color must be a tuple, set, or list!")
  189.         if oldColor and oldColor != boardColor:  # If it's initializing, don't keep redrawing!
  190.             self.redrawBoard()
  191.  
  192.     boardColor = property(getBoardColor, _setBoardColor,
  193.         doc="The color of the board, stored as a 3 or 4 item tuple containing ints between 0 and 255.")
  194.  
  195.     def getBoardWidth(self):
  196.         """The getter, in case you need to run something when this value is accessed."""
  197.         return self._boardWidth
  198.  
  199.     def _setBoardWidth(self, boardWidth):
  200.         if not isinstance(boardWidth, Number):
  201.             raise ValueError("The board width must be a number!")
  202.         elif boardWidth <= 0:
  203.             raise ValueError("The board width must be greater than 0!")
  204.         oldWidth = self._boardWidth
  205.         self._boardWidth = boardWidth
  206.         if oldWidth and oldWidth != boardWidth:  # If it's initializing, don't keep redrawing!
  207.             self.redrawBoard()
  208.  
  209.     boardWidth = property(getBoardWidth, _setBoardWidth,
  210.         doc="The width of the lines of the board, in pixels.")
  211.  
  212.     def getXColor(self):
  213.         """The getter, in case you need to run something when this value is accessed."""
  214.         return self._xColor
  215.  
  216.     def _setXColor(self, xColor):
  217.         if isinstance(self._xColor, (tuple, set, list)):
  218.             if 3 >= len(self._xColor) >= 4:
  219.                 for i in self._xColor:
  220.                     if not isinstance(i, Number):
  221.                         raise ValueError("The X color must have only numbers in it!")
  222.                 oldColor = self._xColor
  223.                 self._xColor = xColor
  224.             else:
  225.                 raise ValueError("The X color must be of length 3 or 4.")
  226.         else:
  227.             raise ValueError("The X color must be a tuple, set, or list!")
  228.         if oldColor and oldColor != xColor:  # If it's initializing, don't keep redrawing!
  229.             self.redrawBoard()
  230.  
  231.     xColor = property(getXColor, _setXColor,
  232.         doc="The color of the X, stored as a 3 or 4 item tuple containing ints between 0 and 255.")
  233.  
  234.     def getOColor(self):
  235.         """The getter, in case you need to run something when this value is accessed."""
  236.         return self._oColor
  237.  
  238.     def _setOColor(self, oColor):
  239.         if self._oColor:
  240.             raise ValueError("You can't change the O color once it's been initialized!")
  241.         if isinstance(self._oColor, (tuple, set, list)):
  242.             if 3 >= len(self._oColor) >= 4:
  243.                 for i in self._oColor:
  244.                     if not isinstance(i, Number):
  245.                         raise ValueError("The O color must have only numbers in it!")
  246.                 oldColor = self._oColor
  247.                 self._oColor = oColor
  248.             else:
  249.                 raise ValueError("The O color must be of length 3 or 4.")
  250.         else:
  251.             raise ValueError("The O color must be a tuple, set, or list!")
  252.         if oldColor and oldColor != oColor:  # If it's initializing, don't keep redrawing!
  253.             self.redrawBoard()
  254.  
  255.     oColor = property(getOColor, _setOColor,
  256.         doc="The color of the O, stored as a 3 or 4 item tuple containing ints between 0 and 255.")
  257.  
  258.     def getBoardSize(self):
  259.         """The getter, in case you need to run something when this value is accessed."""
  260.         return self._boardSize
  261.  
  262.     def _setBoardSize(self, boardSize):
  263.         if self._boardSize:
  264.             raise ValueError("You can't change the board size once it's been initialized!")
  265.         if isinstance(boardSize, Number):
  266.             if boardSize >= 5:
  267.                 oldSize = self._boardSize
  268.                 self._boardSize = boardSize
  269.             else:
  270.                 raise ValueError("The board size cannot be less than 5px by 5px!")
  271.         else:
  272.             raise ValueError("The board size must be a number!")
  273.         if oldSize and oldSize != boardSize:  # If it's initializing, don't keep redrawing!
  274.             self.redrawBoard()
  275.  
  276.     boardSize = property(getBoardSize, _setBoardSize,
  277.         doc="The length of the (square) board.")
  278.  
  279.     def __init__(self, x, y, boardSize, boardColor=None, xColor=None, oColor=None, boardWidth=None, pen=None):
  280.         """Create the canvas, and anything else needed to start the program initially."""
  281.         super(TicTacToeBoardBase, self).__init__()
  282.         self._board = TicTacToeBoard()
  283.         self._boardPosition = [x, y]
  284.         self._boardSize = boardSize
  285.         self._boardWidth = boardWidth or self.defaultBoardWidth
  286.         self._boardColor = boardColor or self.defaultBoardColor
  287.         self._xColor = xColor or self.defaultXColor
  288.         self._oColor = oColor or self.defaultOColor
  289.         self._pen = pen or Turtle()
  290.         self._mouseX, self._mouseY = None, None
  291.         self._mouseMovedCallbacks = []
  292.         self._mouseClickedCallbacks = []
  293.         # You shouldn't need anything else in here, but if you need to do something on board init, do it here.
  294.  
  295.     def drawBoard(self):
  296.         """Draw the board at the given coordinates, with the given width and height.
  297.           Assume (0,0) is in the top left, and the positive direction is right in the X axis, and down in the Y axis.
  298.  
  299.           The width and height should be the total size of the board, and the minimum size should be 5px by 5px."""
  300.         BoxSize = boxSize(self._boardSize, self._boardWidth)
  301.         drawRect = lambda x, y, width, height: rect(self._pen, x, y, width, height, self._boardColor)
  302.         drawRect(self.x + BoxSize, self.y, self._boardWidth, self._boardSize)
  303.         drawRect(self.x + 2 * BoxSize + self._boardWidth, self.y, self._boardWidth, self._boardSize)
  304.         drawRect(self.x, self.y + BoxSize, self._boardSize, self._boardWidth)
  305.         drawRect(self.x, self.y + 2 * BoxSize + self._boardWidth, self._boardSize, self._boardWidth)
  306.         for i in range(9):
  307.             if self.board.getSpace(i % 3, i // 3) == self.X:
  308.                 self.drawX(i % 3, i // 3)
  309.             elif self.board.getSpace(i % 3, i // 3) == self.O:
  310.                 self.drawO(i % 3, i // 3)
  311.  
  312.     def redrawBoard(self):
  313.         """Redraw the board after a value change."""
  314.         self._pen.clear()
  315.         self.drawBoard()
  316.  
  317.     def drawX(self, xIndex, yIndex):
  318.         """Draw an X at the given x index or y index, treating it as a 3x3, zero-indexed array.
  319.           Raise an exception when an X is drawn over an existing X or existing O."""
  320.         currentLetter = self.getSpace(xIndex, yIndex)
  321.         if currentLetter == self.X:
  322.             raise BoardSpaceOccupied("There's already an X in the {} {}!".format(TicTacToeBoard.NamesY[yIndex],
  323.                 TicTacToeBoard.NamesX[xIndex]))
  324.         elif currentLetter == self.O:
  325.             raise BoardSpaceOccupied("There's an O in the {} {}!".format(TicTacToeBoard.NamesY[yIndex],
  326.                 TicTacToeBoard.NamesX[xIndex]))
  327.         BoxSize = boxSize(self._boardSize, self._boardWidth)
  328.         goto = lambda x, y: self._pen.goto(*windowToTurtleCoordinates(x + (BoxSize + self._boardWidth) * xIndex,
  329.             y + (BoxSize + self._boardWidth) * yIndex,
  330.             self._pen.getscreen().window_width(),
  331.             self._pen.getscreen().window_height()))
  332.         oldColor = self._pen.pencolor()
  333.         oldSize = self._pen.pensize()
  334.         self._pen.pencolor(*self.xColor)
  335.         self._pen.pensize(self.boardWidth / 5)
  336.         self._pen.penup()
  337.         goto(self.x + BoxSize * .15, self.y + BoxSize * .15)
  338.         self._pen.pendown()
  339.         goto(self.x + BoxSize * .85, self.y + BoxSize * .85)
  340.         self._pen.penup()
  341.         goto(self.x + BoxSize * .85, self.y + BoxSize * .15)
  342.         self._pen.pendown()
  343.         goto(self.x + BoxSize * .15, self.y + BoxSize * .85)
  344.         self._pen.penup()
  345.         self._board.putX(xIndex, yIndex)
  346.         self._pen.pencolor(*oldColor)
  347.         self._pen.pensize(oldSize)
  348.  
  349.     def drawO(self, xIndex, yIndex):
  350.         """Draw an X at the given x index or y index, treating it as a 3x3, zero-indexed array.
  351.           Raise an exception when an X is drawn over an existing X or existing O."""
  352.         currentLetter = self.getSpace(xIndex, yIndex)
  353.         if currentLetter == self.X:
  354.             raise BoardSpaceOccupied("There's already an X in the {} {}!".format(TicTacToeBoard.NamesY[yIndex],
  355.                 TicTacToeBoard.NamesX[xIndex]))
  356.         elif currentLetter == self.O:
  357.             raise BoardSpaceOccupied("There's an O in the {} {}!".format(TicTacToeBoard.NamesY[yIndex],
  358.                 TicTacToeBoard.NamesX[xIndex]))
  359.         BoxSize = boxSize(self._boardSize, self._boardWidth)
  360.         goto = lambda x, y: self._pen.goto(*windowToTurtleCoordinates(x, y, self._pen.getscreen().window_width(),
  361.             self._pen.getscreen().window_height()))
  362.         oldColor = self._pen.pencolor()
  363.         oldSize = self._pen.pensize()
  364.         self._pen.pencolor(*self.oColor)
  365.         self._pen.pensize(self.boardWidth / 5)
  366.         self._pen.penup()
  367.         goto(self.x + BoxSize / 2 + (BoxSize + self._boardWidth) * xIndex,
  368.             self.y + BoxSize * .15 + (BoxSize + self._boardWidth) * yIndex)
  369.         self._pen.pendown()
  370.         self._pen.setheading(180)
  371.         self._pen.circle(BoxSize * .35)
  372.         self._pen.penup()
  373.         self._board.putO(xIndex, yIndex)
  374.         self._pen.pencolor(*oldColor)
  375.         self._pen.pensize(oldSize)
  376.  
  377.     _boardPositions = {
  378.         win.vertLeft: lambda self, BoxSize: (
  379.             self.x + BoxSize / 2., self.y + BoxSize / 2., self.x + BoxSize / 2.,
  380.             self.y + self._boardSize - BoxSize / 2.),
  381.         win.vertMiddle: lambda self, BoxSize: (
  382.             self.x + BoxSize * 3 / 2. + self._boardWidth, self.y + BoxSize / 2.,
  383.             self.x + BoxSize * 3 / 2. + self._boardWidth, self.y + self._boardSize - BoxSize / 2.),
  384.         win.vertRight: lambda self, BoxSize: (
  385.             self.x + BoxSize * 5 / 2. + 2 * self._boardWidth, self.y + BoxSize / 2.,
  386.             self.x + BoxSize * 5 / 2. + 2 * self._boardWidth, self.y + self._boardSize - BoxSize / 2.),
  387.         win.horizTop: lambda self, BoxSize: (
  388.             self.x + BoxSize / 2., self.y + BoxSize / 2., self.x + self._boardSize - BoxSize / 2.,
  389.             self.y + BoxSize / 2.),
  390.         win.horizMiddle: lambda self, BoxSize: (
  391.             self.x + BoxSize / 2., self.y + BoxSize * 3 / 2. + self._boardWidth,
  392.             self.x + self._boardSize - BoxSize / 2., self.y + BoxSize * 3 / 2. + self._boardWidth),
  393.         win.horizBottom: lambda self, BoxSize: (
  394.             self.x + BoxSize / 2., self.y + BoxSize * 5 / 2. + 2 * self._boardWidth,
  395.             self.x + self._boardSize - BoxSize / 2., self.y + BoxSize * 5 / 2. + 2 * self._boardWidth),
  396.         win.diagonalTopLeft: lambda self, BoxSize: (
  397.             self.x + BoxSize / 2., self.y + BoxSize / 2., self.x + self._boardSize - BoxSize / 2.,
  398.             self.y + self._boardSize - BoxSize / 2.),
  399.         win.diagonalTopRight: lambda self, BoxSize: (
  400.             self.x + self._boardSize - BoxSize / 2., self.y + BoxSize / 2., self.x + BoxSize / 2.,
  401.             self.y + self._boardSize - BoxSize / 2.)
  402.     }
  403.  
  404.     def drawLine(self, winCase):
  405.         """Draw the victory line for the given winCase."""
  406.         pos = self._boardPositions[winCase]
  407.         BoxSize = boxSize(self.boardSize, self.boardWidth)
  408.         self._pen.penup()
  409.         goto = lambda x, y: self._pen.goto(*windowToTurtleCoordinates(x, y, self._pen.getscreen().window_width(),
  410.             self._pen.getscreen().window_height()))
  411.         goto(*pos(self, BoxSize)[0:2])
  412.         self._pen.pendown()
  413.         goto(*pos(self, BoxSize)[2:])
  414.         self._pen.penup()
  415.  
  416.     def onClick(self, x, y, button=1):
  417.         """Run when the mouse is clicked."""
  418.         winX, winY = turtleToWindowCoordinates(x, y, self._pen.getscreen().window_width(),
  419.             self._pen.getscreen().window_height())
  420.         for i in self._mouseClickedCallbacks:
  421.             i(winX, winY, button)
  422.  
  423.     def addMouseClickedCallback(self, callback):
  424.         self._mouseClickedCallbacks.append(callback)
  425.  
  426.     def clearMouseClickedCallbacks(self):
  427.         self._mouseClickedCallbacks = []
  428.  
  429.     def isWon(self):
  430.         return self._board.won()
  431.  
  432.  
  433. def turtleToWindowCoordinates(x, y, width, height):
  434.     """Convert turtle coordinates to window coordinates."""
  435.     return x + width / 2., -(y - height / 2.)
  436.  
  437.  
  438. def windowToTurtleCoordinates(x, y, width, height):
  439.     """Convert window coordinates to turtle coordinates"""
  440.     return x - width / 2., -y + height / 2.
  441.  
  442.  
  443. def turtleXToWindowX(x, width):
  444.     """Convert X coord in turtle coordinates to window coordinates"""
  445.     return x + width / 2.
  446.  
  447.  
  448. def turtleYToWindowY(y, height):
  449.     """Convert Y coord in turtle coordinates to window coordinates"""
  450.     return -(y - height / 2.)
  451.  
  452.  
  453. def boxSize(boardSize, boardWidth):
  454.     """The size of each box on the board."""
  455.     return (boardSize - boardWidth * 2) / 3.
  456.  
  457.  
  458. def boxIndexAtCoordinates(boardSize, boardWidth, boardX, boardY, x, y):
  459.     """Returns the index of the box at the given x and y coordinates, or False if it is not on a box."""
  460.     if boardX <= x <= boardX + boardSize and boardY <= y <= boardY + boardSize:  # Check if it's on the board
  461.         localX, localY, BoxSize = x - boardX, y - boardY, boxSize(boardSize, boardWidth)  # Relative coords to the board
  462.         if localX % (BoxSize + boardWidth) > BoxSize or localY % (BoxSize + boardWidth) > BoxSize:  # If it's on a line
  463.             return False
  464.         else:
  465.             return int(localX // (BoxSize + boardWidth)), int(
  466.                 localY // (BoxSize + boardWidth))  # "Magic!" Return the index.
  467.     return False  # It's not on the board. No need for an else, since it's the last statement of the function.
  468.  
  469.  
  470. def rect(pen, x, y, width, height, color):  # Draws a rectangle of x,y,width,height and color.
  471.     winX, winY = windowToTurtleCoordinates(x, y, pen.getscreen().window_width(), pen.getscreen().window_height())
  472.     pen.penup()
  473.     pen.goto(winX, winY)
  474.     pen.pendown()
  475.     pen.pencolor(color)
  476.     pen.fillcolor(color)
  477.     if width == 1 and height == 1:
  478.         pen.dot()
  479.         return
  480.     elif width == 1:
  481.         pen.sety(winY - height)
  482.         return
  483.     elif height == 1:
  484.         pen.setx(winX + width)
  485.         return
  486.     pen.begin_fill()
  487.     pen.setheading(90)
  488.     for i in range(2):
  489.         pen.right(90)
  490.         pen.forward(width)
  491.         pen.right(90)
  492.         pen.forward(height)
  493.     pen.end_fill()
Add Comment
Please, Sign In to add comment