I was hoping someone could review my C++ console based noughts and crosses (Tic Tac Toe) application. I have not looked at any other documentation, this is purely programmed from the top of my head. Can you tell me what I've done well, what I haven't done well, and suggest any improvements I can make to it. If you decide to run this program ensure C++ 17 is specified (not that you need to be told that). Please treat it how it's supposed to be treated. I haven't included validation for inputs.
#include <iostream>
#include <vector>
#include <map>
#include <utility>
#include <algorithm>
void Displaygrid(const std::vector<std::vector<std::pair<int, unsigned char>>>&grid)
{
std::for_each(grid.begin(), grid.end(), [&](auto pairVec)
{
std::for_each(pairVec.begin(), pairVec.end(), [&](auto pair)
{
if (pair.second != '-') {
std::cout << pair.second << " ";
}
else
{
std::cout << pair.first << " ";
}
}
);
std::cout << "\n";
});
}
bool CheckForAWinner(const std::vector<std::vector<std::pair<int, unsigned char>>>&grid, const unsigned char key)
{
if (grid.at(0).at(0).second == key && grid.at(0).at(1).second == key && grid.at(0).at(2).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else if (grid.at(1).at(0).second == key && grid.at(1).at(1).second == key && grid.at(1).at(2).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else if (grid.at(2).at(0).second == key && grid.at(2).at(1).second == key && grid.at(2).at(2).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else if (grid.at(0).at(0).second == key && grid.at(1).at(0).second == key && grid.at(2).at(0).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else if (grid.at(0).at(1).second == key && grid.at(1).at(1).second == key && grid.at(2).at(1).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else if (grid.at(0).at(2).second == key && grid.at(1).at(2).second == key && grid.at(2).at(2).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else if (grid.at(0).at(0).second == key && grid.at(1).at(1).second == key && grid.at(2).at(2).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else if (grid.at(2).at(0).second == key && grid.at(1).at(1).second == key && grid.at(0).at(2).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else if (grid.at(2).at(0).second == key && grid.at(1).at(1).second == key && grid.at(0).at(2).second == key) {
std::cout << key << " is the winner" << std::endl;
return true;
}
else
{
return false;
}
}
bool ClaimSquare(std::vector<std::vector<std::pair<int, unsigned char>>>& grid, int move, const unsigned char player)
{
for (auto& vec : grid)
{
auto validSquare = std::find_if(vec.begin(), vec.end(), [&](auto pair) {
return pair.first == move;
});
if (validSquare != vec.end())
{
if (validSquare->second == '-')
{
validSquare->second = player;
return true;
}
else
{
std::cout << "This square has already been claimed. Choose a different square!" << std::endl;
return false;
}
}
}
}
void PlayerMove(std::vector<std::vector<std::pair<int, unsigned char>>>& grid, unsigned char player)
{
int move = 0;
do
{
move = 0;
Displaygrid(grid);
std::cout << player << " turn: " << std::endl;
std::cout << "Enter a number on the grid (e.g. 1): ";
std::cin >> move;
}
while (ClaimSquare(grid, move, player) == false);
}
void PlayNoughtsAndCrosses()
{
const unsigned char player1 = 'O';
const unsigned char player2 = 'X';
std::vector<std::vector<std::pair<int, unsigned char>>>grid =
{
{std::make_pair(1,'-'), std::make_pair(2,'-'), std::make_pair(3,'-') },
{std::make_pair(4,'-'), std::make_pair(5,'-'), std::make_pair(6,'-') },
{std::make_pair(7,'-'), std::make_pair(8,'-'), std::make_pair(9,'-') }
};
do
{
PlayerMove(grid, player1);
if (CheckForAWinner(grid, player1))
{
break;
}
PlayerMove(grid, player2);
}
while (CheckForAWinner(grid, player2) == false);
}
int main()
{
PlayNoughtsAndCrosses();
}