Python Forum
Why do I have an infinite loop?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Why do I have an infinite loop?
#1
I'm developing a program that will simply generate all the possible colors if I restrict the rgb values to multiples of 51. Its working out so far, but right now some of my functions generate an infinite loop and I have no clue why. I initially ignored this, but then I opened up taskmanager to find out how much RAM the thing was taking, and I found it was perpetually increasing. Now I want to fix it, but I have no clue why its doing what its doing.

import pygame
pygame.init()

block=50

screenW=25*block
screenH=20*block

x=0
y=0

screen=pygame.display.set_mode((screenW,screenH))

red=False
green=False
blue=False
rg=False
rb=False
gb=False

def drawR():

    r=255
    g=0
    b=0

    global x
    global y
    global red

    x=0
    y=0

    while r>=0 and red==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("red",r,g,b)
        r-=51
        y+=block
        if r<=0:
            red=True

def drawG():

    r=0
    g=255
    b=0

    global x
    global y
    global green

    x=block
    y=0

    while g>=0 and green==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("green",r,g,b)
        g-=51
        y+=block
        if g<=0:
            green=True

def drawB():

    r=0
    g=0
    b=255

    global x
    global y
    global blue

    x=block*2
    y=0

    while b>=0 and blue==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("blue",r,g,b)
        b-=51
        y+=block
        if b<=0:
            blue=True

def drawRG():
    r=255
    g=255
    b=0

    global x
    global y
    global rg

    x=block*3
    y=0

    while r>=51 and g>=51 and rg==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("redgreen",r,g,b)
        r-=51
        if r<51:
            r=255
            g-=51
        if r==0 and g==51:
            rg=True
        y+=block
        if y>block*4:
            y=0
            x+=block

def drawRB():
    r=255
    g=0
    b=255

    global x
    global y
    global rb

    x=block*8
    y=0

    while r>=51 and b>=51 and rb==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("redblue",r,g,b)
        r-=51
        if r<51:
            r=255
            b-=51
        if r==0 and b==51:
            rb=True
        y+=block
        if y>block*4:
            y=0
            x+=block

def drawGB():
    r=0
    g=255
    b=255

    global x
    global y
    global gb

    x=block*13
    y=0

    while b>=51 and g>=51 and rg==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("bluegreen",r,g,b)
        b-=51
        if b<51:
            b=255
            g-=51
        if b==0 and g==51:
            gb=True
        y+=block
        if y>block*4:
            y=0
            x+=block

def main():

    while True:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                pygame.quit()
                exit()

        drawR()
        drawG()
        drawB()
        drawRG()
        drawRB()
        drawGB()

        pygame.display.update()

main()
What makes no sense is the first three functions (drawR, drawG, and drawB) do NOT make an infinite loop, but the latter three do (at least, they do when they print out the rgb value of each square they draw). They're based on the first three, so I can't fathom why they would do this. Their loops DO have an end point, just like the ones that draw the primary colors. Yeah, they're a bit more elaborate, but that's just because they have to change two values rather than one. I would guess this is a logic error somewhere, except I already made sure that the loops DON'T repeat. I have no clue what could be wrong.

I take it I'm just going to get an answer here? Go figure.

And then someone comes in and sabotages my thread. Aren't you all considerate? The owners of python should sue you for defamation at this rate.
Reply
#2
The first three run and then set the global variable to False. The last three don't do that so they are never told to stop.
Reply
#3
Uh, what are you talking about? The drawRG function sets its variable to true on line 104, and that variable is set to global on line 91. In my program, I have those variables set to false if the functions aren't done, and true when they are. Note how they're all declared false at the start of the program, and they're all outside the main loop.
Reply
#4
Ohhh.... I remember you.

If they were getting set to True then they would stop, that is the entire, specific purpose a while loop.

Add "rg", "rb", and "bg" to you print statements. They all stay False.
Reply
#5
Strangely enough, I already tried to do that after I posted my last comment, but for some reason they won't print, even though the thing is printing the rgb values fine (I did that earlier to make sure it was rendering things right, it wasn't showing the right number of squares earlier). Also, changing the order of the commands doesn't fix the problem either. At this point, I'm starting to think my program is ignoring some of the lines.

Another thing I find really strange is it doesn't just do one loop over and over; it loops through all three. If they're caught in an infinite loop, then how can the program be cycling between all three of them? Shouldn't it remain locked in one loop?

I decided to put lines in the main loop to set the variables to True. That fixed the problem. I'm still mystified that it was ignoring the identical lines I typed in the original program.

Okay then, now I have another problem. Its suddenly not rendering one of the blocks of color! Specifically, the green-blue box. There is literally no difference between the function and the others; I copy-pasted them! And it WAS working before!

import pygame
pygame.init()

block=50

screenW=25*block
screenH=20*block

x=0
y=0

screen=pygame.display.set_mode((screenW,screenH))

list=[255,204,153,102,51]

red=False
green=False
blue=False
rg=False
rg_b=False
rb=False
rb_g=False
gb=False
gb_r=False

def drawR():

    r=255
    g=0
    b=0

    global x
    global y
    global red

    x=0
    y=0

    while r>=0 and red==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("red",r,g,b)
        r-=51
        y+=block
        if r<=0:
            red=True

def drawG():

    r=0
    g=255
    b=0

    global x
    global y
    global green

    x=block
    y=0

    while g>=0 and green==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("green",r,g,b)
        g-=51
        y+=block
        if g<=0:
            green=True

def drawB():

    r=0
    g=0
    b=255

    global x
    global y
    global blue

    x=block*2
    y=0

    while b>=0 and blue==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("blue",r,g,b)
        b-=51
        y+=block
        if b<=0:
            blue=True

def drawRG():
    r=255
    g=255
    b=0

    global x
    global y
    global rg

    x=block*3
    y=0

    while r>=51 and g>=51 and rg==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("redgreen",r,g,b)
        r-=51
        if r<51:
            r=255
            g-=51
        if r==0 and g==51:
            rg=True
        y+=block
        if y>block*4:
            y=0
            x+=block

def drawRB():
    r=255
    g=0
    b=255

    global x
    global y
    global rb

    x=block*8
    y=0

    while r>=51 and b>=51 and rb==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("redblue",r,g,b)
        r-=51
        if r<51:
            r=255
            b-=51
        if r==0 and b==51:
            rb=True
        y+=block
        if y>block*4:
            y=0
            x+=block

def drawGB():
    r=0
    g=255
    b=255

    global x
    global y
    global gb

    x=block*13
    y=0

    while b>=51 and g>=51 and rg==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("bluegreen",r,g,b)
        b-=51
        if b<51:
            b=255
            g-=51
        if b==0 and g==51:
            gb=True
        y+=block
        if y>block*4:
            y=0
            x+=block

##def drawRG_B():
##    z=0
##    for i in list:
##        r=255
##        g=255
##        b=i
##
##
##        global x
##        global y
##        global rg_b
##
##        rg_b=False
##
##        x=block*z
##        y=block*5
##
##        print(z)
##
##        while r>=51 and g>=51 and b>=51 and rg_b==False:
##            pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
##            print("redgreen-blue",r,g,b)
##            r-=51
##            if r<51:
##                r=255
##                g-=51
##            if r==0 and g<=51 and b<=51:
##                rg_b=True
##                z+=5
##                
##            y+=block
##            if y>block*9:
##                y=block*5
##                x+=block
        

def main():

    while True:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                pygame.quit()
                exit()

        global rg
        global rb
        global gb


        drawR()
        drawG()
        drawB()
        drawRG()
        rg=True
        drawRB()
        rb=True
        drawGB()
        gb=True
##        drawRG_B()

        pygame.display.update()

main()
This is getting stupid. Oh, and ignore the commented-out stuff. I gave up hope I was going to get help and started working on the functions for that would draw the boxes that had all three colors mixed in. Sadly though, it wasn't drawing all of them (its supposed to draw a series of five boxes with progressively higher blue values, it only draws the first), and it really ramped up the issue with the RAM (no pun intended). Honestly, I'll probably just delete that and start over once I fix the issue with the 2-color functions.
Reply
#6
The bottom 3 function use:
 if b==0 and g==51:
            gb=True
The top 3 use "<="
Reply
#7
Doing that change doesn't fix the issue. Nor does removing the gb=True line in the main loop. What? Did making those global in the main loop mess up something?
Reply
#8
Why are you not using range loops ?
You can do that. All with one function.
import os
import pygame
from itertools import product

def draw_color(surface, x, y, color, c_range, block):
    y_top = y
    red = range(color.r, -1, -c_range)
    green = range(color.g, -1, -c_range)
    blue = range(color.b, -1, -c_range)
    for r, g, b in product(red, green, blue):
        pygame.draw.rect(surface, (r, g, b), (x, y, block, block))
        y += block
        if y > block * 4 + y_top:
            x += block
            y = y_top

def main():
    pygame.init()
    # Center Screen before creating main surface.
    os.environ['SDL_VIDEO_CENTERED'] = '1'

    block = 50
    size = block * 25, block * 25

    # Basic pygame setup
    pygame.display.set_caption("Colors")
    surface = pygame.display.set_mode(size)
    clock = pygame.time.Clock()
    rect = surface.get_rect()
    delta = 0
    fps = 60


    # Main Loop
    running = True
    while running:
        # Event Loop
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # Draw
        surface.fill(pygame.Color('black'))
        draw_color(surface, 0, 0, pygame.Color('red'), 50, block)
        draw_color(surface, block, 0, pygame.Color('green'), 50, block)
        draw_color(surface, block * 2, 0, pygame.Color('blue'), 50, block)
        draw_color(surface, block * 4, 0, pygame.Color(255, 255, 0), 50, block)
        draw_color(surface, block * 12, 0, pygame.Color(0, 255, 255), 50, block)
        draw_color(surface, block * 4, block * 6, pygame.Color(255, 0, 255), 50, block)

        # Render to screen
        pygame.display.flip()

        # Sleep/Idle and Delta
        delta = clock.tick(fps)

main()
99 percent of computer problems exists between chair and keyboard.
Reply
#9
I can make no sense of that code. Also, it imports two modules I've never even heard of.

At this point, I'm thinking I need to just re-do the functions for the two-color blocks before moving on. Besides, I've tweaked the functions so much I can't even understand my own loops anymore.

And yes, I did think about making one function that could render everything, but I couldn't think of a way to get such to work, at least while using only python and pygame code. Honestly, at one point I was thinking it would actually take less lines of code if I just manually entered in every single possible combination rather than having an algorithm make them for me, and at this rate I'm still open to that being a possibility.
Reply
#10
I re-did the two-color functions, and now I no longer have an infinite loop. Also, the functions are far simpler this time since I based them off the single-color ones.

import pygame
pygame.init()

block=50

screenW=25*block
screenH=20*block

x=0
y=0

screen=pygame.display.set_mode((screenW,screenH))

list=[255,204,153,102,51]

red=False
green=False
blue=False

redgreen=False
redblue=False
greenblue=False

def drawR():

    r=255
    g=0
    b=0

    global x
    global y
    global red

    x=0
    y=0

    while r>=0 and red==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("red",r,g,b)
        r-=51
        y+=block
        if r<=0:
            red=True

def drawG():

    r=0
    g=255
    b=0

    global x
    global y
    global green

    x=block
    y=0

    while g>=0 and green==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("green",r,g,b)
        g-=51
        y+=block
        if g<=0:
            green=True

def drawB():

    r=0
    g=0
    b=255

    global x
    global y
    global blue

    x=block*2
    y=0

    while b>=0 and blue==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("blue",r,g,b)
        b-=51
        y+=block
        if b<=0:
            blue=True
        
def drawRedGreen():

    r=255
    g=255
    b=0

    global x
    global y
    global redgreen

    x=block*3
    y=0

    while r>=0 and g>=0 and redgreen==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("redgreen",r,g,b)
        r-=51
        y+=block
        if y>=block*5:
            y=0
            x+=block
        if r<=0:
            r=255
            g-=51
        if g<=0:
            redgreen=True

def drawRedBlue():

    r=255
    g=0
    b=255

    global x
    global y
    global redblue

    x=block*8
    y=0

    while r>=0 and g>=0 and redblue==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("redgreen",r,g,b)
        r-=51
        y+=block
        if y>=block*5:
            y=0
            x+=block
        if r<=0:
            r=255
            b-=51
        if b<=0:
            redblue=True

def drawGreenBlue():

    r=0
    g=255
    b=255

    global x
    global y
    global greenblue

    x=block*13
    y=0

    while g>=0 and b>=0 and greenblue==False:
        pygame.draw.rect(screen,(r,g,b),(x,y,block,block))
        print("redgreen",r,g,b)
        g-=51
        y+=block
        if y>=block*5:
            y=0
            x+=block
        if g<=0:
            g=255
            b-=51
        if b<=0:
            greenblue=True

def main():

    while True:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                pygame.quit()
                exit()

        global rg
        global rb
        global gb


        drawR()
        drawG()
        drawB()
        drawRedGreen()
        drawRedBlue()
        drawGreenBlue()

        pygame.display.update()

main()
Next up is all the three-color values. I wasn't able to get that part work before, and also my program takes a second to display stuff. Hopefully it'll be easier this time now that I have 2-color functions that work better.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020