Build a TicTacToe class for two players, X and O, on a 3 by 3 board. One object is one game: it remembers the board and whose turn it is, lets the players take turns, and tells who has won.
The board: rows and columns are numbered 0, 1 and 2. Cell (0, 0) is the top-left corner, (0, 2) the top-right, (2, 0) the bottom-left and (2, 2) the bottom-right. A cell holds 'X', 'O' or '.' when it is still empty.
Build:
- A new game. The constructor
public TicTacToe()fills the privatechar[,] board(3 by 3, read asboard[r, c]) with'.'using two nested loops. The private fieldchar playerstarts as'X'. All nine cells are empty and X moves first. public void Move(int r, int c)plays one turn at the given row and column (always between 0 and 2, so you do not need to check the range).- If the cell is not empty, ignore the call: nothing changes and it is still the same player's turn.
- Otherwise put the current player's mark in the cell, then give the turn to the other player (X becomes O, O becomes X).
public char Winner()returns the winner as achar:'X','O'or'.'.- A player wins by having the same mark in all three cells of a row, a column, or one of the two diagonals ((0,0), (1,1), (2,2) and (0,2), (1,1), (2,0)). Three empty cells in a line are not a win.
- If nobody has three in a row, return
'.'. That covers a game still in progress, an empty board and a draw.
You start with this code, which plays six games and prints the result of each one:
class Solution {
public void MainFunction() {
var game = new TicTacToe();
game.Move(0, 0);
game.Move(1, 0);
game.Move(0, 1);
game.Move(1, 1);
game.Move(0, 2);
Console.WriteLine(game.Winner() + " wins!");
game = new TicTacToe();
game.Move(0, 0);
game.Move(0, 1);
game.Move(0, 0);
game.Move(1, 0);
game.Move(1, 1);
game.Move(2, 2);
game.Move(2, 1);
Console.WriteLine(game.Winner() + " wins!");
game = new TicTacToe();
game.Move(0, 0);
game.Move(0, 1);
game.Move(1, 1);
game.Move(0, 2);
game.Move(2, 2);
Console.WriteLine(game.Winner() + " wins!");
game = new TicTacToe();
game.Move(0, 2);
game.Move(0, 0);
game.Move(1, 1);
game.Move(0, 1);
game.Move(2, 0);
Console.WriteLine(game.Winner() + " wins!");
game = new TicTacToe();
game.Move(0, 0);
game.Move(0, 1);
game.Move(0, 2);
game.Move(1, 1);
game.Move(1, 0);
game.Move(1, 2);
game.Move(2, 1);
game.Move(2, 0);
game.Move(2, 2);
Console.WriteLine("No winner: " + game.Winner());
game = new TicTacToe();
Console.WriteLine("No winner: " + game.Winner());
}
}
Games played: X fills the top row; then a game where X tries to play on a cell that is already taken (ignored, and still X's turn) and O wins the middle column; X on the main diagonal; X on the other diagonal; a full board with no three in a row; and a brand-new game.
Expected output:
X wins! O wins! X wins! X wins! No winner: . No winner: .
There are eight winning lines: three rows, three columns and two diagonals. A loop over
i from 0 to 2 can check row i and column i together; the two diagonals come after the loop. Skip a line whose first cell is empty.
Check for a taken cell first and leave the move method before touching the board or the turn. Only a successful move passes the turn to the other player.
class TicTacToe {
private char[,] board = new char[3, 3];
private char player = 'X';
public TicTacToe() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
board[i, j] = '.';
}
public void Move(int r, int c) {
if (board[r, c] != '.') return;
board[r, c] = player;
player = (player == 'X') ? 'O' : 'X';
}
public char Winner() {
for (int i = 0; i < 3; i++) {
if (board[i,0] != '.' && board[i,0] == board[i,1] && board[i,1] == board[i,2]) return board[i,0];
if (board[0,i] != '.' && board[0,i] == board[1,i] && board[1,i] == board[2,i]) return board[0,i];
}
if (board[0,0] != '.' && board[0,0] == board[1,1] && board[1,1] == board[2,2]) return board[0,0];
if (board[0,2] != '.' && board[0,2] == board[1,1] && board[1,1] == board[2,0]) return board[0,2];
return '.';
}
}
Free plan: 30 tutor messages. Premium is unlimited.
