Programming Tic Tac Toe

0 Reynaldo Gunawan · June 13, 2015
For my next project, i am asked to create Tic Tac Toe in C. The only clue that i got is that i need 3-dimensional array, as the users will put in the number of column and row to indicate which box they want to play. 

The question also says that i need to prove whether the box is already full or whether one of the player has his/her symbol three times in a line, well everyone knows Tic Tac Toe.

I know that i need a tremendous amount of functions to make this program, but i don't even know where to start and which and how many variables i would need. I've created the structure of the game without the number like the photos below, but that's only like 1/1000 done of what i need to do. I am so screwed...

If someone has any ideas, please let me know. I'm not expecting a whole complete program, as i would not learn as much from it anyway. I appreciate your replies.

Example of the format:

./images/forum/upload/2015-06-13/b985899b892f2ec437b27c4afe79c665.png/images/forum/upload/2015-06-13/12b00650949cfe1723bd16879b3dfb8f.png

Post a Reply

Replies

- page 1
Oldest  Newest  Rating
0 Reynaldo Gunawan · June 26, 2015
Try to check the first page. There are many useful informations that have been posted to start from scratch ^^
0 Chinedu Douglas · June 26, 2015
wanna start from scratch ,Any help for Me
0 Reynaldo Gunawan · June 25, 2015
@AlanJohnson hmm okay. I still have a reeaaally looooong way to go then. Thanks again for your help on this one. It really saved me this semester
0 Alan Johnson · June 24, 2015
You just had a few errors in your programming logic, for example the move() would never work and the way you were returning the input wasn't right.
0 Reynaldo Gunawan · June 24, 2015
@AlanJohnson, sorry i just got the time to check what you fixed. IT IS EXACTLY HOW I WANT IT! Wow thanks a lot. May i ask what kind of problems that i had? And why would the type of array that i had wouldn't work?
0 Homer Simpson · June 24, 2015
main.cpp
#include "engine.h"

int main()
{
    engine.play();
    return 0;
}


engine.h
#ifndef ENGINE_H
#define ENGINE_H

#include "board.h"

class Engine{
    private:
        
        char symbol; // is set to 'X' or 'O'
        
        int display_menu();
        // returns true if theres no moves left or if a player has won
        bool game_over();
        // return true if there are no available move, otherwise it returns false
        bool is_out_of_moves();
        // return true if a player has won, otherwise it returns false;
        bool player_won();
        // changes the symbol 
        void swap_turns();
        
    public:
        // 'X' is set to always be first
        Engine(char x) { symbol = x; };
        // run the game
        void play();
};

extern Engine engine;

enum choices {
    SINGLEPLAYER = 1, TWO_PLAYERS, ABOUT, EXIT
};

#endif // ENGINE_H


engine.cpp
#include "engine.h"
#include "misc.h"

#include <cstdio>
#include <cstdlib>
#include <iostream>

Engine engine('X');

int Engine::display_menu()
{
    std::cout << "\n\n\n\n\n\n\n\n\n\n\n\n-=[ Tic Tac Toe ]=-" << std::endl;
    std::cout << "\n1. Single Player" << std::endl;
    std::cout << "2. Two players" << std::endl;
    std::cout << "3. About" << std::endl;
    std::cout << "4. Exit\n" << std::endl;
    std::cout << "Your selection: ";
}

//////////////////////////////////////////////////////////////////////

void Engine::play()
{
    int choice = 0;
    
    do {
        display_menu();
        std::cin >> choice;
        // ensure the user entered an integer value
        if (is_invalid_input()) 
            choice = 0;
        
        
        switch (choice) {
        
            case SINGLEPLAYER:
                board.init();
            break;
            
            case TWO_PLAYERS:
                board.init();
                
                // keep looping until theres no available moves or a player wins
                while (!game_over()) {
                    int loc; // location
                    std::cout << "Player " << symbol << " move: ";
                    std::cin >> loc;    // set the symbol at that location
                    
                    if (is_invalid_input()) // ensure the user entered an integer value
                        loc = 0;
         
                    if (board.update(loc, symbol)){ // returns true if the users space is availible
                        if (game_over()) break; // check to see if player won or ran out of moves
                        swap_turns(); // if not change the symbol
                    } else {
                        chill();            // else let the user know they entered an invalid location
                        board.display();    // redisplay the board
                    }
                }
             break;
             
             case ABOUT:
                std::cout << "\n\t\tCreated by: Homer Simpson" << std::endl;
                chill();
             break;
             
             case EXIT:
                std::cout << "\n\n\t\tThank you for playing!\n" << std::endl;
             break;
             
             default:
                std::cout << "[!!] Inavalid Selection!!" << std::endl;
        }
        
    } while (choice != EXIT);
}

///////////////////////////////////////////////////////////////////////

bool Engine::game_over()
{
    if (board.out_of_moves() || player_won()) {
        if (board.out_of_moves()){
            std::cout << "\t\tNO WINNER!!!" << std::endl;
            chill();
        }
        return true;
    }
    return false;
}

///////////////////////////////////////////////////////////////////////////

void Engine::swap_turns()
{
    symbol = (symbol == 'X') ? 'O' : 'X';
}

///////////////////////////////////////////////////////////////////////////

bool Engine::player_won()
{
    for (int i = 0; i < DIMENSIONS; ++i) {
        for (int j = 0; j < DIMENSIONS; ++j) {
            // check to see if we have a winner
            if(((board.tiles[0] == symbol) && (board.tiles[1] == symbol) && (board.tiles[2] == symbol)) || // horizontally
               ((board.tiles[0][j] == symbol) && (board.tiles[1][j] == symbol) && (board.tiles[2][j] == symbol)) || // vertically
               ((board.tiles[0][0] == symbol) && (board.tiles[1][1] == symbol) && (board.tiles[2][2] == symbol)) || // diagnol checks
               ((board.tiles[2][0] == symbol) && (board.tiles[1][1] == symbol) && (board.tiles[0][2] == symbol))) { 
                std::cout << "\t\t\t" << symbol << " has won!!!" << std::endl;
                chill();
                return true;
            } 
        }
    }
    
    return false;
}

//////////////////////////////////////////////////////////////////////////////

misc.h
#ifndef MISC_H
#define MISC_H

// equivalent to system(PAUSE) -- it prompts the user to press enter before continuing
void chill();
// if the user entered invalid input it resets the stream
bool is_invalid_input();

#endif // MISC_H


misc.cpp
#include "misc.h"

#include <cstdio>
#include <iostream>

/////////////////////////////////////////////////////////////////////////////////

void chill()
{
    std::cout << "\n\nPress ENTER to continue...\n" << std::endl;
    std::cin.ignore();
    std::fflush(stdin);
    std::cin.get();
}

////////////////////////////////////////////////////////////////////////////////

bool is_invalid_input()
{
    if (std::cin.fail()) {
        std::cin.clear();               // clear the error flag
        std::cin.ignore(256, '\n');     // ignore until newline
        return true;
    }
    
    return false;
}


///////////////////////////////////////////////////////////////////////////////////


board.h
#ifndef TIC_TAC_TOE_BOARD_H
#define TIC_TAC_TOE_BOARD_H

#define CONVERT_TO_CHAR(x) (x + 48)
#define DIMENSIONS 3
#define MIN_TILE 1
#define MAX_TILE 9

#include <vector>

class Board {
    private:
        
        // returns true if the user entered a valid location; otherwise notifies user and returns false
        bool is_valid_location(int);
        // displays the current state of the game
        
    public:
        void init();
        
        // takes the location of the place marker and inserts the correct symbol; calls display() after
        bool update(int, char);
        // sets a place marker by displaying a 3 x 3 matrix numbered from 1 - 9
        void clear();
        void display();
        bool out_of_moves(); // returns true when there are no available locations
        
        char tiles[DIMENSIONS][DIMENSIONS]; // 3 x 3 matrix
};

extern Board board;

#endif // TIC_TAC_TOE_BOARD_H


board.cpp
#include "board.h"

#include <iostream>

Board board;

///////////////////////////////////////////////////////////////

void Board::init()
{
    clear();
    display();
}

///////////////////////////////////////////////////////////////

bool Board::update(int location, char symbol)
{
    if (!is_valid_location(location)) 
        return false;
        
    // iterate through the matrix and check if the location is empty
    for (int i = 0; i < DIMENSIONS; ++i) {
        for (int j = 0; j < DIMENSIONS; ++j) {
            // if the place holder is still then insert the symbol and display 
            if (tiles[j] == CONVERT_TO_CHAR(location)) {
                tiles[j] = symbol;
                display();
                return true;
            }
        }
    }
    
    std::cout << "[!!] Invalid placement!\n" << std::endl;
    return false;
}

///////////////////////////////////////////////////////////////

bool Board::is_valid_location(int location)
{
    if ((location < MIN_TILE) || (location > MAX_TILE)) {
        std::cout << "[!!] Invalid placement!\n" << std::endl;
        return false;
    } 
    
    return true;
}

/////////////////////////////////////////////////////////////////

bool Board::out_of_moves()
{
    int place_marker = CONVERT_TO_CHAR(1);
    for (int i = 0; i < DIMENSIONS; ++i) {
        for (int j = 0; j < DIMENSIONS; ++j) {
            if (tiles[j] == place_marker) return false;
            ++place_marker;
        }
    }
    
    return true;
}

//////////////////////////////////////////////////////////////

void Board::display()
{
    // create some blank space
    std::cout << "\n\n\n\n\n\n\n\n\n\n\n" << std:: endl;
    // iterate through every row
    for(int i = 0; i < DIMENSIONS; ++i) {
        // draw the horizontal lines and center the board
        if (i > 0) std::cout << "\t\t\t___________" << std::endl; 
        // iterate through every column
        for (int j = 0; j < DIMENSIONS; ++j) {
            // center the board
            if (j == 0)
                std::cout << "\t\t\t";
            // display the tiles and the horizontal lines
            std::cout << tiles[j] << " | ";
        }
        // align the board
        std::cout << std::endl;
    }
    
    // more blank spaces
    std::cout << "\n\n\n\n" << std::endl;
}

////////////////////////////////////////////////////////////////

void Board::clear()
{
    int place_marker = CONVERT_TO_CHAR(1); // ascii code for 1
    // iterate through every row
    for (int i = 0; i < DIMENSIONS; ++i) {    
        // iterate through every column    
        for (int j = 0; j < DIMENSIONS; ++j) {
            tiles[j] = place_marker;
            ++place_marker;
        }
    }
}

//////////////////////////////////////////////////////////////////


My atrocious mess...
+1 Alan Johnson · June 23, 2015
Fixed it up for you, let me know if its not as you want it.

http://pastebin.com/fh2qbVQX
0 Reynaldo Gunawan · June 23, 2015
Hahaha right, i put everything in german. Keep forgetting. Wow thanks a lot. I'll translate them real quick
0 Alan Johnson · June 23, 2015
Can you send me or post here your full assignment brief in english? I'll fix this up for you.
0 Reynaldo Gunawan · June 23, 2015
/* 
 * File:   ticTacToe.c
 * Author: reynaldogunawan
 *
 * Created on June 13, 2015, 1:24 PM
 */

#include
#include
#include

/*
 * 
 */
int i;
int j;
char* playBoard[3][3] = {0};
int turn;

int input();
void displayBoard();
void move();
void emptyBoard();
bool gameOver();
int end = 0;

int main() {

    printf("***** Willkommen in Tic Tac Toe! ****** \n");
    printf("\tSpieler X spielt erstmal.\t \n");
    
    
    emptyBoard();
    displayBoard();
    
    while(!gameOver()){
        int koordinates = input();
        move(koordinates);
        displayBoard();

    }
    
    printf("\nNeu Starten? \n(Drücken Sie eine beliebige Zahl, um erneut zu spielen. Sonst 0, um das Spiel zu beenden.) \n");
    scanf(" %d", &end);
    
    (end == 0) ? printf("Danke für Spielen\n") : main();

    return (EXIT_SUCCESS);
}



int input(){
    printf("Koordinaten eingeben (Zeile Spalte): ");
    
    int pos[2];
    
    fpurge(stdin);
    
    scanf(" %d %d", &pos[0], &pos[1]);
    pos[0]--;       //damit die eingegebenen Koordinaten die Positionen im Array entsprechen
    pos[1]--;
    
    if((pos[0] < 0 || pos[0] > 2) || (pos[1] < 0 || pos[1] > 2)){
        printf("Koordinaten unbekannt. Versuchen Sie noch einmal... \n\n");
        input();
    }
    else if(playBoard[pos[0]][pos[1]] != ' '){
        printf("Koordinaten ist schon besetz. \n\n");
        input();
    }
    
    return pos[2];
}

void displayBoard(){
    for(i = 0; i < 42; i++){
        printf("-");
    }
    printf("\n");
    printf("\t\t    1  2  3 \n");
    for(i = 0; i < 3; i++){
        printf("\t\t");
        printf("%d  ", i+1);
        for(j = 0; j < 3; j++){
            printf("", playBoard[i][j]);
            if(j == 2){
                printf("\n");
            }
        }
    }
    for(i = 0; i < 42; i++){
        printf("-");
    }
    printf("\n");
    return;
}

void emptyBoard(){
    for(i = 0; i < 3; i++){
        for(j = 0; j < 3; j++){
            playBoard[i][j] = ' ';
        }  
    }    
}

void move(){
    int pos[2];
    playBoard[pos[0]][pos[1]] = turn ? 'O' : 'X';
    turn = !turn;
}

bool gameOver(){
    
    bool result = false;
    
    /* Vertical */
    if((playBoard[0][0] == 'O' && playBoard[1][0] == 'O' && playBoard[2][0] == 'O') || 
            (playBoard[0][1] == 'O' && playBoard[1][1] == 'O' && playBoard[2][1] == 'O') || 
            (playBoard[0][2] == 'O' && playBoard[1][2] == 'O' && playBoard[2][2] == 'O')){
        printf("Spieler 'O' hat gewonnen! \n");
        result = true;
    }
    if((playBoard[0][0] == 'X' && playBoard[1][0] == 'X' && playBoard[2][0] == 'X') || 
            (playBoard[0][1] == 'X' && playBoard[1][1] == 'X' && playBoard[2][1] == 'X') || 
            (playBoard[0][2] == 'X' && playBoard[1][2] == 'X' && playBoard[2][2] == 'X')){
        printf("Spieler 'X' hat gewonnen! \n");
        result = true;
    }
    /* Horizontal */
    if((playBoard[0][0] == 'O' && playBoard[0][1] == 'O' && playBoard[0][2] == 'O') || 
            (playBoard[1][0] == 'O' && playBoard[1][1] == 'O' && playBoard[1][2] == 'O') || 
            (playBoard[2][0] == 'O' && playBoard[2][1] == 'O' && playBoard[2][2] == 'O')){
        printf("Spieler 'O' hat gewonnen! \n");
        result = true;
    }
    if((playBoard[0][0] == 'X' && playBoard[0][1] == 'X' && playBoard[0][2] == 'X') || 
            (playBoard[1][0] == 'X' && playBoard[1][1] == 'X' && playBoard[1][2] == 'X') || 
            (playBoard[2][0] == 'X' && playBoard[2][1] == 'X' && playBoard[2][2] == 'X')){
        printf("Spieler 'X' hat gewonnen! \n");
        result = true;
    }
    /* Diagonal */
    if((playBoard[0][0] == 'O' && playBoard[1][1] == 'O' && playBoard[2][2] == 'O') ||
            (playBoard[0][2] == 'O' && playBoard[1][1] == 'O' && playBoard[2][0] == 'O')){
        printf("Spieler 'O' hat gewonnen! \n");
        result = true;
    }
    if((playBoard[0][0] == 'X' && playBoard[1][1] == 'X' && playBoard[2][2] == 'X') ||
            (playBoard[0][2] == 'X' && playBoard[1][1] == 'X' && playBoard[2][0] == 'X')){
        printf("Spieler 'X' hat gewonnen! \n");
        result = true;
    }
    /* Board is full */
    if((playBoard[0][0] != ' ' && playBoard[1][0] != ' ' && playBoard[2][0] != 'O') && 
            (playBoard[0][1] != ' ' && playBoard[1][1] != ' ' && playBoard[2][1] != ' ') && 
            (playBoard[0][2] != ' ' && playBoard[1][2] != ' ' && playBoard[2][2] != ' ')){
        printf("Das Spiel ist unentschieden! \n");
        result = true;
    }
    return result;
    
    
}




So, i finally made this for my college assignment, based on @AlanJohnson 's code. Freaking due dates are making me under pressured and uncreative. I made it so that it matches my assignment, so some changes were made. 

There is however still a problem and that is when I made a mistake by the input. The next input and the turn of the player seem to be messed up, and the conditions are, somehow, invalid. If someone can spot the mistake that i made, it would be really cool, cause I spent hours trying to fix it, but meh, i suck.

Thank you in advance

C

107,034 followers
About

One of the most popular languages of all time.

Links
Moderators
Bucky Roberts Administrator