Win conditions and taking turns

確認済のバージョン: 5.3

-

難易度: 初級

We need to test the grid spaces on the board and see if there has been a win. We don't have the player sides properly set up, but we will need to check the grid spaces' Text property to see if the string values match "three in a row" and that these values match the side that's currently playing. To do this we will need a variable to hold the character representing the current side that is actively playing. This variable will eventually change as we alternate turns, but for now it will be a constant value. We will need to set this value when the game starts and we will need to return this value in GetPlayerSide rather than "?".

Open the GameController script for editing.

Define a private string variable called "playerSide":

private string playerSide;

In Awake, set playerSide to "X".

playerSide = "X";

In GetPlayerSide, return playerSide rather than "?";

return playerSide;

This will now send the playerSide to GridSpace when it calls GetPlayerSide, and this sets us up for sending the current player's side when we alternate the sides.

The next step is to check for a win.

In EndTurn, remove the Debug.Log line.

Debug.Log("End Turn is not implemented");

To check for a win, we need to look at the three rows, the three columns and the two diagonals on our board to see if all three of the grid spaces in any series all match.

This game is small enough to test the winning conditions using brute force. We can simply check a row, comparing the three spaces with the current player’s value to see if all three spaces match the current player.

This line of code will need to go into the EndTurn function, so when we call EndTurn, we check to see if the current player has won the game. This will be done by creating a rather complex if statement. We will be checking if button0 equals playerSide and if button1 equals playerSide and if button2 equals playerSide. If all of these prove true, we have a win.

In this line of code we are checking the top row to see if all three spaces match the current player. This is why we need to know exactly which buttons are in what spaces. We know that the grid spaces are in order, left to right and top to bottom, so by checking the text values from buttonList [0], buttonList [1] and buttonList [2] we will be checking the values for the top row:

Now, if a row, column or diagonal does test true for a win then we need to do a few things to end the game. In the very least we need to disable all of the buttons on the board so that the game cannot continue and not one can click any unused buttons.

So, when the win conditions are met, let’s call a function where we can do all of our "Game Over" logic.

Add a function that returns void called "GameOver":

void GameOver ()
{
}

The first action we would want to take when the game is over would be to turn off all of the unused buttons. To do this, we need to access each button. We can do this through our buttonList. There is no need to actually test each button to see if it is interactable or not. This is a waste of resources when running and time when coding. We can simply set all of the buttons to non-interactable by looping through all of the elements in our buttonList. If that button is already non-interactable due to a move already taken, it will stay non-interactable. The property will simply be set to the same non-interactable value. This is a little like running a hand down a row of switches and shutting them all off. Whether they were on or off to begin with is irrelevant.

In the GameOver function, create a new for loop that iterates through all of the elements in our buttonList.

for (int i = 0; i < buttonList.Length; i++)
{
}

In the for loop, for each element in the list, find the parent GameObject’s Button *component and *disable the button by making it non-interactable.

buttonList[i].GetComponentInParent().interactable = false;

Now, we need to call GameOver when the winning conditions have been met to execute this code.

When we click all three spaces in the top row, our code should detect a win. At this point, all of the rest of the buttons should be disabled. Currently, if we try to "win" by clicking any of the other rows, columns or diagonals, the game will not detect a win, obviously, but we do know that our base code is working as expected and doing what we want to do.

We now need to check the remaining rows, columns and diagonals.

Open the GameController script for editing.

We already have code that checks the first row. To do so, the code checks the following elements:

Change the index value, [ ], for each row, column, row and diagonal so that each if statement checks a unique row, column, row or diagonal. (See list of columns, rows and diagonals above.) For example, here is the line checking the second row:

Now, all possible winning conditions should work and when the winning conditions have been met, the board should be disabled.

Next, we need to change sides when a turn is done and actually be able to play against another person.

Currently we don't really have a game. We can check for win conditions and when we get three "X"s in a row, the game is over. We now need to be able to change sides. To change sides, we will need to check what side we are on and alternate the player values; swapping "X" for "O" or vice versa.

To do this, let’s create a function that will change the player sides.

Create a new function that returns void called "ChangeSides".

void ChangeSides ()
{
}

In that function, we need to test our current side and swap the player’s team.

Add code to check the playerSide value and assign the other team’s value to playerSide.