⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tetris.c

📁 该程序是在linux下运行的俄罗斯方块游戏的原代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
 * Title: tetris.c
 * Type: GCC (*.c)
 * Description: 
 * Copyright: Copyright (c) 2003
 * Company: djws
 * author djws
 * version 1.1
 */

/*  if you include "curses.h"
		to compile this file, you need use the command
		cc [file.c] -lcurses -ltermcap 
 */

/* delete the file you don't need */
#include <stdio.h>

#include <unistd.h>
#include <stdlib.h>
//#include <errno.h>

#include <string.h>

//#include <time.h>
//#include <sys/types.h>

//#include <sys/socket.h>
//#include <netinet/in.h>
//#include <arpa/inet.h>

//#include <signal.h>

#include <curses.h>
//#include <sys/ioctl.h>
//#include <termio.h>

/* add you own head file */

//#include "tetris.h"

typedef struct {
	int x;
	int y;
	int flag;
} Block;

typedef struct {
	char username[20];
	int score;
} History;

typedef struct {
	/* 0: one player
	   1: two player 
	 */
	int players;	
	/* 0: Normal
	   1: SpeedUp
	   2: Horrible
	 */
	int mode;
	/* 0-9 */
	int speed;
	/* 0: retrorse
	   1: direct
	 */
	int rotate;
	/* 0-12 */
	int level;
	/* speed up scale */
	int scale;
} Options;

#define RETRORSE(flag) (bdata[flag][4][0])    //get new block
#define DIRECT(flag) (bdata[flag][4][1])
#define XOFF(flag, i) (bdata[flag][i][0])    //get block position
#define YOFF(flag, i) (bdata[flag][i][1])

// menu entry
#define MAXM 4
// option entry
#define MAXOM 7
// temp string length
#define MAXLEN 50
// container scale 12*21
#define CONX 21
#define CONY 12
// menu scale 18*47
#define MEUX 18
#define MEUY 47
// screen scale 100*33
#define SCRX 33
#define SCRY 100
// level up step
#define LEVELUP opt.scale

int block_check(Block* blk);    //check the block can be put to container or not
int block_rand();    //get a random flag (18 is not allowed);

int block_ctrl(WINDOW *win, Block* blk, int cmd);
int block_clear(WINDOW *win, Block* blk);    //clear the block on the screen
int block_draw(WINDOW *win, Block* blk);    //draw the block on the screen

int block_left(WINDOW *win, Block* blk);    //block move left
int block_right(WINDOW *win, Block* blk);   //block move right
int block_down(WINDOW *win, Block* blk);    //block descend
int block_drop(WINDOW *win, Block* blk);    //block landfall

int block_rotate(WINDOW *win, Block* blk, int dec);    //block rotate

void map_set(int x, int y);    // set appointed cell
void map_clr(int x, int y);    // clear appointed cell
unsigned char map_get(int x, int y);    //get appointed cell
void map_clear();    // clear the container
void map_init();    // init the container
void map_fill(Block* blk);    //put the block into the container
int map_refresh();    // clear the full line

void screen_redraw(WINDOW *main, WINDOW *container, long points, long lines);
void game_end();

void row_left(int xz, WINDOW *win, char *str);
void row_right(int xz, WINDOW *win, char *str);

void play();
void history();
void options();

void menu();

/* I want to use someone's data first, but I find that I cann't understand it, so I create my own */
/* these codes is so silly, and me too */

/* the struct is {{x0,y0}, {x1,y1}, {x2,y2}, {x3,y3}, {retrorse,direct}} */
static int bdata[19][5][2] = {         // shape		flag

{{0,0}, {0,1}, {1,0}, {1,1}, {0,0}},   // "■■"		0
                                       // "■■"


{{0,2}, {1,0}, {1,1}, {1,2}, {2,4}},   // "  ■"		1
                                       // "■■■"


{{0,0}, {0,1}, {1,1}, {2,1}, {3,1}},   // "■■"		2
                                       // " ■"
                                       // " ■"

{{0,0}, {0,1}, {0,2}, {1,0}, {4,2}},   // "■■■"		3
                                       // "■  "


{{0,0}, {1,0}, {2,0}, {2,1}, {1,3}},   // "■ "		4
                                       // "■ "
                                       // "■■"

{{0,0}, {1,0}, {1,1}, {1,2}, {6,8}},   // "■  "		5
                                       // "■■■"
                             

{{0,1}, {1,1}, {2,0}, {2,1},{7,5}},    // " ■"		6
                                       // " ■"
                                       // "■■"

{{0,0}, {0,1}, {0,2}, {1,2}, {8,6}},   // "■■■"		7
                                       // "  ■"
                             

{{0,0}, {0,1}, {1,0}, {2,0}, {5,7}},   // "■■"		8
                                       // "■ "
                                       // "■ "

{{0,1}, {1,0}, {1,1}, {1,2}, {10,12}}, // " ■ "		9
                                       // "■■■"
                             

{{0,1}, {1,0}, {1,1}, {2,1}, {11,10}}, // " ■"		10
                                       // "■■"
                                       // " ■"

{{0,0}, {0,1}, {0,2}, {1,1}, {12,10}}, // "■■■"		11
                                       // " ■ "
									   

{{0,0}, {1,0}, {1,1}, {2,0}, {9,11}},  // "■ "		12
                                       // "■■"
                                       // "■ "

{{0,0}, {0,1}, {1,1}, {1,2}, {14,14}}, // "■■ "		13
                                       // " ■■"
                            

{{0,1}, {1,0}, {1,1}, {2,0}, {13,13}}, // " ■"		14
                                       // "■■"
                                       // "■ "

{{0,1}, {0,2}, {1,0}, {1,1}, {16,16}}, // " ■■"		15
                                       // "■■ "
                           

{{0,0}, {1,0}, {1,1}, {2,1}, {15,15}}, // "■ "		16
                                       // "■■"
                                       // " ■"
//17 and 18 is special
{{0,0}, {0,1}, {0,2}, {0,3}, {18,18}}, // "■■■■"	17
               
                            

{{0,0}, {1,0}, {2,0}, {3,0}, {17,17}}  // " ■  "	18
                                       // " ■  "
                                       // " ■  "
                                       // " ■  "
};

/* the container */
unsigned char map[CONX][CONY];

/* game options 
   default:
		one player
		SpeedUp mode
		speed 0
		level 0
		scale 50
 */
static Options opt;
	
/* now it's the menu */
void
menu() {
	
	int i = 0;
	char *menustr[MAXM];			
	char tmp[MAXLEN];
	WINDOW *win;
	int xz=0;
	menustr[0] = "Play";
	menustr[1] = "History";
	menustr[2] = "Options";
	menustr[3] = "Exit";
	opt.players = 0;
	opt.mode = 1;
	opt.speed = 0;
	opt.rotate = 0;
	opt.level = 0;
	opt.scale = 50;
	initscr();				
	
	while(1) {
		win=newwin(MEUX, MEUY, (SCRX-MEUX)/2, (SCRY-MEUY)/2);
		box(win, 0, 0);				
		strcpy(tmp, "Tetris for UNIX");
		mvwprintw(win, 
			2, (MEUY-strlen(tmp))/2, 
			tmp);
		strcpy(tmp, "Copyright (C) 2002-2003 djws");
		mvwprintw(win, 
			4, (MEUY-strlen(tmp))/2, 
			tmp);
		strcpy(tmp, "All Rights Reserved");
		mvwprintw(win, 
			6, (MEUY-strlen(tmp))/2, 
			tmp);
		mvwprintw(win, 
			8, 1, 
			"*********************************************");
		keypad(win, TRUE);
		
		for(i=0; i<2*MAXM; i+=2) {			/* 显示菜单内容 */
			strcpy(tmp, menustr[i/2]);
			mvwaddstr(win, 
				i+9, (MEUY-strlen(tmp))/2, 
				tmp);
		}
			wstandout(win);			/* 开始反相显示 */
			strcpy(tmp, menustr[xz]);
			mvwaddstr(win, 
				2*xz+9, (MEUY-strlen(tmp))/2, 
				tmp);	/* 反相显示第一个菜单 */
			wstandend(win);			/* 结束反相显示 */
		
		switch(wgetch(win)) {			/* 读用户输入 */
			case KEY_LEFT:			/* KEY_LEFT、KEY_UP、KEY_DOWN、KEY_RIGHT为光标移动键 */
			case KEY_UP:
				wstandend(win);			/* 正常显示上一菜单 */
				strcpy(tmp, menustr[xz]);
				mvwaddstr(win, 
					2*xz+9, (MEUY-strlen(tmp))/2, 
					tmp);
				wmove(win, 
					2*xz+9, (MEUY-strlen(tmp))/2);
				wstandout(win);
				wrefresh(win);			/* 刷新当前窗口 */
				if(xz == 0)
					xz = MAXM-1;
				else 
					xz--;	/* 判断是否为第一个菜单,决定光标走向 */
				wstandout(win);			/* 反白显示当前菜单 */
				strcpy(tmp, menustr[xz]);
				mvwaddstr(win, 
					2*xz+9, (MEUY-strlen(tmp))/2, 
					tmp);
				wmove(win, 
					2*xz+9, (MEUY-strlen(tmp))/2);
				wstandend(win);
				wrefresh(win);
				break;		/* 刷新当前窗口 */
			case KEY_RIGHT:
			case KEY_DOWN:
				wstandend(win);
				strcpy(tmp, menustr[xz]);
				mvwaddstr(win, 
					2*xz+9, (MEUY-strlen(tmp))/2, 
					menustr[xz]);
				wmove(win, 
					2*xz+9, (MEUY-strlen(tmp))/2);
				wrefresh(win);
				wstandout(win);
				if(xz == MAXM-1)
					xz = 0;
				else 
					xz++;
				wstandout(win);
				strcpy(tmp, menustr[xz]);
				mvwaddstr(win, 
					2*xz+9, (MEUY-strlen(tmp))/2, 
					menustr[xz]);
				wmove(win, 
					2*xz+9, (MEUY-strlen(tmp))/2);
				wstandend(win);
				wrefresh(win);
				break;
			case 10:	/* 如输入回车键则执行不同的函数 */
				switch(xz) {
					case 0:
						wclear(win);
						wrefresh(win);
						keypad(win, FALSE);
						play();
						keypad(win, TRUE);
						touchwin(win);
						wclear(win);
						wrefresh(win);
						break;
					case 1:
						wclear(win);
						wrefresh(win);
						keypad(win, FALSE);
						history();
						keypad(win, TRUE);
						touchwin(win);
						wclear(win);
						wrefresh(win);
						break;
					case 2:
						wclear(win);
						wrefresh(win);
						keypad(win, FALSE);
						options();
						keypad(win, TRUE);
						touchwin(win);
						wclear(win);
						wrefresh(win);
         				break;
					case 3:
						touchwin(win);
						wclear(win);
						wrefresh(win);/* 结束游戏 */
						cbreak();
						echo();
						endwin();
						exit(0);	/* 结束画形操作方式,退出 */
				}    //end switch(xz)
				break;
			default:
				//beep();
				noecho();
				break;	/* 无效输入,不显示并响铃提醒 */
		}    //end switch(wgetch(win))	
	}    //end while(1)
}	//end menu()

int
block_check(Block* blk) {
	if(((blk->x)<0) || ((blk->y)<0))
		return 0;
	if(((blk->x)>=CONX) || ((blk->y)>=CONY))
		return 0;
	int x = 0;
	int y = 0;
	int i = 0;
	for(i=0; i<4; i++) {
		x = (blk->x)+XOFF(blk->flag, i);
		y = (blk->y)+YOFF(blk->flag, i);
		if((x<0) || (y<0))
			return 0;
		if((x>=CONX) || (y>=CONY))
			return 0;
		if(map[x][y] == 1)
		//map_get(x, y);
			return 0;
	}
	return 1;
}

/* return a random flag number */
/* there are 7 kinds of basic shape, all the shape has the same probability */
/* for more fun, flag==18 is not allowed */
int
block_rand() {
	int flag = 0;
	srand((unsigned)time(NULL));
	flag = (rand()%28);
	switch(flag) {
		case 19:
		case 20:
		case 21:
			return 0;
		case 22:
			return 13;
		case 23:
			return 14;
		case 24:
			return 15;
		case 25:
			return 16;
		case 18:
		case 26:
		case 27:
			return 17;
		default:
			return flag;
	};
}

/* the interface doesn't seem beautiful, but the funciton can be modified later  */
/* now it just return 0, but for future, so all the function which use it return a int variable */
int
block_ctrl(WINDOW *win, Block* blk, int cmd) {
	int i = 0;
	char z[3] = "■";
	if(cmd == 0)
		strcpy(z, "  ");
	for(i=0; i<4; i++) {
		mvwaddstr(win, 
			(blk->x)+XOFF(blk->flag, i)+1, (blk->y)*2+YOFF(blk->flag, i)*2+1,
			z);
	}
	wmove(win, 0, 0);
	return 0;
}

int
block_clear(WINDOW *win, Block* blk) {
	return block_ctrl(win, blk, 0);
}

int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -