C を用いて作っております。
とても効率のよいアルゴリズムでは無いですが、まず完成させるまでは自分の考えられる範囲で作りたいと思っております。
今現在ブロックの地面に積む処理で困っております。
ブロックを90度、またはマイナスに90度回した際のみ、なぜか地面に落ちたブロックが崩壊してしまいます。
ブロックは2つの配列を用意し、相互間を転置したブロックを渡しあっております。
回転の状態を記録しておき、どちらの配列を参照するか判断しています。
プログラムはこちらです。
/***** ヘッダー ****/
#include<stdio.h>
#include<stdlib.h> //exit()
#include<conio.h> //getch(),kbhit()
#include<windows.h> //Sleep
/**** 定数 ****/
#define HIGHT 20
#define WIDTH 15
#define SUMBLOCK 7
/**** プロトタイプ宣言 ****/
void Draw_map(void); //ステージ(メイン)の出力
void Draw_block(int b); //空白かブロックの出力
void Check_map(); //ブロックの固定、新規ブロックの取得
void Set_block(int mode); //回転用ブロックのセット
void Move_block(int dir); //ブロックの移動
void Turn_block(int dir, int type); //ブロックの回転
void Hold_block(); //ブロックの固定
void Output_test(int type);
void Key_inp();
void Timer_funk();
void title(); //タイトルの表示
struct BLOCKS{ //ブロックデータ
int block[4][4]; //最大4 * 4ドット
int block_size; //サイズ
};
struct BLOCKS block_data[SUMBLOCK] =
{
{//四角 //ブロック0
{
{ 1, 1 },
{ 1, 1 }
}, 2
},
{//とつ //ブロック1
{
{ 0, 1, 0 },
{ 1, 1, 1 },
{ 0, 0, 0 }
}, 3
},
{//エル //ブロック2
{
{ 1, 0, 0 },
{ 1, 1, 1 },
{ 0, 0, 0 }
}, 3
},
{//逆エル //ブロック3
{
{ 0, 0, 1 },
{ 1, 1, 1 },
{ 0, 0, 0 }
}, 3
},
{//エヌ //ブロック4
{
{ 0, 1, 0 },
{ 1, 1, 0 },
{ 1, 0, 0 }
}, 3
},
{//逆エヌ //ブロック5
{
{ 0, 1, 0 },
{ 0, 1, 1 },
{ 0, 0, 1 }
}, 3
},
{//横棒 //ブロック6
{
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 }
}, 4
},
};
struct BLOCKS block_data2[SUMBLOCK]; //回転処理後のデータ
struct STAGE{
int stage[20][15]; //ステージ全体 20*15
int x; //ブロックの現在位置 X
int y; //ブロックの現在位置 Y
int direction; //回転位置
int ground; //地面に付いているかいないか
int b_type; //落下中ブロックのタイプ
};
struct STAGE st = //マップデータ
{
{
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
}, 5, 0, 0, 0, 2
};
int FLAG = 0;
/***********************************************************/
/************************* MAIN関数 ************************/
/***********************************************************/
int main(void)
{
int c=0;
Set_block(8);
title(); //タイトル
printf("[S]Key:Start!\n");
while (1){
if (_kbhit() != 0){
c = _getch();
if (c == 115){ //S_key
printf("Start!!!\n");
break;
}
}
}
system("cls");
Timer_funk();
return 0;
}
/**************** タイマー *******************/
void Timer_funk()
{
int time=0;
time = 0;
while (1){
for (time = 0; time < 20; time++){
Sleep(1); //1[ms]のウェイト
Key_inp(); //回転処理の常時受け付け
}
system("cls");
Check_map(); //移動先のチェック
FLAG = 0; //チェック済み
Draw_map();
st.y += 1;
}
}
/**************** キー入力受付*****************●*/
void Key_inp()
{
int key=0;
if (_kbhit() != 0){
key = _getch();
if (key == 99){ //C_key(左回り)
Turn_block(1, st.b_type);
}
else if (key == 122){ //Z_key(右回り)
Turn_block(0, st.b_type);
}
else if (key == 75){ //←_key(左へ移動)
st.x -= 1;
}
else if (key == 77){ //→_key(右へ移動)
st.x += 1;
}
system("cls");
Draw_map();
// printf("X=%02d Y=%02d\n", st.x, st.y);
}
}
/**************** マップ描画 ******************●*/
void Draw_map()
{
int i, j, size;
size = block_data[st.b_type].block_size;
for (i = 0; i < HIGHT; i++){ //マップ縦全体
for (j = 0; j < WIDTH; j++){ //マップ横全体
if( (i >= st.y && i <= st.y + size) && ( j >= st.x && j <= st.x + size) ){
if (st.direction % 2 == 0){
Draw_block(block_data2[st.b_type].block[i-st.y][j-st.x] + st.stage[i][j]);
}
else{
Draw_block(block_data[st.b_type].block[i-st.y][j-st.x] + st.stage[i][j]);
}
}else{
Draw_block(st.stage[i][j]);
}
}
printf("\n");
}
printf("X=%02d Y=%02d\n",st.x,st.y);
}
/************* 空白orブロック描画 ************●*/
void Draw_block(int b)
{
if(b >= 1) printf("■");
else printf(" ");
}
/********** 回転用ブロックのセット ***********●*/
void Set_block(int mode) //mode:8 全初期化 mode:0~6 指定初期化
{ //初期ブロックデータを回転用データにセット
int i, j, k, size;
if (mode == 8){ //全初期化
for (i = 0; i < SUMBLOCK; i++){
size = block_data[i].block_size;
for (j = 0; j < size; j++){
for (k = 0; k < size; k++){
block_data2[i].block[j][k] = block_data[i].block[j][k];
}
}
}
}
else if (mode >= 0 && mode <= 6){
}
}
/*************** あたり判定 *******************/
void Check_map()
{
int i, j, size;
size = block_data[st.b_type].block_size;
for(i = st.y; i < st.y + size; i++){ //現在のY座標から現在のY座標+ブロックのサイズ分
for(j = st.x; j < st.x + size; j++){ //現在のX座標から現在のX座標+ブロックのサイズ分
if( block_data[st.b_type].block[i-st.y][j-st.x] * st.stage[i+1][j] == 1){
Hold_block(); //ブロック固定
FLAG = 1;
break;
}else if(i == st.y + size && j == st.x + size){//配列末までマップとの重複なし
st.y += 1; //y座標をひとつ下げる
}
}
if(FLAG==1) break;
}
}
/*************** ブロック固定 *******************/
void Hold_block()
{
int i,j,size;
size = block_data[st.b_type].block_size;
for(i=st.y; i < st.y + size; i++){ //現在のY座標から現在のY座標+ブロックのサイズ分
for(j=st.x; j < st.x + size; j++){ //現在のX座標から現在のX座標+ブロックのサイズ分
if (st.direction % 2 == 0 && block_data2[st.b_type].block[i-st.y][j-st.x] != 0){//回転回数偶数でブロックデータがあれば
st.stage[i][j] = 1; //ブロック情報をマップに書き込み
}
else if(block_data[st.b_type].block[i-st.y][j-st.x] != 0){ //回転位置(奇数):a←b
st.stage[i][j] = 1; //ブロック情報をマップに書き込み
}
}
}
st.y = 0;
}
/*************** ブロック回転 *****************/
void Turn_block(int dir, int type) //回転方向、種類
{
int i, j;
int size = block_data[type].block_size; //ブロックのサイズ
for (i = 0; i < size; i++){
for (j = 0; j < size; j++){
if (dir == 1){ //右回なら
if (st.direction % 2 == 0){ //回転位置(偶数):b←a
block_data[type].block[j][size - 1 - i] = block_data2[type].block[i][j];
}
else{ //回転位置(奇数):a←b
block_data2[type].block[j][size - 1 - i] = block_data[type].block[i][j];
}
}
else if (dir == 0){ //左回なら
if (st.direction % 2 == 0){ //回転位置(偶数):b←a
block_data2[type].block[i][j] = block_data[type].block[j][size - 1 - i];
}
else{ //回転位置(奇数):a←b
block_data[type].block[i][j] = block_data2[type].block[j][size - 1 - i];
}
}
}
}
if (dir == 1){ //右回なら回転位置+
if (st.direction == 3) st.direction = 0; //回転位置3→0
else st.direction += 1;
}
else if (dir == 0){ //左回なら回転位置-
if (st.direction == 0) st.direction = 3; //回転位置0→3
else st.direction -= 1;
}
}
void title()
{
printf(" ■■■ ■ ■ ■ ■■■■\n");
printf(" ■ ■ ■ ■\n");
printf("■■■■■ ■■■ ■ ■ ■\n");
printf(" ■ ■ ■ ■■\n");
printf(" ■■ ■ ■ ■ ■\n\n");
}
/******* ブロック単体 出力テスト用 *********/
void Output_test(int type)
{
int i, j;
int size;
size = block_data[type].block_size;
for (i = 0; i < size; i++){
for (j = 0; j < size; j++){
if (st.direction % 2 == 0){
Draw_block(block_data2[type].block[i][j]);
}
else{
Draw_block(block_data[type].block[i][j]);
}
}
printf("\n");
}printf("\n");
}
長らく悩んでいるのですが原因が分からず困っております。
質問するには長いプログラムで大変恐縮なのですが、ぱっとみて何か思い当たる点がございましたらご教示くださると幸いです。
よろしくお願い致します。