翌日開発


真ん中に長い間隔があります.部活であれ対外活動であれ、いろいろなことに追われているが、実は遊んでいる.怠け者のせいだ.いずれにしても、家のネットが切れているので、何もすることがないので、退屈な時にキーボードを取り直しました.前回はゲームベースの制作のみでしたが、今回はプレイヤーが移動する積み木とその周辺機能を制作します.
int acblock[4][4];	//활성화 된 블록
まずacblock配列を宣言し,次いで7つの三元群のうちの1つをランダムに抽出してこの配列に格納した.これはプレイヤーが操作できる積み木になります.そのためには、ランダム関数rand関数を使用する必要がありますが、前の最初の見出しではと<時間.宣言h>.はrand関数を含むヘッダ,はtimeと同様に,その名の通り,時間に関連する関数を含むヘッダである.
rand関数を使用するには時間関数が必要です.rand関数は、プログラムのデバッグ時に1回のみ生成され、再変更されない特定のシード値に基づいてランダム数列を生成します.つまり,再オープンプログラムを閉じても,常に同じ数列を生成する.これを防止するために、シード値としての最適値が現在の時間の値であるため、プログラムを実行するたびにシード値を変更する必要があります.h>を宣言する.
srand(time(NULL));		//시간에서 시드값 끌어오기
まず、メイン関数で宣言し、シード値を生成します.
void acran(void)
{
	int i, j;
	int num;
	
	num=rand()%7;	//블록 종류가 7개이기 때문에
	
	for(i=0; i<4; i++)
	{
		for(j=0; j<4; j++)
		{
			acblock[i][j]=block[num][0][i][j];
		}
	}
}
acran関数を確立し,acblockアレイをランダムに三元グループにロードした.
次に、ブロックを画面に表示するために出力する必要があります.まず、ブロックの横座標がx座標8格子を占めることを考慮して、ブロックが最初に出力する座標を(16,10)とする.
int x=16; 
int y=10;
次に、次のようにグローバル変数をタイトルに宣言します.複数の関数にわたって使用されるためです.出力ブロックの関数を追加します.
void printsq(int arr[4][4])
{
	int i, j;
	
	for(i=0; i<4; i++)
	{
		gotoxy(x, y+i);
		
		for(j=0; j<4; j++)
		{
			if(arr[i][j]==1)
				printf("▣");
	
			else if(arr[i][j]==0)
				printf("  ");	//스페이스 두 칸
		}
	}
}
しかし,このようにコードを記述すると,後の元のブロックが新しく出現したブロックの2つのスペースで覆われ,見えない場合が生じる.
void printsq(int arr[4][4])
{
	int i, j;
	
	for(i=0; i<4; i++)
	{
		gotoxy(x, y+i);
		
		for(j=0; j<4; j++)
		{
			if(arr[i][j]==1)
				printf("▣");
	
			else if(arr[i][j]==0)
				gotoxy(x+2*(j+1), y+i);
		}
	}
}
したがって、このように変更することで、gotoxyを使用してブロックが出力する部分をカーソルをスキップするのではなく、ブロックのない空き領域にスペースを出力することができ、既存のブロックが上書きされないようにすることができる.次に、ブロックが出力を続けると、移動時に残像が残るため、既存の位置から出力された部分を消去し、移動位置で再出力する必要があるため、次の関数が作成されます.出力ブロックの関数では,■部分のみが2つの空白となる.
void rvprintsq(int arr[4][4])	//잔상 삭제
{
	int i, j;
	
	for(i=0; i<4; i++)
	{
		gotoxy(x, y+i);
		
		for(j=0; j<4; j++)
		{
			if(arr[i][j]==1)
				printf("  ");	//스페이스 두 칸
	
			else if(arr[i][j]==0)
				gotoxy(x+2*(j+1), y+i);
		}
	}
}
そして回転と移動です.回転時には、ブロックの中央に仮想点を基準として、以下の簡単な演算で座標を回転します.
void turnL(void)	//좌로 회전 
{
	int n=0;
	rvprintsq(acblock);	//잔상 삭제
    
	n=acblock[0][0];
	acblock[0][0]=acblock[3][0];
	acblock[3][0]=acblock[3][3];
	acblock[3][3]=acblock[0][3];
	acblock[0][3]=n;
	
	n=acblock[1][0];
	acblock[1][0]=acblock[3][1];
	acblock[3][1]=acblock[2][3];
	acblock[2][3]=acblock[0][2];
	acblock[0][2]=n;
	
	n=acblock[2][0];
	acblock[2][0]=acblock[3][2];
	acblock[3][2]=acblock[1][3];
	acblock[1][3]=acblock[0][1];
	acblock[0][1]=n;
	
	n=acblock[1][1];
	acblock[1][1]=acblock[2][1];
	acblock[2][1]=acblock[2][2];
	acblock[2][2]=acblock[1][2];
	acblock[1][2]=n;
	
    	printsq(acblock);	//회전된 모습 출력
}
ブロックの移動は先ほど宣言したグローバル変数x,yを利用して,単純に方向キー入力を受ける場合,左右移動はx+=2とx−=2,下向き移動はy−=1である.
void moveL(void)	//좌로 이동 
{
	rvprintsq(acblock);	//잔상 삭제
	
	if(x>10)	//블록이 게임 화면을 벗어나지 않도록
		x-=2;
		
	printsq(acblock);	//이동한 자리에 출력
}
右側、下、上に似ていればいいです.しかしこのときブロックがゲーム画面から離れないと宣言したif(x>10)という文法はブロックの位置を座標で制限する方式で、この方式では左壁で貼る場合、ブロックはL形なので左側の格子がすべて空いていても、下の写真のようにこれ以上前に進むことはできません.
したがって,その後,前回設計したゲームフレームを配列に保存し,座標を計算し,衝突するか否かを計算する関数を生成する.これからは積み重ねた積み木と重なるのを避けるため、一時的な方法として使いましょう.
次に、キーボード入力を受信したときに作成した関数を実行する関数を作成します.
通常のキーや特殊なキーではなく方向キーを入力する場合は、いくつかの問題に注意する必要があります.つまり、彼らは2回アスキーコードを返します.まず、方向キーは上下左右224、次に左キーは75、右キーは77、上キーは72、下キーは80を返します.
if(kbiht())
{
    int a = 0;
    
    a =_getch();
    {
    	if(a==224)
        {
        	if(a==75)
         	    printf("왼쪽 방향키");
        }
    }  
}
    
したがって、次の方法で2回の値を取得する必要があります.getch()関数ヘッダーで、コードの上部に宣言します.
int kb(void)
{
	int kb=0;

	kb=_getch();
	
	if(kb==224)
	{
		kb=_getch();
			
		if(kb==75)
			moveL();	
		
		else if(kb==77)
			moveR();
			
		else if(kb==80)
		{
			moveD();
			return 1;
		}	
	}
		
	else if(kb==100)
		turnL();
		
	else if(kb==115)
		turnR();
	
	return 0;	
}
ここでキーボード入力を受信するには盲点があります.c言語はプログラム向けのプログラミング言語であり,前に実行した関数が完了するまで次の関数は実行できない.ただし、ゲームを作るときは、ゲームとキーボード入力を同時に行います.私がやっているテトリスは毎秒1段下に進み、キーボード入力を受け取ったら、回転と移動を同時にさせたいと思っています.
Sleep(1000);	//1초 기다리기(1000밀리세컨드)
kbhit();	//입력받기
このとき,このようにsleep関数を用いてユーザを1秒待たせると,待機する1秒以内にキーボード入力が受信できず,ゲーム中の他の要素も実行できなくなる.
for(i=0; i<100; i++) //100 * 10 = 1초(1000밀리세컨드)
{
	Sleep(10);	//10밀리세컨드 기다리기
    	kbhit();	//키보드 입력
}
しかしこれを実現すると,1秒で0.01秒ごとにキーボード入力が受信される.すなわち,1秒遅延とキーボード入力を同時に行うことができる.関数を作成するために適用しましょう.
void moveac(void)
{
	int i;

	while(1) // 무한반복
	{	
		printsq(acblock); //블록 출력
		for(i=0; i<100; i++)	//100*10 밀리세컨트 = 1초
		{
			if(kbhit()) //키보드 입력이 있다면
			{
				if(kb()==1); 
					continue;	//밑으로 이동할 때 지연시간 초기화(0.5초 지났을 때 밑으로 하강시 다시 1초 기다려야 1칸 하강)
			}
				
			Sleep(10);
		}
		rvprintsq(acblock); //잔상 지우기
		y+=1; //1초마다 한 칸씩 밑으로 내려감
	}
	
}
さあ.これにより、ブロックが回転したり移動したりすることができます.しかし,これまで作成したコードのみを用いて実現すれば,ブロックは停止せず,下がり続けるだけである.次に,特定の部分に到達し,条件を満たすと停止部分を実現する.
頭を働かせてキーボードを握ろうと努力したが、整理してみるとボリュームが少ないという.勉強って、もともとそういう人生なんですよね.これからも頑張りましょう.