(bell dings)
- Hello and welcome to part three
of my Rubik's Cube coding challenge.
So I've done two parts already,
if you watch those,
I'm very thankful to you.
But I'm going to do something really important in this.
And it's really not about the Rubik's Cube at all,
it's really about animation.
And I want to be able to just do something
to make it a little more visually pleasing
to watch it do stuff.
So what it does right now is,
if I hit the space bar,
it's going to shuffle a whole bunch of moves.
All the possible moves,
up, down
left, right
clockwise, counterclockwise.
It could do any move along any axis.
It's also then going to whatever,
it's doing a random sequence of 100 moves
and then it's going to do those in reverse.
And you can see it looks kind of like it's solving it,
of course it's not.
Just doing a random sequence
and then applying it in reverse.
Hit the space bar again,
it's going to go again.
It's actually doing the same sequence again.
So this would be I think more,
I would be a little more confident
that it's working correctly,
if I could actually watch the,
the cubies
rotate themselves to actually turn.
So in order to do that,
I need to add animation,
I need to actually use the rotate function
to do that.
So (chuckles), I have to figure out how to do that.
Alright I think a way that's going to make sense
to do this is
to create a class,
called move.
And each move is what?
It's a given axis,
like what's the axis that's moving,
what's the direction it's moving
and then if I'm going to do an animation,
I need to animate an angle from zero to 90 degrees.
So I need an angle
which will start as zero.
I need to have an axis
and maybe what I'll do is just do x,
y
and z.
An angle and an axis.
And I'll have that access
distort in variables x, y and z.
So the x will be one
or negative one,
if it's right or left.
The y will be one
or negative one, if it's up or down.
The z will be one
or negative one, if it's front or back.
So, that's kind of I think how I'll deal
with this right now.
So when I make a move,
I have to give it an x, a y
and a z.
And that's all I have to give it.
And a direction.
So I need to know whether I'm rotating,
whether I'm rotating clockwise
or counter clockwise.
Or the angle is going up
or the angle is going down.
So this dot x equals x.
This dot y equals y.
This dot Z equals Z.
This dot direction equals direction.
And this is this.
Ultimately I've kind of done this already
in the sense that I have these functions,
called turn z,
turn y, turn x.
And those actually move the cubes around
and rotate their faces.
But they do it instantaneously.
So what I think I want to do is,
create an animation that happens,
then I finish that animation
then I quickly move everything around.
And it'll look as if it's happening seamlessly.
So let's just say,
for the sake of argument,
I'm going to have one move.
Move m.
I'll call it move.
And move m,
forget about this,
well I'll leave the sequence thing in here
for a second.
Move, is a new move
which is going to rotate the z-axis,
the front face.
So that is zero, zero,
one in a clockwise direction.
That's a move.
Then I want to say,
move dot start.
I think I'll have a function called start
and what does that do?
It sets a variable,
I'll have a variable called animating.
And it sets animating
equal to true.
I don't know that I'm going to need this,
but I feel like I might need a flag
to know when I've started
or stopped.
So then I need
an update function
and what update will do,
is, I could use LERP
for to like interpolate from zero to 90 degrees
or I could just increase the angle.
So let's just increase the angle right now.
I'm going to say, angle plus equals direction times,
you know some amount like point one.
So I'm going to increment the angle by point one
and if angle is greater than HALF_PI,
then,
angle should go back
to being zero actually.
And then I'm going to say,
animating equals false.
So let's just see if I can get this to happen.
So basically, if I have a move,
then I say move dot start,
then in draw, I just want to say
move dot update.
And if I run this.
(chuckles) so the data of the move is happening.
That angle is changing
but I need to actually rotate these.
So the way that I could do that is,
right here when I'm showing the cube,
I could check
and say,
if cube, well right here you could just say,
if cube dot z
equals move dot z.
Let's just do that alright.
If cube dot z equals move z.
Then I want to rotate
z
by move dot angle.
And I'm going to want to have a push
and a pop here.
Right? That should then,
z cannot be resolved
or is not a field.
Move has a z.
Cube index i.
If cube index i right.
If cube index i dot z.
Here we go! Look at it!
It's turning!
(grunts) It's kind of doing something.
What's it doing?
Why is it keep going?
Okay (chuckles).
So, (clears throat)
update, (laughs)
should only update the angle
if it's animating.
So once it reaches the end,
it stops animating.
So now, we should see it
turn.
You know what, I think,
I'm having this weird issue with processing
which is that, it takes a little while
for processing to start.
So what I'm actually going to do is,
I'm going to have move dot start
go into,
when I press the space bar.
Just so I can be sure it hasn't started yet.
So I'm going to run this sketch.
I'm going to hit the space bar.
There we go.
Look at that. It moves,
but look at this, it moves
but the red stuff doesn't stay there.
Because all I'm doing is creating the animation
of the moving,
I'm not actually updating the data.
But I need to update the data
so I can do all the future moves.
But I think there's an easy thing I can do here
which is I can say, move dot update if
move dot finished.
Then, what do I want to do?
Turn z move dot direction.
Turning z, isn't that a function?
Turn z move dot z,
move dot direction.
So I think there's got to be a way
I can encapsulate this into one function.
There's no finished,
so I probably could just use the animating Boolean right?
Let's add another one (laughs).
Finished is false,
finished is true
and then,
Boolean finished,
returned finished.
So now, what should happen is,
it should animate, (laughs)
because it's doing this over
and over again.
So it ultimately,
I want them,
when the move is finished,
I want to turn it once
and then be done.
So really what I should do,
is put this turn z
into the move.
Yes.
So actually, I don't know if I need
that Boolean variable at all.
What I want, is when it's done,
I want to actually just say turn z,
move according to this z
and this direction right?
And then I don't need this finished stuff.
I'm going to keep that in there just in case I need it.
So now, it should turn.
There we go!
Look at this!
(exclaims excitedly)
So now, I'm turning it.
So this is the idea.
This is the logic.
I just want to hit the space bar,
it's doing every single move.
Now the question is,
now that I've got this working,
how can I make every move work in the same way?
So there's some things
that are kind of hard coded in here.
For example, this shouldn't always be turn z.
Right, this should sometimes be turn x
or turn y
or turn
z.
Before I do that though,
let me just make sure it works in other directions.
So for example,
if I were to say a negative one,
that should be the back of the cube.
Okay. So that's working.
And if I were to say one,
negative one,
that should be the front of the cube
but going now in counter clockwise direction.
Okay.
So that doesn't work.
So why doesn't that work?
Because if I'm going in counterclockwise direction,
I'm going all the way to negative HALF_PI.
So that's something I need to fix.
So here, if angle,
so I could say, if absolute value of the angle
is greater than HALF_PI.
So if I'm going in the negative direction,
I need to check negative HALF_PI.
That should fix that.
Great! So now I can go in either direction.
Only in the z axis.
So what if I make a move,
that is now
the x axis?
So if I say one, zero,
zero, one,
this should be right.
I think I have things flipped
so it might end up being in the left,
in the way that we're looking at it.
But if I want to rotate along the x axis.
So if I do that now,
it's confused.
It's doing something totally nonsensical.
So here what I really want to say if
absolute value of cube index i dot z is greater than zero.
So I probably should have a variable
that's keeping track of the actual index.
But really what I want to just say is,
is cubes,
is it the z axis?
Then do this.
So now, nothing should happen.
Something did happen.
It's still doing this.
But then we shouldn't see that animation.
Okay.
So let's try to get the x axis.
Else,
if the absolute value of cube x
and cube x equals move x,
then I should say,
rotate x move dot angle.
Alright. So this now would do the x axis.
And this should be an else-if
cause I'm never going to do two
at the same time.
So this should be rotating the x axis.
The issue is now in move update,
when I get to this part,
I don't want to do turn z,
I want to do turn x.
So that I could do the same thing I guess.
If absolute value of z is greater than zero,
turn z.
Otherwise if absolute value of x,
is great zero,
turn x,
x direction,
So let's,
this should be x.
so I'm kind of getting lucky here
cause there's only three possible axes.
But it definitely would be useful
for me to use like a numeral bowl
with like a index
to the access.
But let's just see if this works.
So now, this should be
the x-axis.
Awesome!
So that works.
I've got the x-axis.
Now I should be able to the y-axis,
turn the y-axis.
Let's just check a y move.
Let's make the move,
zero,
one, zero.
It's not animating.
Why is it not animating?
I didn't do that here.
I need to add the y.
So now, this should do the y-axis.
Something's wrong
I'm going the wrong direction.
So I think this should be negative angle (laughs)
Cause my y-axis is flipped.
Yeah! There we go!
You know,
I might have,
whatever! It works! (laughs)
There might be something
that I'm actually done wrong here.
But I want,
the data is moving correctly.
I just need make sure the animation matches that.
So now,
instead of having,
this all moves
be just these letters,
now all moves
is,
an array of move objects.
Move,
new move array
with new move.
So up is
zero, one, zero
in the one direction.
You know what,
let's just do,
I might as well just do them all.
I mean I can always invert them
but let's do it,
let's just actually do them all.
So this is,
this is up in both directions.
This is,
okay, hold on. (chuckles)
I'm going to speed through this
so you don't have to watch all this.
(lively music)
(bell dings)
Alright I put in all the moves.
Up, down.
Left, right.
Front, back.
Clockwise, counterclockwise.
This should be everything.
It should be 12 in there.
One, two, three, four, five,
six, seven, eight, nine, 10, 11, 12.
That's all the moves.
So I should be able to now pick any given move
and,
all moves
and animate that one.
And just sort of see.
This sequence stuff has to change.
So, the sequence stuff I'm going to do in a second
but I was using strings before.
That won't work
and take this out.
So any given move,
I should be able to do.
So this is move three,
index three,
zero, one, two, three.
So that should be the bottom.
I've already spun it. (laughs)
That should be the bottom in a certain direction.
Whatever!
Great.
So hopefully that's the right one that matches up.
Now the sequence
is, let's make it an Array List.
An Array List of move objects.
This will be the sequence.
And I know if you're a cue bird,
there's actually like a back to
which is what I'll just consider
that back in the same direction twice,
for now.
So we can consider this to be an Array List
of moves.
And when I'm making that sequence,
if I'm going to make,
let's just do 10,
I'm going to pick the size
and I'm going to say,
pick an index.
Then I'm going to have move m equals all moves,
get that index.
And this has an extra,
wait, int-random all moves size,
sorry, all moves is an array,
moves is an Array List.
So that's all moves index r.
That stays the same
and then I'm going to say sequence,
dot add m.
So this is me putting in
10 moves in a sequence.
So let's not worry about inverting the sequence,
let's not flip case,
I think is no longer a thing anymore.
And then I need a current indexes current move
which is counter.
So I also need this to be,
let's call this current move.
So there's a current move
and current move starts at,
current moves equals sequence get
counter.
So it gets the first one.
Then I'm going to say,
current move update,
guess what, this finished thing is going to come in handy.
Perfect! If current move
is finished,
then index, (murmurs inaudibly) counter,
plus plus
and
current move equals
sequence
dot get counter.
And I definitely need to
make sure
that I only do this
if counter is less than sequence dot length.
So I'll put this if statement in here
I don't think,
and I'm going to do this,
put this sequence in there
and then I'm going to say if started around here.
So this is how
sequence dot size not length.
So this is the same exact algorithm
but instead of the move being indicated
by a single character,
it's now this object.
So I'm updating that move,
when it's done,
as long as I'm not at the end of the sequence,
go to the next one
and then get the next one.
And then this current move,
is what determines
the rotation.
And so I called it just move before
but let's call it current move.
And I think this should work now.
Move dot start,
okay, I'm not going to worry,
this should be,
just started equals true.
So now it's just a Boolean
but I'm not starting...
this could be current move start.
This actually could be current move start.
So because this,
this can actually current move update could happen,
if it's not animating.
So yes.
So I just want to start,
hitting the space bar starts the first move
which does all of these.
And then each one,
cause I have this start function,
needs to actually explicitly call start.
Okay this I think should work.
(drum rolls) So if I press the space bar,
you can see the move happen in sequence.
(drum rolls)
Wait,
if counter is less than,
it's got to be less than size minus one
because this is where I increment.
So I'm going to the next one.
The last one is size minus one.
So that's good.
So let's give it 50 random moves.
And let's say get it started.
So now it's playing 50 random moves.
It's a little silly
that sometimes the moves are inverted.
So now I should be able to add that sequence.
(laughs) What just happened there?
I'm not making a copy of the move.
So a move is like animated
and finished.
And then it, when it gets it again,
if it does that move again,
it's not like a copy of the move.
So this should actually be,
when I make that sequence,
yes, this should be like all moves dot clone
or, cause there's a way to clone objects
but I'm just going to write my own copy function.
So all moves index r dot copy,
or when I call start,
I could set,
I think it's actually as simple
as just setting...
you know what, I might be able
to just not do a copy
but set the angle back to zero.
Couldn't I do that?
If animating equals true,
finished equals false,
like that might actually work.
So I could have made a copy of the move
but I think just in start,
since I have to do that with everything,
that might fix it.
Let's see if that fixes it.
A bunch of moves.
It's going to do the same move again.
Just by the laws of probability.
I think this is working, dare I say
and I could still spin around it.
I mean, it doesn't look like it's making any mistakes.
So now let's make a speed.
Let's just make that a global variable.
And right now it's point one.
So let's make it like point five
to make it kind of faster.
And then in move, this,
I mean I suppose that could be a property
of the move itself.
But let's just see it do it faster.
Cause that's more fun to watch it do it faster.
So let's see if now,
if I add the moves in reverse,
when it's done, it should be solved.
Then I have all the moves.
Now all I need to do,
is go through the sequence backwards right?
Start with the last element
of the sequence, go down to zero.
This is why I kind of want to,
I do need to make a copy
because I need to make it a completely different move,
in the opposite direction.
So I do want to say,
move, next move equals sequence
get i
and I really actually need a copy here.
So we'll see this both ways
because then I want to say like next move dot reverse.
So in the move object,
or though I could just point to the other move
but I'm going to do it this way.
I'm just figuring out.
Missed having fun figuring this out.
I'm going to make a function called copy
which returns a new move with what?
X, y, z and direction.
And then I'm going to make a function called
reverse
which just says,
direction times equals negative one.
so this, if I make those two functions,
as I'm going through the sequence,
I'm copying all of them
but reversing them.
And now I have, it should be twice as long.
So let's just do this
with just like five moves,
just to see if it works.
I've got to add them.
No wonder.
I've got to add those moves.
Okay.
Let's go. Here we go.
So it should do those moves in reverse and boom!
There's the Rubik's Cube back in its original state.
Now, here we go.
Let's make it full screen
and enjoy,
this.
Make it a little bit faster.
Enjoy this Rubik's Cube doing 500 moves,
then in reverse.
This is going to take a long time.
Let's not do 500. (laughs)
Let's just do 100.
And you will get the feeling
of the cube solving itself.
You know I really should do something
where if I pick a certain move,
I'm not allowed to pick the reverse
of that move next
cause that's going to make it look really weird.
And like why is it doing that?
But that's neither here
nor there.
Let me actually draw the counter
so I can see what move we're on.
Cause that'll be somewhat useful.
So I'm going to say,
fill 255,
text
counter,
I don't know.
It's just going to end up being in 3D space
in some weird location.
Let's just say 100,
counter 100, 100.
The scale is going to be weird.
Let's just try that.
Text size
32.
Alright. Let me put this,
let's have some fun with this.
Let me put this on speed of 1.5.
Let me make it do 1000 moves
and here we go.
And thank you for watching this coding challenge.
(chuckles) You're not really seeing the rotation.
It's just like shaking.
Okay that's too fast.
Let's try a speed just of like 1.0.
Alright.
Thanks for watching this coding challenge
where I am shuffling the Rubik's Cube
with random moves,
then playing those moves back in reverse.
When it gets to 2,000 moves,
it will actually,
be back in its original orientation.
I hope that works.
I hope you make your own version of this.
If I come back
and make a par four,
which I intend to do,
I'm going to see if I can use a genetic algorithm
to take any shuffled state
and evolve a solution
within maybe a certain number of moves,
I suppose 20 might be the number
to pick in terms
of the genetic information
which will be a sequence of moves.
This should be similar to what I did
with searching for the phrase
to be or not to be,
in the space of all possible random phrases.
We'll see if that works.
I have no idea if that will work.
But I'm going to come back
and do more with this in part four,
in a future coding challenge.
And please share with me.
Go to the codingtraining.com,
look at the link in this video's description too.
If you make a version of this,
whether it's in JavaScript
or processing
or some other programming language
or environment,
you can submit a link to your version
so that I can see it
and the rest of the community can as well.
Alright, thanks very much.
(blows kiss) Goodbye.
(bell dings)
(lively music)