Color puzzle

I don’t remember if something like this was posted before, but this was something I just threw together. The object is to change all the circles from red to green. When you tap a circle, it will flip its color (red to green or green to red) along with each circle on both sides of it. It starts at 5 circles, but will increase by 2 circles each time you change them to all green. If someone want to make this more interesting, go for it.

supportedOrientations(LANDSCAPE_ANY)

function setup()
    nbr=5
    setup2()
end

function setup2()
    prnt=true
    sol={}
    win=false
    pos=0
    moves=0
    tab={}
    for z=1,nbr do
        a=360/nbr*z
        x=math.sin(math.rad(a))*350+WIDTH/2
        y=math.cos(math.rad(a))*350+HEIGHT/2
        table.insert(tab,vec3(x,y,0))    
    end    
end

function draw()
    background(227, 181, 107, 255)
    if pos>0 then
        swap(pos-1)
        swap(pos+1)
        swap(pos)
        pos=0
    end
    for a,b in pairs(tab) do
        fill(255,0,0)
        if b.z==1 then
            fill(0,255,0)
        end
        ellipse(b.x,b.y,50)
        fill(255)
        text(a,b.x,b.y)
    end
    fill(255)
    text(#tab.." circles",WIDTH/2,HEIGHT/2+50)
    text("Moves = "..moves,WIDTH/2,HEIGHT/2)    
    check()
    if win then
        text("Change complete.",WIDTH/2,HEIGHT/2-50)
        text("Tap screen for next round.",WIDTH/2,HEIGHT/2-100)
        if prnt then
            prnt=false
            output.clear()
            print(table.concat(sol," "))
        end
    end
    fill(0, 0, 255, 255)

end

function check()
    win=true
    for z=1,#tab do
        if tab[z].z==0 then
            win=false
        end        
    end
end

function swap(p)
    if p<1 then
        p=#tab
    elseif p>#tab then
        p=1
    end
    if tab[p].z==1 then
        tab[p].z=0
    else
        tab[p].z=1
    end
end

function touched(t)
    if t.state==BEGAN then
        if win then
            nbr=nbr+2
            setup2()
            output.clear()
            return
        end
        pos=0
        for z=1,#tab do
            if t.x>tab[z].x-25 and t.x<tab[z].x+25 and 
                    t.y>tab[z].y-25 and t.y<tab[z].y+25 then
                pos=z
                moves=moves+1
                table.insert(sol,pos)
                return
            end
        end
    end
end

I remember these games. And they are maddening. Took me 9 moves for the five circles. Edit: 5 moves now. Edit 2: And 25 moves for 7 circles.

There’s probably a pattern. Once you know what it is, the games probably too easy.

Changed code to show circle numbers and once the change is complete, I print the tapped sequence.

Cool game!
The fun does diminish once you figure out the strategy… :slight_smile:

Here’s another color puzzle. The object is to return the colored square back to the starting position. To start, select EASY, MEDIUM, or HARD which will make random moves to mix the colors. Easy makes 10 random moves, medium makes 20, and hard makes 40. Each puzzle can be solved since I always start with a completed puzzle. To move, swipe a column up or down, or a row right or left. A swipe moves each row or column one square. A color can’t be moved off the playing field. I didn’t add code to verify if a puzzle is solved. Press the restart icon to play another game.

supportedOrientations(LANDSCAPE_ANY)
displayMode(FULLSCREEN)

function setup()
    --clearProjectData()
    mix=readProjectData("mix")
    if mix==nil then
        mix=1
    else
        mix=mix+1
    end
    moves=0
    setup1()
end

function setup1()
    comp=false
    start=true
    col={color(0,0,255,255),color(0,255,0,255),color(0,255,255,255),color(255,0,0,255),
        color(255,0,255,255),color(255,255,0,255),color(128,128,128,255),color(0,0,128,255),
        color(0,128,0,255),color(0,128,128,255),color(128,0,0,255),color(128,0,128,255)}
    rectMode(CENTER)
    tab={}
    for x=1,16 do
        tab[x]={}
        for y=1,16 do
            tab[x][y]=vec4(0,0,0,0)
            if x>2 and x<15 and y>2 and y<15 then
                tab[x][y]=col[x-2]
            end
        end
    end
    xo=200
    yo=30
end

function draw()
    background(50,50,50)
    for x=1,16 do
        fill(0,0,0)
        if x>2 and x<15 then
            fill(col[x-2])
        end
        rect(x*40+xo,HEIGHT-30,40,40)   
        if x<3 or x>14 then
            fill(255)
            ellipse(x*40+xo,HEIGHT-30,6)
        end
    end
    for x=1,16 do
        for y=1,16 do
            fill(tab[x][y].x,tab[x][y].y,tab[x][y].z)
            rect(x*40+xo,y*40+yo,40,40) 
            if x<3 or x>14 or y<3 or y>14 then
                fill(255)
                ellipse(x*40+xo,y*40+yo,6)
            end
        end
    end
    if done then
        fill(255)
        rect(WIDTH/2,HEIGHT/2,400,100)
        fill(255,0,0)
        fontSize(70)
        text("COMPLETE",WIDTH/2,HEIGHT/2)
    end
    if start then
        fontSize(60)
        fill(255)
        text("Tap screen to mix colors",WIDTH/2,HEIGHT-100)
    end
    fill(255)
    fontSize(40)
    text(string.format("Level %d",mix),100,HEIGHT/2)
    text(string.format("Moves %d",moves),100,HEIGHT/2-50)
end

function touched(t)
    if t.state==BEGAN then
        xm,ym=0,0
        x=(t.x-xo+20)//40
        y=(t.y-yo+20)//40
    end
    if t.state==MOVING then
        xm=xm+t.deltaX
        ym=ym+t.deltaY
    end
    if t.state==ENDED then
        if done then
            mix=mix+1
            done=false
        end
        if start then
            done=false
            start=false
            for z=1,mix do
                xm,ym=0,0
                a=math.random(1,2)
                if z%2==0 then
                    if a==1 then
                        xm=50
                    else
                        xm=-50
                    end
                else
                    if a==1 then
                        ym=50
                    else
                        ym=-50
                    end
                end
                x=math.random(3,14)
                y=math.random(3,14)
                move()
                moves=0
            end
            return
        end
        move()
        complete()
    end
end

function complete()
    comp=true
    for x=3,14 do
        for y=3,14 do
            a=tab[x][y]
            b=col[x-2]
            if a.x~=b.x or a.y~=b.y or a.z~=b.z or a.w~=b.w then
                comp=false                
            end
        end
    end
    if comp then
        done=true
        saveProjectData("mix",mix)
        setup1()
    end
end

function move()
    if x<1 or x>16 or y<1 or y>16 then
        return
    end
    if math.abs(xm)>40 or math.abs(ym)>40 then
        moves=moves+1
    end
    if xm>40 and tab[16][y].x==0 and tab[16][y].y==0 and tab[16][y].z==0 then
        for x=16,2,-1 do
            tab[x][y]=tab[x-1][y]
        end
        if tab[1][y].x>0 or tab[1][y].y>0 or tab[1][y].z>0 then
            tab[1][y]=vec4(0,0,0,255)
        elseif tab[2][y].x>0 or tab[2][y].y>0 or tab[2][y].z>0 then
            tab[2][y]=vec4(0,0,0,255)
        end
    elseif xm<-40 and tab[1][y].x==0 and tab[1][y].y==0 and tab[1][y].z==0 then
        for x=2,16 do
            tab[x-1][y]=tab[x][y]
        end
        if tab[16][y].x>0 or tab[16][y].y>0 or tab[16][y].z>0 then
            tab[16][y]=vec4(0,0,0,255)
        elseif tab[15][y].x>0 or tab[15][y].y>0 or tab[15][y].z>0 then
            tab[15][y]=vec4(0,0,0,255)
        end
    elseif ym>40 and tab[x][16].x==0 and tab[x][16].y==0 and tab[x][16].z==0 then
        for y=16,2,-1 do
            tab[x][y]=tab[x][y-1]
        end
        if tab[x][1].x>0 or tab[x][1].y>0 or tab[x][1].z>0 then
            tab[x][1]=vec4(0,0,0,255)
        elseif tab[x][2].x>0 or tab[x][2].y>0 or tab[x][2].z>0 then
            tab[x][2]=vec4(0,0,0,255)
        end
    elseif ym<-40 and tab[x][1].x==0 and tab[x][1].y==0 and tab[x][1].z==0 then
        for y=2,16 do
            tab[x][y-1]=tab[x][y]
        end           
        if tab[x][16].x>0 or tab[x][16].y>0 or tab[x][16].z>0 then
            tab[x][16]=vec4(0,0,0,255)
        elseif tab[x][15].x>0 or tab[x][15].y>0 or tab[x][15].z>0 then
            tab[x][15]=vec4(0,0,0,255)
        end
    end
end

Changed the above code to start at level 1 and increase the level each time a puzzle is complete. The number of moves was also added. Each level number is the number of random moves used to mix the puzzle. You should be able to solve each puzzle in the level number of moves.

@dave1707 , that’s a wonderful little game! Enjoyed it up to level 7, but then it becomes too hard :wink:

Very well done too, intuitive controls. I’ve not seen this particular type of color puzzle before - is this your own idea?

I had the idea for this for a long time but never got around to doing it. It’s like a flat Rubics cube.

It does a little bit resemble Rubik’s cube… And yet it still feels fresh and original. Brilliant idea, i must say.

Thanks for the comment. Just like Rubics cube, there’s probably a sequence of moves that flips colors around without affecting the other colors around it. I haven’t really tried playing it beyond level 4, I just enjoyed writing it.

Cool! But for me, with the last bit of code, the game controls don’t appear–like choosing the difficulty level and the reset icon for example.

I’m on an old iPad running iOS 9.x, could that be messing it up?

@UberGoober There are no control or level settings. With the latest code, after you tap the screen to mix the colors, you slide your finger up or down to move a column one square up or down. You slide your finger right or left to move a row one square right or left. The game starts at level 1 and increases a level with each completed game. The level is saved so you can start where you left off or restart that level if you get too mixed up.

PS. I tried this on my iPad 1 and it worked OK after I replaced the // divide with math.floor.

Can you show exactly how you wrote the math.floor? Did you math.floor the whole equation?

@UberGoober Here’s the math.floor code in the touched function.

function touched(t)
    if t.state==BEGAN then
        xm,ym=0,0
        x=math.floor((t.x-xo+20)/40)      -- math floor here
        y=math.floor((t.y-yo+20)/40)      -- math.floor here
    end
    if t.state==MOVING then
        xm=xm+t.deltaX
        ym=ym+t.deltaY
    end

Ok so thanks but that did not noticeably change anything–maybe it fixed something I didn’t get far enough to see.

I have it working now, or actually I understand how it works now.

I thought when it said “tap screen to mix colors” that the colors were going to get all scrambled, and when they all were still in neat little columns it confused me. But I get it now. It’s cool!

@UberGoober I guess I didn’t explain well enough what was supposed to happen. As the levels get higher, the colors will get more scrambled as I move more rows and columns around. In the lower levels, not many rows or columns get moved, so it doesn’t look that mixed up. The reasoning there was to get you used to moving the rows or columns around to easily solve a level.

If I may make a suggestion, a clearer way to scale complexity isn’t to scale the amount of scrambling, but to scramble fully all the time, and instead scale the number of columns and rows.

For example you could start with a 3x3 puzzle or something and add more rows and columns each time.

By moving just one bar by just one bump it just looks like I accidentally moved the bar myself.

Just to +1 everybody else: this is a neat and unique concept and I like it.

@UberGoober I think even if I started with a 4x4 puzzle and really mixed it up, it might be too hard or take too long to solve. Then going to a 5x5 would be harder, etc. Once you understand how the puzzle starts and how to move the rows and columns, the current size seems OK. So far I’ve gotten to level 7.