테트리스 개발 5일차

나묘쿠·2022년 1월 18일
0

테트리스

목록 보기
5/8

힘들다. 하지만 해냈다. 생각보다 쉬웠다. 물론 성공하고 난 뒤엔 뭐든 별게 아니지만 말이다. 4일차 글을 쓰고 계속 테트리스에 대해 생각해보았다. 물론 넷플릭스도 보고 게임도 하고 책도 읽고 할 건 다 했다. 저번 4일차 글을 쓸 때 회전할 때 겹치는 문제는 단순히 겹치네? 그럼 이동. 의 문제가 아니라 게임 룰과 관련된 문제라고 했었는데, 그래서 이런저런 다양한 테트리스들을 했다. 그리고 내린 결론은. 다들 제멋대로다. 오락실의 고전 테트리스는 벽에 붙어있으면 I자 블록은 회전이 안 되는데 반해 다른 블록들은 잘만 회전한다. 그러면서 또 어떤 기준에선 회전이 안 되더라. 온라인 무료 테트리스들은 회전을 하면 블록이 예측이 안 되는 이상한 곳으로 날아가는 경우도 있었고 뿌요뿌요 테트리스는 룰이 너무 전문적이어서 참고가 되지 않았다. 며칠을 계속 고민했다. 그러다 모바일로 한 무료 테트리스 게임을 하다가 그냥 나도 내 마음대로 하기로 했다. 결국 생각해낸 알고리즘의 기본 틀은

뭐 그냥 이렇게 생각나는 대로 썼다. 많이 틀렸고 서술도 개판이지만 이 기본 틀은 도움이 많이 되었다.

어쨌든. 먼저 간섭이 되는 구간을 나누었다.

테트리스의 arr[j][i]를 저렇게 분석해보았다. 1부터 9까지의 영역은 I자 블록을 제외한 블록들이 움직이는 공간이고 (0, 1)과 (2, 3)은 I자 블록만 사용하는 공간이고 나머지 공간은 사용되지 않는 공간이다.

왼쪽과 간섭하는 공간은 1, 2, 3
오른쪽과 간섭하는 공간은 7, 8, 9
윗쪽과 간섭하는 공간은 1, 4, 7
아랫쪽과 간섭하는 공간은 3, 6, 9
I자 블록일 땐 (0, 1), (2, 3)이 간섭될 수 있고
(2, 1)은 모든 블록이 간섭될 수 있다.

int blockcheckturnL(void)		//회전시 왼쪽 간섭체크 
{
	int j;
	
	for(j=0; j<3; j++)
	{
		if(acblock[j][1]==1&&gameblock[y-11+j][(x-10)/2+1]==1)
		{
			if(j==0)
				return 1;
					
			else if(j==1)
				return 1;
				
			else if(j==2)
				return 1;
		}
	}
	return 0;
}

int blockcheckturnR(void)		//회전시 오른쪽 간섭체크 
{
	int j;
	
	for(j=0; j<3; j++)
	{
		if(acblock[j][3]==1&&gameblock[y-11+j][(x-10)/2+3]==1)
		{
			if(j==0)
				return 2;
					
			else if(j==1)
				return 2;
				
			else if(j==2)
				return 2;
		}
	}
	return 0;
}

int blockcheckturnU(void)		//회전시 위쪽 간섭체크 
{
	int i;
	
	for(i=1; i<4; i++)
	{
		if(acblock[0][i]==1&&gameblock[y-11][(x-10)/2+i]==1)
		{
			if(i==1)
				return 3;
					
			else if(i==2)
				return 3;
				
			else if(i==3)
				return 3;
		}
	}
	return 0;
}

int blockcheckturnD(void)		//회전시 아래쪽 간섭체크 
{
	int i;
	
	for(i=1; i<4; i++)
	{
		if(acblock[2][i]==1&&gameblock[y-11+2][(x-10)/2+i]==1)
		{
			if(i==1)
				return 4;
					
			else if(i==2)
				return 4;
				
			else if(i==3)
				return 4;
		}
	}
	return 0;
}

요렇게 상하좌우 간섭을 체크할 함수를 만들어준다.
그 다음은 대망의 회전 체크 알고리즘이다. 사실 간단하다.

회전, 상하좌우 간섭 검사 후, 간섭시 블록을 피해 이동, 이동한 좌표에서 간섭 확인, 간섭시 한번 더 피해 이동, 이동한 좌표에서 간섭 다시 확인, 간섭시 이동한 좌표 모두 원상복귀 후 다시 반대로 회전.

이 알고리즘을 상하좌우에 맞추어 코드를 만들었다.

가장 먼저 I자블록의 (0, 1)좌표와 (2, 3)좌표에서 간섭하는지 확인한다. (0, 1)에서 간섭시 x좌표를 2만큼 더해준다. (2, 3)에서 간섭시 y좌표를 1만큼 빼준다.

다음은 하단 간섭체크이다. 좌우 간섭체크보다 하단 간섭체크를 먼저 한 이유는 좌/우가 간섭되어 일어나는 좌표이동보다 하단이 간섭되어 일어나는 좌표이동이 일관적이기 때문이었다. 다 만들고 나니 400줄 짜리 코드가 되었다. 용기는 나지 않지만 정리가 가능하다면 정리를 해야겠다. 그리 잘 쓴 주석은 아니지만 코드 분석은 주석을 참고하길 바란다.

int blockcheckturn(void)		//회전시 간섭체크 
{
	if(acblock[3][2]==1&&gameblock[y-11+3][(x-10)/2+2]==1)		//I자블록의 (2, 3) 좌표 간섭 체크 
	{
		y-=1;
		
		if(blockcheckturnU()==3)		//이동한 좌표가 위쪽 간섭 시 이동한 좌표 초기화, 회전 불가 신호 
		{
			y+=1;
			return 1;
		}
		
		else
		{
			if(blockcheckturnD()==4)		//이동한 좌표가 아랫쪽 간섭 시 한 칸 더 이동 
			{
				y-=1;
				
				if(blockcheckturnU()==3)		//다시 이동한 좌표가 위쪽 간섭시 이동한 좌표 초기화, 회전 불가 신호  
				{
					y+=2;
					return 1;
				}
				
				else
					return 0;
			}
			
			else 
				return 0;
		}
	}
	
	else if((acblock[1][0]==1&&gameblock[y-11+1][(x-10)/2]==1)&&x>=10)		//I자블록의 (0, 1)간섭 체크 
	{
		x+=2;
		
		if(blockcheckturnR()==2)		//이동한 좌표가 오른쪽 간섭시 이동한 좌표 초기화, 회전 불가 신호 
		{
			x-=2;
			return 1;
		}
		
		else
			return 0;
	}
	
	else if(blockcheckturnD()==4)		//하단 간섭 체크 
	{
		if(acblock[3][2]==1)		//I자 블록 간섭시 
		{
			y-=2;
			
			if(blockcheckturnU()==3||(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1))		//위쪽, 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=2;
				return 1;
			}
			
			else 
				return 0;
		}
		
		y-=1;
		
		if(blockcheckturnU()!=3)		//이동한 좌표 상단 간섭 안 할 때  
		{
			if(blockcheckturnL()==1)		//좌측 간섭체크, 간섭시 좌표이동 
			{
				x+=2;
			
				if(blockcheckturnD()==4)		//이동한 좌표 하단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y+=1;
					return 1;
				}
				
			
				else if(blockcheckturnL()==1)		//이동한 좌표 좌측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y+=1;
					return 1;
				}
			
				else if(blockcheckturnR()==2)		//이동한 좌표 우측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y+=1;
					return 1;
				}
			
				else if(blockcheckturnU()==3)		//이동한 좌표 상단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y+=1;
					return 1;
				}
				
				else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y+=1;
					return 1;
				}
				
				else
					return 0;
			}
			
			else if(blockcheckturnR()==2)		//오른쪽 간섭 체크, 간섭시 좌표이동 
			{
				x-=2;
			
				if(blockcheckturnD()==4)				//이동한 좌표 하단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y+=1;
					return 1;
				}
				
			
				else if(blockcheckturnL()==1)		//이동한 좌표 좌측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y+=1;
					return 1;
				}
			
				else if(blockcheckturnR()==2)		//이동한 좌표 우측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y+=1;
					return 1;
				}
			
				else if(blockcheckturnU()==3)		//이동한 좌표 상단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y+=1;
					return 1;
				}
				
				else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y+=1;
					return 1;
				}
				
				else
					return 0;
			}
		}
		
		else		//상단 간섭시 이동한 좌표 초기화, 회전 불가 신호 
		{
			y+=1;
			return 1;
		}		
	}
	
	else if(blockcheckturnL()==1)		//좌측 간섭 체크 후 간섭시 좌표이동 
	{	
		if(acblock[1][0]==1)		//I자 블록 간섭일 시 좌표이동 
		{
			x+=4;
			
			if(blockcheckturnR()==2||(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1))		//이동한 좌표 우측 간섭 체크, 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				x-=4;
				return 1;
			}
			
			else 
				return 0;
		}
		
		x+=2;
		
		if(blockcheckturnR()==2)		//이동한 좌표 우측 간섭 체크, 간섭시 좌표 이동 
		{
			x-=2;
			y-=1;
			
			if(blockcheckturnD()==4)		//이동한 좌표 하단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
				
			
			else if(blockcheckturnL()==1)		//이동한 좌표 좌측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
			
			else if(blockcheckturnR()==2)		//이동한 좌표 우측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
			
			else if(blockcheckturnU()==3)		//이동한 좌표 상단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
			
			else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
			
			else
				return 0;
		}
		
		else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
		{
			y+=1;
			return 1;
		}
		
		else
			return 0;
	}
	
	else if(blockcheckturnR()==2)		//우측 간섭 체크, 간섭시 좌표이동 
	{
		x-=2;
		
		if(blockcheckturnL()==1)		//이동한 좌표 좌측 간섭체크, 간섭시 좌표이동 
		{
			x+=2;
			y-=1;
			
			if(blockcheckturnD()==4)		//이동한 좌표 하단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
				
			
			else if(blockcheckturnL()==1)		//이동한 좌표 좌측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
			
			else if(blockcheckturnR()==2)		//이동한 좌표 우측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
			
			else if(blockcheckturnU()==3)		//이동한 좌표 상단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}
			
			else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
			{
				y+=1;
				return 1;
			}	
			
			else
				return 0;
		}
		
		else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
		{
			y+=1;
			return 1;
		}
		
		else
			return 0;
	}
	
	else if(blockcheckturnU()==3)		//상단 간섭 체크, 간섭시 좌표이동 
	{
		y+=1;
		
		if(blockcheckturnD()!=4)		//이동한 좌표 하단 간섭 안 할 때 
		{
			if(blockcheckturnL()==1)		//이동한 좌표 좌측 간섭 체크, 간섭시 좌표이동 
			{
				x+=2;
			
				if(blockcheckturnD()==4)		//이동한 좌표 하단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y-=1;
					return 1;
				}
				
			
				else if(blockcheckturnL()==1)		//이동한 좌표 좌측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y-=1;
					return 1;
				}
			
				else if(blockcheckturnR()==2)		//이동한 좌표 우측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y-=1;
					return 1;
				}
			
				else if(blockcheckturnU()==3)		//이동한 좌표 상단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x-=2;
					y-=1;
					return 1;
				}
				
				else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					y+=1;
					return 1;
				}
				
				else
					return 0;
			}
			
			if(blockcheckturnR()==2)		//이동한 좌표 우측 간섭체크, 간섭시 좌표이동 
			{
				x-=2;
			
				if(blockcheckturnD()==4)		//이동한 좌표 하단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y-=1;
					return 1;
				}
				
			
				else if(blockcheckturnL()==1)		//이동한 좌표 좌측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y-=1;
					return 1;
				}
			
				else if(blockcheckturnR()==2)		//이동한 좌표 우측 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y-=1;
					return 1;
				}
			
				else if(blockcheckturnU()==3)		//이동한 좌표 상단 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					x+=2;
					y-=1;
					return 1;
				}
				
				else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
				{
					y+=1;
					return 1;
				}
			
				else
					return 0;
			}
		}
		
		else		//하단 간섭 시 이동한 좌표 초기화, 회전 불가 신호 
		{
			y-=1;
			return 1;
		}		
	}
	
	else if(acblock[1][2]==1&&gameblock[y-11+1][(x-10)/2+2]==1)		//이동한 좌표 중앙 간섭 체크, 간섭시 이동한 좌표 초기화, 회전 불가 신호 
	{
		y+=1;
		return 1;
	}
	
	else
		return 0;
	
}

이렇게 회전 가능/불가능 신호를 보내는 코드를 만들었다.
이 코드만 몇날 며칠을 계속 뜯어고쳤다. 다 만들고 나서는 (2, 1)의 간섭을 고려하지 않아 계속


위의 사진처럼 블록이 이상하게 겹치는 상황이 발생했다. 위 상황이 계속 발생하는데 원인을 몰라 해매던 도중에 딱 저렇게 겹친 것을 보고 (2, 1)의 간섭을 고려하지 않아 일어나는 일이라는 것을 깨닫고 수정하였다.

그 다음은 회전을 시키는 코드를 만들어야 한다. 기존에 있던 코드를 조금 바꿔서

void calcturnL(void)
{
	int n=0;
	
	n=acblock[2][3];		//회전축 기준 꼭짓점 회전 
	acblock[2][3]=acblock[2][1];
	acblock[2][1]=acblock[0][1];
	acblock[0][1]=acblock[0][3];
	acblock[0][3]=n;
	
	n=acblock[1][3];		//회전축 기준 모서리 회전 
	acblock[1][3]=acblock[2][2];
	acblock[2][2]=acblock[1][1];
	acblock[1][1]=acblock[0][2];
	acblock[0][2]=n;
	
	n=acblock[1][0];		//일자블록만 포함되는 부분 회전 
	acblock[1][0]=acblock[3][2];
	acblock[3][2]=n;
}

void calcturnR(void)
{
	int n=0;
	
	n=acblock[0][3];		//회전축 기준 꼭짓점 회전 
	acblock[0][3]=acblock[0][1];
	acblock[0][1]=acblock[2][1];
	acblock[2][1]=acblock[2][3];
	acblock[2][3]=n;
	
	n=acblock[0][2];		//회전축 기준 모서리 회전 
	acblock[0][2]=acblock[1][1];
	acblock[1][1]=acblock[2][2];
	acblock[2][2]=acblock[1][3];
	acblock[1][3]=n;
	
	n=acblock[1][0];		//일자블록만 포함되는 부분 회전 
	acblock[1][0]=acblock[3][2];
	acblock[3][2]=n;
}

이렇게 회전연산을 하는 코드를 함수로 빼고
기존 함수는 회전기능을 종합하는 함수로 사용한다. 코드 분석은 주석을 참고하길 바란다.

void turnL(void)		//반시계방향 회전 
{
	if(acblock[1][2]==1&&acblock[2][1]==1&&acblock[2][2]==1&&acblock[1][1]==1)		//정사각형 블록일시 생략 
		return;
	
	rvprintsq(acblock);		//잔상제거 
	
	calcturnL();	//회전연산
	
	if(blockcheckturn()==1)		//회전 불가 신호시 다시 원상복구  
		calcturnR();
		
	printsq(acblock);		//블록 출력 
}

void turnR(void)		//시계방향 회전 
{
	if(acblock[1][2]==1&&acblock[2][1]==1&&acblock[2][2]==1&&acblock[1][1]==1)		//정사각형 블록일시 생략 
		return;
		
	
	rvprintsq(acblock);		//잔상제거 
	
	calcturnR();	//회전연산
	
	if(blockcheckturn()==1)		//회전 불가 신호시 다시 원상복구  
		calcturnL();
	
	printsq(acblock);		//블록 출력 
}

뭐 이런식으로 썼다. 하지만 코드를 검토하던 도중 정말 어이없는 버그를 찾았는데 그게 뭐냐하면

void turnL(void)		//좌로 회전 
{
	if(acblock[1][2]==1&&acblock[2][1]==1&&acblock[2][2]==1&&acblock[1][1]==1)		//정사각형 블록일시 생략 
		return;
	
	rvprintsq(acblock);		//잔상제거 
	
	calcturnL();
	
	if(blockcheckturn()==1)
		calcturnR;
		
	printsq(acblock);		//블록 출력 
}

calcturnR(); 이라 써야 하는데 그냥 calcturnR;으로 괄호를 빼먹고 썼다.... 회전 간섭 함수가 채 완성되지 않았을 때 찾아 고친 버그인데 이 버그를 고쳤더니 잘 작동하던 회전간섭이 도로 말썽을 일으켰었다. 뭐 결국엔 주먹구구식으로 굴러가던 코드를 제대로 고쳤다는 이야기니까 잘된거지만...당시엔 상당히 골이 아팠다.

나머지 기능을 만들기 전에 이제 커서를 보이지 않게 할 것이다.

void cursorview()
{
    CONSOLE_CURSOR_INFO cursorInfo = { 0, };
    cursorInfo.dwSize = 1; //커서 굵기 (1 ~ 100)
    cursorInfo.bVisible = FALSE; //커서 Visible TRUE(보임) FALSE(숨김)
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
}

를 사용해주고 (인터넷에서 복사해온 것이다. 출처 : https://coding-factory.tistory.com/691)

main함수에 cursorview();를 선언해주면

반짝거리던 커서가 보이지 않게 된다.
사진의 색깔은 지금부터 넣어볼 것이다.

windows.h 헤더의 SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), i); 함수를 사용하여 텍스트의 색깔을 바꿀 수 있다. 이때 i는 색상 코드이다.

이것도 인터넷에서 가져왔다.
출처 : https://m.blog.naver.com/wcwtmt/10172917569

여기서 우리가 필요한 색깔은

I블록 11번
T블록 13번
O블록 14번
L블록 4번
J블록 9번
S블록 10번
Z블록 12번 색깔이다.

int compareblock(int arr[4][4], int a)
{
	int i, j;
	
	for(i=0; i<4; i++)
	{
		for(j=0; j<4; j++)
		{
			if(arr[i][j]!=block[a][i][j])
				return 1;
		}
	}
	
	return 0;
}

이렇게 2차원 배열을 블록들의 첫 번째 모양과 비교해주는 함수를 만들고

int setcolor(int arr[4][4])		//블록의 모양에 따라 필요한 색 코드 반환 
{
	int i;
	
	for(i=0; i<7; i++)
	{
		if(compareblock(arr, i)==0)
			break;
	}
	
	if(i==0)		//I
		return 11;		//하늘색 
	
	else if(i==1)		//T
		return 13;		//핑크색 
	
	else if(i==2)		//O
		return 14;		//노란색 
		
	else if(i==3)		//L
		return 4;		//다홍색 
		
	else if(i==4)		//J
		return 9;		//파랑색 
		
	else if(i==5)		//S
		return 10;		//연두색 
	
	else if(i==6)		//Z
		return 12;		//빨간색 
}

이렇게 블록의 모양에 따라 필요한 색깔의 번호를 반환하는 함수도 만들어준다.

void blockprint(void)		//대기중인 블록 출력 
{
	x=40;
	y=10;	
	SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), setcolor(blocksetprint[0]));	
	printsq(blocksetprint[0]);		//첫번째 대기 
	
	y=15;
	SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), setcolor(blocksetprint[1]));
	printsq(blocksetprint[1]);
	
	y=20;
	SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), setcolor(blocksetprint[2]));
	printsq(blocksetprint[2]);
	
	y=25;
	SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), setcolor(blocksetprint[3]));
	printsq(blocksetprint[3]);
	
	y=30;
	SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), setcolor(blocksetprint[4]));
	printsq(blocksetprint[4]);		//다섯번째 대기 
}

대기 블록을 출력하는 함수도 이렇게 바꿔주고
main 함수의 moveac(); 바로 위에
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), setcolor(acblock)); 를 선언해준다.
기분 탓인지는 모르겠지만 이 텍스트를 설정해주는 함수가 상당히 부하가 큰 것 같다. 이 함수를 사용한 후에 게임이 더 무거워진 듯한 느낌이 든다.

후 힘들었다. 이제 남은 것은 게임 스타트 화면, 줄 완성시 제거, 가장 윗칸에 닿을 시 게임 오버가 있겠다. 이 세가지만 완성되면 게임은 모두 완성 되는 것이다. 욕심내서 더 구현하고 싶은 것이 있다면 게임의 bgm과 대기중인 블록의 칸을 확실하게 디자인 하는 것이다.
잠도 안 자고 8시간을 계속 만들었으니 이건 다음에 하고 일단 자야겠다.

profile
사고의 흐름을 따라가 보자.

0개의 댓글