#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#include <fcntl.h>
#define TTY_PATH "/dev/tty"
#define STTY_US "stty raw -echo -F "
#define STTY_DEF "stty -raw echo -F "
#define WIDTH 12
#define HEIGHT 22
struct Point{
int x;
int y;
};
struct Point shapes[19][4]={
{{0,0},{-1,0},{1,0},{2,0}},
{{0,0},{0,-1},{0,1},{0,2}},
{{0,0},{-1,-1},{-1,0},{0,-1}},
{{0,0},{0,-1},{0,-2},{1,0}},
{{0,0},{0,1},{1,0},{2,0}},
{{0,0},{-1,0},{0,1},{0,2}},
{{0,0},{0,-1},{-1,0},{-2,0}},
{{0,0},{-1,0},{0,-1},{0,-2}},
{{0,0},{0,-1},{1,0},{2,0}},
{{0,0},{1,0},{0,1},{0,2}},
{{0,0},{-1,0},{-2,0},{0,1}},
{{0,0},{-1,0},{1,0},{0,-1}},
{{0,0},{0,1},{0,-1},{1,0}},
{{0,0},{-1,0},{1,0},{0,1}},
{{0,0},{-1,0},{0,-1},{0,1}},
{{0,0},{1,0},{0,-1},{-1,-1}},
{{0,0},{1,-1},{0,1},{1,0}},
{{0,0},{1,-1},{-1,0},{0,-1}},
{{0,0},{-1,-1},{-1,0},{0,1}}
};
int shapeIndex=0;
int x=0,y=0;
int screen[HEIGHT][WIDTH]={0};
void change();
void drowPoint();
void fallDown();
void addToStaticScreen();
void createShape();
void clearLines();
void moveLines();
void initScreen(){
int i;
for(i=0;i<WIDTH;i++){
screen[0][i]=2;
screen[HEIGHT-1][i]=2;
}
int j;
for(j=0;j<HEIGHT;j++){
screen[j][0]=2;
screen[j][WIDTH-1]=2;
}
}
void userCtrl(){
char c=getChar();
switch(c){
case 'a':
if(leftMove())
x--;
break;
case 'd':
if(rightMove())
x++;
break;
case 's':
fallDown();
break;
case 'w':
change();
break;
case 3:
system(STTY_DEF TTY_PATH);
exit(0);
break;
}
}
void fallDown(){
if(downMove()){
y++;
}else{
addToStaticScreen();
clearLines();
createShape();
}
}
void clearLines(){
int count=0;
int i;
for(i=HEIGHT-2;i>0;i--){
if(isFull(i)){
count++;
}else if(count>0){
moveLines(i,i+count);
}
}
}
int isFull(int line){
int i;
for(i=0;i<WIDTH-1;i++){
if(screen[line][i]==0){
return 0;
}
}
return 1;
}
void moveLines(int src,int desc){
int i;
for(i=1;i<WIDTH-1;i++){
screen[desc][i]=screen[src][i];
screen[src][i]=0;
}
}
void addToStaticScreen(){
int i;
for(i=0;i<4;i++){
int pointX=shapes[shapeIndex][i].x+x;
int pointY=shapes[shapeIndex][i].y+y;
screen[pointY][pointX]=1;
}
}
int leftMove(){
int px=x-1;
int py=y;
int i;
for(i=0;i<4;i++){
int pointX=shapes[shapeIndex][i].x+px;
int pointY=shapes[shapeIndex][i].y+py;
if(screen[pointY][pointX]!=0){
return 0;
}
}
return 1;
}
int rightMove(){
int px=x+1;
int py=y;
int i;
for(i=0;i<4;i++){
int pointX=shapes[shapeIndex][i].x+px;
int pointY=shapes[shapeIndex][i].y+py;
if(screen[pointY][pointX]!=0){
return 0;
}
}
return 1;
}
int downMove(){
int px=x;
int py=y+1;
int i;
for(i=0;i<4;i++){
int pointX=shapes[shapeIndex][i].x+px;
int pointY=shapes[shapeIndex][i].y+py;
if(screen[pointY][pointX]!=0){
return 0;
}
}
return 1;
}
void change(){
int peIndex=shapeIndex;
switch(peIndex){
case 1:
peIndex=0;
break;
case 2:
break;
case 6:
peIndex=3;
break;
case 10:
peIndex=7;
break;
case 14:
peIndex=11;
break;
case 16:
peIndex=15;
break;
case 18:
peIndex=17;
break;
default:
peIndex++;
break;
}
if(changeMove(peIndex)){
shapeIndex=peIndex;
}
}
int changeMove(int peIndex){
int i;
for(i=0;i<4;i++){
int pointX=shapes[peIndex][i].x+x;
int pointY=shapes[peIndex][i].y+y;
if(screen[pointY][pointX]!=0){
return 0;
}
}
return 1;
}
void draw(){
int i,j;
for(i=0;i<4;i++){
drowPoint(shapes[shapeIndex][i].x+x,shapes[shapeIndex][i].y+y);
}
for(i=0;i<HEIGHT;i++){
for(j=0;j<WIDTH;j++){
if(screen[i][j]!=0){
drowPoint(j,i);
}
}
}
fflush(stdout);
}
void createShape(){
x=WIDTH/2;
y=2;
shapeIndex=rand()%19;
}
int getChar()
{
fd_set rfds;
struct timeval tv;
int ch = 0;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 10;
if (select(1, &rfds, NULL, NULL, &tv) > 0)
{
ch = getchar();
}
return ch;
}
void drowPoint(int x, int y)
{
printf("\033[%d;%dH", y+1, x*2+1);
if(x==0||x==WIDTH-1||y==0||y==HEIGHT-1){
printf("\033[0;31m◆\033[0m ");
}else{
printf("\033[1;36m■ \033[0m");
}
}
int main(){
srand(time(0));
system(STTY_US TTY_PATH);
createShape();
initScreen();
printf("\033[?25l");
int count=0;
while(1){
system("clear");
draw();
userCtrl();
if(++count==10){
fallDown();
count=0;
}
usleep(50*1000);
}
return 0;
}