Hi there,
I am trying to do an exercise from a C++ book. It goes:
Develop a program that will move the knight around an empty chessboard. The chessboard is represented by an 8-by-8 two-dimensional array board[][] . Each of the squares is initialized to 0. We describe each of the 8 possible moves in terms of both thir horizontal and vertical components. For example, a move of type 0, as shown in the attachment, consists of moving 2 squares horizontally to the right and one square vertically upward. Move 2 consists of moving 1 square horizontally to the left and 2 squares vertically upward. Horizontal moves to the left and vertical moves upward are indicated with negative numbers. The 8 moves may be described by 2 one-dimensional arrays horizontal[] and vertical[] as follow:

horizontal[0] = 2
horizontal[1] = 1
horizontal[2] = -1
horizontal[3] = -2
horizontal[4] = -2
horizontal[5] = -1
horizontal[6] = 1
horizontal[7] = 2
vertical[0] = -1
vertical[1] = -2
vertical[2] = -2
vertical[3] = -1
vertical[4] = 1
vertical[5] = 2
vertical[6] = 2
vertical[7] = 1

Let the variable currentRow and currentColumn indicate the row and column of the knight's current position. TO make a move of type moveNumber where moveNumber is between 0 and 7 your program uses the statements

currentRow += vertical[ moveNumber ] ;	
currentColumn += horizontal[ moveNumber ] ;

Keep a counter that varies from 1 to 64. Record the latest count in each square the knight moves to. Remember to test each potential move to see if the knight has already visited that square and of course test every potential move to make sure that the knight doesn't lend off the chessboard. Now write a program that moves the knight around the chessboard. RUn the program. How many moves did the knight make?

Now, here is what I came up so far:

header file knight.h:

class Knight
{
public:

const static int rows = 8 ;		//static variables so they can be
const static int columns = 8 ;	//accessed from knight_main.cpp

const static int verRow = 8 ; 	//indicates the vertical moves
const static int horRow = 8 ;	//and the horizontal ones


Knight( const int chessboard[][ columns ], const int horizontalMoves[], const int verticalMoves[] ) ;	//constructor to initialize the arrays

void knightsMove( ) ; 	//the knight's move

void display() ;//print out the knight's moves on the chessboard

private:

int board[ rows ][ columns ] ;	//2 dimensions array to store the chessboard

int horizontal[ horRow ] ; //1 dimension array holding the horizontal moves

int vertical[ verRow ] ; //1 dimension array holding the vertical moves


} ;

knight.cpp file:

#include<iostream>
using namespace std ;

#include "knight.h"
const char NL = '\n';


//constructor
Knight::Knight( const int chessboard[][ columns ], const int horizontalMoves[], const int verticalMoves[] )

{

//copying chessboard[][] into board[][]
for( int boardRows = 0 ; boardRows <= rows ; boardRows++ )

	{

		for( int boardColumns = 0 ; boardColumns <= columns ; boardColumns++ )

			{

			   board[ boardRows ][ boardColumns ] = chessboard[ boardRows ][ boardColumns ] ;

			}


	}

//copying horizontalMoves[] and verticalMoves[] into respectively horizontal[] and vertical[]

for( int verticalRow = 0 ; verticalRow <= verRow ; verticalRow++ )

	{

		vertical[ verticalRow ] = verticalMoves[ verticalRow ] ;

	}

for( int horizontalRow = 0 ; horizontalRow <= horRow ; horizontalRow++ )

	{

		horizontal[ horizontalRow ] = horizontalMoves[ horizontalRow ] ;

	}

}	//constructor ends

//knight's move starts here

void Knight::knightsMove()
{

int moveNumber ; //represents a knight's move

int counter = 0 ;  //counts the moves up to 64

int currentRow = 0 ; //determine the current position of the

int currentColumn = 0 ;//knight in the chessboard

cout << " The current position of the knight is: " << endl ;

//nested loop to make sure we attempt 64 moves
for( int chessboard_rows = 0; chessboard_rows <= 7; chessboard_rows++ )

    {
		for ( int chessboard_colums = 0, moveNumber = 0; chessboard_colums <= 7, moveNumber <= 7; chessboard_rows++, moveNumber++ )

		{

			currentRow += vertical[ moveNumber ] ;	// row value

			currentColumn += horizontal[ moveNumber ] ; //column value

			cout << " ( " << currentRow << " , " << currentColumn << " ) " ;


			if( ( ( ( currentRow <= 7 ) && ( currentRow >= 0 ) ) && ( ( currentColumn <= 7) && ( currentColumn >= 0) ) ) && ( board[ vertical[ moveNumber ] ][ horizontal[ moveNumber ] ] = 0 ) )

			  {

				  counter++ ;

				  board[ vertical[ moveNumber ] ][ horizontal[ moveNumber ] ]++ ; //to keep track of the squares the knight has visited

			  }

			  else

			  {

			  currentRow -= vertical[ moveNumber ] ;//brings the values of currentRow and

	  		  currentColumn -= horizontal[ moveNumber ] ;//currentColumn back to what they were before the move

			  vertical[ moveNumber ]++ ;	//jump to

			  horizontal[ moveNumber ]++ ;	//next move

			  chessboard_rows-- ;	//decrease the counters so we

			  moveNumber-- ;	//don't count the invalid moves

			  }

		}//inner loop



    }//outer loop


}//end of knightsMove()

//print off the array containing the chessboard

void Knight::display()

{
	int chessboard_rows ;

for(  chessboard_rows = 0 ; chessboard_rows <= rows ; chessboard_rows++ )

	{

		cout << " row " << chessboard_rows << endl ;

	}

		for ( int chessboard_colums = 0 ; chessboard_colums <= columns ; chessboard_colums++ )

			{

			cout << board[ chessboard_rows ][ chessboard_colums ] << NL ;

			}

} //end of display()

knight_main.cpp

#include <iostream>
using namespace std ;
#include "knight.h"

int main()

{

int chessboard[ Knight::rows ][ Knight::columns ] = { 0 } ;

int horizontalMoves[ Knight::horRow ] = { 2, 1, -1, -2, -2, -1, 1, 2 } ;

int verticalMoves[ Knight::verRow ] = { -1, -2, -2, -1, 1, 2, 2, 1 } ;

Knight move( chessboard, horizontalMoves, verticalMoves ) ; //pass the arrays to the constructor so that it can copy it into board[ rows ][ columns ], horizontal[ moveH ] and vertical[ moveV ]

move.knightsMove() ;	//move the knight

move.display() ;

return 0 ;

}

Basically this is what I was trying to do in my program:
In knight_main.cpp I created 3 arrays that I then passed to the constructor which copies them into the arrays declared in knight.h. The function knightsMove() with the nested loop simulates 64 moves (and here the first problems because for whatever reason when I attempt

currentRow += vertical[ moveNumber ] ;

) the first element of the array has a rubbish value. Then I check that the knight doesn't land off the chessboard, that I don't make more than 7 moves and that I don't move in a square that the knight has already visited and if the conditions are met I increase the counter to keep track of the moves and I record which square the knight has visited with

board[ vertical[ moveNumber ] ][ horizontal[ moveNumber ] ]++ ;

. If the conditions are false then with the following

currentRow -= vertical[ moveNumber ] ;//brings the values of currentRow and

	  		  currentColumn -= horizontal[ moveNumber ] ;//currentColumn back to what they were before the move

			  vertical[ moveNumber ]++ ;	//jump to

			  horizontal[ moveNumber ]++ ;	//next move

			  chessboard_rows-- ;	//decrease the counters so we

			  moveNumber--

I go back to the previous values of currentRow and currentCOlumns and try the following move.

Any suggestion about what I have done wrong?
Sorry for the long post.

I couldn't find your problem but as a suggestion i'd say you should focus more on how you structure your program so that you eliminate much of the overhead by breaking the design in more pieces of functionality.The code becomes more readable and more easy to modify that way.I wrote an example of a little better approach though it is not complete and it is only meant to hint you on how to build a more complex concept out of bits of functionality.

#include <iostream>
#include <string>

class Position  {  
   int Posx,Posy;   //actual coordinates
   std::string charPos;   
                    //all this so you can adress a piece or a cell by a letter and a number
                    //instead of plain x y coordinates
public:
   Position () : Posx(0), Posy(0) {}
   Position (int n,std::string chr) : charPos("abcdefgh"), Posx(n), Posy(0) {
      std::string::size_type indx=charPos.find("chr",0);
      if (indx!=std::string::npos)  {   
          Posy=indx;   //if letter in range return a number
        }
      else if (indx>8)  std::cout << "Invalid X position\n";         
         
      else std::cout << "Invalid Y position\n";
    }

   ~Position () {}

   int X() const {
      return Posx;
    }
   int Y() const {
      return Posy;
    }
 };
         
class ChessPiece  {
public:
   virtual void Move();
   ~ChessPiece () {}
 };

class Knight : public ChessPiece { 
   Position p;   
public:
   Knight () {}
   Knight (Position p_) : p(p_) {}
   ~Knight () {}

   void Move ();
 };


class Bishop : public ChessPiece {
   Position p;   
public:
   Bishop () {} 
   Bishop (Position p_) : p(p_) {}
   ~Bishop () {}

   void Move ();
 };

             //the rest of the pieces

class Cell  {
   bool Color; //black or white
   ChessPiece Piece;     //each cell can hold one piece
   Position Pos;     //position
   bool NotEmpty;  
public:
   Cell () : NotEmpty(0) {}
   Cell (int XPos_,std::string YPos_,std::string Color_,ChessPiece Piece_=ChessPiece()) //default chesspiece if none
      : Piece(Piece_), Pos(Position(XPos_,YPos_)) , NotEmpty(1)  {

         if (Color_=="black")  Color=0;
         else if (Color_=="white") Color=1;
         else std::cout << "Invalid color state\n";
     }

   ~Cell () {}

   bool HoldsPiece()  {
      return NotEmpty;    //returns whether there is a piece on the cell
    }

   ChessPiece GetPiece() const {  //get the piece of a cell
      return Piece;
    }

   void SetPiece (const ChessPiece& piece)  {  //assign a piece to a cell
      Piece=piece; 
    }

   std::string GetColor ()  {
      if (Color)  return "white";
      else return "black";
    }
 };  


class Grid  {
   Cell Cells[8][8];
   //or you could use vector but that is a bit more tricky
   //std::vector<std::vector<Cell> > Cells;

   Knight BlackKnight[2];
   Bishop WhiteBishop[2];

   //and so on

public:
   Grid () {  //creating an empty grid 
      std::string CharPos[]={"a","b","c","d","e","f","g","h"};
      std::string Color[]={"black","white"};
      bool FlipColor=0;
                                
      for (int x=0;x<8;x++)  {
         for (int y=0;y<8;y++)  {
            Cells[x][y]=Cell (x,CharPos[y],Color[FlipColor]);
            !FlipColor; //flip the color of the next cell
          }
       }
    }
   ~Grid () {}

   Cell GetCell (const Position& p)  {  //returns a cell
      return Cells[p.X()][p.Y()];    //example: GetCell (Position(5,"g")); 
    }

   ChessPiece GetCellPiece (const Position& p)  {  //returns a cell's piece
      ChessPiece Piece=Cells[p.X()][p.Y()].GetPiece();
      return Piece;
    }
 };

Edited 5 Years Ago by caut_baia: n/a

caut_baia thanks for posting the code. I had a look at that but there are things that I haven't encountered as yet, like the : operator (what is it?), destructors (I believe the tilde ~ signify the presence of a destructor) and virtual functions, so I am slightly hesitant to base my program on that particular code.
I am sure there are probably dozen different ways to solve this problem and I am sure that my code might not be the best in terms of performance but I think I should stick more to the way the exercise is asking me to do things. Having said that I am absolutely happy to improve the code when it gets to the point that it become unusable if that's the case for mine, but, as I said, I would like to use the suggestions that the outline of the exercise is giving.
Is there any way that I can improve my code (as in could you help me to identify what's wrong with it...it doesn't seem to work for whatever reason...)
thanks

When declaring a class's constructor you can initialize class variables without entering the constructor's body ex:

struct A  { //struct is the equivalent of a class with data declared public by default
   int var;
   A (int var_) : var(var_) {} //initialization of var equivalent to
   A (int var_)  {
      var=var_;
    }
 };

Also the destructor is a special method called when an object goes out of scope and performs clean up of the intialized variables.Whenever you declare a class there is an implicit default constructor declared automatically if you haven't declared one yourself but by having a user defined constructor like the one mentioned above forces you to implement a default constructor and destructor

class B {}; //constructor and destructor are implictly generated by the compiler

struct A {  //here you provide your own by having A(int x) {} declared
   A () {} //default constructor
   A (int x) {} //user defined 
   ~A () {}  /destructor
 };

There is also a copy constructor and an assignment operator declared implictly if you don't define any.They provide copy operations for objects of the same type and are declared like this:

struct A  {
   int x;
   A (const A& a)  { //passing by const reference is faster for larger structures
                     //then passing by value
      x=a.x; //performs a copy of the x variable
    }
 };
A a; 
A b(a); //b is a copy of a - calls A's copy constructor

As for the problem you're having my untrained eye can't spot the specific error your getting which i assume it's a logical one and not a syntax error.Maybe someone else can help in that regard.Good luck

This article has been dead for over six months. Start a new discussion instead.