第8講 テトリス開発(4つのブロックを一元的に描くまで)
第6話 16パターンを1元的に処理する
を同一のfor文で実現する方法
#include "DxLib.h"
void hajimennogamen(); //ゲームの最初の画面を担当する社員
void gamemain(); //ゲーム画面を担当する社員
void make(); //ゲームオーバー画面を担当する社員
void kachi(); //ゲームクリア画面を担当する社員
char m; //ゲームモードを決定する整数 0:ゲームの最初の画面 1:ゲーム画面 2:ゲームオーバー 3:ゲームクリア画面
int x=100,y=100; //整数型の箱xとyを用意
int h ; //画像に付けられた出席番号を収納する箱を用意
int siro = GetColor(255, 255, 255); //白色の出席番号収納する箱
int kiiro = GetColor(255, 255, 0); //黄色の出席番号収納する箱
int mizuiro = GetColor(0, 255, 255); //水色の出席番号を収納する箱
char taisyoutonarukey_mae[100];
char jyu(int taisyoutonarukey);
void chizusakusei(); //地図作成(壁建設)社員
char chizu[12][27]; //配置担当
void block(); //ブロックを描く社員
char p[4][4][4] = { //x座標に加える数
-1,0,1,2,
0,0,0,0,
-2,-1,0,1,
0,0,0,0,

0,1,1,0,
0,1,1,0,
-1,0,0,-1,
-1,0,0,-1,

0,0,0,1,
0,0,1,2,
-1,0,0,0,
-2,-1,0,0,

0,0,1,1,
-1,0,0,1,
-1,-1,0,0,
-1,0,0,1
};
char q[4][4][4] = { //y座標に加える数
0,0,0,0,
-1,0,1,2,
0,0,0,0,
-2,-1,0,1,

-1,-1,0,0,
0,0,1,1,
0,0,1,1,
-1,-1,0,0,

-2,-1,0,0,
1,0,0,0,
0,0,1,2,
0,0,0,-1,

-1,0,0,1,
1,1,0,0,
-1,0,0,1,
0,0,-1,-1
};

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
  ChangeWindowMode(true); //ウィンドウモードの切り替え
  SetGraphMode(440, 540, 32); //ウインドウサイズの変更
  if (DxLib_Init() == -1)return(-1);  // DXライブラリ初期化処理

  SetDrawScreen(DX_SCREEN_BACK); //裏画像を描画対象に加える(2017/06/28追加) 画面のちらつき対策
  m=1;
  while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
    if(m==0)hajimennogamen();
    if(m==1)gamemain();
    if(m==2)make();
    if(m==3)kachi();
  }

  WaitKey();   // キー入力待ち
  DxLib_End();  // DXライブラリ終了処理
  return 0;
}
void block(){
  int x,y;
  int i;
  
for(i=0;i<4;i++)chizu[3+p[0][3][i]][4+q[0][3][i]]=2;
  for(i=0;i<4;i++)chizu[7+p[1][2][i]][8+q[1][2][i]]=2;
  for(i=0;i<4;i++)chizu[3+p[2][0][i]][16+q[2][0][i]]=2;
  for(i=0;i<4;i++)chizu[8+p[3][1][i]][20+q[3][1][i]]=2;

  for (x = 0; x < 12; x++) {
    for (y = 0; y < 27; y++) {
      if (chizu[x][y] == 2) {
        DrawBox(20 * x, 20 * y, 20 * (x + 1) - 1, 20 * (y + 1) - 1, kiiro, true);
      }
    }
  }
}
void chizusakusei() {
  int x, y;
  int gazou = LoadGraph("画像/kb00.png");
  for (x = 0; x < 12; x++) {
    for (y = 0; y < 27; y++) {
      chizu[x][y] = 0;
    }
  }
  for (y = 0; y < 27; y++) {
    chizu[0][y] = 1;
    chizu[11][y] = 1;
  }
  for (x = 1; x < 11; x++) {
    chizu[x][0] = 1;
    chizu[x][26] = 1;
  }
  for (x = 0; x < 12; x++) {
    for (y = 0; y < 27; y++) {
      if (chizu[x][y] == 1) {
        DrawGraph(20 * x, 20 * y, gazou, true);
      }
    }
  }
  DeleteGraph(gazou);
}
void hajimennogamen(){ //ゲームの最初の画面
  int gazou;
  gazou = LoadGraph("画像/02.png");
  DrawGraph(0, 0, gazou, true);
  if (jyu(KEY_INPUT_RETURN) != 0) m=1;
}
void gamemain(){ //ゲーム画面
  chizusakusei(); //地図作成(壁建設)
  block(); //ブロックを描く
}
void make(){ //ゲームオーバー画面
  int gazou;
  gazou = LoadGraph("画像/03.png");
  DrawGraph(0, 0, gazou, true);
  if (jyu(KEY_INPUT_RETURN) != 0) m=3;
}
void kachi(){ //ゲームクリア画面
  int gazou;
  gazou = LoadGraph("画像/04.png");
  DrawGraph(0, 0, gazou, true);
  if (jyu(KEY_INPUT_RETURN) != 0) m=0;
}
char jyu(int taisyoutonarukey) { //taisyoutonarukey(たいしょうとなるキー)は、今対象としているキーの出席番号
  if (CheckHitKey(taisyoutonarukey) != 0) {
    if (taisyoutonarukey_mae[taisyoutonarukey] == 0) {
      taisyoutonarukey_mae[taisyoutonarukey] = 1;
      return 1;
    }
  }
  else {
    taisyoutonarukey_mae[taisyoutonarukey] = 0;
    return 0;
  }
  return 0;
}
コピペ用添付ファイル
つまり、ランダムにいろいろなブロックの4つの回転状態を実現するには、
for(i=0;i<4;i++)chizu[x+p[
s][k][i]][y+q[s][k][i]]=2;
skを制御してやればよいのです。
姉妹編では、ブロックの種類を考えて、
for(i=0;i<4;i++)chizu[tyouhoukei_x+p[block_syurui][tyouhoukei_kaiten][i]][tyouhoukei_y+q[block_syurui][tyouhoukei_kaiten][i]]=2;
のように長ったらしく表現してしまい、
初心者を混乱に陥れてしまったの反省があります。
今のプログラミング教育の世界では、
変数名は内容がわかるようにと、
長い英単語で書くことが主流になっていますが、
私は、
for(i=0;i<4;i++)chizu[x+p[s][k][i]][y+q[s][k][i]]=2;
にように書く方が圧倒的にわかりやすいと考えています。
初心者の方にとってもそうですし、
プログラミングに慣れている人にとってもそうだと思っています。
確かに、sのような1文字の変数名では、
それが何を表す変数名であったかわからなくなる可能性は確かにありますが、
for(i=0;i<4;i++)chizu[x+p[s][k][i]][y+q[s][k][i]]=2; //sはブロックの種類、kはブロックの回転状態を表す
と注釈文を入れれば、その変数が何を表しているか一目瞭然です。
例え、英単語をローマ字に置き換えて
for(i=0;i<4;i++)chizu[tyouhoukei_x+p[block_syurui][tyouhoukei_kaiten][i]][tyouhoukei_y+q[block_syurui][tyouhoukei_kaiten][i]]=2;
としたとしても、初心者はblock_syuruiやtyouhoukei_kaiten自体に何か意味があると考えてしまうと思います。
ですが、変数名はただの箱の名前にすぎません。
言いかえると、箱のラベルにすぎません。
ラベルが貼ってなかったり、マジックで箱の用途が書いてあらず、
同じような箱が何十個もあったら、
区別が付きません。
そこで、わかるように付けたラベルまたはマジックによる書き込みが変数名なのです。

尚、
for(i=0;i<4;i++)chizu[x+p[s][k][i]][y+q[s][k][i]]=2;
は、実際の運用の際には、
for(i=0;i<4;i++)chizu[x+p[s][k][i]][y+q[s][k][i]]=2+s;
とします。
ブロックごとに色を塗り替えるためです。
当然そのときには、
  for (x = 0; x < 12; x++) {
    for (y = 0; y < 27; y++) {
      if (chizu[x][y] == 2) {
        DrawBox(20 * x, 20 * y, 20 * (x + 1) - 1, 20 * (y + 1) - 1, kiiro, true);
      }
    }
  }
は少し改良しなければなりません。

次話では、
for(i=0;i<4;i++)chizu[x+p[s][k][i]][y+q[s][k][i]]=2; //sはブロックの種類、kはブロックの回転状態を表す
によってどうして一元的に処理できてしまうのかを、トレースしてみます。
64通りも場合の数がありますので、すべてについてトレースする訳にはいきませんので、
ランダムにいくつか選んでということになりますが。
皆さんは、記述した以外のパターンでもトレースして下さい。



第5話へ  第7話へ

002

初心者のための excel 2016 マクロ VBA 入門講義 基礎から応用まで
vc++ c言語 c++ 入門 初心者 基礎から応用まで
ecliqse c++ 入門
魔方陣 数独で学ぶ VBA 入門

数独のシンプルな解き方・簡単な解法の研究
VB講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 C++ 入門 基礎から応用まで第1部
ecliqse java 入門
java 入門 サイト 基礎から応用まで
本サイトトップへ