Play Tic Tac Toe


By real programmers standards this is a dumb version. But it works, much to my suprise. Give it a shot. Sometimes the simpler things are best.

Download a ziped microsoft DOS/windows executable ttt.zip 22.9 KB
I also found that this executable, compiled for microsoft, also runs with wine on linux. Just download, unzip it, and type "wine ttt.exe" at the command line.

C++ Source Code:
//
// by Floyd Reed July 30, 2002
//
// so far pretty stupid, only fills in when win in one move
// will try to add blocking in one move and a larger play 
// again loop.  Would like a more general planning depth
// based on relative likelihood of outcomes but having trouble
// getting it that far
//

#include 
#include 	// required for rand function
#include 	// required for srand seed with time

int  print_board(char [3][3]);
int win_check(char [3][3]);
int computers_move (char [3][3]);

int main()
{
	srand (time(NULL));		// uses time to seed random generator
	int x,y,nStart; 
	int nWin = 0;
	int nComputer=0;
	int nPlayer=0;
	int nDraw=0;
	// flips a coin to see who starts
	cout << "\nTick, Tack, Toe; Version 6\n  by Reed-ware, 2002\n\n";
	int nPlay=1;
	char cPlay;
	while (nPlay)
	{
		int nTotalTurns = 0; 
		cout << "Lets flip a coin to see who starts.\n"
			<< "Enter your choice: heads (h) or tails (t)? ";
		char cChoice;
		cin >> cChoice;
		char cCoinResult;
		if (int (rand()%2) == 0) {cCoinResult='h';}
		else {cCoinResult='t';}
		cout << "Flip . . . " << cCoinResult << "\n";
		if (cCoinResult == cChoice) {cout << "You win! Go first.\n"; nStart=1;}
		else {cout << "I win! I'll go first.\n"; nStart=0;}
	
		// creates and initializes the game board
		char cBoard[3][3];
		int i;
		int j;
		for (i=0; i<3; i++)
		{
			for (j=0; j<3; j++) {cBoard[i][j]=' ';}
		}
		
		while(1) // if go first picks an empty place on the board
		{
			if (nStart==1) {break;}
			x=int(rand()%3);
			y=int(rand()%3);
			if (cBoard[x][y]==' ') {cBoard[x][y]='X'; break;}
	
			int count3 = 0;
			if (count3>1000) {cout << "\nError 4"; break;}
			count3++;
		}
		if (nStart==0) {nTotalTurns++;}
	
		print_board(cBoard);
	
		// play the game until a win or draw
		while(1)
		{
			// users move
			while (1)
			{
				cout << "Your x coordinate: ";
				cin >> x;
				x--;
				cout << "Your y coordinate: ";
				cin >> y;
				y--;
				if (cBoard[x][y]==' ') {cBoard[x][y]='O'; break;}
				else{cout<<"Not an option!\n";}
	
				int count2 = 0;
				if (count2>1000) {cout << "\nError 3"; break;}
				count2++;
			}

			// print the board
			print_board(cBoard);
	
			// descides if there is a win
			nWin = win_check(cBoard);
			if (nWin!=0) {break;}	
	
			// descide if a draw, important to put this after the win check
			nTotalTurns++; 
			if (nTotalTurns==9) {break;}
	
			// computers move
			int nMove;
			nMove = computers_move(cBoard);
			if (nMove==1) {x=0; y=0;}
			if (nMove==2) {x=0; y=1;}
			if (nMove==3) {x=0; y=2;}
			if (nMove==4) {x=1; y=0;}
			if (nMove==5) {x=1; y=1;}
			if (nMove==6) {x=1; y=2;}
			if (nMove==7) {x=2; y=0;}
			if (nMove==8) {x=2; y=1;}
			if (nMove==9) {x=2; y=2;}
			cBoard[x][y]='X';
	
			cout << "My move.\n";
	
			// print the board
			print_board(cBoard);
	
			// descides if there is a win
			nWin = win_check(cBoard);
			if (nWin!=0) {break;}
	
			// descide if a draw, important to put this after the win check
			nTotalTurns++; 
			if (nTotalTurns==9) {break;}
	
			int count = 0;
			if (count>1000) {cout << "\nError 2"; break;}
			count++;
	
		}
	
		if (nWin==1) {cout << "\nI won!!!\n";nComputer++;} // computer won
		if (nWin==2) {cout << "\nYou won!!!\n";nPlayer++;} // user won
		if (nWin==0) {cout << "\nIt's a draw.\n";nDraw++;} // 9 turns with no win
		cout << "Computer: " << nComputer << ", Player: " << nPlayer << ", Draws: " << nDraw << "\n";
		cout << "Want to play again? (y) or (n): ";
		cin >> cPlay;
		if (cPlay=='n') {nPlay=0;}
	}
		//cout << "\nHit a 1 and enter to close";
		//int nWait;
		//cin >> nWait;
	
	return 0;
}


int  print_board(char cBoard[3][3])
{
	cout	<< "\n"
			<< "\t1: " << cBoard[0][0] << "|" << cBoard[1][0] << "|" << cBoard[2][0] << "\n"
			<< "\t   -+-+-\n"
			<< "\t2: " << cBoard[0][1] << "|" << cBoard[1][1] << "|" << cBoard[2][1] << "\n"
			<< "\t   -+-+-\n"
			<< "\t3: " << cBoard[0][2] << "|" << cBoard[1][2] << "|" << cBoard[2][2] << "\n"
			<< "\t   1 2 3\n\n";
	return 0;
}


int win_check(char cBoard[3][3])
{
	// descides if there is a win
	int nWin=0;
	int i;
	for (i=0; i<3; i++) // scan columns
	{
		if (cBoard[i][0] == 'O' && cBoard[i][1] == 'O' && cBoard[i][2] == 'O')
		{nWin=2;}
		if (cBoard[i][0] == 'X' && cBoard[i][1] == 'X' && cBoard[i][2] == 'X')
		{nWin=1;}
	}
	for (i=0; i<3; i++) // scan rows
	{
		if (cBoard[0][i] == 'O' && cBoard[1][i] == 'O' && cBoard[2][i] == 'O')
		{nWin=2;}
		if (cBoard[0][i] == 'X' && cBoard[1][i] == 'X' && cBoard[2][i] == 'X')
		{nWin=1;}
	}
	// scan forward diagonal
	if (cBoard[0][2] == 'O' && cBoard[1][1] == 'O' && cBoard[2][0] == 'O')
	{nWin=2;}
	if (cBoard[0][2] == 'X' && cBoard[1][1] == 'X' && cBoard[2][0] == 'X')
	{nWin=1;}
	// scan backward diagonal
	if (cBoard[0][0] == 'O' && cBoard[1][1] == 'O' && cBoard[2][2] == 'O')
	{nWin=2;}
	if (cBoard[0][0] == 'X' && cBoard[1][1] == 'X' && cBoard[2][2] == 'X')
	{nWin=1;}

	return nWin;
}


int computers_move (char cBoard[3][3])
{
	//srand (time(NULL));
	int x, y;
	int nMove;
	int nNextMove=0;
	int nWin = 0;
	int nLookAhead = 4;
	int nReplicates = 100;
	int nOutcome[9][2]; // stores results of next possible outcomes
	int i;
	int j;
	int k;
	// int l;
	// sets outcome array
	for (i=0; i<9; i++)
	{
		for (j=0; j<2; j++) {nOutcome[i][j]=0;}
	}
	char cBoardCopy[3][3];
	for (i=0; i<3; i++)
	{
		for (j=0; j<3; j++)
		{
			cBoardCopy[i][j]=cBoard[i][j];
		}
	}
	// DEFENSE
	// looks for a lose in one move and blocks it
	for (i=0; i1000) {cout << "\nError 1"; break;}
			count++;
		}

		// sorts out position code
		if (x==0)
		{
			if (y==0) {nMove=1;}
			if (y==1) {nMove=2;}
			if (y==2) {nMove=3;}
		}
		if (x==1)
		{
			if (y==0) {nMove=4;}
			if (y==1) {nMove=5;}
			if (y==2) {nMove=6;}
		}
		if (x==2)
		{
			if (y==0) {nMove=7;}
			if (y==1) {nMove=8;}
			if (y==2) {nMove=9;}
		}
		// descides if there is a lose in 1 move
		nWin = win_check(cBoardCopy);
		if (nWin==2) // if there is a win in 1 move break and return coordinates
		{
			nNextMove=nMove; // stores winning move as next move
			break;
			cBoardCopy[x][y]=' '; // reset board
		}
		// reset board
		for (k=0; k<3; k++)
		{
			for (j=0; j<3; j++)
			{
				cBoardCopy[k][j]=cBoard[k][j];
			}
		}
	} // close replicate loop

	// OFFENSE
	// looks for a win in one move and takes it
	// tries random possible next moves
	for (i=0; i1000) {cout << "\nError 1"; break;}
			count++;
		}

		// sorts out position code
		if (x==0)
		{
			if (y==0) {nMove=1;}
			if (y==1) {nMove=2;}
			if (y==2) {nMove=3;}
		}
		if (x==1)
		{
			if (y==0) {nMove=4;}
			if (y==1) {nMove=5;}
			if (y==2) {nMove=6;}
		}
		if (x==2)
		{
			if (y==0) {nMove=7;}
			if (y==1) {nMove=8;}
			if (y==2) {nMove=9;}
		}

		// descides if there is a win in 1 move
		nWin = win_check(cBoardCopy);
		if (nWin==1) // if there is a win in 1 move break and return coordinates
		{
			nNextMove=nMove; // stores winning move as next move
			break;
			cBoardCopy[x][y]=' '; // reset board
		}


		/* this next section hangs up the program

		for(l=0; l1000) {cout << "\nError 5"; break;}
				count2++;
			}
			// descides if there is a win
			nWin = win_check(cBoardCopy);
			if (nWin == 1) {nOutcome[nMove-1][0]++;break;} // computer wins
			if (nWin == 2) {nOutcome[nMove-1][1]++;break;} // user wins
			if (nWin == 3) {break;} // a draw
		
			// simulates computers move
			while(1) // picks an empty place on the board
			{
				x=int(rand()%3);
				y=int(rand()%3);
				if (cBoardCopy[x][y]==' ') {cBoardCopy[x][y]='X'; break;}
			
				int count3 = 0;
				if (count3>1000) {cout << "\nError 6"; break;}
				count3++;
			}
			// descides if there is a win
			nWin = win_check(cBoardCopy);
			if (nWin == 1) {nOutcome[nMove-1][0]++;break;} // computer wins
			if (nWin == 2) {nOutcome[nMove-1][1]++;break;} // user wins
			if (nWin == 3) {break;} // a draw
		} // close look ahead loop
		
		//cout << "\n" << nMove; 
		//for (j=0; j<9; j++)
		//{
		//	cout << " " << nOutcome[j][0];
		//}
		*/

		// reset board
		for (k=0; k<3; k++)
		{
			for (j=0; j<3; j++)
			{
				cBoardCopy[k][j]=cBoard[k][j];
			}
		}
	} // close replicate loop
	if (nNextMove == 0) // if no wins or losses picks randomly
	{
		while(1) // picks an empty place on the board
		{
			x=int(rand()%3);
			y=int(rand()%3);
			if (cBoardCopy[x][y]==' ') {cBoardCopy[x][y]='X'; break;}
		}
		// sorts out position code
		if (x==0)
		{
			if (y==0) {nMove=1;}
			if (y==1) {nMove=2;}
			if (y==2) {nMove=3;}
		}
		if (x==1)
		{
			if (y==0) {nMove=4;}
			if (y==1) {nMove=5;}
			if (y==2) {nMove=6;}
		}
		if (x==2)
		{
			if (y==0) {nMove=7;}
			if (y==1) {nMove=8;}
			if (y==2) {nMove=9;}
		}
		nNextMove=nMove;
	}
	return nNextMove;
}



C Programming | Floyd's Home | MountainSmoke.com

Copyright: © Floyd A. Reed 1996-2003, all rights reserved.
URL: http://www.mountainsmoke.com/floyd/pi.htm
Contact: floyd@mountainsmoke.com
Revised: Thursday February 13, 2003