Lesson 4 of 11
Colors and Winners
In this lesson
The pair check whether a cell is fully surrounded by a color passed as a parameter, and add an empty color as the enum default because a new matrix is all black. A komi mode flag, off once a stone is played, keeps the default test passing, and logic moves into a new rules class. A broken large refactoring is undone and redone in smaller steps, and the board forwards get winner to the rules, explained with the Law of Demeter.
Transcript
[00:05] (external link, opens in new tab) You can just say yeah basically that's yeah >> I'll just rename it later. So, is there a way to check it's surrounded in the easiest way?
[00:38] (external link, opens in new tab) If if there are positions in one two and so surrounded equals position stat matrix one two equals n Right? So that would determine if there are stones there.
[01:10] (external link, opens in new tab) And then we also want to verify if the they're the same, too. That doesn't seem simple, actually. >> I think we're Yeah, I think we're we're too deep. Here's how here's an example how to simp simplify. Okay. >> Okay. >> what if we just did the whole thing here?
[01:41] (external link, opens in new tab) This thing. Okay. Extract into a variable. Control alt v fully surrounded. Okay. Then the whole thing here you would extract
[02:20] (external link, opens in new tab) I can just check if it's fully surrounded. >> Nice. is fully surrounded. Was it the one and one? You're >> right. >> And then you can just say if is fully surrounded just return whatever the color is. >> Color next to it. >> Sorry. >> Right. A color next to it. The >> color next to it. Oh yeah. There's no color there. >> Sure.
[02:51] (external link, opens in new tab) >> But I can tell already that probably still going to fail because of the white part. It's not surrounded by white. >> Ah, interesting. So, we don't have any scenarios where black is the surrounder, >> right? We basic we left that out because we wanted to try that, >> but it wouldn't fail. Oh, it fails because if it's the color white. Okay, interesting. So I guess we have to go back and say okay we have to have a scenario of the black or we can have the opposite test.
[03:27] (external link, opens in new tab) How's that? >> Well the the point of that test originally was to make it so that black passes. >> Sure. >> Okay. Because if we do it the way right now, if we change it to white, the original implementation we had before this would still make it pass. >> Okay. Okay. So, this is test is currently going to fail. And what we're going to do now, we're just going to make we're going to make another test that to get rid of this white thing here to get rid of this assumption.
[04:02] (external link, opens in new tab) How's that? Or the other if we really want to make it pass right now, we can just copy it. Copy that method and replace the replace the white with black and use that method for here for now. Another way would be to So if I did this Oh, we can just check. Oh, hold on. Something even simpler. just pass in the color.
[04:35] (external link, opens in new tab) >> Yeah. Yeah. >> As a parameter. >> Yeah. That that that that would work. >> So we can be so we can say control alt extract parameter place for occurrences surrounding stone color. ah surrounding stone color
[05:08] (external link, opens in new tab) Surrounded by so and then I would say say it's really surrounded by and then you can say surrounded it's really surrounded by stone color black >> very cool >> let's See? Well, we haven't fixed it yet. We're just checking, but we're not using the color. >> Yeah, we did return the color, right?
[05:45] (external link, opens in new tab) >> Color. Do we actually need to check? >> Yeah, we need to check and then return if surrounded so that the other tests will pass. >> True. That's true. So if surrounded, >> you can put the sorry >> if surrounded and then I'll put the return stone color matrix one two inside there.
[06:16] (external link, opens in new tab) >> Yeah, but just return color one is just return color one >> and that's it. This one, the bottom one, you might want to >> Oh, yeah. >> re turn >> current. >> I don't think it's Yeah, I think maybe back to the It's just default stone white.
[06:52] (external link, opens in new tab) Oh, it's so current winner. Oh, so white was black. >> Are we expecting white? Oh, it's a different test actually. >> Oh, I understand why. >> by default because >> Yeah. >> Well, actually, no. Oh, because fully surrounded doesn't check if if they're actually stones.
[07:22] (external link, opens in new tab) So in our by default the surround the stone matrix is all white. So when you do this it's going to say it's going to return true because everything here is white. I don't know if that makes sense. >> Hello. >> Yeah, I'm trying to understand what you just said. Oh, so the stone color matrix if you break into this >> Yeah. >> every everything is going to be white or black.
[07:52] (external link, opens in new tab) >> Okay. >> But is is black. So we need to have it also needs to check that the it's filled position is filled. So I could type
[08:33] (external link, opens in new tab) Oh, we could just check it directly in the winner, don't we? One. So I'm talking about we need to do that. We need to check it's filled and it's the correct color. So we need to do that for for each of them. But I'm not What do you mean by it's if it's the winner? >> You need to Okay. So I think I understand. Finally. Is So maybe we're getting too deep.
[09:04] (external link, opens in new tab) Do you think we could could have solved it a different way? Or are we jumping the gun a bit? >> Are we jumping the gun a bit? I don't think it's too deep. >> Mhm. >> surround kind of >> kind of corrects the >> the definition of it's fully surrounded by >> because >> the >> because they have the stone color but not doesn't say it's filled or not. >> But we just have to check for X and Y if they're filled just once.
[09:35] (external link, opens in new tab) We don't have to check for each one. It's only surrounded if it's filled. >> So we can just check just once, right? Because if it's false, we can just return false, >> right? So we can say >> if not position status matrix X and Y. Actually, we don't have to check the position stat. We can just say the color status matrix,
[10:09] (external link, opens in new tab) Right? >> No, I was talking about >> you you want to check if the stone that's being surrounded is actually have has a stone in there, right? No, I want to check that this the ones being the So I want to check that if there is actually stones surrounding it because right now it is right now when by default the array is just all black. So all we're doing right now is just checking if this is black, this is black, this is black, this is black.
[10:43] (external link, opens in new tab) But it could be that these there's actually nothing. Why are they all black? That's what I don't understand. >> Because when we initialize the matrix >> Yeah. >> by default it's all black. It's not all null like you >> is that is that the default? Are you sure? >> I'm pretty sure we can we can run it through debugger and I'm pretty sure that that's that's what's happening. Okay. So, we still have to check for a failed position.
[11:13] (external link, opens in new tab) Okay. not a color. >> Yeah. >> Okay. But so what I'm saying hold on hold on is what I'm trying to say is that if not what is it position status metrics >> x and y position status
[11:44] (external link, opens in new tab) Filled just return false. >> That's it. >> I think that would make the other tests automatically fail because for the black territories this will be false. This will be empty position. So this would automatically return false and you will automatically return the current window surrounded would automatically be false. >> Okay. And what did you want to check? You wanted to check you want to check for each one also this the position status.
[12:17] (external link, opens in new tab) >> Yeah. So it basically would be this. >> Yeah, I understand. >> But like the filled on left, filled on right, filled on bottom, filled on top. >> Yeah, I understand now because just the fact that it has a color doesn't mean it's filled. >> Right. Right. You But you said it better than I did. >> Uhhuh. I understand. Maybe we just have to have a default color that's empty instead. Then >> we can do that. >> And then we don't need the position status at all. >> Yep.
[12:48] (external link, opens in new tab) >> That would that would be that would be a good way to eliminate one matrix. >> let's see. So we can go to stone color. >> Am I missing it? >> No, it's on the right side. >> Oh, yeah. >> It's not on the right. Oh, we did. We didn't move it. Oh, that's why. Just move it here.
[13:18] (external link, opens in new tab) We'll move it later. Okay. Color black, white, color, >> empty. And when we initialized it, we just wanted to say that it was >> Where did we initialize it? >> we initialize it right here. It's it's an array. >> So we need to have empty as the default. >> Yeah. So you can set it as zero. You can make the enum int and set that zero.
[13:52] (external link, opens in new tab) >> Okay. Interesting. So, let's run the test. You think that's the that was the whole point, >> right? But, for the fully surrounded, it's going to say it's going to say true anyways because of the because they're all empty. So, it's going to say surrounded by empty. >> But, we did add things to the position. >> Say again.
[14:23] (external link, opens in new tab) But we did add positions to the board. They're not all empty. >> I see. >> Right. We added two stones here. >> I'm talking about the the komi test because one of the tests that was failing was the one where we did not add anything. >> so which one is failing right now? Let's see. Determined by default because of komi. Okay. So this test is actually passing. >> Yes. >> But but because of komi it's not. Mhm. >> Uhhuh.
[14:53] (external link, opens in new tab) >> Because of >> So we can Okay. So in that case, we can just decide if we're in komi mode or not, right? >> Okay. Yeah. Yeah. That would be the simplest simplest way (external link, opens in new tab) to determine that. >> So here's the way I'm thinking about it. Komi can be just a simple flag. Once someone is played, we're not in komi mode anymore, >> right? So basically if in komi mode then what do we do?
[15:24] (external link, opens in new tab) Return true. >> I think the simplest would be would to put that into get winner and then set komi mode in in add stone. >> Okay. So get winner right if in komi mode return. Come on stone color white. That's all.
[15:55] (external link, opens in new tab) >> Right. >> And just equals true. And >> it would be set to false. Add stone. >> Sorry, >> it would be set to false. >> Add stone. Exactly. So, add stone in mode equals false. Let's see.
[16:27] (external link, opens in new tab) Okay, 11 passed. Yay. You see how simple that was? Oh god. Go is not a simple game. Actually I think we can get rid of some of this stuff actually. >> Okay, >> I'm pretty sure. >> because do we need a current winner? >> I'm trying to understand >> what do we do then? What do we do here? >> If it's well actually we don't have a test to make that part fail.
[17:01] (external link, opens in new tab) So until I think if we remove the current winner part we the test will still pass. Okay. So we have komi mode and let's see can we start to refactor some of it now? What do you think? >> Yeah. >> You want to separate some concerns here? >> Single responsibility principle (external link, opens in new tab) etc. >> Oh okay. Yeah. >> What do you think?
[17:37] (external link, opens in new tab) >> Yeah, I think we should do it. >> Okay. What do you want? How do you want to refactor it? >> I was thinking that maybe the board should not be the one that determines if a stone is surrounded or not. Okay. >> Or is that is that to >> No, we can try to do that. Sure. So, you want to check if so how would where how would you do it?
[18:10] (external link, opens in new tab) >> So, you would pass it to an object that would you you pass the board to an object that that does the calculation that does the that that does the checks. >> Mhm. Okay. So for example you might say you create a class here class rules maybe.
[18:41] (external link, opens in new tab) >> Yeah. And we might have like a public board.
[19:22] (external link, opens in new tab) Board just even a field like that. >> and then we can say check if stone around position is or removed if needed. We can just move that with function FF6. See again or control shift R. Extract members convert
[19:53] (external link, opens in new tab) Extract class from parameters. Pretty sure we could have moved that. What if we made it public? So we can move that. Alt enter. Now we can see if we can move that yeah but basically we can say public check class if needed remove surrounded stone
[20:24] (external link, opens in new tab) And then the whole position status matrix well it changes the position status matrix of the current board. Right. Right. >> But then we can just say empty position just refactors this whole thing to say control alt m empty
[21:03] (external link, opens in new tab) And then we can say just take this whole thing and just of course surrounded by where is that fully rounded by we would get the
[21:38] (external link, opens in new tab) We refactor this into a method of m get stone color basically. >> Mhm. >> Make that here x again. No, I mean I used using command access.
[22:25] (external link, opens in new tab) Just the whole thing like board get stone color. He didn't make it public yet. Get stone color. Ah, this is not fun. That's life, right? Alt enter. Make it public. Same thing here, right? So, we could just do
[23:27] (external link, opens in new tab) Okay. And board bank position empty. Let's see if there's anything else we missed. is fully surrounded. Actually we need to say rule right >> is fully surrounded by let's enter
[23:59] (external link, opens in new tab) We might want to make it public but we also want to make it into a field. So now we have a like a private space. >> Cool. >> Almost there. >> Yep. >> Rules.
[24:36] (external link, opens in new tab) Just need to initialize it. >> Mhm. So, I'm going to use ReSharper for that. Alt insert. Pretty sure there is an insert here. Is that an insert? Nope, that's not an insert. Press alt insert on your computer. Okay. Constructor and then we will choose rules.
[25:08] (external link, opens in new tab) We don't want to use rules for Do we want to use rules for now? What >> you mean? Do you want to use >> do you want to inject them from any test right now? >> Not really. >> No, >> can do it later. >> Yeah. >> We say rules
[25:46] (external link, opens in new tab) That make sense? >> Makes sense. >> Okay, that was a big refactoring. I'm not happy that I did such a big refactoring >> and neither is the computer index was outside the bounds of the array. Let's see. I guess we should have taken the refactoring in smaller steps, but I think I went a bit too fast at that. I think it's probably something simple. Let's see.
[26:18] (external link, opens in new tab) Let's see. This is where did we end up? Output Where is the add stone? Here. Here. Check stones positions and remove if needed. X and Y. And we want to go to rules. Move surrounded stone.
[26:50] (external link, opens in new tab) It's a dead stone color. >> Mhm. Turn matrix XUS one. Interesting. >> >> what >> it should be for Oh, what happened to my screen? Interesting.
[27:22] (external link, opens in new tab) There you go. Run. Run all the tests. All right. Less failures >> this time. >> Different thing, huh? >> Mhm. >> Okay. Go game. It's expected empty. Was this interesting? Did we missed? So, what did we miss? I think now we're looking at the wrong at the wrong stone every time,
[27:56] (external link, opens in new tab) Right? >> okay. So, here's what I'm going to do. >> Hold on. >> Okay, we're back. You know what I think I'm going to do? I'm going to backtrack the whole thing. >> I'm going to try to do it in smaller steps. What do you think? >> I think so, too. I think I agree. See what we did. >> What the hell happened?
[28:41] (external link, opens in new tab) Okay. >> Is it to the top? Yeah. >> Yeah. >> Okay. R. >> All right. >> Okay. That was quick. You know what? But you want to try to do do a git commit for now >> and say we just have the add stone left and surround opposite color. No, which one did we just make pass? >> we made
[29:12] (external link, opens in new tab) Oops. Everything just died. Show hold desktop. Okay. All good. >> yeah. Well, let me commit first still. >> Can you put that also on top of Visual Studio >> so people can see how you commit and stuff?
[29:43] (external link, opens in new tab) >> I'm not very good at git. Still do punk git. What should I say? Default winner default for returning default winner. Okay. And komi.
[30:13] (external link, opens in new tab) Okay. Awesome. So now we can try and do do the refactoring in a smaller way. So one way to do it is to we have a class rules, right? >> Mhm. >> And what we can do is to say yeah prop
[30:43] (external link, opens in new tab) Board port and we can have a constructor here. Can you push press alt insert? Okay. And then we'll say that rules equals new rules.
[31:34] (external link, opens in new tab) Just create the field rules. I did create so low down there. Okay. Next thing is we want to just move the whole thing to somewhere, right? And just say >> so we want to move is fully surrounded by. So we need to make a method for stone color matrix >> extract method right
[32:06] (external link, opens in new tab) Well there's there's several ways we can do it I think one way would be to just make it static and just pass it the stone color matrix. Another way would be to actually first of all refactor all these things. Yeah. Extract a method just like you said. So that all these things are 12 m
[32:37] (external link, opens in new tab) Get stone color. Let's make sure that we didn't break anything so far and just go one by one. >> Right. But >> yeah, >> I can tell already that
[33:08] (external link, opens in new tab) I mean because it's doing xus one right here. Oops. And then you also need to do parenthesis up there. >> Yep. Go ahead and fix it. All right. And it's supposed to be x - one still. >> Did was it not xus one? >> It won't x - one. But when you did the extract method, >> it just made it x. >> Then how come the test continued to pass? >> Because maybe the maybe that it was not looking maybe the surround left part did not determine it.
[33:45] (external link, opens in new tab) So, you think we should have like went back and find a test, write a test to make it fail? >> Well, hopefully. >> Yeah, cuz otherwise, what was the point? I mean, it used to be like that. I'm trying to understand. >> No, it was not like that before. So, if we control Z back, how come my controls not working anymore? This is weird.
[34:18] (external link, opens in new tab) So see that's that's what originally was X we had X minus one. >> Uhhuh. And it and it changed it into X. >> Interesting. >> Aha. So that might have been what broke us, right? >> Mhm. Yep. >> Interesting. >> But we still want to refactor. So can you go ahead? It will be faster if you do it on your end. The whole refactoring thing, but keep it with a minus one. All right. >> even though it >> I I don't want to change functionality.
[34:50] (external link, opens in new tab) >> Alt Mr. Alt Mr. Alt is all the refactoring stuff. >> Okay. >> yeah. Okay. X - one. Yeah. Yeah. Well, actually, no. It what's interesting is that it sends X and here you have an X minus one. >> So actually it's pretty good. It was okay.
[35:21] (external link, opens in new tab) >> No. >> Well, the problem would be for the other the other stone matrix because it'll be X and XUS one. >> Yeah, but we'll just have Oh, because Okay, I understand. But wouldn't it be I mean the minus one is like an implementation detail. It's part of the the way the matrix works, right? No. >> No. It's because we're we're trying to get surrounded on the left. That's why we had the XY. >> Okay. >> Right.
[36:17] (external link, opens in new tab) Alt R that sucker, right? >> Okay, we didn't break anything yet. It's a good start. Now we can make it public yeah just move the whole thing up to board here
[36:52] (external link, opens in new tab) And here everything just becomes board. >> Mhm. Man, just make public. Let's see. >> Okay. Doesn't compile. We have to fix this. >> Yeah.
[37:33] (external link, opens in new tab) >> Okay, now we're good. 11 passed. >> Mhm. >> what else? >> We also want to do check stones around position and remove if needed. >> Okay, you want to try that? >> Right. So you just >> so >> you make the remove surround zone public so that you can call it from the outside >> and basically just move the method. Yeah.
[38:29] (external link, opens in new tab) Okay. >> anything else? >> Do we want to move surrounded stone part of it? What >> do we want to move add this to the rules or >> I'm not sure if we want to add this to the rules or not. >> Well, this changes the state of the board. So, we're just telling the board to remove something or add something. >> So, it's not a rule. It's just we're just telling it to remove. Right. >> Right. >> Okay. >> Actually, it does remove only if it's full fully surrounded.
[39:00] (external link, opens in new tab) >> Oh, but it's checking for the rules. Okay. Remove surrounded stone and it's calling is fully surrounded by. So maybe we should rename it to remove surrounded stone if surrounded. Oh no, actually remove surrounded. Never mind. >> Remove if surrounded stone. How's that? >> Remove if surrounded. Remove stone if surrounded. >> Okay.
[39:38] (external link, opens in new tab) Okay. Are you happy with that so far? Do you want anything else? >> So, >> what about get winner? I guess that's supposed to be in the rules, right? >> Yeah. Either in the rules or something that determines winners, but yeah. Yeah, maybe it should be in the rules. >> I agree. It should be in the rules. >> Okay. So, let's see if there's anything. Should I just move move it first and then fix whatever problems there are? >> Actually, if you remove it right now, it will have the tests won't compile and I would rather that we can get the winner from the board and it will just use the rules underneath.
[40:15] (external link, opens in new tab) >> Oh, >> just a forward mechanism. >> Okay. So >> so the way you did you just copy the whole method to the board and then you make a forward call it >> right. So oh then you have a board in komi mode and you have and then you have a current winner thing. >> Sure. Do we still >> So we would have to make a property for the board.
[40:47] (external link, opens in new tab) Well, first of all, well, first of all, let's do the Yeah, we still need the in komi mode, right? >> So, but you can go ahead and create it. >> All right, first let me >> get color. Get stone color.
[41:22] (external link, opens in new tab) No, no, no, no. In komi mode is a is a is a logical thing, right? We have that's part of the rules. Komi is a rule, right? >> I see. >> So, it's just an internal flag. Okay. >> The board doesn't care if it's in komi mode or not. It's just a state. >> I see. >> Well, at least that's the way I think about it, >> right? But the board would be setting the komi mode. >> I don't think so. I think the board would just tell the the the rules that a move was made and then it it would just either set it or not set it.
[41:56] (external link, opens in new tab) But >> Okay. Oh, what's the easy way to make it into a public property from here? >> Oh, I guess >> No, you just go to the red stuff and press alt enter. >> Make local make property. >> Not why not a field >> is a field. >> Yeah, field is always better than a property >> unless you're using it public use for some reason. Okay. In komi mode
[42:27] (external link, opens in new tab) And the default is true. Right. >> Right. >> That's also a field, right? >> Are you lost? >> No, I'm not lost. >> The default is white. >> Right. >> Cool. Now we can see the rules. Now we just have to forward
[43:17] (external link, opens in new tab) Okay. And also now we can get rid of in komi mode. >> now we just have to let the rules notify the rules that a stone was added in which color. That's it. Right. >> Okay. >> Then it will just set it. >> Okay. So we need to make a another method for it then. >> Yeah. What I'm saying is that komi mode is nobody cares about. It's an internal state. >> Okay. So rules >> say like notify stone added or something like that.
[43:52] (external link, opens in new tab) >> Okay. >> And just give it the stone color and XY just so the rules can do whatever they want with it. Right. >> Okay. >> Mhm. Okay. And this one will just be >> And we also need to to determine the current winner. Right.
[44:23] (external link, opens in new tab) >> Right. >> Exactly. And we have to remove the current winner from the the board just here. >> Okay. And so then we can remove that. Awesome. Cool. >> Okay, let's try that. >> Of course. Yeah. Let's see what happens. >> Yes. Cool. >> Very cool. I like it. I like it more and more.
[44:54] (external link, opens in new tab) >> Okay. >> so do we want to Okay. So now, now this also about the get winner thing. Now that we have it passing, do we want to remove get winner from the board? I kind of like it that the board is my my my main agent engine API. >> I kind of like it. It's simple. Do you do you not like it? Do you have Do you have a different API in mind? Do you always want to get Bot rules? I mean, feels like a breaking the law of Demeter here.
[45:27] (external link, opens in new tab) >> Law Sean was law of Demeter. De diameter. I'm not sure how to pronounce it. The idea that you always get something dot something means you should just have the something dot something in hand. If you always say board rules, just use rules instead. Just move rules ahead. See what I'm saying? >> I I think so. >> If in my test I keep saying board. >> Mhm. >> Then something in my design is really telling me that I should do that rule should be one level earlier.
[46:02] (external link, opens in new tab) And so that whatever API I'm trying to use, get winner should be on the thing I'm trying to use. So if if if I were to get rid of get winner here >> then in my tests, right, what would happen? Look at that. >> It would either be board rules.getwinner or I need an instance of the rules that I would pass to board and then I would >> and then the API kind of sucks if I need two instances to determine something. >> Right. Right? Now I need to do like rules.get winner, >> but I need to do it every time to do something.
[46:38] (external link, opens in new tab) >> That law of Demeter means that I'm trying I'm trying to get the same thing every time in multiple in and it's in down a chain of responsibility somewhere. >> So if I keep getting it every time, I'll just promote it to be a first first level API >> just to keep things simple. So I kind of like that it's simpler that this way. And but you know some people may not agree that's okay.
[47:10] (external link, opens in new tab) >> Okay. Where are we in terms of the Excel file? >> So let's take a look. >> In terms of Excel file, >> is there anything we can make green? >> I think the komi is green now. >> So we can mark this green. Yeah. And where is the determining the winner? >> Right there. >> Does that make sense so far? >> Yeah.
[47:40] (external link, opens in new tab) No. >> Well, we haven't counted territories yet. We're still working on that. >> Yeah, we're still working on it. >> Hold on. Be right back. >> Okay. Cuz it's >> Let's finish things for today. Raymond, I guess we'll have to have another session. >> All right. >> Okay. Awesome. See you maybe tomorrow or or later this week. >> Yeah, >> thanks everyone for watching as well. >> Raymond, say bye. >> Bye.