Search code examples
pythonpython-3.xpygamebubble-sort

I want to make a visualized bubble sort in pygame, the sort works but the visualization doesn't


like the title says I wanted to create a visualized bubble sort with python and pygame. The sort works perfectly but when it comes to visualize it it never gets the correct output.

Here's the code:

import pygame
import sys
import time

pygame.init()

Vector_len = 0
x = 0
numbers_to_order = []
IsRunning = True

Vector_len = eval(input("How many numbers do you want to sort? "))

for i in range(Vector_len):
    numbers_to_order.append(0)

for i in range(len(numbers_to_order)):
    numbers_to_order[i] = eval(input("Insert number at index "+str(i+1)+": "))

print("Inserted array: "+str(numbers_to_order))

screen = pygame.display.set_mode((1000,500))

while IsRunning:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            IsRunning = False

    for i in range(len(numbers_to_order)):

        for j in range(len(numbers_to_order)):
            try:
                if numbers_to_order[j] > numbers_to_order[j+1]:
                    x = numbers_to_order[j]
                    numbers_to_order[j] = numbers_to_order[j+1]
                    numbers_to_order[j+1] = x
            except(IndexError):
                pass
            pygame.draw.rect(screen,(255,255,255),(j*(1000/len(numbers_to_order)),500-(numbers_to_order[j])*50,(1000/len(numbers_to_order)),(numbers_to_order[j])*50))
            print((j*(1000/len(numbers_to_order)), (numbers_to_order[j])*50))
            pygame.display.flip()
            time.sleep(0.05)

print("Sorted array: "+str(numbers_to_order))
pygame.quit()
sys.exit()

When running, instead of showing the bars sorting correctly, they are displayed in a wrong order but the sort is correct. Any help?


Solution

  • The major issue is that you've to clear the display in every frame and to draw the entire "list" in every frame. Note, if a bar for a large number was drawn at position, then a bar for a smaller number won't "clear" that.

    screen.fill(0)
    for k, n in enumerate(numbers_to_order):
        pygame.draw.rect(screen,(255,255,255),(k*(1000/len(numbers_to_order)),500-(numbers_to_order[k])*50,(1000/len(numbers_to_order)),(n)*50))
    

    I recommend not to use nested loops in the game loop, which draw the scene. Use the main application loop and increment the control variables i and j in the loop:

    i = 0
    j = 0
    
    while IsRunning:
    
        # [...]
    
        if j < len(numbers_to_order)-1:
            j += 1
        elif i < len(numbers_to_order)-1:
            i += 1
            j = 0
    

    Further i recommend to use pygame.time.Clock()

    See the example:

    # start control variables
    i = 0
    j = 0
    IsRunning = True
    
    # main loop
    clock = pygame.time.Clock()
    while IsRunning:
    
        # handle events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                IsRunning = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                IsRunning = False
    
        # clear screen
        screen.fill(0)
    
        # draw the entire range
        for k, n in enumerate(numbers_to_order):
            pygame.draw.rect(screen,(255,255,255),(k*(1000/len(numbers_to_order)),500-(numbers_to_order[k])*50,(1000/len(numbers_to_order)),(n)*50))
    
        # update the display
        pygame.display.flip()
        clock.tick(10)
    
        # sort (1 step)
        print((j*(1000/len(numbers_to_order)), (numbers_to_order[j])*50))
        try:
            if numbers_to_order[j] > numbers_to_order[j+1]:
                x = numbers_to_order[j]
                numbers_to_order[j] = numbers_to_order[j+1]
                numbers_to_order[j+1] = x
        except(IndexError):
            pass
    
        # increment control variables
        if j < len(numbers_to_order)-1:
            j += 1
        elif i < len(numbers_to_order)-1:
            i += 1
            j = 0