C , C++언어로 Linux 테트리스 만들기

SangHoon Lee·2020년 4월 9일
2

안녕하세요 저는 C++을 공부하고있는 대학생입니다.
제가 리눅스를 이용해서 테트리스를 만들었느데, 기본적으로 라즈베리파이3를 사용하였으며, GPIO 컨트롤을 이용하여 화면을 제어 할 수 있는 테트리스를 만들었습니다.

우선. 화면의 좌표를 잡기 위해 간단히 숙지 해 두어야 할 것이 있습니다.
화면에서 가로가 X축, 세로가 Y축입니다. 다만 우리가 기존에 알고있는 좌표계에서의 X축의 양의방향 과 음의방향은 같지만, Y축은 반대로, 컴퓨터상에서 양의방향은 아래쪽방향 이며 음의방향은 위쪽 방향 입니다.

그리고 간단하게 제가 이 테트리스를 만들기 전, 아이디어를 말씀드리자면 배열을 이용해서 하였습니다. 테트리스 배열판을 가로 세로축으로 크기를 정한다음, 2차원배열을 이용해서 오리지널 맵 과 카피 맵 두가지 맵에 대한 배열을 만들어서 표현하였습니다. 소스코드는 아래와 같습니다.

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

#define MAIN_X 10
#define MAIN_Y 20

int map[MAIN_X][MAIN_Y] = {0, };
int mapcpy[MAIN_X][MAIN_Y] = {0, };

void gotoxy(int x,int y) {
	printf("\033[%d;%df",y,x);
	fflush(stdout);
}

int maps(int n)
{
	for(int i =0; i<MAIN_X; i++)
	{
		for(int j =0; j<MAIN_Y; j++)
		{
			if(i==MAIN_X-1||j==0||j==MAIN_Y-1)
			{
				map[i][j]=1;
				mapcpy[i][j] = 1;
			}
			else
			{
				map[i][j] =0;
				mapcpy[i][j]=0;
			}
		}
	}
	if(n == 1)
	{
		for(int i =0; i<MAIN_X; i++)
		{
			for(int j =0; j<MAIN_Y; j++)
			{
				if(map[i][j]==1)
				{
					printf("%c[43m",27);
					printf("■");
					printf("%c[49m",27);
				}
				else printf(" ");
			}
			printf("\n");
		}
	}
        else
        {
                for(int i =0; i<MAIN_X; i++)
                {
                        for(int j =0; j<MAIN_Y; j++)
                        {
                                if(mapcpy[i][j]==1)
                                {
                                        printf("%c[43m",27);
                                        printf("■");
                                        printf("%c[49m",27);
                                }
                                else printf(" ");
                        }
                        printf("\n");
                }
        }
}

리눅스에는 기본적으로 gotoxy 함수가 없습니다. gotoxy 함수는 컴퓨터 좌표계를 이동시켜주는 역할을 합니다. 윈도우 헤더 안에 함수가 있지만, 저는 사용자 정의함수를 이용하여 새로 구현하였습니다.

이 소스코드는 map.h 라는 이름을 가지고있습니다.
아까 말씀드린 것 처럼, 사각형 문자를 이용해서 벽을 표현하였고, 그 벽이있는 부분을 0으로 모두 초기화 된 배열에서 1로 값을 치환하였습니다. 그 이유는, 충돌처리를 하기 위함입니다.

다음으로는 테트리스 블록에 관한 소스코드를 보여드리겠습니다.

#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdlib.h>

int block[7][4][4][4]={
	{
		{
			1,1,0,0,
			1,1,0,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,1,0,0,
			1,1,0,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,1,0,0,
			1,1,0,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,1,0,0,
			1,1,0,0,
			0,0,0,0,
			0,0,0,0
		}
	},
	{
		{
			1,1,1,1,
			0,0,0,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,0,0,0,
			1,0,0,0,
			1,0,0,0,
			1,0,0,0
		},
		{
			1,1,1,1,
			0,0,0,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,0,0,0,
			1,0,0,0,
			1,0,0,0,
			1,0,0,0
		}
	},
	{
		{
			1,1,0,0,
			0,1,1,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,1,0,0,
			0,1,1,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
		}
	},
	{
		{
			0,1,1,0,
			1,1,0,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,0,0,0,
			1,1,0,0,
			0,1,0,0,
			0,0,0,0
		},
		{
			0,0,0,0,
			0,1,1,0,
			1,1,0,0,
			0,0,0,0
		},
		{
			1,0,0,0,
			1,1,0,0,
			0,1,0,0,
			0,0,0,0
		}
	},
	{
		{
			1,1,1,0,
			1,0,0,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,1,0,0,
			0,1,0,0,
			0,1,0,0,
			0,0,0,0
		},
		{
			0,0,1,0,
			1,1,1,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,0,0,0,
			1,0,0,0,
			1,1,0,0,
			0,0,0,0
		}
	},
	{
		{
			1,0,0,0,
			1,1,1,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			0,1,0,0,
			0,1,0,0,
			1,1,0,0,
			0,0,0,0
		},
		{
			1,1,1,0,
			0,0,1,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,1,0,0,
			1,0,0,0,
			1,0,0,0,
			0,0,0,0
		}
	},
	{
		{
			0,1,0,0,
			1,1,1,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			1,0,0,0,
			1,1,0,0,
			1,0,0,0,
			0,0,0,0
		},
		{
			1,1,1,0,
			0,1,0,0,
			0,0,0,0,
			0,0,0,0
		},
		{
			0,1,0,0,
			1,1,0,0,
			0,1,0,0,
			0,0,0,0
		}
	}
};

4차원배열로 표현하였습니다. 각각, 모양(shape) ,회전(rotation) , 블록 모양(2차원 배열) 로 표현하였습니다.
sensor.h라는 이름으로 만들어 주었습니다.

다음은 센서 제어를 이용한 소스코드를 보여드리겠습니다.

#include <iostream>
#include <stdio.h>
#include <wiringPi.h>

#define up 29
#define upL 23
#define right 28
#define rightL 22
#define down 27
#define downL 1
#define left 21
#define leftL 0

void sensor()
{
	wiringPiSetup();

	pinMode(up,INPUT);
	pinMode(upL,OUTPUT);
	pinMode(left,INPUT);
	pinMode(leftL,OUTPUT);
	pinMode(down,INPUT);
	pinMode(downL,OUTPUT);
	pinMode(right,INPUT);
	pinMode(rightL,OUTPUT);

	int curnumU =0;
	int curnumD =0;
	int curnumL =0;
	int curnumR =0;
//void up{
	if(digitalRead(up)==0)
	{
		digitalWrite(upL,1);
		curnumU = 5;
	}
	else
	{
		digitalWrite(upL,0);
		curnumU = 0;
	}

//void left{
        if(digitalRead(left)==0)
	{
		digitalWrite(leftL,1);
		curnumL = 3;
	}
        else
	{
		digitalWrite(leftL,0);
		curnumL = 0;
	}

//void right{
        if(digitalRead(right)==0)
	{
		digitalWrite(rightL,1);
		curnumR = 1;
	}
        else
	{
		digitalWrite(rightL,0);
		curnumR = 0;
	}

//void down{
        if(digitalRead(down)==0)
	{
		digitalWrite(downL,1);
		curnumD = 2;
        else
	{
		digitalWrite(downL,0);
		curnumD = 0;
	}
}

스위치랑 LED를 이용해서 제어 한 소스코드입니다. wiringPi 핀 번호를 이용해서 GPIO를 다루었습니다.
curnumD 숫자의 5 1 2 3 의미는, 키보드 패드 오른쪽 숫자패드에,
동서남북 방향의 키보드를 이용해서 컨트롤 하기 위함입니다. (혹시 키보드로 컨트롤 해야 할 경우를 대비해서 만들어 두었습니다.)

이렇게 부족한 실력이지만, 테트리스를 만들어보았는데요. 무엇보다도 혼자 만들었다는것에 보람을 느꼈고, 쭉 해보면서 저 스스로 부족한 부분을 많이 찾아보기도 하였고, 개인적으로 아쉬웠던 점을 보면서 조금 더 보완하고 돌아보았던 계기가 되었던 것 같습니다.
main 파일은 코드 길이가 900줄정도 되어서, 따로 올리기엔 힘들 것 같습니다. 그래서 핵심이 되는 헤더파일을 간단하게 정리함으로써 간단하게 올려보았습니다.
처음으로 1200줄정도 되는 코드를 작성해보아서 제가 가진 실력이 어느정도인지 알 수 있었고, 좋은 경험이 되었던 것 같습니다. 기존보다 더 열심히 해야 할 것 같습니다.

profile
C++ 공부하고있는 대학생입니다.

0개의 댓글