Previous question: https://codereview.stackexchange.com/questions/70650/tic-tac-toe-in-c11-follow-up Is there any way to improve this code? #include <iostream> #include <cctype> #include <algorithm> #include <functional> #include <array> enum struct Player : char { none = '-', first = 'X', second = 'O' }; std::ostream& operator<<(std::ostream& os, Player p) { return os << static_cast<char>(p); } enum struct Type : int { row = 0, column = 1, diagonal = 2 }; enum struct Lines : int { first = 0, second = 1, third = 2 }; class TicTacToe { public: TicTacToe(); bool isFull() const; void draw() const; void turn(Player player); bool check(Player player) const; private: bool applyMove(Player player, int position); static const std::size_t mDim = 3; std::array<Player, mDim * mDim> mGrid; }; // utility functor to compute matching condition template<int dim> struct Match { Match(Type t, Lines i) : mCategory(t), mNumber(i){} bool operator() (int number) const { switch (mCategory) { case Type::row: return (std::abs(number / dim) == static_cast<int>(mNumber)); case Type::column: return (number % dim == static_cast<int>(mNumber)); case Type::diagonal: if (mNumber == Lines::first) return ((std::abs(number / dim) - number % dim) == static_cast<int>(mNumber)); else return ((std::abs(number / dim) + number % dim) == static_cast<int>(mNumber)); } return false; } Type mCategory; Lines mNumber; }; TicTacToe::TicTacToe() { mGrid.fill(Player::none); } bool TicTacToe::applyMove(Player player, int position) { if (mGrid[position] != Player::none) return false; mGrid[position] = player; return true; } bool TicTacToe::isFull() const { return 0 == std::count_if(mGrid.begin(), mGrid.end(), [](Player i) { return i == Player::none; }); } bool TicTacToe::check(Player player) const { // check for row or column wins std::array<bool, 8> win; win.fill(true); int j = 0; // checking condition loop std::for_each(mGrid.begin(), mGrid.end(), [&](Player i) { int x = j++; // columns if (Match<mDim>(Type::column, Lines::first)(x)) win[0] &= i == player;; if (Match<mDim>(Type::column, Lines::second)(x)) win[1] &= i == player; if (Match<mDim>(Type::column, Lines::third)(x)) win[2] &= i == player; // rows if (Match<mDim>(Type::row, Lines::first)(x)) win[3] &= i == player; if (Match<mDim>(Type::row, Lines::second)(x)) win[4] &= i == player; if (Match<mDim>(Type::row, Lines::third)(x)) win[5] &= i == player; // diagonals if (Match<mDim>(Type::diagonal, Lines::first)(x)) win[6] &= i == player; if (Match<mDim>(Type::diagonal, Lines::third)(x)) win[7] &= i == player; }); for (auto i : win) { if (i) return true; } return false; } void TicTacToe::draw() const { //Creating a onscreen grid std::cout << ' '; for (auto i = 1; i <= mDim; ++i) std::cout << " " << i; int j = 0; char A = 'A'; for (auto i : mGrid) { if (Match<mDim>(Type::column, Lines::first)(j++)) std::cout << "\n " << A++; std::cout << ' ' << i << ' '; } std::cout << "\n\n"; } void TicTacToe::turn(Player player) { char row = 0; char column = 0; std::size_t position = 0; bool applied = false; std::cout << "\n" << player << ": Please play. \n"; while (!applied) { std::cout << "Row(1,2,3,...): "; std::cin >> row; std::cout << player << ": Column(A,B,C,...): "; std::cin >> column; position = mDim * (std::toupper(column) - 'A') + (row - '1'); if (position < mGrid.size()) { applied = applyMove(player, position); if (!applied) std::cout << "Already Used. Try Again. \n"; } else { std::cout << "Invalid position. Try again.\n"; } } std::cout << "\n\n"; } class Game { public: Game() = default; void run(); private: TicTacToe mTicTacToe; std::array<Player, 2> mPlayers{ { Player::first, Player::second } }; int mPlayer = 1; void resultScreen(bool winner); std::function<void()> display = std::bind(&TicTacToe::draw, &mTicTacToe); std::function<void(Player)> turn = std::bind(&TicTacToe::turn, &mTicTacToe, std::placeholders::_1); std::function<bool(Player)> win = std::bind(&TicTacToe::check, &mTicTacToe, std::placeholders::_1); std::function<bool()> full = std::bind(&TicTacToe::isFull, &mTicTacToe); }; void Game::run() { while (!win(mPlayers[mPlayer]) && !full()) { mPlayer ^= 1; display(); turn(mPlayers[mPlayer]); } resultScreen(win(mPlayers[mPlayer])); } void Game::resultScreen(bool winner) { display(); if (winner) { std::cout << "\n" << mPlayers[mPlayer] << " is the Winner!\n"; } else { std::cout << "\nTie game!\n"; } } int main() { Game game; game.run(); }