字幕列表 影片播放 列印英文字幕 (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)
B1 中級 編碼挑戰#142.3。魔術方塊第三部分 (Coding Challenge #142.3: Rubik's Cube Part 3) 8 0 林宜悉 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字