Tic-Tac-Toe
You can use
system("cls")on Windows to clear the console.system("clear")should do the same on Linux & MacOS.You may use this to clear the board if you don't want a log of the moves.
Make a Tic-Tac-Toe Game.
The game should run untill a player wins, or until it's a draw.
For each turn, the player should input 2 numbers that represents a field on the playing board. The move should be made, and the board should be checked for wins.
Hint
There are many ways to make games like this. I would recommend structuring your program like this:
- instructions for the game
infinite loop
{
- print the board
- get input from the player who's turn it is
- verify input
- check if the game is won, and break the loop if it is
- check if the game is drawn, and break the loop if it is
- switch to the other player and set up for the next loop cycle
}
Answer - without functions
This is a version that doesn't use functions, for those who haven't completed 1.7.7 yet. I would highly recommend using functions to improve code readability.
#include <iostream>
// Tic tac toe
int main()
{
// Set up playing field
int playing_field[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; ++j)
{
playing_field[i][j] = 0;
}
}
// Print instructions
std::cout << "Welcome to tic tac toe!\n";
std::cout << "To play, enter the x and y coordinates of the field you want to set.\n";
std::cout << "The x coordinate is the first number, the y coordinate is the second number.\n";
std::cout << "The coordinates start at 0, so the top left field is 0 0, the bottom right field is 2 2.\n";
std::cout << "The first player to get 3 in a row wins!\n\n\n";
int player_turn = 1;
// Game loop - runs until someone wins or the board is full
// If we use continue before switching the players turn, the same player will play again.
// If the player input is invalid, we can use continue to let them play again.
while (true)
{
std::cout << "\n\n-------\n";
// Print board - loop through all fields and print them
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; ++j)
{
if (playing_field[i][j] == 1)
std::cout << " O";
else if (playing_field[i][j] == 2)
std::cout << " X";
else
std::cout << " -";
}
std::cout << "\n";
}
std::cout << "-------\n";
// Get player input
int x, y;
std::cout << "Player " << player_turn << " turn: ";
std::cin >> x >> y;
// Check if input is valid (between 0 and 2)
if (x < 0 || x > 2 || y < 0 || y > 2)
{
std::cout << "Invalid input\n";
continue;
}
// Check if field is taken
if (playing_field[y][x] != 0)
{
std::cout << "Field is taken\n";
continue;
}
// Set field
playing_field[y][x] = player_turn;
// Check if player won
bool player_won = false;
// Diagonal check
if ((playing_field[0][0] == player_turn && playing_field[1][1] == player_turn && playing_field[2][2] == player_turn)
|| (playing_field[0][2] == player_turn && playing_field[1][1] == player_turn && playing_field[2][0] == player_turn))
player_won = true;
// We can use the same loop for horizontal and vertical check
for (int i = 0; i < 3; i++)
{
// Horizontal check
if (playing_field[i][0] == player_turn && playing_field[i][1] == player_turn && playing_field[i][2] == player_turn)
player_won = true;
// Vertical check
if (playing_field[0][i] == player_turn && playing_field[1][i] == player_turn && playing_field[2][i] == player_turn)
player_won = true;
}
// If player won, print winner and break out of game loop
if (player_won)
{
std::cout << "Player " << player_turn << " won!\n";
break;
}
player_turn = player_turn == 1 ? 2 : 1;
// Check if board is full / if it's a draw
bool board_full = true;
// Search for empty fields - if we find one, the board is not full
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; ++j)
{
if (playing_field[i][j] == 0)
board_full = false;
}
}
// If board is full, and there is no winner, it's a draw
if (board_full)
{
std::cout << "Draw!\n";
break;
}
}
}
For further gameplay you could wrap this game in a function that returns the id of the winner, or 0 if it's a draw. Then you can run a loop that keeps track of the score. This way you can play multiple games in one instance and kepe track of the score.
Answer - Using functions
#include <iostream>
void print_board(int board[3][3])
{
std::cout << "\n\n-------\n";
// loop through all fields and print them
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; ++j)
{
if (board[i][j] == 1)
std::cout << " O";
else if (board[i][j] == 2)
std::cout << " X";
else
std::cout << " -";
}
std::cout << "\n";
}
std::cout << "-------\n";
}
// Returns false if input is invalid, and continue should be used
bool validate_input(int board[3][3], int x, int y)
{
// Check if input is valid (between 0 and 2)
if (x < 0 || x > 2 || y < 0 || y > 2)
{
std::cout << "Invalid input\n";
return false;
}
// Check if field is taken
if (board[y][x] != 0)
{
std::cout << "Field is taken\n";
return false;
}
return true;
}
// Returns true if `player` won
bool player_win_check(int player, int board[3][3])
{
// Diagonal check
if ((board[0][0] == player && board[1][1] == player && board[2][2] == player) || (board[0][2] == player && board[1][1] == player && board[2][0] == player))
return true;
// We can use the same loop for horizontal and vertical check
for (int i = 0; i < 3; i++)
{
// Horizontal check
if (board[i][0] == player && board[i][1] == player && board[i][2] == player)
return true;
// Vertical check
if (board[0][i] == player && board[1][i] == player && board[2][i] == player)
return true;
}
// If we didn't return true yet, the player didn't win
return false;
}
bool full_board_check(int board[3][3])
{
// Search for empty fields - if we find one, the board is not full
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; ++j)
{
if (board[i][j] == 0)
return false;
}
}
// If we didn't return false yet, the board is full
return true;
}
// Tic tac toe
int main()
{
// Set up playing field
int playing_field[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; ++j)
{
playing_field[i][j] = 0;
}
}
// Print instructions
std::cout << "Welcome to tic tac toe!\n";
std::cout << "To play, enter the x and y coordinates of the field you want to set.\n";
std::cout << "The x coordinate is the first number, the y coordinate is the second number.\n";
std::cout << "The coordinates start at 0, so the top left field is 0 0, the bottom right field is 2 2.\n";
std::cout << "The first player to get 3 in a row wins!\n\n\n";
int player_turn = 1;
// Game loop - runs until someone wins or the board is full
// If we use continue before switching the players turn, the same player will play again.
// If the player input is invalid, we can use continue to let them play again.
while (true)
{
print_board(playing_field);
// Get player input
int x, y;
std::cout << "Player " << player_turn << " turn: ";
std::cin >> x >> y;
// Continue if input is invalid
if (!validate_input(playing_field, x, y))
continue;
// Set input field to player's number
playing_field[y][x] = player_turn;
// If player won, print winner and break out of game loop
if (player_win_check(player_turn, playing_field))
{
std::cout << "Player " << player_turn << " won!\n";
break;
}
// Check if board is full / if it's a draw
// If board is full, and there is no winner, it's a draw
if (full_board_check(playing_field))
{
std::cout << "Draw!\n";
break;
}
// Switch player turn
player_turn = player_turn == 1 ? 2 : 1;
}
}
For further gameplay you could wrap this game in a function that returns the id of the winner, or 0 if it's a draw. Then you can run a loop that keeps track of the score. This way you can play multiple games in one instance and kepe track of the score.