Last week I wrote a C++ program on Ultimate Tic Tac Toe. The issue was that the program was a bit lengthy (~230 lines) and it is needed to be around 150 lines.
I absolutely am not asking you to go through the whole code. Just skimming through might reveal possible contractions to code, and tips in general to write short but readable C++ code.
Code
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
using namespace std;
inline int X (int pos) {
return pos / 3;
}
inline int Y (int pos) {
return pos % 3 - 1;
}
string rule(80, '_');
class Grid
{
private:
char subgrid[3][3];
char left, right;
public:
Grid(){}
void set (int x, int y, char cell);
char get (int x, int y);
};
void Grid::set (int x, int y, char cell) {
subgrid[x][y] = cell;
}
char Grid::get(int x, int y) {
return subgrid[x][y];
}
class Game
{
private:
Grid grid[3][3];
char player;
size_t cur;
public:
Game();
void display();
void play();
void input (int& g);
bool checkWin (Grid grid);
void showScore();
};
Game::Game() {
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 3; ++j)
for (size_t k = 0; k < 3; ++k)
for (size_t l = 0; l < 3; ++l)
{
grid[i][j].set(k, l, '.');
}
player = 'x';
cur = 0;
}
void Game::play()
{
int g, s;
display();
while (1) {
display();
cout << "\n Player " << player << " - Enter Grid: ";
cin >> g;
if (g > 0 && g < 10) {
break;
}
display();
cout << "\n Try again.";
cin.get();
}
s = g;
while (1) {
display();
if (checkWin(grid[X(cur)][Y(cur)])) {
display();
cout << "\n Player " << player << " won!";
cin.get();
cin.ignore();
break;
}
player = player == 'x' ? 'o' : 'x';
cur = g;
input(g);
}
}
void Game::display()
{
system("cls");
cout << "\n ULTIMATE TIC TAC TOE\n" << rule;
for (size_t i = 0; i < 3; ++i)
{
for (size_t k = 0; k < 3; ++k)
{
cout << "\n";
char left, right;
left = right = ' ';
for (size_t j = 0; j < 3; ++j)
{
if (k == 1)
{
if (3*i + j + 1 == cur) {
left = '>';
right = '<';
}
else {
left = right = ' ';
}
}
cout << " " << left << " ";
for (size_t l = 0; l < 3; ++l) {
cout << grid[i][j].get(k, l) << " ";
}
cout << right;
}
}
cout << "\n\n";
}
cout << "\n";
}
void Game::input(int& g)
{
int s;
while (1) {
display();
cout << "\n Player " << player << " - Enter subgrid: ";
cin >> s;
if (s > 0 && s < 10)
{
if (grid[X(g)][Y(g)].get(X(s), Y(s)) == '.') {
break;
}
}
display();
cout << "\n Try again.";
cin.ignore(); cin.get();
}
grid[X(g)][Y(g)].set(X(s), Y(s), player);
g = s;
}
bool Game::checkWin(Grid grid)
{
char p = player;
int row = 1, col = 1, main_diag = 1, anti_diag = 1;
for (size_t i = 0; i < 3; ++i)
{
row = col = 1;
if (grid.get(i, 3-1-i) != p) {
anti_diag = 0;
}
if (grid.get(i, i) != p) {
row = col = main_diag = 0;
}
else {
for (size_t j = 0; j < 3; ++j)
{
if (grid.get(i, j) != p) {
row = 0;
}
if (grid.get(j, i) != p) {
col = 0;
}
}
}
if (row || col) {
return 1;
}
}
if (main_diag || anti_diag) {
return 1;
}
return 0;
}
int main()
{
Game game;
game.display();
cout << "\n Welcome to Ultimate Tic Tac Toe." <<
"\n Press Enter to start.";
cin.get();
int input, error = 0;
enum menu { play = 1, scores, quit };
do {
game.display();
if (error) {
cout << " Invalid option. Try again.\n";
error = 0;
}
else {
cout << " Select an option: \n";
}
cout << " 1) Play\n 2) Scores\n 3) Quit\n" << "\n> ";
cin >> input;
switch (input) {
case play:
game.play(); break;
case scores:
//showScores();
break;
case quit:
std::exit(0);
default:
error = 1;
}
system("cls");
} while (error);
system("pause");
return 0;
}