Thread: Phantom redefinition

  1. #1
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    937

    Phantom redefinition

    My compiler keeps giving me this error:
    Code:
    multiple definitions of 'cellspace::positions::CENTER'
    first defined here
    For all of the objects defined in namespace 'position'. Then, "first defined here" does not specify or point to any line of code or linking. Is there a compiler issue? Here's the file where namespace 'position' is. I'm using Bloodshed Dev C++.
    Code:
    #ifndef CELL_H
    
    #define CELL_H
    
    #include "coordinates.h"
    
    #include <sstream>//for print()
    
    #include <string>//also for print()
    
    using namespace std;
    
    namespace cellspace
    
    {
    
    enum POS_TYPE {POS_TYPE_ZERO, CENTER, CORNER, OTHER};
    
    class cell : public coordinates::coord
    
    {
    
          private:
    
                  bool occupied;
    
                  char symbol;// usually X or O or universal skip character '-'
    
          public:
    
                 cell();
    
                 cell(int x_in, int y_in);
    
                 cell(int x_in, int y_in, char symbol_in);
    
                 ~cell(){}
    
                 const bool is_occupied();
    
                 const char get_symbol();
    
                 cell operator = (cell other);
    
                 cell operator = (coord other);
    
                 bool operator == (POS_TYPE other);
    
                 bool operator == (coord other);
    
                 const coord opposite(bool apply_to_this);
    
                 cell assign(int x_in, int y_in, char symbol_in);
    
                 cell assign(char symbol_in);
    
                 string print();
    
                 void wipe();
    
    };
    
    
    
    namespace positions
    
    {
    
              coordinates::coord CENTER(1,1);
    
              coordinates::coord TOP_LEFT(0,2);
    
              coordinates::coord TOP_RIGHT(2,2);
    
              coordinates::coord TOP_CENTER(1,2);
    
              coordinates::coord BOTTOM_LEFT(0,0);
    
              coordinates::coord BOTTOM_RIGHT(2,0);
    
              coordinates::coord BOTTOM_CENTER(1,0);
    
              coordinates::coord LEFT_CENTER(0,1);
    
              coordinates::coord RIGHT_CENTER(2,1); 
    
    }
    
    }
    
    #endif
    "If you tell the truth, you don't have to remember anything"
    -Mark Twain

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You need to extern the definitions in the header file. Otherwise, every source file that includes "cell.h" will contain an instance of those objects - making the linking unhappy.
    Code:
       extern coordinates::coord CENTER;
    gg

  3. #3
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    937
    I'm getting the same error, and the compiler isn't even mentioning the extern when specifying the redefinition. And I swear that they're not defined in any other file. Plus, there's the #ifndef preventing file redefinition.
    "If you tell the truth, you don't have to remember anything"
    -Mark Twain

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    "Inclusion guards" only prevent circular inclusion when compiling a single source file.

    Post your code and compiler/linker errors.

    gg

  5. #5
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    937
    I see what you mean now, but I don't yet see how I'm going to fix it. Here's the whole code and errors.

    *edit* I know I put the externs in the wrong place. Discard that and related errors *edit*
    Errors:
    Code:
    In file included from board.h:4,
                     from main.cpp:3:
    cell.h:36: warning: `CENTER' initialized and declared `extern' cell.h:37: warning: `TOP_LEFT' initialized and declared `extern'
    cell.h:38: warning: `TOP_RIGHT' initialized and declared `extern'
    cell.h:39: warning: `TOP_CENTER' initialized and declared `extern'
    cell.h:40: warning: `BOTTOM_LEFT' initialized and declared `extern'
    cell.h:41: warning: `BOTTOM_RIGHT' initialized and declared `extern' cell.h:42: warning: `BOTTOM_CENTER' initialized and declared `extern'
    cell.h:43: warning: `LEFT_CENTER' initialized and declared `extern'
    cell.h:44: warning: `RIGHT_CENTER' initialized and declared `extern' g++.exe board.o cell.o coordinates.o main.o record.o  -o "ttt.exe" -L"C:/DEV-CPP/lib"   cell.o(.bss+0x0):cell.cpp: multiple definition of `cellspace::positions::CENTER'
    board.o(.bss+0x0):board.cpp: first defined here
    cell.o(.bss+0xc):cell.cpp: multiple definition of `cellspace::positions::TOP_LEFT'
    board.o(.bss+0xc):board.cpp: first defined here
    cell.o(.bss+0x18):cell.cpp: multiple definition of `cellspace::positions::TOP_RIGHT'
    board.o(.bss+0x18):board.cpp: first defined here
    cell.o(.bss+0x24):cell.cpp: multiple definition of `cellspace::positions::TOP_CENTER'
    board.o(.bss+0x24):board.cpp: first defined here
    cell.o(.bss+0x30):cell.cpp: multiple definition of `cellspace::positions::BOTTOM_LEFT'
    board.o(.bss+0x30):board.cpp: first defined here
    cell.o(.bss+0x3c):cell.cpp: multiple definition of `cellspace::positions::BOTTOM_RIGHT'
    board.o(.bss+0x3c):board.cpp: first defined here
    cell.o(.bss+0x48):cell.cpp: multiple definition of `cellspace::positions::BOTTOM_CENTER'
    board.o(.bss+0x48):board.cpp: first defined here
    cell.o(.bss+0x54):cell.cpp: multiple definition of `cellspace::positions::LEFT_CENTER'
    board.o(.bss+0x54):board.cpp: first defined here
    cell.o(.bss+0x60):cell.cpp: multiple definition of `cellspace::positions::RIGHT_CENTER'
    board.o(.bss+0x60):board.cpp: first defined here
    main.o(.bss+0x0):main.cpp: multiple definition of `cellspace::positions::CENTER'
    board.o(.bss+0x0):board.cpp: first defined here
    main.o(.bss+0xc):main.cpp: multiple definition of `cellspace::positions::TOP_LEFT'
    board.o(.bss+0xc):board.cpp: first defined here
    main.o(.bss+0x18):main.cpp: multiple definition of `cellspace::positions::TOP_RIGHT'
    board.o(.bss+0x18):board.cpp: first defined here
    main.o(.bss+0x24):main.cpp: multiple definition of `cellspace::positions::TOP_CENTER'
    board.o(.bss+0x24):board.cpp: first defined here
    main.o(.bss+0x30):main.cpp: multiple definition of `cellspace::positions::BOTTOM_LEFT'
    board.o(.bss+0x30):board.cpp: first defined here
    main.o(.bss+0x3c):main.cpp: multiple definition of `cellspace::positions::BOTTOM_RIGHT' board.o(.bss+0x3c):board.cpp: first defined here
    main.o(.bss+0x48):main.cpp: multiple definition of `cellspace::positions::BOTTOM_CENTER'
    board.o(.bss+0x48):board.cpp: first defined here
    main.o(.bss+0x54):main.cpp: multiple definition of `cellspace::positions::LEFT_CENTER'
    board.o(.bss+0x54):board.cpp: first defined here
    main.o(.bss+0x60):main.cpp: multiple definition of `cellspace::positions::RIGHT_CENTER'
    board.o(.bss+0x60):board.cpp: first defined here
    collect2: ld returned 1 exit status
    coordinates.h
    Code:
    #ifndef COORDINATES_H
    #define COORDINATES_H
    #include <vector>
    
    namespace coordinates
    {
     class coord
     {
           public:
                  coord();
                  coord(int x_in, int y_in);
                  ~coord();
                  const int getx();
                  const int gety();
                  const bool is_defined();
                  bool operator > (coord other);
                  bool operator > (int other);
                  bool operator < (coord other);
                  bool operator < (int other);
                  bool operator == (coord other);
                  bool operator == (int other);
                  bool operator >= (coord other);
                  bool operator >= (int other);
                  bool operator <= (coord other);
                  bool operator <= (int other);
                  coord operator = (coord other);
                  operator int ();
                  coord assign(int x_in, int y_in);
                  void clear();
           protected:
                   int x;
                   int y;
                   bool defined;
      };
    
      namespace exception
      {
               class undefined{};
      }
    }
    #endif
    coordinates.cpp
    Code:
    #include "coordinates.h"
    using namespace coordinates;
    
    coord::coord() {defined = false;}
    coord::coord(int x_in, int y_in) {x = x_in; y = y_in; defined = true;}
    coord::~coord(){}
    const int coord::getx() {
          if(!defined) throw exception::undefined();
          return x;
          }
    const int coord::gety() {
          if(!defined) throw exception::undefined();
          return y;
          }
    const bool coord::is_defined() {return defined;}
    bool coord::operator > (coord other) {
         if(!defined || !other.is_defined()) throw exception::undefined();
         return ( (other.getx() + other.gety()) <= (x + y)) ? false : true;}
    bool coord::operator > (int other) {
         return (other <= (x + y)) ? false : true;}
    bool coord::operator < (coord other) {
         return ( (other.getx() + other.gety()) >= (x + y)) ? false : true;}
    bool coord::operator < (int other) {
         return (other <= (x + y)) ? false : true;}
    bool coord::operator == (coord other) {
         return (other.getx() == x && other.gety() == y) ? true : false;}
    bool coord::operator == (int other) {
         return (other == (x + y)) ? true : false;}
    bool coord::operator >= (coord other) {
         return ( (other.getx() + other.gety()) > (x + y)) ? false : true;}
    bool coord::operator >= (int other) {
         return (other > (x + y)) ? false : true;}
    bool coord::operator <= (coord other) {
         return ( (other.getx() + other.gety()) < (x + y)) ? false : true;}
    bool coord::operator <= (int other) {
         return (other < (x + y)) ? false : true;}
    coord coord::operator = (coord other)
    {
          if(!other.is_defined()) throw exception::undefined();
          else {
               x = other.getx();
               y = other.gety();
               if(!defined) defined  = true;
               }
    return *this;
    }
    coord coord::assign(int x_in, int y_in)
    {
          coord val(x,y);
          x = x_in;
          y = y_in;
          if(!defined) defined = true;
          return val;
    }
    void coord::clear () {defined = false;}
    coord::operator int () {
                    if(!defined) throw exception::undefined();
                    return x + y;
    }
    cell.h:
    Code:
    #ifndef CELL_H
    #define CELL_H
    #include "coordinates.h"
    #include <sstream>//for print()
    #include <string>//also for print()
    using namespace std;
    namespace cellspace
    {
    enum POS_TYPE {POS_TYPE_ZERO, CENTER, CORNER, OTHER};
    class cell : public coordinates::coord
    {
          private:
                  bool occupied;
                  char symbol;// usually X or O or universal skip character '-'
          public:
                 cell();
                 cell(int x_in, int y_in);
                 cell(int x_in, int y_in, char symbol_in);
                 ~cell(){}
                 const bool is_occupied();
                 const char get_symbol();
                 cell operator = (cell other);
                 cell operator = (coord other);
                 bool operator == (POS_TYPE other);
                 bool operator == (coord other);
                 const coord opposite(bool apply_to_this);
                 cell assign(int x_in, int y_in, char symbol_in);
                 cell assign(char symbol_in);
                 string print();
                 void wipe();
    };
    
    namespace positions
    {
              extern coordinates::coord CENTER(1,1);
              extern coordinates::coord TOP_LEFT(0,2);
              extern coordinates::coord TOP_RIGHT(2,2);
              extern coordinates::coord TOP_CENTER(1,2);
              extern coordinates::coord BOTTOM_LEFT(0,0);
              extern coordinates::coord BOTTOM_RIGHT(2,0);
              extern coordinates::coord BOTTOM_CENTER(1,0);
              extern coordinates::coord LEFT_CENTER(0,1);
              extern coordinates::coord RIGHT_CENTER(2,1); 
    }
    }
    #endif
    cell.cpp:
    Code:
    #include "cell.h"
    using namespace std;
    using namespace coordinates;
    using namespace cellspace;
    
    cell::cell()
    {
     symbol = '\0';
     defined = false;
     occupied = false;
    }
    
    cell::cell(int x_in, int y_in)
    {
     x = x_in;
     y = y_in;
     defined = true;
     symbol = '\0';
     occupied = false;
    }
    
    cell::cell(int x_in, int y_in, char symbol_in)
    {
     x = x_in;
     y = y_in;
     defined = true;
     symbol = symbol_in;
     occupied = (symbol_in == '\0') ? false : true;
    }
    
    const bool cell::is_occupied()
    {
         if(!defined) throw coordinates::exception::undefined();
         return occupied;
    }
    
    const char cell::get_symbol()
    {
          if(!occupied) return '\0';
          return symbol;
    }
    
    const coord cell::opposite(bool apply_to_this = true)
    {
     coord val;
     if(apply_to_this == false)
          val.assign( (-(x) + 2), (-(y) + 2) );
     else {
          if(!defined) throw coordinates::exception::undefined();
          x = -(x) + 2;
          y = -(y) + 2;
          }
     return val;
    }
    
    cell cell::operator = (coord other)
    {
         if(!other.is_defined()) throw coordinates::exception::undefined();
         else {
              x = other.getx();
              y = other.gety();
              if(!defined) defined = true;
              }
         return *this;
    }
    
    cell cell::operator = (cell other)
    {
           if(!other.is_defined()) throw coordinates::exception::undefined();
         else {
              if(other.is_occupied())
              {
               occupied = true;
               symbol = other.get_symbol();
               x = other.getx();
               y = other.gety();
               if(!defined) defined = true;
              }
              else
              {
               occupied = false;
               symbol = '\0';
               x = other.getx();
               y = other.gety();
               if(!defined) defined = true;
               }
              }
         return *this;
    }
    
    cell cell::assign(int x_in, int y_in, char symbol_in = '\0')
    {
        coord::assign(x_in,y_in);
        occupied = (symbol_in == '\0') ?  false : true;
        symbol = symbol_in;
        return *this;
    }
    
    cell cell::assign(char symbol_in)
    {
        if(!defined) throw coordinates::exception::undefined();
        occupied = (symbol_in == '\0') ?  false : true;
        symbol = symbol_in;
        return *this;
    }
    
    string cell::print()
    {
           ostringstream strm;
           strm << '(' << x << ',' << y << ')';
           return strm.str();
    }
    
    bool cell::operator == (POS_TYPE other)
    {
         switch(other)
         {
          case CENTER: return (x == y == 1);
          case CORNER: return ( ((int)*this == 2 || (int)*this == 4 || (int)*this == 0) && !(x == y == 1) );
          case OTHER: return ( (int)*this == 1 || (int)*this == 3 );
          default: break;
         }
         return false;
    }
    
    bool cell::operator == (coord other)
    {
         if(!defined) throw coordinates::exception::undefined();
         return (coord)(*this) == other;
    }
    
    void cell::wipe()
    {
         symbol = '\0';
         occupied = false;
         clear();
    }
    board.h:
    Code:
    #ifndef BOARD_H
    #define BOARD_H
    #include "cell.h"
    //#include "record.h"
    #include <vector>
    using namespace cellspace;
    using namespace coordinates;
    
    namespace boardspace
    {
    class record;//prototype
    class is_player;//prototype of a predicate
    enum MOVE_MESSAGE {MOVE_MESSAGE_ZERO, SUCCESS, UNKNOWN_ERROR, NO_VACANCY, OUT_OF_BOUNDS}; //TODO: Add as needed.
    enum PLAYER {PLAYER_ZERO, PLAYER1, PLAYER2};
    enum WIN_STATE {WIN_STATE_ZERO, P1_WIN, P2_WIN, KATZ};
    /*char* MessageString(MOVE_MESSAGE msg);*/
    class board
    {
          cell cells[3][3];
          cell win_set[3];
          vector <record> history;
          char P1_symbol;
          char P2_symbol;
          cell * access(coord pos);//for class to read/write itself in reg (x,y) plane style 
          cell * access(int x_in, int y_in);
          PLAYER switch_player(PLAYER& p);//for internal use
          bool won;
          bool empty;
          int curr_turn;
          public:
                 board();
                 board(char P1_in, char P2_in);
                 void initialize(char P1_in, char P2_in);
                 ~board(); 
                 //cell get_cell(coord pos);
                 cell get_cell(int x_in, int y_in);
                 cell get_cell(coord pos);
                 char get_P1() {return P1_symbol;}
                 char get_P2() {return P2_symbol;}
                 bool is_empty() {return empty;}
                 bool get_won() {return won;}
                 int get_curr_turn() {return curr_turn;}
                 cell* get_win_set(int index);
                 vector <record>::iterator get_history_begin() {return history.begin();}
                 vector <record>::iterator get_history_end() {return history.end();}
                 bool is_history_empty() {return history.empty();}
                 record get_entry(int index);
                 vector <record> get_history() {return history;}
                 board operator = (board other);
                 MOVE_MESSAGE move(PLAYER which_player, int x_in, int x_out, board* out, MOVE_MESSAGE* msg_out);
                 MOVE_MESSAGE move(PLAYER which_player, coord pos, board* out, MOVE_MESSAGE* msg_out);
                 WIN_STATE CheckForWin(bool just_check, WIN_STATE* msg_out, vector <coord> skips);
                 vector <record> FindHotSpots();
                 void wipe();
    };//class board
    
    class record
    {
          PLAYER player;
          cell * spot;
          int move_num;
      public:
          record(int move_num_in, cell* spot_in, PLAYER player_in);
          cell* get_spot() {return spot;}
          int get_move_num() {return move_num;}
          PLAYER get_player() {return player;}
          record operator = (record other); 
    };//class record
    
    class is_player //a predicate
    {
          PLAYER p;
          public:
                 is_player() { p = PLAYER_ZERO; }
                 is_player(PLAYER p_in) { p = p_in; }
                 ~is_player() {}
                 bool operator () (record rec) { return (rec.get_player() == p); }
    };//class is_player
    
    namespace exception
    {
              class OUT_OF_BOUNDS {};
    }//namespace exception
    }//namespace boardspace
    #endif
    board.cpp:
    Code:
    #include "coordinates.h"
    #include "cell.h"
    #include "board.h"
    #include <algorithm>
    #include <iostream> 
    using namespace std;
    using namespace cellspace;
    using namespace boardspace;
    
    board::board(char P1_in, char P2_in)
    {
     initialize(P1_in, P2_in);
    }
    
    board::board()
    {
     initialize('X','O');
    }
    
    void board::initialize(char P1_in = 'X', char P2_in = '0')
    {
     curr_turn = 1;
     empty = true;
     won = false;
     P1_symbol = P1_in;
     P2_symbol = P2_in; 
     for(int a = 0; a < 3; a++)
     {
             for(int b = 0; b < 3; b++) cells[a][b].coord::assign(b, -(a) + 2);
     }
    }
    board::~board()
    {
     /*delete [] cells;*/ //caused TREMENDOUS SLOWDOWNS in destruction of all instances of board.
     //because, I suppose, "delete" can be used only with data that was allocated dynamically,
     //or even only via "new". 
    }
    cell board::get_cell(int x_in, int y_in)
    {
     if(x_in > 2 || x_in < 0 || y_in > 2 || y_in < 0) { throw boardspace::exception::OUT_OF_BOUNDS(); }
     return cells[-(y_in) + 2][x_in];
    }
    
    cell board::get_cell(coord pos)
    {
     if(pos.getx() > 2 || pos.getx() < 0 || pos.gety() > 2 || pos.gety() < 0) { throw boardspace::exception::OUT_OF_BOUNDS(); }
     return cells[-(pos.gety()) + 2][pos.getx()];
    } 
    
    inline cell * board::access(int x_in, int y_in)//returns a reference pointing to that part of the board array.
    {
     return &cells[-(y_in) + 2][x_in];
    }
    
    inline cell * board::access(coord pos)//returns a reference pointing to that part of the board array.
    {
     return &cells[-(pos.gety()) + 2][pos.getx()];
    }
    
    board board::operator = (board other)
    {
          empty = other.is_empty();
          P1_symbol = other.get_P1();
          P2_symbol = other.get_P2();
          for(int a = 0; a < 3; a++)
          {
                  for(int b = 0; b < 3; b++) *access(a,b) = other.get_cell(a,b);
          }
          if(other.is_history_empty()) history.clear();
          else history = other.get_history();
          return *this;
    }
    
    MOVE_MESSAGE board::move(PLAYER which_player, int x_in, int y_in, board* out, MOVE_MESSAGE* msg_out)
    {
          MOVE_MESSAGE ret_val = SUCCESS;
          board * temp_board;
          record* temp_rec = NULL;
          if(x_in > 2 || y_in > 2 || x_in < 0 || y_in < 0 || which_player < PLAYER_ZERO) ret_val = OUT_OF_BOUNDS;
          else if(get_cell(x_in,y_in).is_occupied()) ret_val = NO_VACANCY;
          else if(out == NULL)//standard with output
          {
           if(empty) empty = false;
           access(x_in, y_in)->assign((which_player == PLAYER1) ? P1_symbol : (which_player == PLAYER2) ? P2_symbol : '\0');
           temp_rec = new record(curr_turn, access(x_in,y_in), which_player);
          }
          else//standard without output
          {
           temp_board = new board;
           *temp_board = *this;
           temp_board->move(which_player, x_in, y_in, NULL, NULL);
           *out = *temp_board;
           delete temp_board;
          }//end if else-if(s)
          if(msg_out != NULL) *msg_out = ret_val;
          if(temp_rec != NULL)
          {
           history.push_back(*temp_rec);
           curr_turn++;
           delete temp_rec;
          }
          return ret_val;
    }
    
    MOVE_MESSAGE board::move(PLAYER which_player, coord pos, board* out, MOVE_MESSAGE* msg_out)
    {
          MOVE_MESSAGE ret_val = SUCCESS;
          board * temp_board;
          record* temp_rec = NULL;
          if(pos.getx() > 2 || pos.gety() > 2 || pos.getx() < 0 || pos.gety() < 0 || which_player < PLAYER_ZERO) ret_val = OUT_OF_BOUNDS;
          else if(get_cell(pos).is_occupied()) ret_val = NO_VACANCY;
          else if(out == NULL)//standard with output
          {
           if(empty) empty = false;
           access(pos)->assign((which_player == PLAYER1) ? P1_symbol : (which_player == PLAYER2) ? P2_symbol : '\0');
           temp_rec = new record(curr_turn, access(pos), which_player);
          }
          else//standard without output
          {
           temp_board = new board;
           *temp_board = *this;
           temp_board->move(which_player, pos, NULL, NULL);
           *out = *temp_board;
           delete temp_board;
          }//end if else-if(s)
          if(msg_out != NULL) *msg_out = ret_val;
          if(temp_rec != NULL)
          {
           history.push_back(*temp_rec);
           curr_turn++;
           delete temp_rec;
          }
          return ret_val;
    }
    
    cell* board::get_win_set(int index)
    {
          if(!won || index < 0 || index > 2) return NULL;
          return &win_set[index];
    }
    
    record board::get_entry(int index)
    {
     if(index < 1) throw boardspace::exception::OUT_OF_BOUNDS();
     return history[index - 1];
    }
    
    WIN_STATE  board::CheckForWin(bool just_check = false, WIN_STATE* msg_out = NULL,vector <coord> skips = vector <coord> ())//This is a poorly designed function
    {
            WIN_STATE win_msg = WIN_STATE_ZERO;
            int out_loop, in_loop, a = 0, b = 2;
            bool a_skip = false;
            //won = true;//DEBUG
            if(won)
            { 
              win_msg = (win_set[0].get_symbol() == P1_symbol) ? P1_WIN : P2_WIN;
              goto CHECKFORWIN_END;
            }
            won = true;
         
            for(out_loop = 0; out_loop < 3; out_loop++)//Checks rows
            {
             if((access(0,out_loop)->is_occupied()) && (access(0,out_loop)->get_symbol() == access(1,out_loop)->get_symbol()) && (access(0,out_loop)->get_symbol() == access(2,out_loop)->get_symbol()) && (access(1,out_loop)->get_symbol() == access(2,out_loop)->get_symbol()))
             {
              //BEGIN SKIP CODE
              if(!skips.empty())
              {
               for(int q = 0; q < skips.size(); q++)
               {
                if((*access(0,out_loop) == skips[q]) || (*access(1,out_loop) == skips[q]) || (*access(2,out_loop) == skips[q]))
                {
                 a_skip = true;
                 break;
                }
               }
              }//if(!skips.empty())
              if(a_skip) 
              {
               a_skip = false;
               continue;
              }//END SKIP CODE
              if(!just_check)
              {
               for(in_loop = 0; in_loop < 3; in_loop++) win_set[in_loop] = *access(in_loop,out_loop);
              }
              else won = false;
              win_msg = (access(1,out_loop)->get_symbol() == P1_symbol) ? P1_WIN : P2_WIN;
              goto CHECKFORWIN_END;
             }
            }
            for(out_loop = 0; out_loop < 3; out_loop++)//Checks columns
            {
             if((access(out_loop,0)->is_occupied()) && (access(out_loop,0)->get_symbol() == access(out_loop,1)->get_symbol()) && (access(out_loop,0)->get_symbol() == access(out_loop,0)->get_symbol()) && (access(out_loop,1)->get_symbol() == access(out_loop,2)->get_symbol()))
             {
              //BEGIN SKIP CODE
              if(!skips.empty())
              {
               for(int q = 0; q < skips.size(); q++)
               {
                if((*access(out_loop,0) == skips[q]) || (*access(out_loop,1) == skips[q]) || (*access(out_loop,2) == skips[q]))
                {
                 a_skip = true;
                 break;
                }
               }
              }//if(!skips.empty())
              if(a_skip) 
              {
               a_skip = false;
               continue;
              }//END SKIP CODE
              if(!just_check)
              {
               for(in_loop = 0; in_loop < 3; in_loop++) win_set[in_loop] = *access(out_loop,in_loop);
              }
              else won = false;
              win_msg = (access(out_loop,1)->get_symbol() == P1_symbol) ? P1_WIN : P2_WIN;
              goto CHECKFORWIN_END;
             }
            }//Checks '\' diagonal
            if((access(1,1)->is_occupied()) && (access(0,2)->get_symbol() == access(1,1)->get_symbol()) && (access(0,2)->get_symbol() == access(2,0)->get_symbol()) && (access(1,1)->get_symbol() == access(2,0)->get_symbol()))
            {
             //BEGIN SKIP CODE
              if(!skips.empty())
              {
               for(int q = 0; q < skips.size(); q++)
               {
                if((*access(1,1) == skips[q]) || (*access(0,2) == skips[q]) || (*access(2,0) == skips[q]))
                {
                 a_skip = true;
                 break;
                }
               }
              }//if(!skips.empty())
              if(a_skip) 
              {
               a_skip = false;
              }//END SKIP CODE
              else
              {
               if(!just_check)
               {
                win_set[0] = *access(0,2);
                win_set[1] = *access(1,1);
                win_set[2] = *access(2,0);
               }
               else won = false;
               win_msg = (access(1,1)->get_symbol() == P1_symbol) ? P1_WIN : P2_WIN;
               goto CHECKFORWIN_END;
              }
            }//Checks '/' diagonal
            else if((access(1,1)->is_occupied()) && (access(0,0)->get_symbol() == access(1,1)->get_symbol()) && (access(0,0)->get_symbol() == access(2,2)->get_symbol()) && (access(1,1)->get_symbol() == access(2,2)->get_symbol()))
            {
             //BEGIN SKIP CODE
              if(!skips.empty())
              {
               for(int q = 0; q < skips.size(); q++)
               {
                if((*access(1,1) == skips[q]) || (*access(0,0) == skips[q]) || (*access(2,2) == skips[q]))
                {
                 a_skip = true;
                 break;
                }
               }
              }//if(!skips.empty())
              if(a_skip) 
              {
               a_skip = false;
              }//END SKIP CODE
              else
              {
               if(!just_check)
                {
                 win_set[0] = *access(0,0);
                 win_set[1] = *access(1,1);
                 win_set[2] = *access(2,2);
                }
               else won = false;
               win_msg = (access(1,1)->get_symbol() == P1_symbol) ? P1_WIN : P2_WIN;
               goto CHECKFORWIN_END;
              }
            }//end '/' diagonal check
            win_msg = KATZ;
            for(out_loop = 0; out_loop < 3; out_loop++)// Checks for katz game
            {
             for(in_loop = 0; in_loop < 3; in_loop++)
             {
               //BEGIN SKIP CODE
              if(!skips.empty())
              {
               for(int q = 0; q < skips.size(); q++)
               {
                if(*access(in_loop,out_loop) == skips[q])
                {
                 a_skip = true;
                 continue;
                }
               }
              }
              if(a_skip)
              {
               a_skip = false;
               continue;
              }//END SKIP CODE
              if(!access(in_loop,out_loop)->is_occupied())
              {
               win_msg = WIN_STATE_ZERO;
               break;
              }
             }
            }//for loop checking for katz
    
    CHECKFORWIN_END://AHH GOTO REFERENCE! AUUGHHH!!!!
            if(win_msg == WIN_STATE_ZERO) won = false;
            if(msg_out != NULL) *msg_out = win_msg;
            return win_msg;
    }
    
    void board::wipe()
    {
         int x;
         for(x = 0; x < 3; x++)
         {
          for(int y = 0; y < 3; y++) access(x,y)->wipe();
         }
         for(x = 0; x < 3; x++) win_set[x].wipe();
         history.clear();
         won = false;
         empty = true;
         curr_turn = 0;
         P1_symbol = P2_symbol = '\0';
    }
    
    record::record(int move_num_in, cell* spot_in, PLAYER player_in)
    {
     move_num = move_num_in;
     spot = spot_in;
     player = player_in;
    }
    
    record record::operator = (record other)
    {
     move_num = other.get_move_num();
     spot = other.get_spot();
     player = other.get_player();
     return *this;
    }
    
    vector <record> board::FindHotSpots()
    {
     vector <record> hot_spots;
     record* temp_rec = NULL;
     PLAYER the_player = PLAYER1;
     board checker;
     WIN_STATE win_msg;
     MOVE_MESSAGE move_msg;
     for(int loop1 = 0; loop1 < 3; loop1++)
     {
      for(int loop2 = 0; loop2 < 3; loop2++)
      {
       for(int loop3 = 0; loop3 < 2; loop3++)
       {
        if(move(the_player,loop1,loop2,&checker,&move_msg) == SUCCESS)
        {
         checker.CheckForWin(true,&win_msg,vector<coord>());
         switch(win_msg)
         {
          case P1_WIN: {
               temp_rec = new record(-1,access(loop1,loop2),PLAYER1);
               hot_spots.push_back(*temp_rec);
               delete temp_rec;
               temp_rec = NULL;
               break;
               }
          case P2_WIN:  {
               temp_rec = new record(-1,access(loop1,loop2),PLAYER2);
               hot_spots.push_back(*temp_rec);
               delete temp_rec;
               temp_rec = NULL;
               break;
               }
          case KATZ: {
               //cout << "KATZ game coming?\n the_player = " << the_player << endl;
               break;
               }
          }//switch
         }//if
         else if(move_msg == NO_VACANCY) break;
        switch_player(the_player);
        }//loop3
       }//loop2
      }//loop1
     return hot_spots;
    }
    
    PLAYER board::switch_player(PLAYER& p)
    {
     PLAYER ret = ((p == PLAYER1) ? PLAYER2 : (p == PLAYER_ZERO) ? PLAYER_ZERO : PLAYER1);
     p = ret;
     return ret;
    }
    main.cpp:
    Code:
    #include <cstdlib>
    #include <iostream>
    #include "board.h"
    #include "cell.h"
    #include "coordinates.h"
    
    using namespace std;
    using namespace cellspace;
    using namespace boardspace;
    
    char* MessageString(MOVE_MESSAGE msg);
    void proto_test();
    int vital_checks(PLAYER p, board& the_board);//returns 0 if NO move is made, nonzero otherwise
    int auto_move(PLAYER p, board& the_board);
    PLAYER other_player(PLAYER p);
    void print_board(board& ttt);
    void print_record(record in);//to be used in STL algorithms
    
    int main(int argc, char *argv[])
    {
        try {
            proto_test();
        }//try
        catch(coordinates::exception::undefined)
        { cout << "\"UNDEFINED\" exception" << endl; }
        catch(boardspace::exception::OUT_OF_BOUNDS)
        { cout << "\"OUT_OF_BOUNDS\" exception" << endl; }
        catch(...)
        { cout << "UNKNOWN EXCEPTION" << endl; }
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    
    char* MessageString(MOVE_MESSAGE msg)
    {
          switch(msg)
          {
           case SUCCESS: return "SUCCESS";
           case UNKNOWN_ERROR: return "UNKNOWN ERROR";
           case NO_VACANCY: return "NO VACANCY";
           case OUT_OF_BOUNDS: return "OUT OF BOUNDS";
           default: return NULL;
          }
          return NULL;
    }
    
    void proto_test()
    {
        vector <record> hot_spots;
        board ttt;
        board checker;
        MOVE_MESSAGE move_msg;
        WIN_STATE win_msg;
        int inx = 0,iny = 0;
        PLAYER p = PLAYER2;
        char resp;
    
        while(cin >> inx >> iny)
        {
            if(inx == 33)
            {
             cout << "Log" << endl;
             for_each(ttt.get_history_begin(),ttt.get_history_end(),print_record);
             continue;
            }  
            p = other_player(p);
            if(vital_checks(p,ttt))//if the checks made a move
            {
             cout << "The vital checker overrided your move" << endl;
             print_board(ttt);
             if(ttt.CheckForWin(false,&win_msg,vector<coord>()) != WIN_STATE_ZERO)
             {
              switch(win_msg)
              {
               case P1_WIN: { cout << "Player 1 won." << endl; break; }
               case P2_WIN: { cout << "Player 2 won." << endl; break; }
               case KATZ: { cout << "Katz game: draw." << endl; break; }
               default: { cout << "ERROR: Unexpected CheckForWin() result -- win_msg = " << win_msg << endl; break; }
              }
              ttt.wipe();
              checker.wipe();
              ttt.initialize('X','O');
             }
             continue;
            }
            ttt.move(p,inx,iny,NULL,&move_msg);//apply move on ttt to itself
            print_board(ttt);
            cout << MessageString(move_msg) << endl;
           if(ttt.CheckForWin(false,&win_msg,vector<coord>()) != WIN_STATE_ZERO)
           {
            switch(win_msg)
            {
             case P1_WIN: { cout << "Player 1 won." << endl; break; }
             case P2_WIN: { cout << "Player 2 won." << endl; break; }
             case KATZ: { cout << "Katz game: draw." << endl; break; }
             default: { cout << "ERROR: Unexpected CheckForWin() result -- win_msg = " << win_msg << endl; break; }
            }
            ttt.wipe();
            checker.wipe();
            ttt.initialize('X','O');
           }
        }//while(cin)
    }//void proto_function()
    
    void print_record(record in)
    {
         cout << "Move number: " << in.get_move_num() << '\n'
              << "Player: " << in.get_player() << '\n'
              << "Cell coord: " << in.get_spot()->print()/**/ << endl;
    }
    
    void print_board(board& ttt)
    {
         cout << ttt.get_cell(0,2).print() << ttt.get_cell(0,2).get_symbol() << ' ' << ttt.get_cell(1,2).print() << ttt.get_cell(1,2).get_symbol() << ' ' << ttt.get_cell(2,2).print() << ttt.get_cell(2,2).get_symbol() << '\n'
              << ttt.get_cell(0,1).print() << ttt.get_cell(0,1).get_symbol() << ' ' << ttt.get_cell(1,1).print() << ttt.get_cell(1,1).get_symbol() << ' ' << ttt.get_cell(2,1).print() << ttt.get_cell(2,1).get_symbol() << '\n'
              << ttt.get_cell(0,0).print() << ttt.get_cell(0,0).get_symbol() << ' ' << ttt.get_cell(1,0).print() << ttt.get_cell(1,0).get_symbol() << ' ' << ttt.get_cell(2,0).print() << ttt.get_cell(2,0).get_symbol() << endl;
    }   
    
    PLAYER other_player(PLAYER p)
    {
           return ((p == PLAYER1) ? PLAYER2 : (p == PLAYER_ZERO) ? PLAYER_ZERO : PLAYER1);
    }
    
    int vital_checks(PLAYER p, board& the_board)
    {
        vector<record> finds(the_board.FindHotSpots());
        vector<record>::iterator iter;
        if(finds.empty()) return 0;
        else
        {
            iter = find_if(finds.begin(),finds.end(),is_player(p));
            if(iter != finds.end())
            {
             the_board.move(p,iter->get_spot()->getx(),iter->get_spot()->gety(),NULL,NULL);
             return 1;
            }
            else
            {
             iter = find_if(finds.begin(),finds.end(),is_player(other_player(p)));
             if(iter != finds.end())
             {
              the_board.move(p,iter->get_spot()->getx(),iter->get_spot()->gety(),NULL,NULL);
              return 1;
             }
            }
        }
        return 0;     
    }
    
    int auto_move(PLAYER p, board& the_board)
    {
        MOVE_MESSAGE move_msg;
        if(vital_checks(p,the_board)) return 0;
        else
        {
          the_board.move(p,positions::CENTER,NULL,&move_msg);
          if(move_msg == SUCCESS) return 1;
        }
        //TODO: finish function!
        return 0;
    }
    Last edited by CodeMonkey; 06-12-2005 at 12:05 AM.

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> cell.h:36: warning: `CENTER' initialized and declared `extern'
    Meaning, you can't do both.

    In cell.h
    Code:
    namespace cellspace
    {
        namespace positions
        {
            extern coordinates::coord CENTER; // <-- no constructor parameters
        }
    }
    In cell.cpp
    Code:
    namespace cellspace
    {
        namespace positions
        {
            coordinates::coord CENTER(1,1);
        }
    }
    Anything you define within a namespace must be implemented within the same namespace.

    gg

  7. #7
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    937
    Ah. Fixed. Thank you, Codeplug.
    "If you tell the truth, you don't have to remember anything"
    -Mark Twain

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Errors including <windows.h>
    By jw232 in forum Windows Programming
    Replies: 4
    Last Post: 07-29-2008, 01:29 PM
  2. Quantum Random Bit Generator
    By shawnt in forum C++ Programming
    Replies: 62
    Last Post: 06-18-2008, 10:17 AM
  3. failure to import external C libraries in C++ project
    By nocturna_gr in forum C++ Programming
    Replies: 3
    Last Post: 12-02-2007, 03:49 PM
  4. Errors with including winsock 2 lib
    By gamingdl'er in forum C++ Programming
    Replies: 3
    Last Post: 12-05-2005, 08:13 PM
  5. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM