Проблемы с геттером для матрицы 4х4 в c
Здравствуйте, я должен запрограммировать игру тетрис на C к завтрашнему дню, и у меня возникли небольшие проблемы с геттером, который должен возвращать спрайт в виде матрицы 4x4.
Скорее всего, это довольно просто, хотя я не очень знаком с указателями на массивы.
так что в первом файле, где я хранил свои фигуры, это тестовый геттер для 1 фигуры
int shape_i[4][4] = {
{1,0,0,0},
{1,0,0,0},
{1,0,0,0},
{1,0,0,0}
};
int **get_shape(){
return shape_i;}
Теперь из моего файла ничья я называю это так
void draw_shape(){
int **shape= get_shape();
for (int i = 0; i<4; i++){
for (int j=0; j<4; j++){
int value = shape[j][i];
if (value != 0){
SDL_Rect rect;
rect.x = (get_x()+i)*BLOCK_WIDTH;
rect.y = (get_y()+j) *BLOCK_HEIGHT;
rect.h = BLOCK_HEIGHT;
rect.w = BLOCK_WIDTH;
SDL_FillRect(window,&rect,0x044DDE);
}
}
}
SDL_Flip(window);
}
Это не выдает ошибку при компиляции, но моя программа останавливается, как только достигает get_shape()
1 ответ
TL; DR: скопировать данные в массив фигур с помощью memcpy
см. второй пример ниже. Другие примеры - это альтернативные подходы с объяснениями.
В C вы не можете вернуть массивы. Вы можете только вернуть указатель на первый элемент массива. Первым элементом вашего массива является сам массив, массив из 4 int
s.
Синтаксис определения указателя на массив из четырех целых чисел несколько барочный:
int (*p)[4];
Еще более барокко, когда вы должны определить его как тип возвращаемого значения функции:
int (*get_shape(int c))[4] { ... }
Способ обойти это заключается в использовании typedef
:
typedef int (*Shape)[4];
Теперь ваши переменные и прототип функции выглядят так:
Shape p = get_shape(c);
Shape get_shape(int c) { ... }
Вот полный пример:
#include <stdlib.h>
#include <stdio.h>
typedef int (*Shape)[4];
int shape_i[4][4] = {{1,0,0,0}, {1,0,0,0}, {1,0,0,0}, {1,0,0,0}};
int shape_l[4][4] = {{1,0,0,0}, {1,0,0,0}, {1,1,0,0}, {0,0,0,0}};
int shape_z[4][4] = {{1,0,0,0}, {1,1,0,0}, {0,1,0,0}, {0,0,0,0}};
Shape get_shape(int c)
{
switch (c) {
case 'I': return shape_i;
case 'L': return shape_l;
case 'Z': return shape_z;
}
return NULL;
}
int main()
{
int c;
for (c = 'A'; c <= 'Z'; c++) {
Shape p = get_shape(c);
if (p) {
int i, j;
for (j = 0; j < 4; j++) {
for (i = 0; i < 4; i++) {
putchar(p[j][i] ? '#' : ' ');
}
puts("");
}
puts("--");
}
}
return 0;
}
Обратите внимание, что определение форм все еще требует от вас использования int[4][4]
потому что массивы не указатели. Вам нужны массивы, где вы определяете свои данные. Также обратите внимание, что это решение возвращает указатель на оригинал shape_i
, Когда вы изменяете данные в p
Вы модифицируете shape_i
через p
, уничтожая тем самым вашу форму прототипа.
Если вы хотите заполнить массив данными, просто передайте данные. Это общий подход даже для одномерных массивов: передайте массив и сделайте так, чтобы функция заполнила его. Вернуть (иначе не связанное) значение, которое сообщает вам, была ли операция успешной.
int get_shape(int shape[4][4], int c)
{
switch (c) {
case 'I': memcpy(shape, shape_i, sizeof(shape)); return 1;
case 'L': memcpy(shape, shape_l, sizeof(shape)); return 1;
case 'Z': memcpy(shape, shape_z, sizeof(shape)); return 1;
}
return 0;
}
memcpy
это функция стандартной библиотеки, для которой вы должны включить <string.h>
, Возвращаемое значение просто для проверки правильности формы. Используйте это так:
int p[4][4];
if (get_shape('I')) {
// p is now filled with a copy of shape_i
}
Я думаю, что это метод, который вы должны использовать. Это скопирует содержимое shape_t
в p
И это то, что вы хотите здесь. Вы собираетесь вращать и переворачивать свой текущий блок p
тогда как вы хотите сохранить свой блок-прототип shape_i
без изменений для будущих "клонов".
Я уже говорил выше, что вы не можете вернуть массивы в C. Что вы можете сделать, это обернуть ваш массив в struct
и верни это. Структуры передаются по значению и не распадаются на указатели, такие как массивы.
struct Shape {
int data[4][4];
};
struct shape shape_i = {{{1,0,0,0}, {1,0,0,0}, {1,0,0,0}, {1,0,0,0}}};
struct Shape get_shape(void) {
return shape_i;
};
struct Shape p = get_shape();
Это также скопирует содержание, но вы должны получить доступ к элементам как p.data[i][j]
,