c 中 4x4 矩阵的 getter 问题
Problems with a getter for a 4x4 matrix in c
你好,明天我必须用 C 语言编写一个俄罗斯方块游戏,我在使用 getter 应该 return 精灵作为 4x4 矩阵时遇到了一些麻烦。
虽然我不太熟悉数组指针,但它很可能非常简单。
所以在我存储形状的第一个文件中,这是对 1 个形状的测试 getter
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()
时停止
TL;DR:使用 memcpy
将数据复制到形状数组,请参见下面的第二个示例。其他示例是带有解释的替代方法。
在 C 中,您不能 return 数组。您只能 return 指向数组第一个元素的指针。你的数组的第一个元素本身就是一个数组,一个 4 int
s.
的数组
定义一个指向由四个整数组成的数组的指针的语法有点古怪:
int (*p)[4];
当您必须将其定义为函数的 return 类型时,它就更奇怪了:
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]
,因为数组不是指针。您需要在其中定义数据的数组。另请注意,此解决方案 return 是指向原始 shape_i
的指针。当你修改p
中的数据时,你通过p
修改了shape_i
,从而破坏了你的形状原型。
如果要用数据填充数组,只需将数据传入即可。即使对于 one-dimensional 数组,这也是一种常用方法:传递一个数组并让函数填充它。 Return 一个(否则不相关的)值,告诉您操作是否成功。
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>
。 return 值只是为了检查形状是否有效。像这样使用它:
int p[4][4];
if (get_shape('I')) {
// p is now filled with a copy of shape_i
}
我认为这是您应该使用的方法。它会将shape_t
的内容复制到p
,这就是你想要的。您将旋转和翻转当前块 p
,而您希望保持块原型 shape_i
不变,以便将来 "clones".
我在上面说过你不能在 C 中使用 return 数组。你可以做的是将数组包装在 struct
和 return 中。结构按值传递,不会像数组那样退化为指针。
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]
.
的形式访问元素
你好,明天我必须用 C 语言编写一个俄罗斯方块游戏,我在使用 getter 应该 return 精灵作为 4x4 矩阵时遇到了一些麻烦。
虽然我不太熟悉数组指针,但它很可能非常简单。
所以在我存储形状的第一个文件中,这是对 1 个形状的测试 getter
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()
时停止TL;DR:使用 memcpy
将数据复制到形状数组,请参见下面的第二个示例。其他示例是带有解释的替代方法。
在 C 中,您不能 return 数组。您只能 return 指向数组第一个元素的指针。你的数组的第一个元素本身就是一个数组,一个 4 int
s.
定义一个指向由四个整数组成的数组的指针的语法有点古怪:
int (*p)[4];
当您必须将其定义为函数的 return 类型时,它就更奇怪了:
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]
,因为数组不是指针。您需要在其中定义数据的数组。另请注意,此解决方案 return 是指向原始 shape_i
的指针。当你修改p
中的数据时,你通过p
修改了shape_i
,从而破坏了你的形状原型。
如果要用数据填充数组,只需将数据传入即可。即使对于 one-dimensional 数组,这也是一种常用方法:传递一个数组并让函数填充它。 Return 一个(否则不相关的)值,告诉您操作是否成功。
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>
。 return 值只是为了检查形状是否有效。像这样使用它:
int p[4][4];
if (get_shape('I')) {
// p is now filled with a copy of shape_i
}
我认为这是您应该使用的方法。它会将shape_t
的内容复制到p
,这就是你想要的。您将旋转和翻转当前块 p
,而您希望保持块原型 shape_i
不变,以便将来 "clones".
我在上面说过你不能在 C 中使用 return 数组。你可以做的是将数组包装在 struct
和 return 中。结构按值传递,不会像数组那样退化为指针。
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]
.