Winning Positions
Start course
4h 7m

In this course, you'll start experimenting with XML code and diving deeper into layouts, namely linear and constraint layouts. We'll also look at animations and build a few fun features with them. Then, we'll take a deeper dive into the Kotlin programming language and constraint layouts, before building a fully functioning Tic-Tac-Toe game.

On top of that, we'll then build a second app which can play YouTube videos within it, and you'll learn how to work with APIs and API keys.

Intended Audience

This course is intended for beginners to Android app development or anyone who wants to master coding in Kotlin.


Since this is a beginner-level course, there are no requirements, but any previous experience with coding would be beneficial.


Hello and welcome back. In the last video, we left off where we were able to track the game state based on which slots have been tapped, and in this video we'll pick up from there, make a few modifications and also figure out how to track when a player has won. And we'll start off with a slight modification to the interface. You see from this situation, let's say I have a cross over here, circle over here, cross over here and so on. If I tap on a slot which has already been tapped, let's say this cross which has already been taken. If I tap on it again, it gets replaced with a circle and you see from the game state down here, that zero for the first slot has gotten replaced with a one and we definitely don't want that. 

So, we need to modify our logic to not allow this to happen when a slot has already been taken and only allow taps to happen when a slot has a tag of two and two only. So, let's go ahead and add this in our code right here. After we get the tag of the tappedSlot, we want to make sure that if game state at the tappedSlot, if the value at that index of game state is equal to two. If that is the case, then we want all of this below to proceed. So, we're going put an open curly brace over here and then all this logic will go within there right, within this if condition and then at the end of the animation, we're going close this. So, I'll put a closing curly brace over here. 

So, that will automatically tab all this logic in by one, so we can tell that all this code is within this if block right here. So, if the slot is two, then we allow all this to happen, otherwise we don't. So, let's see if this worked. I'm going to apply changes and rerun activity. I'll also pull up the logs so we can see that this is actually working. So, cross circle, we see that these two have changed. Now let's try to tap on this again. You see nothing happens, tap on this again, nothing happens. Perfect, so that's working. Now there are slightly more complicated scenario of tracking when a win has happened and there are a few ways to do this. What we'll do is use an array of winning positions and see if each of them in those positions have the same player value. So, let's see what I'm talking about. I'm going to pull up my playground right here, get rid of this and we'll construct what I'm talking about here. 

So, let's look at some winning positions. I'll pull up my emulator, you see, 0, 1, 2, right, these three. If these three have the same sign or the same player, then that's a win. Similarly, this one this one and this one, so 0, 1, 2, 3, 4, 5, 6, 7, 8. Those are three combinations, let's write them down real quick over here, I'm going to say 0, 1 and 2 if they are in a row, that's a win. 3, 4, 5, if they happen that's a win, 6,7,8, if they happen, that's a win, Let's look at some other combinations. If this one this one this one vertical, if any of these roles vertical have the same sign that's a win, so that's 0, 1, 2, 3, 4, 5, 6. So, 0, 3 and 6 let's put that down 0, 3, 6. Then similarly right here 1,4,7 and then 2, 5, 8. Those are also winning combinations. So, 1, 4, 7 and 2, 5, 8.

Now we have the horizontal and vertical winning positions covered, all that's left are the diagonals. So, 0, 1, 2, 3, 4, so 0, 4 and 8, that's a winning combination, and 2, 4 and 6, that's a winning combination. So, we'll go with 0, 4, and 8, and 2, 4 and 6. So, we have all of these winning combinations. If any of these have the same sign, so either all of these indices are zero or all of these indices are one that's a win. If any of them get satisfied as soon as it's satisfied it's a win for one of the players. So, what we can do is have these as many lists. We're going to have a list called winning positions and it's going to include all of these many lists in it. Let's see what that would look like. I'm going to say val winning positions equals list of, and these positions are not going to change so I can use a list of and then each one of these would be a list. 

So, I'm going to take that closing brace, put it right at the end over here, and then each one of these are a list. So, list of, there you go, there's 1,  list of, there's the second position, you see what's happening. So, I'm going to pause this video, fill in the rest and be back in a second. Welcome back, I filled this in and clean it up a little bit. So, what we have here is a list of lists and each one of these are individual lists. You see all the elements of this list is a list in itself. Now that we have this after each tap where the game state changes, we'll check against these combinations to see if that change has caused one of these winning conditions to be satisfied. So, let's bring in our game state and test this out. 

Our game state is this, so I'm going to simulate the same thing here. We'll say game state equals, and this is immutable list, so I'll say immutable list of, there we go. We have our game state, we have our winning positions. Now let's assume that a tap has happened and a couple of positions have changed, let's turn our game state into a win. So, one of these combinations, let's go with 0, 4, and 8. So, zero will change it to one, then 1, 2, 3, this is four, will change this to 1, and eight will change this to one. So, technically this is a win since it satisfies circles have won based on this combination here. And if you're wondering what this would look like in the emulator, so that's a circle in position 1 right here and then 4 right here and 8 right here. So, there will be a circle and it would be a diagonal win for circles. So, how do we code what happens when we tap a slot? 

Well, we can loop through each one of these elements and see if all of their individual elements as indices in the game state array are the same sign after that tap has happened. So, we can say four, actually this might be towards the bottom of the screen, so I'm going to get rid of these. So, you can see better, there we go. So, let's call it combo. So, for combo in winning positions and we'll do something, so open and close curly brace. So, if let's look at the first one. I want to check this list 0, 1, 2 from our game state have to be the same value. So, that's 0, 1 and 2 have to be the same value. And we're getting the 0, 1, 2 from here. So, if game state and our 0, 1, 2 list is combo the first time around. So, from our game state array, combo and the first position is zero. If this is equal to game state combo, the second position of my combo, so 1 and then we'll check if 1 is equal to 2. So, and and you specify and condition with two and percent. 

So, we have this combination, right, which is comparing the first with the second and then we have to compare the second with the third. So, first with second and then second with the third. So, and game state combo, 1 equals game state combo 2. So, if the element in the first slot is equal to the element in the second slot and the element in the second slot is equal to the element in the third slot, then the element in the first slot is equal to the element in the third slot by default, because they're all equal. So, if this happens, then we have a winner. But we have a bit of a problem here, we're checking that all of them are the same, but we're not checking for if all of them are two. Because if the value is two, then all the slots are basically untapped. It's neither a circle nor a cross. So, in that case we don't have a winner because it's all empty. 

So, we have to check for that as well. So, we have to put in another condition here. We have to say and let's just make sure one of the slots is not equal to 2. So, we'll say gameState [combo[0]] is not equal to 2. All right, I'll move this to the next line. So, we have some room here. So, the first time around as we are looping through all of our list, so combo in winningPosition. combo is our first list right here 0, 1, 2 and we're checking if gameState. So, gameState [combo[0] ]. Combo is this one right here, is the first one so that's zero. All right, so gameState [0] which is 1 is ==. So, meaning is it equal to gameState [combo[1] ]. So, again we have gameState [combo [1] ]. What is combo[1]? We're looking at combo which is still this one, combo[1] is 1. Which means gameState [combo[1] ] is gameState[1]. All right, so gameState[1] is 2. 

So, right away we see that this which is 1 is not equal to this which means this condition is going to fail so we don't have a winner. It's going to go to the next one, it's going to go to the next one. It is going to keep going then it's going to eventually come to this one right here where combo is list of 0, 4, and 8. Let's see what happens there. gameState [combo[0] ]. So, gameState [combo[0] ] is 0. All right, so gameState[0], that's 1 is equal to gameState [combo[1] ]. All right, so let's see gameState combo which is 0, 4, 8 combo[1] is 4. All right, so gameState[4] is right here. That's 1, okay? So, this has passed. All right, these two are equal and gameState combo[1] is it equal to gameState combo[2]? All right. So, let's check that. combo[1] we know is 4, combo is this 2 is 8. So, gameState [combo[2] ] which means gameState[8] is also 1. 

So, we see that 1 = 1 = 1. These two combinations are both true and gameState [combo[0] ] which is right here is not equal to 2, which means it's not empty. So, all of this has passed which means I have a winning position, right? At 0, 4 and 8. So, for now if this happens, we'll open curly brace and within here we'll simply do a print line of "We have a winner". Let's see what happens if we run this. Check it out. We have a winner, okay? Now what if I change this and make this a zero, which means no one has won. If I run this, you see nothing happens, we don't have a winner. Let's test out another combination. We know that 0, 1 and 2 which means this one, this one and this one if they're the same sign then that's a winner. So, let's test this. So, what I'll do is change the first one to 0, second one to 0, the third one to 0. This satisfies this first winning combination. So, let's run and see if we have a winner. Check it out, we have a winner. Perfect. 

All right, so our logic is working but this is pretty complex compared to logic that we have applied before this. So, take a couple of minutes to digest this and perhaps replay this video or write it out, write out at every step and see what's happening. Basically, this part right here, what combo is at any given time, what gameState combo is at any given time? All of this, write it out and try to make sense of it through one complete run and let it sink in. But basically now that we can detect winners based on this, let's go ahead and add this winning positions array to our app. So, I'm simply going to copy this, command C, go back to our app. I already have gameState so I don't need to paste that. There we go. I have my winning positions and now that I have the winning positions in my drop-in after my taps have happened and a slot has been filled, I'm going to test out my combination right here. 

All right, so a circle or a cross drops into the board, I'm going to do my comparison right here. So, back to our playground, I'll take this entire logic, command C, paste it down here. All right, so for combo in winning positions, do the comparison and if we have a winner, I'm not going to print line that we have a winner. Let's create a toast and say we have a winner, okay? So, we'll say Toast. There we go, .makeText. The context is going to be this as it has always been so far, and then I'll simply say we have a winner and we'll do Toast.LENGTH_LONG, let's do LENGTH_LONG and we have to show it, so .show. All right, let's test it out. Apply changes and run. All right, it worked. Let's pull up the emulator, okay? There's a cross, circle, cross, I'll put another circle here and then I'll put a cross over here which would indicate a win, let's see if it works. There we go, we have a winner. Great, let's try out one more combination. 

I'll restart the app. All right. There's a cross, there's a circle, I'll put a cross over here. There's a circle, I put a cross over here. All right. This should work. If I put a circle here, that means we'll have a winner. Let's see if it works. There we go, we have a winner. Excellent. So, we have a working game. But notice even after we have a winner, we are able to tap on a slot and it's going to keep saying we have a winner because we have a winner and one of the conditions is satisfied. But once we have a winner, we shouldn't be able to do this, right? But we are able to. So, that's the next item to fix. But we have covered a lot in this video and are able to detect winners. So, we'll leave it at that here and in the next video, we'll get started with fixing this issue of being able to continue playing after a win has taken place. See you there.


About the Author

Mashrur is a full-time programming instructor specializing in programming fundamentals, web application development, machine learning and cyber security. He has been a technology professional for over a decade and has degrees in Computer Science and Economics. His niche is building comprehensive career focused technology courses for students entering new, complex, and challenging fields in today's technology space.

Covered Topics