アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんばんは!

C言語初心者です!(もとい、プログラミング入門者ですが)
配列の再初期化?について質問です。

現在、テトリスを作っていて、
周りの壁を表す配列 int Stage[21][12]
テトリミノ(ブロック)を表す配列 int block[4][4]
Stageとblockを加算して(※1)、現在の状態を画面状態を示す int Field[21][12]
があります。(すべてグローバル変数です。)

このうち、配列Filedはテトリミノが刻一刻と落下するので、内容を一度初期化してから、再度、配列Stageと配列blockの内容を配列Fieldに取り込む必要があります。


その際の、配列の再初期化の方法なのですが、一般的にどのように初期化するのでしょうか?




方法1)配列に0を代入していく

for( int i = 0 ; i < sizeof( field ) / sizeof( field[0] ) ; i++ ) {
for ( int j = 0 ; j < sizeof( field[0] ) / sizeof( field[0][0] ) ; j++ ) {
field[ i ][ j ] = 0;
}
}

方法2)空の配列をコピー

int initStage[21][12] = { 0 };
memcpy(stage, initStage, sizeof(stage));

「C言語 配列の再初期化」の質問画像

質問者からの補足コメント

  • へこむわー

    > 方法2)空の配列をコピー
    >
    > int initStage[21][12] = { 0 };
    > memcpy(stage, initStage, sizeof(stage));

    stageではなく、fieldでした

      補足日時:2016/04/30 22:05

A 回答 (6件)

単純に配列の中身をゼロ初期化するのであれば、


for (i=0; i<(sizeof(field) / sizeof(int)); i++) *(field + i) = 0;
もしくは、
memset(field, 0, sizeof(field);
ですね。

ちなみに、RAMが64KBしかなく、CPUのクロック周波数が4MHz程度で、
画面描画は直接VRAMに書くしかなかった時代の人なら、
ブロック周辺の背景に当たるデータをいったんその大きさの領域に退避し、
ブロックの形状と背景を重ね合わせて表示、
ブロックが移動するごとにその領域だけ一旦元へ戻し、
移動先(回転後の形状も同様)ブロックの領域のみまた同じように重ね合わせて表示すると思います。
(これを文字通り『重ね合わせ処理』と呼んでいました)
現代のコンピュータはかなり高性能なので気にならないかもしれませんが、
質問者様が作っているプログラムは画面全体を毎回再描画していると思うので、
スペックのかなり低いマシンでは画面全体がチラついた感じになると思います。
    • good
    • 0

ポインタを使ってループします。


2重ループでは無く、sizeof(stage) を使い単ループの回数を設定します。
    • good
    • 0

私は、memsetは使いません。


最近のコンパイラなら、最適化の技術も相当のものなので、forでのループとmemsetのどちらが効率がよいかなどと簡単に判断できません。
それなら、CPU等に依存するmemsetによる書き換えよりは、環境依存の少ないforループを選びます。



余談ですが

「21」って何の数?「12」って何の数?
幅を増やそうとしたら、12 を変えることになりますが、例えば
int a = 12 ;
とあったら、この「12」という数値は「幅」なのか、それとも、幅とはまったく関係のない値なのか、判断できますか?
「幅を表わす12」の全て、変更忘れをしない自信はありますか?

このような「意味のある数値」には、#define で名前を付けるのがよいでしょう。
    • good
    • 2

配列全てを一つの値にするのではなくて、テンプレート配列(周囲の壁を含むフィールドの状態)からfield[][]へコピーするのですよね?



forでループさせても、memcpyを使用しても、どちらでも良いのではないでしょうか?
    • good
    • 0

方法1でも問題なし。

C使いなら多少行儀悪いですが
memsetを使う人が多いでしょう。
    • good
    • 0

memset()でできるっぽいですね。



以下サンプルプログラム。
全角スペース2個("  ")をタブか半角スペースに変換すれば
実行できます。

空の2次元配列を用意し、初期の配列状態を表示。
適当な場所に適当な値を設定し、現在の配列状態を表示。
memsetして、現在の配列状態を表示しています。

プログラムの最後でsizeof(Stage)を出力すると、1008となっており、
配列の長さ 21 * 12 * 4(int型1つ当たりの大きさ)と一致しています。


#include <stdio.h>

void pri(int Stage[21][12]) {
  printf("Stage[][]の中身\n");
  for (int i = 0; i < 21; i++) {
    for (int j = 0; j < 12; j++) {
      printf("%d\t", Stage[i][j]);
    }
    printf("\n");
  }
  printf("\n");
}

int main(){
  int Stage[21][12] = { 0 };

  pri(Stage);

  //適当な値を設定
  Stage[3][4] = 34;
  Stage[18][1] = 181;

  pri(Stage);

  memset(Stage, 0x00, sizeof(Stage));

  pri(Stage);

  printf("sizeof(Stage) = %d\n", sizeof(Stage));

  return 0;
}


[参考]
http://www9.plala.or.jp/sgwr-t/lib/memset.html
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!