Jump to content
  • Advertisement
Sign in to follow this  
kaktusas2598

Optimize Tic Tac Toe

This topic is 3007 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Today I finished my first game in console with AI - Tic Tac Toe, however to finish it I had to write bunch of code in AImove function. Can anyones suggest me what simple techniques to use to shorten this code(especially AImove function)? You don't have to write code what I need, just suggest me something, I need to think about this :) Here's the code:
#include<iostream>
#include<vector>

using namespace std;

const char O = 'O';
const char X = 'X';
const char E = ' ';

void humanMove(vector<char> &b);
void AImove(vector<char> &b);
void inits();
bool win(vector<char> &b, char m);
void drawBoard(vector<char> &b);
int main()
{
	vector <char> board(9,' ');
	inits();
	while(win(board,O) == false)
	{
		humanMove(board);
		drawBoard(board);
		win(board,X);
		AImove(board);
		drawBoard(board);
		win(board,O);
	}
}
void inits()
{
	cout <<"\t\tWelcome to ultimate Tic-Tac-Toe challenge!\n\n";
	cout <<"To do your turn follow these instructions:\n";
	cout <<" 0 || 1 || 2\n 3 || 4 || 5\n 6 || 7 || 8\n";
}
void humanMove(vector<char> &b)
{
	int move;
m:
	cout <<"Enter your move: ";
	cin >> move;
	cout <<"\n";
	//check if move is legal
	if(b[move] != O)
    b[move] = X;	
	else
	{
		cout <<"Move is\n illegal!\n"; goto m;
	}
}
void drawBoard(vector<char> &b)
{
	cout <<"\n\n";
	cout << " "<<b[0]<<"||"<<b[1]<<"||"<<b[2]<<"\n";
	cout <<"--------\n";
	cout << " "<<b[3]<<"||"<<b[4]<<"||"<<b[5]<<"\n";
	cout <<"--------\n";
	cout << " "<<b[6]<<"||"<<b[7]<<"||"<<b[8]<<"\n";
}
bool win(vector<char> &b, char m)
{
	//check for win
	if(b[0] == m && b[1] == m && b[2] == m)
	{
		cout << m <<" wins!!!"; return true;
	}
	else if(b[3] == m && b[4] == m && b[5] == m)
	{
		cout << m <<" wins!!!"; return true;
	}
	else if(b[6] == m && b[7] == m && b[8] == m)
	{
		cout << m <<" wins!!!"; return true;
	}
	else if(b[0] == m && b[3] == m && b[6] == m)
	{
		cout << m <<" wins!!!"; return true;
	}
	else if(b[1] == m && b[4] == m && b[7] == m)
	{
		cout << m <<" wins!!!"; return true;
	}
	else if(b[2] == m && b[5] == m && b[8] == m)
	{
		cout << m <<" wins!!!"; return true;
	}
	else if(b[2] == m && b[4] == m && b[6] == m)
	{
		cout << m <<" wins!!!"; return true;
	}
	else if(b[0] == m && b[4] == m && b[8] == m)
	{
		cout << m <<" wins!!!"; return true;
	}
	//chec for tie
	else if(b[0] !=E && b[1] !=E && b[2] !=E && b[3] !=E && b[4] !=E && b[5] !=E && b[6] !=E && b[7] !=E && b[8] !=E)
	{
		cout << " TIE!!!"; return true;
	}
	return false;
}
void AImove(vector<char> &b)
{
	//if can win in one turn
	//012
	if(b[0] == O && b[1] == O && b[2] == E){
		b[2] = O; return;}
	else if(b[0] == O && b[2] == O && b[1] == E){
		b[1] = O; return;}
	else if(b[2] == O && b[1] == O && b[0] == E){
		b[0] = O; return;}
	//345
	else if(b[3] == O && b[4] == O && b[5] == E){
		b[5] = O; return;}
	else if(b[3] == O && b[5] == O && b[4] == E){
		b[4] = O; return;}
	else if(b[5] == O && b[4] == O && b[3] == E){
		b[3] = O; return;}
	//678
	else if(b[6] == O && b[7] == O && b[8] == E){
		b[8] = O; return;}
	else if(b[6] == O && b[8] == O && b[7] == E){
		b[7] = O; return;}
	else if(b[8] == O && b[7] == O && b[6] == E){
		b[6] = O; return;}
	//036
	else if(b[0] == O && b[3] == O && b[6] == E){
		b[6] = O; return;}
	else if(b[0] == O && b[6] == O && b[3] == E){
		b[3] = O; return;}
	else if(b[3] == O && b[6] == O && b[0] == E){
		b[0] = O; return;}
	//147
	else if(b[0] == O && b[1] == O && b[2] == E){
		b[2] = O; return;}
	else if(b[0] == O && b[1] == O && b[2] == E){
		b[2] = O; return;}
	else if(b[0] == O && b[1] == O && b[2] == E){
		b[2] = O; return;}
	//258
	else if(b[2] == O && b[5] == O && b[8] == E){
		b[8] = O; return;}
	else if(b[2] == O && b[8] == O && b[5] == E){
		b[5] = O; return;}
	else if(b[8] == O && b[5] == O && b[2] == E){
		b[2] = O; return;}
	//246
	else if(b[4] == O && b[6] == O && b[2] == E){
		b[2] = O; return;}
	else if(b[2] == O && b[4] == O && b[6] == E){
		b[6] = O; return;}
	else if(b[6] == O && b[2] == O && b[4] == E){
		b[4] = O; return;}
	//048
	else if(b[0] == O && b[4] == O && b[8] == E){
		b[8] = O; return;}
	else if(b[0] == O && b[8] == O && b[4] == E){
		b[4] = O; return;}
	else if(b[8] == O && b[4] == O && b[0] == E){
		b[0] = O; return;}
	//if human can win in one turn
	//012
	if(b[0] == X && b[1] == X && b[2] == E){
		b[2] = O; return;}
	else if(b[0] == X && b[2] == X && b[1] == E){
		b[1] = O; return;}
	else if(b[2] == X && b[1] == X && b[0] == E){
		b[0] = O; return;}
	//345
	else if(b[3] == X && b[4] == X && b[5] == E){
		b[5] = O; return;}
	else if(b[3] == X && b[5] == X && b[4] == E){
		b[4] = O; return;}
	else if(b[5] == X && b[4] == X && b[3] == E){
		b[3] = O; return;}
	//678
	else if(b[6] == X && b[7] == X && b[8] == E){
		b[8] = O; return;}
	else if(b[6] == X && b[8] == X && b[7] == E){
		b[7] = O; return;}
	else if(b[8] == X && b[7] == X && b[6] == E){
		b[6] = O; return;}
	//036
	else if(b[0] == X && b[3] == X && b[6] == E){
		b[6] = O; return;}
	else if(b[0] == X && b[6] == X && b[3] == E){
		b[3] = O; return;}
	else if(b[3] == X && b[6] == X && b[0] == E){
		b[0] = O; return;}
	//147
	else if(b[0] == X && b[1] == X && b[2] == E){
		b[2] = O; return;}
	else if(b[0] == X && b[1] == X && b[2] == E){
		b[2] = O; return;}
	else if(b[0] == X && b[1] == X && b[2] == E){
		b[2] = O; return;}
	//258
	else if(b[2] == X && b[5] == X && b[8] == E){
		b[8] = O; return;}
	else if(b[2] == X && b[8] == X && b[5] == E){
		b[5] = O; return;}
	else if(b[8] == X && b[5] == X && b[2] == E){
		b[2] = O; return;}
	//246
	else if(b[4] == X && b[6] == X && b[2] == E){
		b[2] = O; return;}
	else if(b[2] == X && b[4] == X && b[6] == E){
		b[6] = O; return;}
	else if(b[6] == X && b[2] == X && b[4] == E){
		b[4] = O; return;}
	//048
	else if(b[0] == X && b[4] == X && b[8] == E){
		b[8] = O; return;}
	else if(b[0] == X && b[8] == X && b[4] == E){
		b[4] = O; return;}
	else if(b[8] == X && b[4] == X && b[0] == E){
		b[0] = O; return;}
	//other turns
	else if(b[4] == E){
		b[4] = O; return;}
	else if(b[0] == E){
		b[0] = O; return;}
	else if(b[2] == E){
		b[2] = O; return;}
	else if(b[6] == E){
		b[6] = O; return;}
	else if(b[8] == E){
		b[8] = O; return;}
	else if(b[1] == E){
		b[1] = O; return;}
	else if(b[3] == E){
		b[3] = O; return;}
	else if(b[5] == E){
		b[5] = O; return;}
	else if(b[7] == E){
		b[7] = O; return;}
}

Share this post


Link to post
Share on other sites
Advertisement
The win function has a lot of code duplication. Here is a first attempt to make it shorter:

#include <algorithm>

bool win(vector<char> &b, char m)
{
static int lines[][3] = {
{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
{0, 4, 8}, {2, 4, 6}
};

for (int i = 0; i < 8; ++i)
{
if (b[lines[0]] == m
&& b[lines[1]] == m
&& b[lines[2]] == m)
{
cout << m << " wins!!!";
return true;
}
}

if (std::count(b.begin(), b.end(), E) == 0)
{
cout << " TIE!!!";
return true;
}

return false;
}


By the way, the human player shouldn't be able to make the same move twice ;)

Share this post


Link to post
Share on other sites
And here is a more "STL-oriented" approach:

#include <algorithm>

class line_finder
{
vector<char>& b;
char m;

public:

line_finder(vector<char>& b, char m) : b(b), m(m) {}

bool operator()(int* line)
{
return b[line[0]] == m
&& b[line[1]] == m
&& b[line[2]] == m;
}
};

bool win(vector<char> &b, char m)
{
static int lines[][3] = {
{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
{0, 4, 8}, {2, 4, 6}
};

if (std::find_if(lines, lines + 8, line_finder(b, m)) != lines + 8)
{
cout << m << " wins!!!";
return true;
}

if (std::count(b.begin(), b.end(), E) == 0)
{
cout << " TIE!!!";
return true;
}

return false;
}


Sooner or later, Zahlman will jump in and tell you about const correctness ;)

Share this post


Link to post
Share on other sites
I don't want it to be initialized every time the win function is entered. I could have made it a global variable, but then every other function would unnecessarily have access to it.

Share this post


Link to post
Share on other sites
ok, now AImove function is way shorter :)


void AImove(vector<char> &b)
{
static int lines[][3] = {
{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
{0, 4, 8}, {2, 4, 6}
};
//if AI can win in one turn
for (int i = 0; i < 8; ++i)
{
if (b[lines[0]] == O
&& b[lines[1]] == O
&& b[lines[2]] == E)
{
b[lines[2]] = O; return;
}
else if(b[lines[0]] == E
&& b[lines[1]] == O
&& b[lines[2]] == O)
{
b[lines[0]] = O; return;
}
else if(b[lines[0]] == O
&& b[lines[1]] == E
&& b[lines[2]] == O)
{
b[lines[1]] = O; return;
}
}
//if human can win in one turn
for (int i = 0; i < 8; ++i)
{
if (b[lines[0]] == X
&& b[lines[1]] == X
&& b[lines[2]] == E)
{
b[lines[2]] = O; return;
}
else if(b[lines[0]] == E
&& b[lines[1]] == X
&& b[lines[2]] == X)
{
b[lines[0]] = O; return;
}
else if(b[lines[0]] == X
&& b[lines[1]] == E
&& b[lines[2]] == X)
{
b[lines[1]] = O; return;
}
}
//other turns
if(b[4] == E){
b[4] = O; return;}
else if(b[0] == E){
b[0] = O; return;}
else if(b[2] == E){
b[2] = O; return;}
else if(b[6] == E){
b[6] = O; return;}
else if(b[8] == E){
b[8] = O; return;}
else if(b[1] == E){
b[1] = O; return;}
else if(b[3] == E){
b[3] = O; return;}
else if(b[5] == E){
b[5] = O; return;}
else if(b[7] == E){
b[7] = O; return;}
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!