• Buzzerb

    @ccc I looked into using timeit to determine performance of all these changes but ultimately decided that performance was almost definitely not the problem my widget was encountering.

    Thank you for the dictionary approach anyway, it’s much more concise than I would’ve managed

    posted in Pythonista read more
  • Buzzerb

    @ccc Not sure how legitimate it is but I read that '+' string concatenation is faster when only combining two strings, and f string is faster with more. Also, is using dict.get with a default significantly slower or faster than just fetching a value because my game is unlikely to get above 8192, and I could always add more pairs to the dictionary.

    posted in Pythonista read more
  • Buzzerb

    @JonB I’m not sure what would classify this as a scene game, could you explain?

    Edit: @ccc In that case I'm not using a scene game

    posted in Pythonista read more
  • Buzzerb

    @ccc Speed isn’t really the problem as far as I know, but it’s possible that your method helps, I’ll test it. And thank you for the all buttons sharing a single action script.

    posted in Pythonista read more
  • Buzzerb

    @JonB I managed to get it working simply by adding del ui after loading my view. All the necessary objects were contained in screen as far as I can tell, so this removed a significant quantity of unnecessary data.

    Edit: Somewhat working- occasional crashes occur

    posted in Pythonista read more
  • Buzzerb

    @JonB I have a working implementation of swiping to move the game, however widgets do not support swipes as far as I can tell (they simply move the list of widgets up and down). Would it be possible to manually implement buttons through the method you listed? I presume begin_touch would work but I don’t know.
    I’m also a little unsure as to how this would allow me to reduce memory use, are you suggesting that one ui.view object displays all of the boxes and text? Would there be any way to reduce the size of the scene, as it also appears to generate a lot of unnecessary variables.

    posted in Pythonista read more
  • Buzzerb

    I’m attempting to make a 2048 game that will run as a widget. The game does work, however it will crash if run in the widget. I can also get it to work by removing any of my colour changing code, however I wish to avoid this. To my (untrained) eye, when looking in the object inspector, the vast majority of variables appear to be UI variables. Therefore, I'm wondering if there is any way to drastically trim the included data attributes and methods. Also, I have tried to modify my code to reduce memory usage but any further suggestions are welcome.

    from random import randint
    from console import alert
    from appex import set_widget_view
    import ui
    
    """These variables need to be global"""
    score = 0 #what it says
    moves = 0
    fails = set() #needs to be global despite only being in one module to exist between calls
    failed = False #Records whether a move was sucessful and therefore whether to add randoms
    playGrid = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]  #The current grid
    tileUI = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] #The corresponding text fields
    
    
    def printGrid():
        """Outputs the current grid onto the UI, along with score, and number of moves"""
        for y in range(4):
            for x in range(4):
                tile = screen["tile" + str(y) + str(x)]
                #Reset normal font colour and size
                tile.text_color = "#000000"
                tile.font = ("<system-bold>", 50)
                if playGrid[y][x] != 0: #Write non-zeros to grid pos
                    tile.text = str(playGrid[y][x])
                    #Set colours
                    if playGrid[y][x] == 2: 
                        tile.background_color = "#fbffaa"
                    elif playGrid[y][x] == 4:
                        tile.background_color = "#fff1aa"
                    elif playGrid[y][x] == 8:
                        tile.background_color = "#ffb86a"
                    elif playGrid[y][x] == 16:
                        tile.background_color = "#ff703e"
                    elif playGrid[y][x] == 32:
                        tile.background_color = "#ff4f4f"
                    elif playGrid[y][x] == 64:
                        tile.background_color = "#f20000"
                    elif playGrid[y][x] == 128:
                        tile.background_color = "#edf800"
                    elif playGrid[y][x] == 256:
                        tile.background_color = "#7cff61"
                    elif playGrid[y][x] == 512:
                        tile.background_color = "#00f315"
                    elif playGrid[y][x] == 1024:
                        tile.background_color = "#23ffe2"
                    elif playGrid[y][x] == 2048:
                        tile.background_color = "#47b7ff"
                    elif playGrid[y][x] == 4096:
                        tile.background_color = "#0b20ff"
                        tile.text_color = "#ffffff"
                    elif playGrid[y][x] == 8192:
                        tile.background_color = "#9400db"
                        tile.text_color = "#ffffff"
                    else:
                        tile.background_color = "#000000"
                        tile.text_color = "#ffffff"
                        tile.font = ("<system-bold>", 42)
                else:
                    tile.text = "" #Zeros shown as blank
                    tile.background_color = "#ffffff"    
                del tile         
        screen["scoreLabel"].text = "Score: " + str(score)
        screen["movesLabel"].text = "Moves: " + str(moves)
    
            
    def generateNewNumbers():
        """Places a random 2 or 4 onto a random grid position"""
        randomXLocation = randint(0, 3) #Generate random coordinates
        randomYLocation = randint(0, 3)
        while playGrid[randomYLocation][randomXLocation] != 0: #Keep doing it till the location is empty
            randomXLocation = randint(0, 3)
            randomYLocation = randint(0, 3)
        playGrid[randomYLocation][randomXLocation] = randint(1, 2) * 2 #Set that location to 2 or 4
        del randomXLocation, randomYLocation
        
    def moveTilesDirection(direction):
        """Moves the tiles in playGrid in a specified direction.
        
        Usage: moveTilesDirection(direction)
        0 is up, 1 is right, 2 is down, 3 is left
        """
        #failed, fails and moves need to be global, playgrid is a list and does not
        global failed
        global fails
        global moves
        def combineTiles():
            """Combines current tile with previous tile, and add non-zero values to a stack"""
            #score must be global
            global score
            #Non-Local needed to ensure that values are retrived and modified correctly
            nonlocal Ycord
            nonlocal Xcord
            nonlocal lastTile
            nonlocal tileStack
            
            if playGrid[Ycord][Xcord] > 0: #First check there is a value here
                if lastTile == playGrid[Ycord][Xcord]: #If the same as last, combine
                    tileStack.pop() #Remove the last value from stack
                    tileStack.append(lastTile * 2) #and add combined
                    score += lastTile * 2 #Add to score
                    lastTile = -1 #And reset to prevent double combines
                else: #If not the same as last
                    lastTile = playGrid[Ycord][Xcord] #update last tile
                    tileStack.append(lastTile) #and add to row stack
        
        #empty the save of previous grid and update to current (surface copy)
        previousPlayGrid = [playGrid[i][:] for i in range(4)]
        
        #check for directions
        if direction == 0:
            for Xcord in range(4): #for each row/column
                tileStack = [] #reset the stack and last tile
                lastTile = -1
                for Ycord in range(4): #step through row/column
                    combineTiles() #with combine tiles
                while len(tileStack) < 4: #append as many 0's as needed
                    tileStack.append(0)
                for i, tile in enumerate(tileStack): #write to column
                    playGrid[i][Xcord] = tile
        elif direction == 2:
            for Xcord in range(4):
                tileStack = []
                lastTile = -1
                for Ycord in range(3, -1, -1):
                    combineTiles()
                tileStack.reverse() #reverse the complete stack
                while len(tileStack) < 4:
                    tileStack.insert(0, 0) #need to put 0's at start so have to insert at beginning
                for i, tile in enumerate(tileStack):
                    playGrid[i][Xcord] = tile
        elif direction == 1:
            for Ycord in range(4):
                tileStack = []
                lastTile = -1
                for Xcord in range(3, -1, -1):
                    combineTiles()
                tileStack.reverse()
                while len(tileStack) < 4:
                    tileStack.insert(0, 0)
                playGrid[Ycord] = tileStack #easier to write to rows
        elif direction == 3:
            for Ycord in range(4):
                tileStack = []
                lastTile = -1
                for Xcord in range(4):
                    combineTiles()
                while len(tileStack) < 4:
                    tileStack.append(0)
                playGrid[Ycord] = tileStack
        
        #Check this was a valid move
        if previousPlayGrid == playGrid: #if nothing moved
            fails.add(direction) #add this direction to failed set (set ensures no duplicates)
            if len(fails) == 4: #if all 4 directions tried, you lost
                alert("YOU LOST!")
            else: #if not retry without adding random tiles or printing
                failed = True
        else: #if the moved worked, reset fail counters
            fails = set()
            failed = False
            moves += 1
    
    """UI SETUP"""
    def upButton(sender):
        moveTilesDirection(0)
        if failed == False:
            generateNewNumbers()
            printGrid()
    
    def rightButton(sender):
        moveTilesDirection(1)
        if failed == False:
            generateNewNumbers()
            printGrid()
    
    def downButton(sender):
        moveTilesDirection(2)
        if failed == False:
            generateNewNumbers()
            printGrid()
    
    def leftButton(sender):
        moveTilesDirection(3)
        if failed == False:
            generateNewNumbers()
            printGrid()
    
    #finally do something (load the view)
    screen = ui.load_view('ScreenWidget')
    set_widget_view(screen)
    
    #generate starting numbers and print to screen
    generateNewNumbers()
    printGrid()
    

    posted in Pythonista read more
  • Buzzerb

    Thank you for all of the responses

    posted in Pythonista read more
  • Buzzerb

    I am attempting to write a program, within which I need to load a file, and remove all punctuation from it. In attempting to do so, I receive a 'set' object does not support indexing error. I am not sure which variable is a set, and why this is failing. A simplified version of my code is below

    import string
    input_file = open("Test1.txt", "r") #Open the file 'Test1'
    input_file = input_file.read() #Convert the file to a string
    input_file = input_file.translate({None for a in string.punctuation}) #Attempt to remove punctuation. 
    #The error is thrown by the above line
    

    posted in Pythonista read more
  • Buzzerb

    @JonB Thank you so much. If anyone, or Jon, would be able to explain exactly how this works, it would be greatly appreciated.

    posted in Pythonista read more

Internal error.

Oops! Looks like something went wrong!