-3

I am building a Tic Tac Toe game using MVC. The code is the following:

main.cpp:

#include "controller.cpp"

int main()
{
    Controller controller;
    controller.start_game();
}

controller.hpp:

#ifndef controllerTTT
#define controllerTTT

#include <iostream>
#include <array>
#include <string>
#include "common.hpp"
#include "model.cpp"
#include "view.cpp"
#define BOARD_SIZE 3

class Controller
{
    private:
        Model model;
        View view;
        bool player_interaction(Player);
        void single_game();
    public:
        void start_game();
};

#endif

controller.cpp:

#include "controller.hpp"

bool Controller::player_interaction(Player player){
    //code eliminated in order to not post 300 lines of code
}

void Controller::single_game(){
    //code eliminated in order to not post 300 lines of code
}

void Controller::start_game(){
    //code eliminated in order to not post 300 lines of code
}

model.hpp:

#ifndef modelTTT
#define modelTTT

#include <array>
#include "common.hpp"
#define BOARD_SIZE 3

class Model
{
    private:
        Player board[BOARD_SIZE][BOARD_SIZE];
    public:
        Model();
        void do_move(Move_input, Player);
        bool legal_move(Move_input);
        Outcome outcome();
        std::array<Player, BOARD_SIZE*BOARD_SIZE> get_board();
        void reset();
};

#endif

model.cpp:

#include "model.hpp"

Model::Model()
{
    for(int row=0; row<BOARD_SIZE; ++row)
    {
        for(int column=0; column<BOARD_SIZE; ++column)
        {
            this->board[row][column]=Player::none;
        }
    }
}

void Model::do_move(Move_input move_input , Player player)
{
    //code eliminated in order to not post 300 lines of code
}

bool Model::legal_move(Move_input move_input)
{
    //code eliminated in order to not post 300 lines of code
}

Outcome Model::outcome()
{
    //code eliminated in order to not post 300 lines of code
}

std::array<Player, BOARD_SIZE*BOARD_SIZE> Model::get_board(){
    //code eliminated in order to not post 300 lines of code
}

void Model::reset(){
    //code eliminated in order to not post 300 lines of code
}

view.hpp:

#ifndef viewTTT
#define viewTTT

#include <iostream>
#include <array>
#include <windows.h>
#include <string>
#include "common.hpp"
#define BOARD_SIZE 3

class View
{
    public:
        void output_board(std::array<Player, BOARD_SIZE*BOARD_SIZE>);
        void output_message(std::string);
        void output_outcome(Outcome);
        void wait(int miliseconds);
        void reset();
        Move_input get_move();
        std::string get_message();
};

#endif

view.cpp:

#include "view.hpp"

void View::output_board(std::array<Player, BOARD_SIZE*BOARD_SIZE> board){
    //code eliminated in order to not post 300 lines of code
}

void View::output_message(std::string message){
    //code eliminated in order to not post 300 lines of code
}

void View::output_outcome(Outcome outcome){
    //code eliminated in order to not post 300 lines of code
}

void View::wait(int miliseconds){
    //code eliminated in order to not post 300 lines of code
}

void View::reset(){
    //code eliminated in order to not post 300 lines of code
}

Move_input View::get_move(){
    //code eliminated in order to not post 300 lines of code
}

std::string View::get_message(){
    //code eliminated in order to not post 300 lines of code
}

common.hpp:

#pragma once

enum class Player
{
    none='-',
    player1='X',
    player2='O'
};

enum class Outcome
{
    none,
    win1='X',
    win2='O',
    draw
};

struct Move_input{
    int row,column;
};

And I get the following errors when compiled in Code::Blocks:

However, when I build it in a console with this command g++ -std=c++11 main.cpp it works just fine. So what is wrong with my code?

Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62

1 Answers1

3

The problem is two-fold:

  • First, as mentioned, you #include your source files instead of the header files.

  • Secondly your IDE (CodeBlocks) project already lists the source files (it must, or you would not get the errors).

Before explaining why the above two points work together to cause the problem you have, you need to learn how C++ is used to build applications. To make a C++ application you need to perform three steps:

  1. Edit one or more source files
  2. Compile the source files into object files
  3. Link the object files into a single executable file.

Even if you do not explicitly create object files (as with the g++ -std=c++11 main.cpp command) the object files are created implicitly by the g++ front-end program.

Now going back to the problems you have...

Because your CodeBlocks project lists all the source files, they will explicitly be built into object files, and then linked into the final executable program. The problem is that many of the symbols have already been defined in the single main.o object file because you #include source files. So (for example) the symbol Controller::single_game will be defined in both the object file main.o and the object file controller.o. That is not allowed.

You solve that by only including the header files, everywhere. The source code in the .cpp files will be built and linked by CodeBlocks for you.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621