How can I make a function to return two values?

Started by
28 comments, last by sheep19 16 years, 5 months ago
Quote:If I was you, I would simply use this function to check the winner. checkWin(char player) where player is refer to character of each player.

[Snip DailyWTF submission]


* Dies of heart attack *

At least pretend to remove repetitiveness:

int checks[][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)   {    bool row_full = true;    for (int j = 0; j < 3; ++j)     {      row_full =          row_full && (player == board[checks[j] / 3][checks[j] % 3]);    }    if (row_full) return true;  }  return false;
Advertisement
Or to make it board size independent:

const int NumCellsX = 3;const int NumCellsY = 3;const int NumCellsToWin = 3;bool CheckWin(int player){	/* horizontal */	for (int y = 0; y < NumCellsX; y++)	{		int n = 0;				for (int x = 0; x < NumCellsX; x++)		{			if (board[y][x] == player)				n++;		}				if (n > 2)			return true;	}	/* vertical */	for (int x = 0; x < NumCellsX; x++)	{		int n = 0;				for (int y = 0; y < NumCellsX; y++)		{			if (board[y][x] == player)				n++;		}				if (n > 2)			return true;	}	/* diagonal (top left to bottom right) */	for (int x = 0; x <= NumCellsX - NumCellsToWin; x++)	{		int n = 0;				for (int y = 0; y <= NumCellsY - NumCellsToWin; y++)		{			for (int i = 0; i < NumCellsToWin; i++)			{				if (board[y + i][x + i] == player)					n++;			}		}				if (n > 2)			return true;	}	/* diagonal (top right to bottom left) */	for (int x = NumCellsX - 1; x >= NumCellsToWin; x--)	{		int n = 0;				for (int y = NumCellsY - 1; y >= NumCellsToWin; y--)		{			for (int i = 0; i < NumCellsToWin; i++)			{				if (board[y - i][x - i] == player)					n++;			}		}				if (n > 2)			return true;	}		return false;}

I haven't tested it and it could probably be optimized a little more, but it should work.
Quote:Original post by invisal
Your code:
bool checkInput (int node){  // Uglies}


Correct version:
bool checkInput (int node){  return std::find(freenodes.begin(), freenodes.end(), node) != freenodes.end();}



Quote:Your Code
void print(){  // Uglies}


Correct version:
void print(){    cout << "\n" << "Used nodes: ";    std::copy (usedNodes.begin(), usedNodes.end(),      std::ostream_iterator<int>(std::cout, " "));    cout << "\n" << "Free nodes: ";    std::copy (freeNodes.begin(), freeNodes.end(),      std::ostream_iterator<int>(std::cout, " "));    cout << "\n";}
Quote:Original post by WanMaster
Or to make it board size independent:
I haven't tested it and it could probably be optimized a little more, but it should work.

Your code is not perfectly work. It doesb't work when:

- - X
- X -
X - -
DinGY
Yesterday is history.Tomorrow is a mystery. Today is a gift"
[source lang="cpp"//horizontal		for (int i = 0; i < 3; i++)		{			for (int j = 0; j < 3; j++)			{				if (board [j] == board [j+1] && board [j] == board [j+2])				{					if (board [j] == PLAYER_SYMBOL)						return winsP1;					else if (board [j] == PC_SYMBOL)						return winsPC;				}			}		}		//vertical		for (int i = 0; i < 3; i++)		{			for (int j = 0; j < 3; j++)			{				if (board [j] == board [i+1][j] && board [j] == board [i+2][j])				{					if (board [j] == PLAYER_SYMBOL)						return winsP1;					else if (board [j] == PC_SYMBOL)						return winsPC;				}			}		}		//diagonal		for (int i = 0; i < 3; i++)		{			for (int j = 0; j < 3; j++)			{				if (board [j] == board [i+1][j+1] && board [j] == board [i+2][j+2])				{					if (board [j] == PLAYER_SYMBOL)						return winsP1;					else if (board [j] == PC_SYMBOL)						return winsPC;				}				if (board [i+2][j] == board [i+1][j+1] && board [i+2][j] == board [j+2])				{					if (board [i+2][j] == PLAYER_SYMBOL)						return winsP1;					else if (board [i+2][j] == PC_SYMBOL)						return winsPC;				}			}		}		

what about this?
{i'm making the diagonal now)

edit: finished
This code should work perfectly after many of test and it is board size independent.

const int NumCellsX = 3;const int NumCellsY = 3;const int NumCellsToWin = 3;bool CheckWin(int player){    int n = 0;    for(int y=0; y<NumCellsY; y++) {        n = 0;        for(int x=0; x<NumCellsX; x++) {            if (board[x][y] == player) n++; else n = 0;            if (n >= NumCellsToWin) return true;        }    }    for(int x=0; x<NumCellsX; x++) {        n = 0;        for(int y=0; y<NumCellsY; y++) {            if (board[x][y] == player) n++; else n = 0;            if (n >= NumCellsToWin) return true;        }    }    n = 0;    for(int x=0; x < NumCellsX * NumCellsY; x+=(NumCellsX-1)) {        if (board[x%NumCellsY][x/NumCellsX] == player) n++;        if (n >= NumCellsToWin) return true;    }    n = 0;    for(int x=0; x < NumCellsX * NumCellsY; x+=(NumCellsX+1)) {        if (board[x%NumCellsY][x/NumCellsX] == player) n++;        if (n >= NumCellsToWin) return true;    }    return false;}


[Edited by - invisal on November 20, 2007 1:22:37 PM]
DinGY
Yesterday is history.Tomorrow is a mystery. Today is a gift"
Quote:Original post by invisal
Quote:Original post by WanMaster
Or to make it board size independent:
I haven't tested it and it could probably be optimized a little more, but it should work.

Your code is not perfectly work. It doesb't work when:

- - X
- X -
X - -

You're probably right, good thing I put a disclaimer in there. [smile]
Looking at it, it has most definitely something to do with copy/pasting the routines: the for loops should probably have a [x/y] >= NumCellsToWin - 1 end condition, and the n counter should be placed right before the for i loop. O well..*


* Still no guarantees!


Edit: as a sign of good will, I'll post the fugliest alternate solution I could think of:

unsigned int lines[] = {1 << 0 | 1 << 1 | 1 << 2,                        1 << 3 | 1 << 4 | 1 << 5,                        1 << 6 | 1 << 7 | 1 << 8,                        1 << 0 | 1 << 3 | 1 << 6,                        1 << 1 | 1 << 4 | 1 << 7,                        1 << 2 | 1 << 5 | 1 << 8,                        1 << 0 | 1 << 4 | 1 << 8,                        1 << 6 | 1 << 4 | 1 << 2};unsigned int player1 = 0;unsigned int player2 = 0;	bool checkWin(unsigned int player){  for (unsigned int i = 0; i < 8; i++)  {    if ((player | lines) == player)    {      return true;    }  }		  return false;}void applyInput(unsigned int* player, unsigned int x, unsigned int y){  *player |= (1 << (y * 3 + x));}applyInput(&player1, 2, 0);applyInput(&player1, 1, 1);applyInput(&player1, 0, 2);checkWin(player1);

[wink]
I make another function, but this time it requires the last (x, y). The good thing about this function is that it won't loop the entirely element of board array, buy it loop only around the last (x, y) that was moved.

const int NumCellsX = 4;const int NumCellsY = 4;const int NumCellsToWin = 4;bool CheckWin(int player, int last_x, int last_y){    int n = 1, temp_x, temp_y;    temp_x = last_x - 1;    while(temp_x >= 0) {        if (board[last_y][temp_x] == player) n++; else break;        temp_x--;    }    temp_x = last_x + 1;    while(temp_x < NumCellsX) {        if (board[last_y][temp_x] == player) n++; else break;        temp_x++;    }    if (n >= NumCellsToWin) return true;    n = 1;    temp_y = last_y - 1;    while(temp_y >= 0) {        if (board[temp_y][last_x] == player) n++; else break;        temp_y--;    }    temp_y = last_y + 1;    while(temp_y < NumCellsY) {        if (board[temp_y][last_x] == player) n++; else break;        temp_y++;    }    if (n >= NumCellsToWin) return true;    n = 1;    temp_y = last_y - 1;    temp_x = last_x - 1;    while (temp_y >= 0 && temp_x     >= 0) {        if (board[temp_y][temp_x] == player) n++; else break;        temp_y--;        temp_x--;    }    temp_y = last_y + 1;    temp_x = last_x + 1;    while (temp_y < NumCellsY && temp_x < NumCellsX) {        if (board[temp_y][temp_x] == player) n++; else break;        temp_y++;        temp_x++;    }    if (n >= NumCellsToWin) return true;    n = 1;    temp_y = last_y - 1;    temp_x = last_x + 1;    while (temp_y >= 0 && temp_x < NumCellsX) {        if (board[temp_y][temp_x] == player) n++; else break;        temp_y--;        temp_x++;    }    temp_y = last_y + 1;    temp_x = last_x - 1;    while (temp_y < NumCellsY && temp_x >= 0) {        if (board[temp_y][temp_x] == player) n++; else break;        temp_y++;        temp_x--;    }    if (n >= NumCellsToWin) return true;    return false;}[/cpp]
DinGY
Yesterday is history.Tomorrow is a mystery. Today is a gift"
I think this one actually works: (horizontaly and vertically, diagonal tomorrow xD)

#include <iostream>#include <vector>#include <algorithm>#include <ctime>using namespace std;const char PLAYER_SYMBOL = 'X';const char PC_SYMBOL = 'O';const char DEFAULT_SYMBOL = '-';class TicTacToe{private:	vector <int> freeNodes; // the free nodes	vector <int> usedNodes; // the used nodes	char board [3] [3]; // set the boardpublic:	void setBoard () // set the board to empty	{		for (int i = 0; i < 3; i++)		{			for (int j = 0; j < 3; j++)			{				board  [j] = '-';			}		}	}	void setFreeNodes ()	{		for (int i = 1; i <= 9; i++)		{			freeNodes.push_back (i);		}	}	void printBoard () // print the board on the screen	{		cout << "\n";		for (int i = 0; i < 3; i++)		{			for (int j = 0; j < 3; j++)			{				cout << board  [j] << " ";			} 			cout << "\n";		}	}	int getNode ()	{			int node;		cout << "\n" << "Enter a number from 1-9: ";		cin >> node;		return node;	}	bool checkInput (int node)	{		vector <int>::iterator it;		for (it = freeNodes.begin(); it < freeNodes.end(); it++)		{			if (node == *it)			{				return true;			}		}		cout << "\n" << "Invalid input.";		return false;	}	void applyInputToBoard (int node, bool playsP1, bool playsPC)	{		int i, j;		if (node % 3 != 0)		{			i = node / 3;			j = node % 3 - 1;		}		else		{			i = node / 3 - 1;			j = 2;		}		if (playsP1 == true)			board  [j] = PLAYER_SYMBOL; // ('X')		else			board  [j] = PC_SYMBOL; // ('O')	}	void undoInputToBoard (int node) // undo the pc's move (see pcNode)	{		int i, j;		if (node % 3 != 0)		{			i = node / 3;			j = node % 3 - 1;		}		else		{			i = node / 3 - 1;			j = 2;		}				// undo the move		board  [j] = DEFAULT_SYMBOL; // ('-')	}	void addRemoveNodes (int node)	{		usedNodes.push_back (node); // add the node in usedNodes		sort (usedNodes.begin(), usedNodes.end() );		//remove the node from freeNodes		int position = 0;		vector <int>::const_iterator it;		for (it = freeNodes.begin(); it < freeNodes.end(); it++)		{			if (*it == node)			{				break;			}			position ++; // position is the position of the number (node) in the vector		}				/*when (*it = node), position isn't increased, because it breaks the loop. But that doesn't matter because when  erase, I have to delete -1		 because it starts from the the first element. position is already -1 so I don't have to subtract anything.		eg it should have been "freeNodes.erase (freeNodes.begin() + position - 1);", but position is -1 from the 		node's position, so, it's ok.*/				freeNodes.erase (freeNodes.begin() + position);		sort (freeNodes.begin(), freeNodes.end() );	}	int checkWin ()	{		enum Won		{			none = 0,			winsP1 = 1,			winsPC = 2,			tie = 3		};		//horizontal		for (int i = 0; i < 3; i++)		{			int j = 0;							if (board [j] == board [j+1] && board [j] == board [j+2])			{				if (board [j] == PLAYER_SYMBOL)				{					cout << "\n" << "P1 wins horizontal\t" << i << "," << j << " " << i << "," << j+1 << " " << i << "," << j+2;					return winsP1;				}				else if (board [j] == PC_SYMBOL)				{						cout << "\n" << "PC wins horizontal\t" << i << "," << j << " " << i << "," << j+1 << " " << i << "," << j+2;					return winsPC;				}			}		}		//vertical		for (int j = 0; j < 3; j++)		{			int i = 0;			if (board [j] == board [i+1][j] && board [j] == board [i+2][j])			{				if (board [j] == PLAYER_SYMBOL)				{					cout << "\n" << "P1 wins vertical\t" << i << "," << j << " " << i << "," << j+1 << " " << i << "," << j+2;					return winsP1;				}				else if (board [j] == PC_SYMBOL)				{						cout << "\n" << "PC wins vertical\t" << i << "," << j << " " << i << "," << j+1 << " " << i << "," << j+2;					return winsPC;				}			}		}				if (freeNodes.empty() == true)			return tie;		else			return none;	}	int pcNode ()	{		vector <int>::iterator it = freeNodes.begin();		// for every free node, check if can win		for (it = freeNodes.begin(); it < freeNodes.end(); it++)		{			bool winsP1, winsPC;			applyInputToBoard (*it, false, true);			int win = checkWin(); // check if this node is a winning node			if (win == 1)				winsP1 = true;			else if (win == 2)				winsPC = true;			if (winsPC == true) // if this is a winning move, done				return *it;			else // if not, undo the move :)			{				undoInputToBoard (*it);			}		}		/////		srand (static_cast<unsigned int>(time(NULL)));		int node;		int randomNode = 1 + rand() % 9;				it = freeNodes.begin();		while (it < freeNodes.end() )		{			if (randomNode == *it) // if node is free			{				int i = randomNode;				return randomNode;			}						it++;			if (it == freeNodes.end() ) // if the node is not in freeNodes (if it's not free), repeat again			{				it = freeNodes.begin();				randomNode = 1 + rand () % 9;			}		}		node = randomNode;		return node;	}	void print()	{		cout << "\n" << "Used nodes: ";		vector <int>::const_iterator it;		for (it = usedNodes.begin(); it < usedNodes.end(); it++)		{			cout << *it << " ";		}		cout << "\n" << "Free nodes: ";		for (it = freeNodes.begin(); it < freeNodes.end(); it++)		{			cout << *it << " ";		}		cout << "\n";	}};int main(){	cout << "Tic Tac Toe" << "\t" << "by Minas Mina"		 << "\n" << "You: X" << "\t" << "PC: O";	TicTacToe game; // create an object for the class	game.setBoard(); // set the board	game.setFreeNodes();	bool playsP1 = true, playsPC = false;	bool winsP1 = false, winsPC = false, tie = false;	while ( (winsP1 == false) && (winsPC == false) && (tie == false) )	{		if (playsP1 == true)		{			int node;			bool acceptInput = false;						while (acceptInput == false)			{					node = game.getNode();				acceptInput = game.checkInput (node); // check if the node is free				}			game.addRemoveNodes (node);			game.applyInputToBoard (node, playsP1, playsPC); //update the board							int win = game.checkWin();			if (win == 1)				winsP1 = true;			else if (win == 3)				tie = true;			game.printBoard();			playsP1 = false;			playsPC = true;			game.print();		}		if (winsP1 == true || tie == true)			break;				if (playsPC == true)		{				int node = game.pcNode ();			cout << "\n" << "The pc plays " << node;			game.addRemoveNodes (node);			game.applyInputToBoard (node, playsP1, playsPC); //update the board			int win = game.checkWin();			if (win == 1)				winsP1 = true;			else if (win == 2)				winsPC = true;			else if (win == 3)				tie = true;			game.printBoard();			playsP1 = true;			playsPC = false;			game.print();		}	}	if (winsP1 == true)		cout << "\n" << "You win!!";	else if (winsPC == true)		cout << "\n" << "You lose..";	else		cout << "\n" << "Tie.";	cout << "\n";	system ("PAUSE");	return 0;}


(the changes are in the checkWin() function)
Quote:Original post by Simian Man
There are a few options:
...

  • Use a better language :)



  • ha ha ha xD

    (how do I use emoticons?)

    This topic is closed to new replies.

    Advertisement