0

So I'm trying to make a Tetris game and I've come across something odd that I'm unsure about.

I have an array called bottom which stores the value of the lowest block - so, if there is no block in the first column, "bottom" will be 20.

If there's a square block occupying that first column, bottom would be 18. The weird thing is, when I set a breakpoint in my code to try to view the values for bottom, it says there is only one value in the array. In addition, my board, which is a 25 by 10 array, has the same problem, it only displays one dimension.

It seems the problem has to do with some kind of pointer issue, because it says (int (*)[10]) and (int *), where I think it should be a (int [25][10]) and (int [10]). I tried looking up array pointers and references, but the main thing I found was how to make an array of pointers and I'm not really quite sure how to word my searches.

If someone might know what's going wrong please let me know!

main.cpp

#include <chrono>
#include "makeboard.h"

int main() {
    //declares and defines board
    int board[24][10];
    for (int y = 0; y < 24; y++) {
        for (int x = 0; x < 10; x++) {
            board[y][x] = 0;
        }
    }
    makeboard(board);
}

tiles.h

#ifndef tiles_h
#define tiles_h

class O {
    int board[24][10];
    int x, y;
public:
    void set_O (int[24][10], int, int);
};
void O::set_O (int board[24][10], int y, int x) {
    board[y][x] = 1;
    board[y][x+1] = 1;
    board[y-1][x] = 1;
    board[y-1][x+1] = 1;
}

class I {
    int board[24][10];
    int x, y, d;
public:
    void set_I (int[24][10], int, int, int);
};
void I::set_I (int board[24][10], int d, int y, int x) {
    if (d == 1 || d == 3) {
        board[y-3][x] = 1;
        board[y-2][x] = 1;
        board[y-1][x] = 1;
        board[y][x] = 1;
    }
    if (d == 2 || d == 4) {
        board[y][x-1] = 1;
        board[y][x] = 1;
        board[y][x+1] = 1;
        board[y][x+2] = 1;
    }
}

class S {
    int board[24][10];
    int x, y, d;
public:
    void set_S (int[24][10], int, int, int);
};
void S::set_S (int board[24][10], int d, int y, int x) {
    if (d == 1 || d == 3) {
        board[y-1][x] = 1;
        board[y-1][x+1] = 1;
        board[y][x] = 1;
        board[y][x-1] = 1;
    }
    if (d == 2 || d == 4) {
        board[y-2][x] = 1;
        board[y-1][x] = 1;
        board[y-1][x+1] = 1;
        board[y][x+1] = 1;
    }
}

class Z {
    int board[24][10];
    int x, y, d;
public:
    void set_Z (int[24][10], int, int, int);
};
void Z::set_Z (int board[24][10], int d, int y, int x) {
    if (d == 1 || d == 3) {
        board[y][x] = 1;
        board[y][x-1] = 1;
        board[y+1][x] = 1;
        board[y+1][x+1] = 1;
    }
    if (d == 2 || d == 4) {
        board[y-1][x+1] = 1;
        board[y][x+1] = 1;
        board[y][x] = 1;
        board[y+1][x] = 1;
    }
}

class T {
    int board[24][10];
    int d, x, y;
public:
    void set_T (int[24][10], int, int, int);
};
void T::set_T (int board[24][10], int d, int y, int x) {
    if (d == 1 && (board[y+1][x-1] != 1 || board[y+1][x] != 1 || board[y+1][x+1] != 1)) {
        board[y-1][x] = 1;
        board[y][x-1] = 1;
        board[y][x] = 1;
        board[y][x+1] = 1;
    }
    if (d == 2 && (board[y+2][x] != 1 || board[y+1][x+1] != 1)) {
        board[y-1][x] = 1;
        board[y][x] = 1;
        board[y][x+1] = 1;
        board[y+1][x] = 1;
    }
    if (d == 3 && (board[y+1][x-1] != 1 || board[y+2][x] != 1 || board[y+1][x+1] != 1)) {
        board[y][x-1] = 1;
        board[y][x] = 1;
        board[y][x+1] = 1;
        board[y+1][x] = 1;
    }
    if (d == 4 && (board[y+1][x-1] != 1 || board[y+2][x] != 1)) {
        board[y-1][x] = 1;
        board[y][x-1] = 1;
        board[y][x] = 1;
        board[y+1][x] = 1;
    }
}

class J {
    int board[24][10];
    int d, x, y;
public:
    void set_J (int[24][10], int, int, int);
};
void J::set_J (int board[24][10], int d, int y, int x) {
    if (d == 1) {
        board[y-1][x-1] = 1;
        board[y-1][x] = 1;
        board[y-1][x+1] = 1;
        board[y][x+1] = 1;
    }
    if (d == 2) {
        board[y-2][x] = 1;
        board[y-1][x] = 1;
        board[y][x] = 1;
        board[y][x-1] = 1;
    }
    if (d == 3) {
        board[y][x-1] = 1;
        board[y][x] = 1;
        board[y][x+1] = 1;
        board[y-1][x-1] = 1;
    }
    if (d == 4) {
        board[y-2][x] = 1;
        board[y-2][x+1] = 1;
        board[y-1][x] = 1;
        board[y][x] = 1;
    }
}

class L {
    int board[24][10];
    int d, x, y;
public:
    void set_L (int[24][10], int, int, int);
};
void L::set_L (int board[24][10], int d, int y, int x) {
    if (d == 1) {
        board[y-1][x-1] = 1;
        board[y-1][x] = 1;
        board[y-1][x+1] = 1;
        board[y][x-1] = 1;
    }
    if (d == 2) {
        board[y-2][x] = 1;
        board[y-1][x] = 1;
        board[y][x] = 1;
        board[y][x-1] = 1;
    }
    if (d == 3) {
        board[y-1][x-1] = 1;
        board[y-1][x] = 1;
        board[y-1][x+1] = 1;
        board[y][x+1] = 1;
    }
    if (d == 4) {
        board[y-2][x] = 1;
        board[y-1][x] = 1;
        board[y][x] = 1;
        board[y][x+1] = 1;
    }
}

#endif


makeboard.cpp

#include <iostream>
#include <limits>
#include <thread>
#include "makeboard.h"
#include "clearscreen.h"
#include "isBottom.h"
#include "isPressed.h"
#include "tiles.h"
using namespace std;

string icon[3] = { "   ", " o ", " o " };

void makeboard(int board[24][10]) {

    time_t srand( time(NULL) );
    int block = srand % 7 ;
    block = 3;

    //declares pieces
    O o;
    I i;
    S s;
    Z z;
    T t;
    J j;
    L l;

    //declares and defines initial bottom
    int bottom[10];
    for (int i = 0; i < 10; i++) bottom[i] = 23;

    //declares and defines initial block position
    int y = 3;
    int x = 4;
    int d = 1;

    while (!isBottom(board, block, y, x, d, bottom)) {

        if (isPressed(0) && x > 0) {
            x--;
        }
        if (isPressed(2) && x < 10) {
            x++;
        }
        if (isPressed(1)) {
            d += 1;
            if (d == 4) {
                d = 1;
            }
        }

        //moves tile down
        y++;

        //clears screen
        clearscreen();

        //clears non set pieces
        for (int i = 0; i < 24; i++) {
            for (int j = 0; j < 10; j++) {
                if (board[i][j] == 1) {
                    board[i][j] = 0;
                }
            }
        }

        //adds blocks to board
        switch (block) {
            case 1:
                o.set_O(board, y, x);
                break;
            case 2:
                i.set_I(board, d, y, x);
                break;
            case 3:
                s.set_S(board, d, y, x);
                break;
            case 4:
                z.set_Z(board, d, y, x);
                break;
            case 5:
                t.set_T(board, d, y, x);
                break;
            case 6:
                j.set_J(board, d, y, x);
                break;
            case 7:
                l.set_L(board, d, y, x);
                break;
        }

        //builds board
        cout << "╔══════════════════════════════╗" << endl;
        for (int i = 4; i < 24; i++) {
            cout << "║";
            for (int j = 0; j < 10; j++) {
                cout <<  icon[board[i][j]] ;
            }
            cout << "║" << endl;
        }
        cout << "╚══════════════════════════════╝" << endl;
        cout << "  0  1  2  3  4  5  6  7  8  9   " << endl;

        //resets initial tile position
        if (isBottom(board, block, y, x, d, bottom)) {
            y = 2;
            //block = srand % 7;
        }

        //ends game
        if (isBottom(board, block, 3, x, d, bottom)) {
            cout << "You lose!";
            return;
        }

        //delay
        this_thread::sleep_for (chrono::milliseconds(100));
    }
    return;
}

clearscreen.cpp

#include <unistd.h>
#include <term.h>
#include <stdlib.h>
#include "clearscreen.h"

void clearscreen()
{
    if (!cur_term)
    {
        void *a;
        int result;
        setupterm( NULL, STDOUT_FILENO, &result );
        a = malloc(sizeof(int) *result);
        free (a);
        if (result <= 0) free (a); return;
    }
    putp( tigetstr( "clear" ) );
}

isBottom.cpp

#include "isBottom.h"

bool isBottom(int board[24][10], int block, int y, int x, int d, int bottom[10]) {
    switch (block) {
        case 1:
            if (y == bottom[x] || y == bottom[x+1]) {
                board[y][x] = 2;
                board[y][x+1] = 2;
                board[y-1][x] = 2;
                board[y-1][x+1] = 2;
                bottom[x] -= 2;
                bottom[x+1] -= 2;
                return true;
            }
            return false;
            break;
        case 2:
            if (d == 1 || d == 3) {
                if (y == bottom[x]) {
                    board[y-3][x] = 2;
                    board[y-2][x] = 2;
                    board[y-1][x] = 2;
                    board[y][x] = 2;
                    bottom[x] -= 4;
                    return true;
                }
                return false;
                break;
            }
            if (d == 2 || d == 4) {
                if (y == bottom[x-1] || y == bottom[x] || y == bottom[x+1] || y == bottom[x+2]) {
                    board[y][x-1] = 2;
                    board[y][x] = 2;
                    board[y][x+1] = 2;
                    board[y][x+2] = 2;
                    bottom[x-1]--;
                    bottom[x]--;
                    bottom[x+1]--;
                    bottom[x+2]--;
                    return true;
                }
                return false;
                break;
            }
        case 3:
            if (d == 1 || d == 3) {
                if (y == bottom[x-1] || y == bottom[x] || y == bottom[x+1]) {
                    board[y-1][x] = 2;
                    board[y-1][x+1] = 2;
                    board[y][x] = 2;
                    board[y][x-1] = 2;
                    bottom[x-1] = 23 - y;
                    bottom[x] -= 2;
                    bottom[x+1] -= 2;

                    return true;
                    break;

                }
                return false;
                break;

            }
            if (d == 2 || d == 4) {
                if (y == bottom[x-1] || y == bottom[x]) {

                    board[y-2][x] = 2;
                    board[y-1][x] = 2;
                    board[y-1][x+1] = 2;
                    board[y][x+1] = 2;
                    bottom[x-1]--;
                    bottom[x] -= 1;

                    return true;
                    break;

                }
                return false;
                break;

            }


             /*
             case 3:
             s.set_S(board, d, y, x);
             break;
             case 4:
             z.set_Z(board, d, y, x);
             break;
             case 5:
             t.set_T(board, d, y, x);
             break;
             case 6:
             j.set_J(board, d, y, x);
             break;
             case 7:
             l.set_L(board, d, y, x);
             break;
             */
    }
    return true;
}

isPressed.cpp

#include <Carbon/Carbon.h>
#include "isPressed.h"

bool isPressed( unsigned short inKeyCode )
{
    unsigned char keyMap[16];
    GetKeys((BigEndianUInt32*) &keyMap);
    return (0 != ((keyMap[ inKeyCode >> 3] >> (inKeyCode & 7)) & 1));
}

2 Answers2

0

It depends on the scope of your array. For example:

int GetBottom(int* bottom);
int GetBottom2(const int (&bottom)[20]);

int main()
{
    int localArray1d[20] = {};
    int localArray2d[10][25] = {};
    // putting a breakpoint here will allow you to see the full dimensions of the array because this function KNOWS what the object is (e.g. a 1d and 2d array respectively)

    int lastBrick = GetBottom(localArray1d);
    // When the array is passed to GetBottom, it's passed just as a pointer. Although it IS an array, the function GetBottom doesn't know that. We could just as simply pass it a single int*
    int n = 0;
    GetBottom(&n); // here we are only passing a single int pointer. GetBottom has no idea that your object is an array, it only knows it has an int*

    lastBrick = GetBottom2(localArray1d);
    // GetBottom2 only takes an array of 20 elements, so inspecting the object in that function allows you to see all the elements.

    return 0;
}

int GetBottom(int* bottom)
{
    // Having a breakpoint here will not allow you to see all the elements in an array since this function doesn't even know bottom IS an array.
}

int GetBottom2(const int (&bottom)[20])
{
    // A breakpoint here will allow you to fully inspect bottom.
}
Tas
  • 7,023
  • 3
  • 36
  • 51
  • Thank you. That makes a lot of sense. So my new question is, if I'm passing an array into my isBottom function, and the array is: 20 20 20 20 20 20 20 20 20 20, how does the function know which 20 to take? If i place a square block in the bottom left, does it only change one value to 18, or does it change both of the bottom two? – Travis Triglianos May 07 '15 at 02:54
0

It's a little tricky when you refer to arrays the way you do, but an array like int array[5] degrades to int* array when you branch outside the scope in which it is defined. It's because arrays are r-values and need to degrade into a reference or pointer l-value (which lacks that info about how many elements there are) to pass them around. The gotcha part here is that you can still write a function which accepts int parameter[5] and the compiler will accept it, but will silently treat it like int* parameter. The same goes for the debugger.

So depending on your debugger, there's different ways to look at all the elements through a pointer anyway. For example, with this code:

int* ptr = some_array;

... in MSVC, I can only see the first element pointed to by ptr in the watch window. However, if I know that some_array has 10 elements, I can type ptr,10 in the watch window and it'll show me all 10 elements.

Also, again this is debugger-specific, but some debuggers are conveniently programmed to show the contents of standard containers no matter what in a beautifully-readable format. So if you can use contaners like std::vector, it'll make your debugging life easier if you're using such a debugger.