I am doing an assignment where we have to make a sliding tile puzzle. The issue is that my print method for printing the game board is outputting the memory address of my 2D array instead of the actual values, but I have no idea how to fix this. I've tried looking up solutions and all I can find is stuff about vectors which I'm not allowed to use.
code from driver.cpp:
#include <iostream>
#include <conio.h>
#include "Specification.h"
#include <windows.h>    //For color in PrintBoard()
using namespace std;
// direction codes (part of the slideTile() interface)
#define SLIDE_UP        1       // pass to slideTile() to trigger UP movement
#define SLIDE_DOWN      2       // pass to slideTile() to trigger DOWN movement
#define SLIDE_LEFT      3       // pass to slideTile() to trigger LEFT movement
#define SLIDE_RIGHT     4       // pass to slideTile() to trigger RIGHT movement
int main() {
    int tempHeight;
    int tempWidth;
    // instantiate the class
    cout << "Please enter the height for the board: ";
    cin >> tempHeight;
    cout << "Please enter the width for the board: ";
    cin >> tempWidth;
    bool exit = false;
    SlidingPuzzle somePuzzle(tempHeight, tempWidth);
    
    char keyStroke = ' ';
    somePuzzle.isBoardSolved();
    cout << "Press any key to begin..." << endl;
    _getch();
    cout << endl << "Scrambling the tiles..." << endl;
    somePuzzle.ScrambleBoard();
    cout << "Scrambling complete, press any key to begin solving." << endl;
    _getch();
    somePuzzle.isBoardSolved();
    do {
        cout << endl << "(w = Up, s = Down, a = Left, d = Right, e = Exit Game)" << endl;
        cout << "Which way to slide?" << endl;
        keyStroke = _getch(); //sets the key used to continue as the move, keys that aren't options do nothing
        switch (keyStroke) {
        case 'w':
        {
            somePuzzle.SlideTile(SLIDE_UP);
            break;
        }
        case 's':
        {
            somePuzzle.SlideTile(SLIDE_DOWN);
            break;
        }
        case 'a':
        {
            somePuzzle.SlideTile(SLIDE_LEFT);
            break;
        }
        case 'd':
        {
            somePuzzle.SlideTile(SLIDE_RIGHT);
            break;
        }
        case 'e':
        {
            exit = true;
            somePuzzle.~SlidingPuzzle();
            break;
        }
        }
    } while (!somePuzzle.isBoardSolved() || !exit);
    // Exit
    _getch();
    return 0;
}
code from specification.h:
#ifndef __SlidingPuzzle__
#define __SlidingPuzzle__
#include <iostream>
#include <windows.h>    //For color in PrintBoard()
using namespace std;
// CLASS SlidingPuzzle
class SlidingPuzzle {
private:
    int height;
    int width;
    int** theBoard;
    int** solvedBoard;
    HANDLE currentConsoleHandle;
    void cls(HANDLE);
public:
    // CONSTRUCTOR
    SlidingPuzzle();        //Gives default values to the SlidingPuzzle's attributes
    SlidingPuzzle(int, int);
    //Deconstructor
    ~SlidingPuzzle();
    //Getter
    int getHeight();
    int getWidth();
    int** getTheBoard();
    int** getSolvedBoard();
    //Methods
    void InitializeBoard();
    bool isBoardSolved();
    bool SlideTile(int);
    void ScrambleBoard();
    void PrintBoard();
}; // end - SlidingPuzzle
#endif
code from implementation.cpp:
#include "Specification.h"
// CONSTRUCTOR
SlidingPuzzle::SlidingPuzzle() {
    this->height = 0;
    this->width = 0;
    this->theBoard = NULL;
    this->solvedBoard = NULL;
    this->currentConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
}
// Overload
SlidingPuzzle::SlidingPuzzle(int newWidth, int newHeight) {
    this->currentConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    if (newHeight > 0) {
        this->height = newHeight;
    }
    else {
        this->height = 0;
    }
    if (newWidth > 0) {
        this->width = newWidth;
    }
    else {
        this->width = 0;
    }
    this->theBoard = new int* [this->height];
    for (int i = 0; i < this->height; i++) {
        this->theBoard[i] = new int[this->width];
    }
    this->solvedBoard = new int* [this->height];
    for (int i = 0; i < this->height; i++) {
        this->solvedBoard[i] = new int [this->width];
    }
}
//Getters
int SlidingPuzzle::getHeight() {
    return this->height;
}
int SlidingPuzzle::getWidth() {
    return this->width;
}
int** SlidingPuzzle::getTheBoard() {
    return this->theBoard;
}
int** SlidingPuzzle::getSolvedBoard() {
    return this->solvedBoard;
}
//Deconstructor
SlidingPuzzle::~SlidingPuzzle() {
    for (int i = 0; i < this->height; ++i)
        delete[] this->theBoard[i];
    delete[] this->theBoard;
}
//Methods
void SlidingPuzzle::InitializeBoard() {
    for (int i = 0; i < this->height; i++) {
        for (int j = 0; j < this->width; j++) {
            if (i == 0) {
                this->theBoard[i][j] = i + j + 1;
            }
            else if (i == 1) {
                this->theBoard[i][j] = i + j + 3;
            }
            else {
                this->theBoard[i][j] = i + j + 5;
                if (this->theBoard[i][j] == (this->width * this->height)) {
                    this->theBoard[i][j] = -1;
                }
            }
        }
    }
}
bool SlidingPuzzle::isBoardSolved() {
    this->cls(currentConsoleHandle);
    this->PrintBoard();
    int correct = 0;
    //Checks each position to see if the are identical
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            if (this->theBoard[i][j] != this->solvedBoard[i][j]) {
                correct = 1;
            }
        }
    }
    if (correct == 0) {
        cout << "isBoardSolved(): true" << endl;
        return true;
    }
    else {
        cout << "isBoardSolved(): false" << endl;
        return false;
    }
}
bool SlidingPuzzle::SlideTile(int directionCode) {
    int row = 0;
    int col = 0;
    int rowSpace = 0;
    int colSpace = 0;
    //Finds the pivot space
    for (int i = 0; i < height; ++i) {
        for (int j = 0; j < width; ++j) {
            if (this->theBoard[i][j] == -1) {
                row = i;
                col = j;
            }
        }
    }
    switch (directionCode) {
        case 1:
        {
            rowSpace = row - 1;
            colSpace = col;
            break;
        }
        case 2:
        {
            rowSpace = row + 1;
            colSpace = col;
            break;
        }
        case 3:
        {
            rowSpace = row;
            colSpace = col - 1;
            break;
        }
        case 4:
        {
            rowSpace = row;
            colSpace = col + 1;
            break;
        }
    }
    //Ensures that the program doesn't break from trying to move off the board
    if (rowSpace >= 0 && rowSpace < height && colSpace >= 0 && colSpace < width) {
        this->theBoard[row][col] = this->theBoard[rowSpace][colSpace];
        this->theBoard[rowSpace][colSpace] = -1;
    }
    return false;
}
void SlidingPuzzle::ScrambleBoard() {
    for (int i = 0; i < 10000; i++) {
        int move = (rand() % 4);
        move++; //Add 1 so the variable matches the values for the directions
        this->SlideTile(move);
    }
}
void SlidingPuzzle::PrintBoard() {  //Refuses to print, no clue why
    HANDLE hConsole;
    hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            if (this->theBoard[i][j] == -1) {
                cout << " *";
            }
            else {
                if (this->theBoard[i][j] == this->solvedBoard[i][j]) {
                    SetConsoleTextAttribute(hConsole, 2); //changes the color to green for correct postion
                    cout << " " << this->theBoard[i][j];
                    SetConsoleTextAttribute(hConsole, 15); //reverts color to normal
                }
                else {
                    SetConsoleTextAttribute(hConsole, 4); //changes the color to red for incorrect postion
                    cout << " " << this->theBoard[i][j];
                    SetConsoleTextAttribute(hConsole, 15); //reverts color to normal
                }
            }
        }
        cout << endl;
    }
}
void SlidingPuzzle::cls(HANDLE hConsole)
{
    COORD coordScreen = { 0, 0 };    /* here's where we'll home the
                                     cursor */
    BOOL bSuccess;
    DWORD cCharsWritten;
    CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
    DWORD dwConSize;                 /* number of character cells in
                                     the current buffer */
                                     /* get the number of character cells in the current buffer */
    bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
    dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
    /* fill the entire screen with blanks */
    bSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR)' ',
        dwConSize, coordScreen, &cCharsWritten);
    /* get the current text attribute */
    bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
    /* now set the buffer's attributes accordingly */
    bSuccess = FillConsoleOutputAttribute(hConsole, csbi.wAttributes,
        dwConSize, coordScreen, &cCharsWritten);
    /* put the cursor at (0, 0) */
    bSuccess = SetConsoleCursorPosition(hConsole, coordScreen);
}
I have used the suggestions from the comments and now I am finally getting the array to display. However the values in the array are still displaying as memory addresses. I updated the code here to reflect the changes made so far.