改善する方法を何方かよろしくお願いいたします。
#include<stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
int stage[21][12] = {0};
int field[21][12] = {0};
int block[4][4] = {0};
int blocklist[7][4][4] = {
{{0,0,0,0},
{0,1,1,0},
{0,1,1,0},
{0,0,0,0}},
{{0,0,0,0},
{0,1,0,0},
{1,1,1,0},
{0,0,0,0}},
{{0,0,0,0},
{0,0,1,0},
{0,1,1,0},
{0,1,0,0}},
{{0,0,0,0},
{0,1,0,0},
{0,1,1,0},
{0,0,1,0}},
{{0,0,0,0},
{0,1,1,0},
{0,1,0,0},
{0,1,0,0}},
{{0,0,0,0},
{0,1,1,0},
{0,0,1,0},
{0,0,1,0}},
{{0,0,1,0},
{0,0,1,0},
{0,0,1,0},
{0,0,1,0}}
};
int y = 0; //ブロックのステージ上でのy座標
int x = 4; //ブロックのステージ上でのx座標
int gameover = 0; //ゲームオーバー判定。1でゲームオーバー
int oneline,twoline,threeline,fourline;
int block_type; //ブロックの種類用。0~6の乱数を入れる
//関数プロトタイプ宣言
void Initialize(); //ゲーム起動直後の初期設定を行う関数。画面と壁のデータを初期化
int CreateBlock(); //新しいブロックを生成して次のブロックに発生させる
void ShowGameField(); //field[][]の中身に応じて、画面を描画する
void ControlBlock(); //キー入力に応じてブロックに移動や回転等の処理を行わせる
int CheckOverlap(int, int); //落下中のブロックが壁や固定済みブロックに接触していないか判別
void MoveBlock(int, int); //落下中ブロックを一旦消して、任意の座標に移動させる
int TrunBlock(); //ブロックの回転を処理する
void DropBlock(); //ブロックを落下させる。下に移動できない場合ブロックをその位置に固定
void LockBlock(); //着地したブロックを固定済みブロックに加える関数
void CheckLines(); //ブロックが横一列にそろえばそこを消去後、上のブロックをそこに下ろす
int B_type(int);//生成したブロックに番号で色のようなものをつける
int main()
{
int time = 0; //一定時間ごとにブロックを落下させるための時間稼ぎ用
Initialize(); //ステージの初期化
while(!gameover) {
if(kbhit()) {
ControlBlock();
}
if(time < 20000){
time++;
}
else{
//重なりがなければ移動
DropBlock();
time = 0;
}
}
return 0;
}
void Initialize()
{
int i, j; //forループ制御用変数
//画面と壁を初期設定
for(i = 0; i <=20; i++) {
for(j = 0; j <= 11; j++) {
if((j == 0) || (j == 11) || (i == 20)) {
field[i][j] = stage[i][j] = 9;//枠の棒
}
else {
field[i][j] = stage[i][j] = 0;
}
}
}
CreateBlock();
ShowGameField(); //ゲーム直後の画面を描画
}
int CreateBlock()
{
int i, j;
//ブロックの座標を(block4*4)最上段中央にセット
x = 4;
y = 0;
srand((unsigned)time(NULL));
block_type = rand() % 7;
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
block[i][j] = 0;
block[i][j] = blocklist[block_type][i][j];
}
}
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
field[i][j + 4] = stage[i][j + 4] + block[i][j];//+4で中央セット
//初期位置に置いたブロックが既に固定ブロックに重なっていればゲームオーバー
if(field[i][j + 4] > 1) {//0だと既に入っているので1
gameover = 1;
return 1;
}
}
}
return 0;
}
int B_type()
{
int b = 0;
switch(block_type){//CreateBlock内のblock_typeと同じ値
case 0:
b = 11;
break;
case 1:
b = 22;
break;
case 2:
b = 33;
break;
case 3:
b = 44;
break;
case 4:
b = 55;
break;
case 5:
b = 66;
break;
case 6:
b = 77;
break;
}
return b;
}
//画面表示
void ShowGameField()
{
int i, j; //forループ制御用変数
//画面を一旦クリア
system("cls");
//データに応じてブロックや空白を画面表示
for(i = 0; i<21; i++) {
for(j = 0; j < 12; j++) {
switch(field[i][j]) {
case 0:
printf(" ");
break;
case 9:
printf("□");
break;
default:
printf("%d",B_type());//番号でブロックを形成
break;
}
}
printf("\n");
}
//得点表示
printf("\n1行消し:%d回 2行消し:%d回 3行消し:%d回 4行消し:%d回\n",
oneline, twoline, threeline, fourline);
//ゲームオーバーの場合はGAME OVERを表示
if(gameover){
system("cls");
printf("\n\n\n\n\nGAME OVER\n\n");
}
}
void ControlBlock()
{
char key; //受け付けたキーを保存する変数
key = getch(); //キーから一文字入力
//キーに応じて各方向へブロックを移動したり、回転させたりする
switch(key)
{
case 'f':
if(!CheckOverlap(x+1, y)) {
MoveBlock(x+1, y);
}
break;
case 's':
if(!CheckOverlap(x-1, y)) {
MoveBlock(x-1, y);
}
break;
case 'd':
if(!CheckOverlap(x, y+1)) {
MoveBlock(x, y+1);
}
break;
case ' ':
TrunBlock();
}
}
void MoveBlock(int x2, int y2)
{
int i, j; //forループ制御用変数
//今までのブロックを消して
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
field[y+i][x+j] -= block[i][j];//blockで引くことにより0にする。
}
}
//ブロックの座標を更新
x = x2;
y = y2;
//新しい座標でブロックを入れなおす
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
field[y+i][x+j] += block[i][j];
}
}
ShowGameField();//再度読み込み描画
}
int CheckOverlap(int x2, int y2)
{
int i, j; //forループ制御用変数
//ブロックが向かう位置に固定ブロックもしくは壁があるかどうかを検査
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
if(block[i][j]) {
if(stage[y2 + i][x2 + j] != 0) {
return 1;
}
}
}
}
return 0;
}
//ブロックを落とす
void DropBlock()
{
//重なりがなければ移動
if(!CheckOverlap(x, y + 1)) {
MoveBlock(x, y + 1);//下にobj一個分降下
}
//重なりがあれば壁にする
else{
LockBlock();
CreateBlock();
ShowGameField();
}
}
void LockBlock()
{
int i, j; //forループ制御用変数
//ブロックを壁に加える
for(i = 0; i < 21; i++) {
for(j = 0; j < 12; j++) {
stage[i][j] = field[i][j];
}
}
CheckLines(); //横一列がそろってるか判定して処理する関数を呼ぶ
//列完成判定後の壁をフィールドへ
for(i = 0; i<21; i++) {
for(j = 0; j<12; j++) {
field[i][j] = stage[i][j];
}
}
}
//ブロックを回転させる処理
int TrunBlock()
{
int i,j;//forループ制御用
int temp[4][4] = {0};//ブロックを一時的に保存する配列
//ブロックを回転させる前にtenpにセーブ
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
temp[i][j] = block[i][j];
}
}
//ブロックを回転(右回り)
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
// x y y x xとyを反転させ、さらにyも反転
block[i][j] = temp[3 - j][i];//0~3 = 4 (3-j)によってjを反転
}
}
//重なっているブロックが出てしまったらブロックを回転前に戻して中止
if(CheckOverlap(x, y)){//検査結果、引数で真(1)なら回転中止
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
block[i][j] = temp[i][j];
}
}
return 1;
}
//一旦fildeからblockを消して回転後のblockを再表示
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
field[y + i][x + j] -= temp[i][j];
field[y + i][x + j] += block[i][j];
}
}
ShowGameField();
return 0;
}
//横一列が完成しているかを検査。そろっていればそこを消して上のブロック群を下す
void CheckLines()
{
int i,j,k;
int comp;//横一列そろっていれば1、一つでも隙間があると0になる
int lines = 0;//同時に消したラインの数
while(1){
for(i = 0; i < 20; i++){
comp = 1;//compを1にしておき下のfor文で0を代入する
for(j = 1; j < 11; j++){
if(stage[i][j] == 0){//横に見ていき一つでも隙間があると0になる
comp = 0;
}
}
if(comp == 1) break;//「横一列そろっていれば1」forを抜ける
}
if(comp == 0) break;
lines++;
//列の消去
for(j = 1; j < 11; j++){
stage[i][j] = 0;//blockを0に置き換える
}
//消えた列より上にあった固定ブロックを列の消えたところへ下す
for(k = i; k > 0; k--){//消えた「行」から上限の「行」まで遡る
for(j = 1; j < 11; j++){//横に見ていく
stage[k][j] = stage[k -1][j];
}
}
}
//同時に消したラインの数をカウント
switch(lines){
case 1:
oneline++;
break;
case 2:
twoline++;
break;
case 3:
threeline++;
break;
case 4:
fourline++;
break;
default:
break;
}
}