俄罗斯方块游戏数组问题

Tetris Game array issue

所以我正在尝试制作俄罗斯方块游戏,但我遇到了一些我不确定的奇怪事情。

我有一个名为 bottom 的数组,它存储最低块的值 - 因此,如果第一列中没有块,"bottom" 将为 20。

如果第一列有一个方块,bottom 将是 18。奇怪的是,当我在代码中设置断点以尝试查看 bottom 的值时,它说只有一个值阵列。另外,我的板子是一个25×10的阵列,也有同样的问题,它只显示一维。

看来这个问题与某种指针问题有关,因为它说 (int (*)[10])(int *),我认为它应该是 (int [25][10])(int [10]).我尝试查找数组指针和引用,但我发现的主要内容是如何制作指针数组,我不太确定如何用我的搜索措辞。

如果有人知道出了什么问题,请告诉我!

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

这取决于你的数组范围。例如:

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

当你按照你的方式引用数组时有点棘手,但是当你在定义它的范围之外分支时,像 int array[5] 这样的数组会退化为 int* array。这是因为数组是右值,需要降级为引用或指针左值(缺少关于有多少元素的信息)来传递它们。这里的陷阱部分是你仍然可以编写一个接受 int parameter[5] 的函数,编译器会接受它,但会像 int* parameter 一样默默地对待它。调试器也是如此。

因此,根据您的调试器,有不同的方法可以通过指针查看所有元素。例如,使用此代码:

int* ptr = some_array;

...在MSVC中,我只能在手表window中看到ptr指向的第一个元素。但是,如果我知道 some_array 有 10 个元素,我可以在手表 window 中输入 ptr,10,它会显示所有 10 个元素。

另外,这也是特定于调试器的,但是一些调试器被方便地编程为以美观易读的格式显示标准容器的内容。因此,如果您可以使用像 std::vector 这样的容器,那么如果您正在使用这样的调试器,它将使您的调试生活更轻松。