As part of a homework, I created the following Puzzle Class and it works. The thing is, it only work if i put the class in q2.cxx, the main code file. If I place them in three seperate files, I get hell load of problem. Can anyone please look at the code with fresh set of eyes and point out where I messed up? Thanks a lot!!

Also, I'm attaching the files so anyone can download and try them out, along with the test input file.

/*******************************************************************************
*   File        : Puzzle.h                                                    *
*   Author      : Siddharth Dahiya                                            *
*   Date        : 03/01/2010                                                  *
*   Description : The purpose of this program is to read alphabets from an    *
*                 input file and generate a 5x5 puzzle from them. Then it     *
*                 should follow in sturctions provided in the input to move   *
*                 the empty cell around the puzzle to give a final            *
*                 configuration. The end of instructions is marked with a '0' *
*                 character. Also, it takes into consideration, invalid       *
*                 movement insturctions, and in such case, it skips the       *
*                 current puzzle, writes an error message, and carries on with*
*                 the next puzzle until 'Z' the designated 'EOF' character is *
*                 reached. Once completed, it lets the user know its 'Done'.  *
*   Compilation                                                               *
*   Instruction : Run "g++ -ansi -pedantic q2.cxx Puzzle.cxx -o q2"           *
*   Execution                                                                 *
*   Instruction : Run "q2" and follow instructions on screen, if any.         *
*   Special Note: Insure that the input file<input.txt> is in correct format  *
*                 and in the same folder as the executable.                   *
*   REMARKS     : The program utilises the 'file reading' code provided in the*
*                 homework instructions authored by Dr. Sukmoon Chang         *
*******************************************************************************/

#ifndef PUZZLE_H
#define PUZZLE_H

#include <fstream>

class Puzzle
{
    //Private variables
private:
    int BlankTile[2]; //Int array containing position of the blank tile
    char PuzzleBoard[5][5]; //Multi-dimensional char array holding the puzzle

    //Public Methods/Functions
public:
    //Constructor
    Puzzle(ifstream *from);
    //Puzzle destructor
    ~Puzzle(void);
    //This function is used to move the blank tile on the board
    int PlayPuzzle(char step);
    //This method checks if the PuzzleBoard is empty or not
    int CheckContinuity();
    //Overloaded '<<' operator sends a formated Puzzle Board to the output
    friend ostream &operator<<(ostream &os, const Puzzle p);
};

#endif

/*******************************************************************************
*   File        : Puzzle.cxx                                                  *
*   Author      : Siddharth Dahiya                                            *
*   Date        : 03/01/2010                                                  *
*   Description : The purpose of this program is to read alphabets from an    *
*                 input file and generate a 5x5 puzzle from them. Then it     *
*                 should follow in sturctions provided in the input to move   *
*                 the empty cell around the puzzle to give a final            *
*                 configuration. The end of instructions is marked with a '0' *
*                 character. Also, it takes into consideration, invalid       *
*                 movement insturctions, and in such case, it skips the       *
*                 current puzzle, writes an error message, and carries on with*
*                 the next puzzle until 'Z' the designated 'EOF' character is *
*                 reached. Once completed, it lets the user know its 'Done'.  *
*   Compilation                                                               *
*   Instruction : Run "g++ -ansi -pedantic q2.cxx Puzzle.cxx -o q2"           *
*   Execution                                                                 *
*   Instruction : Run "q2" and follow instructions on screen, if any.         *
*   Special Note: Insure that the input file<input.txt> is in correct format  *
*                 and in the same folder as the executable. 'Z' will terminate*
*                 the input immediately regardless of its position as long as *
*                 it is not in the instructions.
*   REMARKS     : The program utilises the 'file reading' code provided in the*
*                 homework instructions authored by Dr. Sukmoon Chang         *
*******************************************************************************/

#include "Puzzle.h"

//Contructor
Puzzle::Puzzle(ifstream *from)
{
    BlankTile[0] = -1;
    BlankTile[1] = -1;

    int continuity = -1;

    //Loop to populate the puzzle board.
    for(int i = 0; i < 5; i++)
    {
        for(int j = 0; j < 5; j++)
        {
            PuzzleBoard[i][j] = '\0';
            *from >> PuzzleBoard[i][j];
            //If the current character is '_', save its position
            if(PuzzleBoard[i][j] == '_')
            {
                BlankTile[0] = i;
                BlankTile[1] = j;
            } else if (PuzzleBoard[i][j] == 'Z'){
                continuity = 0; //If the current character is 'Z' i.e. the end of
                input file, abort the current PuzzleBoard.
                    goto ABORT;
            }
        }
    }
ABORT:
    PuzzleBoard[4][5] = '\0'; //Terminate the array with a null character

    //For safety and ease of use, mark the first two characters of the 
    //character array as null in case there was an abort during the 
    //constructor loops.
    if(continuity == 0){
        PuzzleBoard[0][0] = PuzzleBoard[0][1] = '\0';
    }
}


//Puzzle destructor
Puzzle::~Puzzle(void)
{
    //The destructor is empty since no pointers are being utilised.
}

int Puzzle::CheckContinuity(){
    if(PuzzleBoard[0][0] == '\0' && PuzzleBoard[0][1] == '\0')
        return 0;
    else
        return 1;
}

//This function is used to move the blank tile on the board
int Puzzle::PlayPuzzle(char step)
{
    int valid = -1;
    //Move the tiles is valid instructions are provided, else exit the loop
    if(step == 'A' || step == 'B' || step == 'R' || step == 'L')
    {
        char temp = '\0';
        switch(step)
        {
        case 'A':
            if((BlankTile[0] - 1) >= 0)
            {
                temp = PuzzleBoard[BlankTile[0] - 1][BlankTile[1]];
                PuzzleBoard[BlankTile[0] - 1][BlankTile[1]] = '_';
                PuzzleBoard[BlankTile[0]][BlankTile[1]] = temp;
                BlankTile[0]--;
                temp = '\0';
                valid = 0;
            } else
                valid = -1;
            break;
        case 'B':
            if((BlankTile[0] + 1) < 5)
            {
                temp = PuzzleBoard[BlankTile[0] + 1][BlankTile[1]];
                PuzzleBoard[BlankTile[0] + 1][BlankTile[1]] = '_';
                PuzzleBoard[BlankTile[0]][BlankTile[1]] = temp;
                BlankTile[0]++;
                temp = '\0';
                valid = 0;
            } else
                valid = -1;
            break;
        case 'R':
            if((BlankTile[1] + 1) < 5)
            {
                temp = PuzzleBoard[BlankTile[0]][BlankTile[1] + 1];
                PuzzleBoard[BlankTile[0]][BlankTile[1] + 1] = '_';
                PuzzleBoard[BlankTile[0]][BlankTile[1]] = temp;
                BlankTile[1]++;
                temp = '\0';
                valid = 0;
            } else
                valid = -1;
            break;
        case 'L':
            if((BlankTile[1] - 1) >= 0)
            {
                temp = PuzzleBoard[BlankTile[0]][BlankTile[1] - 1];
                PuzzleBoard[BlankTile[0]][BlankTile[1] - 1] = '_';
                PuzzleBoard[BlankTile[0]][BlankTile[1]] = temp;
                BlankTile[1]--;
                temp = '\0';
                valid = 0;
            } else
                valid = -1;
            break;
        }
    }

    return valid;
}

//Overloaded '<<' operator sends a formated Puzzle Board to the output
ostream &operator<<(ostream &os, Puzzle p)
{
    for(int i = 0; i < 5; i++)
    {
        os << "    " << p.PuzzleBoard[i][0] << ' ' << p.PuzzleBoard[i][1];
        os << ' ' << p.PuzzleBoard[i][2] << ' ' << p.PuzzleBoard[i][3];
        os << ' ' << p.PuzzleBoard[i][4] << endl;
    }
    return os;
}

/*******************************************************************************
 *   File        : q2.cxx                                                      *
 *   Author      : Siddharth Dahiya                                            *
 *   Date        : 03/01/2010                                                  *
 *   Description : The purpose of this program is to read alphabets from an    *
 *                 input file and generate a 5x5 puzzle from them. Then it     *
 *                 should follow in sturctions provided in the input to move   *
 *                 the empty cell around the puzzle to give a final            *
 *                 configuration. The end of instructions is marked with a '0' *
 *                 character. Also, it takes into consideration, invalid       *
 *                 movement insturctions, and in such case, it skips the       *
 *                 current puzzle, writes an error message, and carries on with*
 *                 the next puzzle until 'Z' the designated 'EOF' character is *
 *                 reached. Once completed, it lets the user know its 'Done'.  *
 *   Compilation                                                               *
 *   Instruction : Run "g++ -ansi -pedantic q2.cxx Puzzle.cxx -o q2"           *
 *   Execution                                                                 *
 *   Instruction : Run "q2" and follow instructions on screen, if any.         *
 *   Special Note: Insure that the input file<input.txt> is in correct format  *
 *                 and in the same folder as the executable.                   *
 *   REMARKS     : The program utilises the 'file reading' code provided in the*
 *                 homework instructions authored by Dr. Sukmoon Chang         *
 *******************************************************************************/

#include "Puzzle.h"

#include <fstream>
#include <iostream>

using namespace std;

int main()
{
    int PuzzleCount = 1, continuity = 1;
    // open the file whose name is "filename" for reading
    char *name = "input.txt";

    ifstream from(name); // open the file

    if (!from) // open failed
    {
        cerr << "cannot open input file " << name << endl;
        exit(1);
    }

    //Loop till all the puzzles have been read
    while( continuity != 0)
    {
        Puzzle *p = new Puzzle(&from);
        
        if((continuity = (*p).CheckContinuity()) == 0)
        {
            //If the puzzles have ended, destroy the new Puzzle Pointer
            //And break the loop.
            delete p;
            break;
        }else
        {
            cout << "Puzzle #" << PuzzleCount++ << endl;
            char step;
            int StepValidity = -1;

            //Loop between the steps
            do{
                //Read the movement instruction
                from >> step;
                
                //Verify this is not the end of instructions
                if(step == '0'){
                    StepValidity = -1;
                    break;
                }
                StepValidity = (*p).PlayPuzzle(step);
            }while(StepValidity == 0);

            if(StepValidity == -1 && step != '0')
            {
                cout << "Invalid moves provided. No final configuration possible" << endl;
                //This is a necassary loop to make sure that any movement instruction
                //for the current puzzle are not mistaken for alphabets for the next
                //puzzle. This loops runs till the instructions end.
                while(step != '0')
                    from >> step;
            }
            else if(StepValidity == -1 && step == '0')
                cout << *p;
        }

        delete p;
    }

    cout << "Done";

    from.close();
    return 0;
}

Recommended Answers

All 4 Replies

There are two main problems:
1) >> friend ostream &operator<<(ostream &os, const Puzzle& p);
The last parameter should be passed by reference, not by value. Also change that in the *.cpp implementation file.

2) in Puzzle.h you need to declare the namespaces, such as

#include <fstream>
using std::fstream;
using std::ifstream;
using std::ofstream;
using std::ostream;

or just add std::fstream before each occurence of the c++ class.

commented: If there is an answer, Ancient Dragon has it!! +2

AD, you always have the answer to the questions, AND THEY ARE RIGHT!! Thanks so much, it compiled. But now a new issue has showed up, in Puzzle.cpp, the overloaded operator<< is declared as a friend in the .h file but the .cpp is saying it is not able to access the private variables. Any suggestions?

Also, AD, can you please tell me why it did not work the way, why it needs to have the namespace declared, it might be of use to people like me.

AD, you always have the answer to the questions, AND THEY ARE RIGHT!! Thanks so much, it compiled. But now a new issue has showed up, in Puzzle.cpp, the overloaded operator<< is declared as a friend in the .h file but the .cpp is saying it is not able to access the private variables. Any suggestions?

Yes -- you have to make that parameter const reference too in the *.cpp implementation file.

Also, AD, can you please tell me why it did not work the way, why it needs to have the namespace declared, it might be of use to people like me.

namepsaces always have to be declared. There are at least three ways to do that, which you probably already know.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.