HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

An unbeatable Tic-Tac-Toe game using exhaustive enumeration of all cases

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
enumerationunbeatabletoealltictacgameusingexhaustivecases

Problem

I am a beginner programmer and I've been trying to complete an unbeatable tic-tac-toe program, my code is below. The program itself works, but it seems rather inefficient, as I literally have to type out every case of possible victory or defeat. Any suggestions on how to make the code more efficient, or general suggestions, are appreciated! Everything is in one 500 line program.

```
#include
using namespace std;

const short SIZE = 3;

class Board
{
private:
char square[SIZE][SIZE], aiMark, userMark;
public:
Board();
void instructions();
void showBoard();
//Gets user pre-approved user move.
void userMove(short n, short n2)
{square[n][n2] = userMark;}
bool checker(short n, short n2);
void computerMove(short n);
bool win();
bool lose();
bool full();
void clear();
};

//The constructor initializes each space (square) to a blank space and the markers to x and o.
Board::Board()
{
userMark = 'x', aiMark = 'o';
for(short i = 0; i >choice;

//Determines which code to run based on who is Player 1
//(i.e. runs case 1 if user is Player 1 and case 2 if AI is Player 1).
switch(choice){
//Runs when user is Player 1.
case 1:
cout>num>>num2;

while(num > 3 || num 3 || num2 >num>>num2;
}

//Executes moves.
bobj.userMove(num, num2);
bobj.computerMove(1);
bobj.showBoard();

} while(!bobj.lose() && !bobj.win() && !bobj.full());
break;

//Runs when AI is Player 1.
case 2:
cout>num>>num2;

while(num>3 || num 3 || num2 >num>>num2;
}

//Executes moves.
bobj.userMove(num, num2);
bobj.computerMove(2);

Solution

[..] it seems rather inefficient, as I literally have to type out every case of possible victory or defeat. [..] Everything is in one 500 line program.

Woah. Yes, that is inefficient, regarding developer time and developer annoyance. I'll attempt an answer now nonetheless. My answer consists of two parts: Part one is a (non-exhaustive) list of things that could be improved in your code. Part two is a implementation of the same idea by myself. In order to be able to show you absolutely fine code I'm posting my own code as another question. That way others can review and comment on it easily.

Review
Better not using namespace std;

There's a lot of discussion in this stackoverflow post.
char is a character, nothing else.

char square[SIZE][SIZE], aiMark, userMark;


and later

userMark = 'x', aiMark = 'o';
// a for loop setting all elements of sqaure to ' '


So a "place" on your board can be either ' ', 'x' or 'o'. And it can be the same as str[0] with char const * str = "BOooO";. At least according to the compiler, wo wouldn't stop you doing place[0][0] = str[0], because they're of the same type char. Instead of trying to enforce such a separation by "being careful" you should better let the compiler and the type system do this:

enum class Mark {
  X, O, None
};
// ...
Mark square[SIZE][SIZE];


Member functions that don't modify data members...

... should be marked const:

// NO:
// void instructions();
// Yes (sort of):
void instructions() const;


But ...
Member functions that shouldn't even be members at all

Why is void instructions(); even a member function? It doesn't use / modify / need any data members / other member functions of Board at all.
Better make it a free function (with a descriptive name), like:

void show_instruction_screen();


Names

board.showBoard ? Redundant! Better: board.show(). Even better: stream

  • Checking for win/loose/full: std::count() or std::all_of/std::none_of`

Code Snippets

char square[SIZE][SIZE], aiMark, userMark;
userMark = 'x', aiMark = 'o';
// a for loop setting all elements of sqaure to ' '
enum class Mark {
  X, O, None
};
// ...
Mark square[SIZE][SIZE];
// NO:
// void instructions();
// Yes (sort of):
void instructions() const;
void show_instruction_screen();

Context

StackExchange Code Review Q#144799, answer score: 2

Revisions (0)

No revisions yet.