Basically I am made a class that settles most of the back-end work of a tic-tac-toe game.
I would like to have remarks about my general coding style and possible optimizations.
using System;
namespace TicTacToe_Game
{
public class Game
{
//The game's board itself.
//If the element is 0, the tile is unmarked.
//If the element is 1, the tile is marked by player1.
//If the element is 2, the tile is marked by player2.
private byte[,] board = new byte[3,3];
//Used to check which player's turn it is.
private bool player1_turn = true;
private bool gameWon = false;
public Game() {
//Prepares the game board.
for (int i = 0; i < 3; ++i) {
for (int n = 0; n < 3; ++n) {
board[i, n] = 0;
}
}
}
public byte[,] GetBoard() {
return board;
}
/// <summary>
/// Resets the current game.
/// </summary>
public void ResetGame() {
player1_turn = true;
gameWon = false;
//Resets the game board.
for (int i = 0; i < 3; ++i)
{
for (int n = 0; n < 3; ++n)
{
board[i, n] = 0;
}
}
}
private byte UpdateBoard(byte x, byte y) {
//1 for win, 2 for no win, 0 for error.
byte isWinningMove = 2;
byte marking;
if (player1_turn)
{
marking = 1;
}
else {
marking = 2;
}
//If the marked tile was not occupied.
if (board[x, y] == 0)
{
board[x, y] = marking;
int counter = 0;
//Check each horizontal row for wins.
for (int i = 0; i < 3 && isWinningMove != 1; ++i)
{
for (int n = 0; n < 3; ++n)
{
if (board[i, n] == marking) {
++counter;
}
}
//If there is a row of equivalent markings.
if (counter == 3)
{
//The player wins.
isWinningMove = 1;
}
counter = 0;
}
//Check each verticle column for wins.
for (int i = 0; i < 3 && isWinningMove != 1; ++i)
{
for (int n = 0; n < 3; ++n)
{
if (board[n, i] == marking)
{
++counter;
}
}
//If there is a column of equivalent markings.
if (counter == 3)
{
//The player wins.
isWinningMove = 1;
}
counter = 0;
}
//Check for diagonals.
if ((board[0, 0] + board[1, 1] + board[2, 2]) == (marking * 3))
{
isWinningMove = 1;
}
else if ((board[0, 2] + board[1, 1] + board[2, 0]) == (marking * 3)) {
isWinningMove = 1;
}
}
//If the requested tile to be mark was already occupied.
else {
//Returns an error code.
isWinningMove = 0;
}
return isWinningMove;
}
public bool NewMove(byte row, byte column) {
//If the user made a move when the game is already over.
if (gameWon) {
//Resets the current game first.
ResetGame();
}
//If the new move is not a valid move.
if (row > 2 || column > 2) {
throw new InvalidOperationException();
}
byte status = UpdateBoard(row, column);
bool result;
if (status == 0)
{
throw new InvalidOperationException();
}
else if (status == 1)
{
gameWon = true;
result = true;
}
else {
result = false;
}
//Changes the player turn for the next move.
if (player1_turn)
{
player1_turn = false;
}
else
{
player1_turn = true;
}
return result;
}
public bool NewMove(byte tileNumber)
{
//If the user made a move when the game is already over.
if (gameWon)
{
//Resets the current game first.
ResetGame();
}
if (tileNumber == 0 || tileNumber > 9) {
throw new InvalidOperationException();
}
byte row = 0, column = 0;
for (byte i = 1, x = 0, y = 0; i < 10; ++i) {
if (i == tileNumber) {
row = x; column = y;
break;
}
++y;
if (y == 3) {
++x;
y = 0;
}
}
/*
Tile number is visualized as this way:
1 2 3
4 5 6
7 8 9
*/
byte status = UpdateBoard(row, column);
bool result;
if (status == 0)
{
throw new InvalidOperationException();
}
else if (status == 1)
{
gameWon = true;
result = true;
}
else
{
result = false;
}
//Changes the player turn for the next move.
if (player1_turn)
{
player1_turn = false;
}
else {
player1_turn = true;
}
return result;
}
}
}
NewMove()
methods (both overload), it returns true if the move is a winning move. Otherwise it returns false. \$\endgroup\$