linux环境纯命令行俄罗斯方块C语言版

#include 
#include 
#include 
#include 
#include 
#include 
#include 

enum {
	S_VERTICAL,		
	S_HORIZON,		
	S_SQUARE,		
	S_THUNDER_1,	
	S_THUNDER_2,	
	S_THUNDER_3,	
	S_THUNDER_4,	
	S_EL_1,			
	S_EL_2,			
	S_EL_3,			
	S_EL_4,			
	S_EL_5,			
	S_EL_6,			
	S_EL_7,			
	S_EL_8,			
	S_TBRANCH_1,	
	S_TBRANCH_2,	
	S_TBRANCH_3,	
	S_TBRANCH_4,	
};

enum {
	LEFT,
	RIGHT,
	DOWN,
	UP
};

typedef struct point {
	int x;
	int y;
}point;

struct shape {
	int type;
	point point[4];
	int sid;
};

struct shape smap[] = {
	{0,0,0,1,0,2,0,3,0,0},
	{1,0,3,0,2,0,1,0,0,0},
	{2,0,0,0,1,1,0,1,1,0},
	{3,0,1,1,0,1,1,2,0,0},
	{4,2,2,1,1,2,1,1,0,0},
	{5,0,0,1,0,1,1,2,1,0},
	{6,1,2,1,1,2,1,2,0,0},
	{7,1,2,2,0,2,1,2,2,0},
	{8,2,1,0,0,1,0,2,0,0},
	{9,2,0,1,2,1,1,1,0,0},
	{10,0,0,2,1,1,1,0,1,0},
	{11,1,0,2,0,2,1,2,2,0},
	{12,0,1,0,0,1,0,2,0,0},
	{13,2,2,1,2,1,1,1,0,0},
	{14,2,0,2,1,1,1,0,1,0},
	{15,1,1,2,0,2,1,2,2,0},
	{16,1,1,0,0,1,0,2,0,0},
	{17,1,1,0,2,0,1,0,0,0},
	{18,1,0,2,1,1,1,0,1,0}

};	
		
int bitmap[20][10];
pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER;
struct shape curshape, nextshape;
int g_id = 1;
int score = 0;
int level = 1;
int linestat[20] = {0};
int leftedge = 0, rightedge = 0, bottom = 0;;
long long lasttime = 0;
int state;
int nexts;
struct termios new_setting,init_setting;

void clear_full_line();

int next_shape(int curs)
{
	switch (curs) {
		case S_HORIZON:
		case S_THUNDER_2:
		case S_THUNDER_4:
			return curs - 1;
		case S_EL_4:
		case S_EL_8:
		case S_TBRANCH_4:
			return curs - 3;
		case S_SQUARE:
			return curs;
		default:
			return curs + 1;
	}
}

void draw_bitmap()
{
	int i, j, k;

	printf("\033[2J");	
	
	int news[4][4] = {0};
	for (i = 0; i < 4; i++) {
		news[smap[nexts].point[i].x][smap[nexts].point[i].y] = 1;
	}
	for (i = 0; i < 4; i++) {
		printf("      ");
		for (j = 0; j < 4; j++) {
			if (news[i][j]) {
				printf("[]");
			} else {
				printf("  ");
			}
		}
		printf("\n");
	}
	write(1, "---------------------\n", sizeof("---------------------\n"));

	for (i = 0; i < 20; i++) {
		for (j = 0; j < 10; j++) {
			write(1, bitmap[i][j] ? "[]" : "  ", 2);
			if (j == 9) write(1, "|\n", 2);
		}
	}

	write(1, "---------------------\n", sizeof("---------------------\n"));
	printf("Score:%d  Level:%d\n", score, level);
}

long long gettime_ms()
{
	struct timeval tv;

	gettimeofday(&tv, NULL);
	return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

int random_shape()
{
	srand(gettime_ms());
	return (int)(rand() % 18);
}

int generate_new_shape()
{
	int i;

	curshape.type = nexts;
	curshape.sid = g_id;
	nexts = random_shape();
	for (i = 0; i < 4; i++) {
		curshape.point[i].x = smap[curshape.type].point[i].x;
		linestat[curshape.point[i].x]++;
		curshape.point[i].y = smap[curshape.type].point[i].y + 3;
		if (bitmap[curshape.point[i].x][curshape.point[i].y]) {
    		tcsetattr(0, TCSANOW, &init_setting);
			printf("Game Over!\n");
			exit(0);
		}
		bitmap[curshape.point[i].x][curshape.point[i].y] = curshape.sid;
	}
	leftedge = rightedge = bottom = 0;
	lasttime = gettime_ms();
	g_id++;
	return 0;
}

void update_bitmap()
{
	int i, j;

	for (i = 0; i < 4; i++) {
		bitmap[curshape.point[i].x][curshape.point[i].y] = 0;
		linestat[curshape.point[i].x]--;
		curshape.point[i].x = nextshape.point[i].x;
		curshape.point[i].y = nextshape.point[i].y;
	}
	for (i = 0; i < 4; i++) {
		bitmap[curshape.point[i].x][curshape.point[i].y] = curshape.sid;
		linestat[curshape.point[i].x]++;
	}
}

void clear_full_line()
{
	int	i = 19, j = 19;
	int fulcnt = 0;
	int tmpb[20][10] = {0};
	while (i >= 0) {
		if (linestat[i] != 10) {
			memcpy(tmpb[j], bitmap[i], sizeof(tmpb[j]));
			j--;
		} else {
			score += 10;
			fulcnt++;
		}
		i--;
	} 
	if (fulcnt) {
		memcpy(bitmap, tmpb, sizeof(bitmap));
		memset(linestat, 0, sizeof(linestat));
		for (i = 0; i < 20; i++) 
			for (j = 0; j < 10; j++) 
				if (bitmap[i][j]) linestat[i]++; 
	}
}

void OnKeyDown(int key)
{
	int i, j;
	
	pthread_mutex_lock(&mlock);
	if (bottom && gettime_ms() - lasttime > 500) {
		clear_full_line();
		if (generate_new_shape()) {
			pthread_mutex_unlock(&mlock);
			return;
		}
		goto draw;
	}

	if (key == LEFT) {
		if (leftedge) {
			goto draw;
		}
		int cnt = 0;
		for (i = 0; i < 4; i++) {
			nextshape.point[i].x = curshape.point[i].x;
			nextshape.point[i].y = curshape.point[i].y - 1;
			if (nextshape.point[i].y < 0 || 
				(bitmap[nextshape.point[i].x][nextshape.point[i].y] > 0 && bitmap[nextshape.point[i].x][nextshape.point[i].y] != curshape.sid)) {
				leftedge = 1;
			}
			if (bottom) {
				if (bitmap[nextshape.point[i].x + 1][nextshape.point[i].y] == curshape.sid ||
					bitmap[nextshape.point[i].x + 1][nextshape.point[i].y] == 0) cnt++;
			}
		}
		if (cnt >= 4) {
			bottom = 0;
		}
		if (!leftedge) {
			rightedge = 0;
			update_bitmap();
		}
	} else if (key == RIGHT) {
		if (rightedge) {goto draw;};
		int cnt = 0;
		for (i = 0; i < 4; i++) {
			nextshape.point[i].x = curshape.point[i].x;
			nextshape.point[i].y = curshape.point[i].y + 1;
			if (nextshape.point[i].y >= 10 || 
				(bitmap[nextshape.point[i].x][nextshape.point[i].y] > 0 && bitmap[nextshape.point[i].x][nextshape.point[i].y] != curshape.sid)) {
				rightedge = 1;
			}
			if (bottom) {
				if (bitmap[nextshape.point[i].x + 1][nextshape.point[i].y] == curshape.sid ||
					bitmap[nextshape.point[i].x + 1][nextshape.point[i].y] == 0) cnt++;
			}
		}
		if (cnt >= 4) {
			bottom = 0;
		}
		if (!rightedge) {
			leftedge = 0;
			update_bitmap();
		}
	} else if (key == DOWN) {
		if (bottom) {goto draw;};
		for (i = 0; i < 4; i++) {
			nextshape.point[i].x = curshape.point[i].x + 1;
			nextshape.point[i].y = curshape.point[i].y;
			if (nextshape.point[i].x >= 20 || 
				(bitmap[nextshape.point[i].x][nextshape.point[i].y] > 0 && bitmap[nextshape.point[i].x][nextshape.point[i].y] != curshape.sid)) {
				bottom = 1;
				lasttime = gettime_ms();
			}
		}
		if (!bottom) {
			update_bitmap();
		}
	} else if (key == UP) {
		if (curshape.type == S_SQUARE) goto draw;
		int s = curshape.type;
		int next = next_shape(s);
		for (i = 0; i < 4; i++) {
			nextshape.point[i].x = curshape.point[i].x - smap[s].point[i].x + smap[next].point[i].x;
			nextshape.point[i].y = curshape.point[i].y - smap[s].point[i].y + smap[next].point[i].y;
			int startx = nextshape.point[i].x < curshape.point[i].x ? nextshape.point[i].x : curshape.point[i].x;
			int starty = nextshape.point[i].y < curshape.point[i].y ? nextshape.point[i].y : curshape.point[i].y;
			int j,k;
			
			if (nextshape.point[i].y <  0) {
				leftedge = 1;
				goto draw;
			}
			if (nextshape.point[i].y >= 10) {
				rightedge = 1;
				goto draw;
			}
			if (nextshape.point[i].x >= 20) {
				bottom = 1;
				goto draw;
			}
			int size = s <= S_HORIZON ? 4 : 3;
			for (j = startx; j < startx + size; j++)
				for (k = starty; k < starty + size; k++)
					if (bitmap[j][k] > 0 && bitmap[j][k] != curshape.sid) {
						goto draw;
					}

		}
		
		if (!(leftedge && rightedge && bottom)) {
			curshape.type = next;
			leftedge = rightedge = bottom = 0;
			lasttime = gettime_ms();
			update_bitmap();
		}
	}

	if (leftedge && rightedge && bottom) {
		clear_full_line();
		if (generate_new_shape()) {
			pthread_mutex_unlock(&mlock);
			return;
		}
	}
	
draw:
	draw_bitmap();
	pthread_mutex_unlock(&mlock);
}	

void *t_timer(void *arg)
{
	while (1) {
		if (state == 1) {
			OnKeyDown(DOWN);
		}
		usleep((int)(1000000 * (1.0 / (float)(level))));
	}
}

const char *startlogo = "\
************************************\n\
     Welcome to Russia Square!     *\n\
************************************\n\
LEFT:\ta\nRIGHT:\td\nDOWN:\ts\nROTATE:\tw\n\
PAUSE/RESUME:\tp\n\
Please select Level(>0):";

int main(void)
{
	printf(startlogo);
	scanf("%d", &level);
	if (level <= 0) level = 1;
	// disable echo
	tcgetattr(0, &init_setting);
    new_setting = init_setting;
    new_setting.c_lflag &= ~(ECHO | ICANON);
    tcsetattr(0, TCSANOW, &new_setting);

	pthread_t tid;

	nexts = random_shape();
	generate_new_shape();
	draw_bitmap();
	state = 1;
	usleep(500000);
	pthread_create(&tid, NULL, t_timer, NULL);
	while (1) {
		char ch;
		if (state != 1) {
			ch = getchar();
			if (ch == 'p') {
				state = 1;
			}
			continue;
		}
			
		ch = getchar();
		switch(ch) {
			case 'a':
				OnKeyDown(LEFT);
				break;
			case 'd':
				OnKeyDown(RIGHT);
				break;
			case 's':
				OnKeyDown(DOWN);
				break;
			case 'w':
				OnKeyDown(UP);
				break;
			case 'p':
				state = 2;
				break;
		}
	}
	
exit:
	printf("exit\n");
	return 0;
}	

你可能感兴趣的:(linux环境纯命令行俄罗斯方块C语言版)