Thread: Tic Tac Toe... so close...

  1. #1
    Registered User
    Join Date
    Aug 2005
    Posts
    14

    Unhappy Tic Tac Toe... so close...

    Hey guys, me again. Sorry to pester you so much, but once again I am stuck on an assignment. I'm supposed to create a game of tic tac toe that engages the user with a simple AI from the computer. Now, I have the whole thing mapped out except for one part...checking the win condition. Here's what code I have so far:

    Code:
    // TicTacToeVsAI.c.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "simpio.h"
    #include <stdlib.h>
    
    #define size 3
    #define maxMoves 9
    
    void initBoard(char board[size][size]); //Initializes the board for the first time
    void clearBoard(char board[size][size]); //Initializes the board with 'empty' spaces
    void printBoard(char board[size][size]); //Shows the current status of the board
    bool checkWin(char board[size][size]); //Checks if anyone has won at the current time
    bool TicTacToe(char board[size][size]); //Initializes the game
    void GetMove(char board[size][size]); //Reads in and places the player's choice of location
    void CompMove(char board[size][size]); //Causes the computer to make a move
    
    main()
    {
    	char board[size][size];
    	printf("To play the simple game of tic tac toe, enter the number of the space which \n");
    	printf("you wish to place your mark in. When either player manages to get 3 in a row, \n");
    	printf("diagonally, vertically, or horizontally, that player wins, otherwise,\nthe game is a draw.\n");
    	initBoard(board);
    	printBoard(board);
    	clearBoard(board);
    	TicTacToe(board);
    }
    
    void initBoard(char board[size][size])
    {
    	int row,column;
    	int num=49; //Since this is going to initialize the board in such a way as to show
    //the user how to play, we use num to label the squares of the board
    	for (row=0;row<size;row++)
    	{
    		for (column=0;column<size;column++)
    		{
    			board[row][column]=num;
    			num++;
    		}
    	}
    }
    
    void clearBoard(char board[size][size])
    {	
    	int row,column;
    	for (row=0;row<size;row++)
    	{
    		for (column=0;column<size;column++)
    		{
    			board[row][column]=' '; //By filling the board with spaces, we are 'clearing' the board.
    		}
    	}
    }
    
    void printBoard(char board[size][size])
    {
    	int row,column;
    	for (row=0;row<size;row++)
    	{
    		for (column=0;column<size;column++)
    		{
    			printf("%c", board[row][column]);
    			if (column!=(size-1)) printf("|");
    		}
    		if (row!=(size-1)) printf("\n-+-+-\n");
    	}
    	printf("\n");
    }
    
    bool TicTacToe(char board[size][size])
    {
    	int player=1;
    	int move=0; //The number of moves that have been made so far this game.
    	while (move<=maxMoves)
    	{
    		if (player==1) GetMove(board);
    		else CompMove(board);
    		printBoard(board);
    		player*=-1;
    	}
    	return true;
    }
    void GetMove(char board[size][size])
    {
    	int choice;
    	bool flag=true;
    	printf("Player, please enter your choice of location:  ");
    	while (flag)
    	{
    		choice=GetInteger();
    		switch (choice)
    		{
    		case 1: if (board[0][0]==' ') {board[0][0]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 2: if (board[0][1]==' ') {board[0][1]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 3: if (board[0][2]==' ') {board[0][2]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 4: if (board[1][0]==' ') {board[1][0]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 5: if (board[1][1]==' ') {board[1][1]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 6: if (board[1][2]==' ') {board[1][2]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 7: if (board[2][0]==' ') {board[2][0]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 8: if (board[2][1]==' ') {board[2][1]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 9: if (board[2][2]==' ') {board[2][2]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		}
    	}
    }
    However, I need some help writing the checkWin function which checks the entire board for any win conditions. I'm completely stumped, and I have no idea how to go about this. Although code is appreaceated, even just some prompts on how I might go about this task would be greatly appreciated. Also, I was wondering if there was anyway to make the computer use that strategy where you make a triangle and block your opponent off in an attempt to stalemate the game. I've gotten the ai to the point where it's semi-smart, with the following code:

    Code:
    void NoLose(char board[size][size],int row,int column)
    {
    	if (board[row][column]==' ') board[row][column]='O';
    	else
    	{
    		if ((row==2)&&(column==0)) NoLose(board,row-2,column+1);
    		if ((row==0)&&(column==1)) NoLose(board,row+2,column+1);
    		if ((row==0)&&(column==0)) NoLose(board,row+1,column+2);
    		if ((row==0)&&(column==2)) NoLose(board,row+1,column-2);
    		if ((row==1)&&(column==0)) NoLose(board,row+1,column+2);
    		if ((row==1)&&(column==2)) NoLose(board,row+1,column-2);
    		if ((row==2)&&(column==1)) NoLose(board,row-2,column+1);
    		if ((row==2)&&(column==2)) NoLose(board,row-1,column-2);
    	}
    
    }
    But it still gets killed by anyone with half a brain. Again, thanks in advance for any help
    Last edited by SlayerBlade; 10-10-2005 at 08:49 PM.

  2. #2
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    One thing, your construct:
    Code:
    switch (choice)
    		{
    		case 1: if (board[0][0]==' ') {board[0][0]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    		case 2: if (board[0][1]==' ') {board[0][1]='X'; flag=false;} else printf("Invalid choice, try again\n"); break;
    Could be probably be better written as:
    Code:
    int row, col;
    choice--; /* convert to 0-8 internally */
    row = choice/size;
    col = choice%size;
    
    if (board[row][col]==' ')
    {
        board[row][col]='X';
        flag=false;
    } else
        printf("invalid choice, try again\n");
    Then you don't need to repeat the same code over and over.

    As for the win condition, write code to iterate through each row, check for three of the same kind, write code to iterate through each column, check for three of the same kind, then check the two diagonals. You can use the same simple for loops as you did on Clear/Print/initboard.

  3. #3
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    To check the win condition, you have to see if any of the rows/columns/diagonals have the same value.

    First row (or is it column? depends on how you interpret your matrix)

    board[0][0] == board[0][1] && board[0][0] == board[0][2]

  4. #4
    Registered User
    Join Date
    Sep 2005
    Location
    Sydney
    Posts
    60
    Well, think about how you win Tic Tac Toe. You need to get either three crosses or three naughts in a row, so just write a function to check for that? There aren't that many combinations - three horizontal, three vertical and two diagonal, so you could probably just go through and check all of them. If all three in the top row are the same symbol, then the appropriate player has won. If all three in the middle row are the same, then someone's won. And so on. There may be more efficient ways to do it, I'm not sure, but with only eight combinations to check anyway, it doesn't really matter.

  5. #5
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    But use a loop, instead of explicitly specifying each row/column offset, otherwise it defeats the purpose of having a definable size parameter.

  6. #6
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    But use a loop, instead of explicitly specifying each row/column offset, otherwise it defeats the purpose of having a definable size parameter.
    I think either way would be fine. Moreover, explicitly specifying the row/column offset might be slightly faster than going through the loop (less JMP statements).

  7. #7
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    Quote Originally Posted by Dante Shamest
    I think either way would be fine. Moreover, explicitly specifying the row/column offset might be slightly faster than going through the loop (less JMP statements).
    This is tic tac toe, not global thermonuclear war simulation.

  8. #8
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Which is why I said either way would be fine, but it's not necessary to use a loop.

  9. #9
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    It is necessary to use a loop for two reasons.

    1) The code without a loop is much longer and more convoluted, and leads to repeat code over and over.
    2) He uses a loop for every other routine in the program, relying on the "size" define. Not using a loop would render this pointless.

  10. #10
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Necessary means absolutely essential. As in, if he didn't used loops, it wouldn't work.

    This is my Tic Tac Toe clone, which does not use loops to test the win condition, and it works perfectly.

  11. #11
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    Okay, my mistake. Let me rephrase, he should use a loop.

    And, by posting your tic-tac-toe source, you are doing this guy's assignment for him.

  12. #12
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Quote Originally Posted by cwr
    Okay, my mistake. Let me rephrase, he should use a loop.
    Whether he should or not, it's up to him to decide. As you mentioned, using a loop would save code size, but that's about it.

    And, by posting your tic-tac-toe source, you are doing this guy's assignment for him.
    He's writing a console program in C.
    My program in a Windows GUI program in C++.

  13. #13
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    True, looks good, by the way. I had a quick look at the source. I'd compile/run it, but I don't have Windows.

  14. #14
    Registered User
    Join Date
    Aug 2005
    Posts
    14
    Thanks for the help guys! I now have a working iteration of the checkwin code, however I was just wondering if there was any way to make my comp smarter. Check the original post. I attempted using a conditional recursive function, but it messes up if someone puts their first position in your starting spot.

  15. #15
    Registered User
    Join Date
    Sep 2005
    Location
    Sydney
    Posts
    60
    Quote Originally Posted by Dante Shamest
    Whether he should or not, it's up to him to decide. As you mentioned, using a loop would save code size, but that's about it.
    Using a loop would also make it less likely that he would make a mistake when coding and make the code more readable and maintainable.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help me with my simple Tic tac toe prog
    By maybnxtseasn in forum C Programming
    Replies: 2
    Last Post: 04-04-2009, 06:25 PM
  2. tic tac toe
    By holden in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 05-09-2004, 09:59 AM
  3. Help with Tic Tac Toe game
    By snef73 in forum C++ Programming
    Replies: 1
    Last Post: 04-25-2003, 08:33 AM
  4. Need some help with a basic tic tac toe game
    By darkshadow in forum C Programming
    Replies: 1
    Last Post: 05-12-2002, 04:21 PM
  5. Ghost in the CD Drive
    By Natase in forum A Brief History of Cprogramming.com
    Replies: 17
    Last Post: 10-12-2001, 05:38 PM