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;
}