C++实现俄罗斯方块_源码_详细注释

1.在linux下安装ncurses库

sudo apt-get update
sudo apt-get install libncurses5-dev

2.编译时-l 选项引入 ncurses 库

g++ main.cpp -l ncurses

3.源码

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

using namespace std;

void swap(int &a, int &b){
	int t=a;
	a = b;
	b = t;
}
int getrand(int min, int max)	//得到一个(min,max)区间的随机整数
{
	return(min+rand()%(max-min+1));
}

WINDOW *create_newwin(int height,int width,int starty,int startx);//调用newwin创建新窗口,并显示边框
void destory_win(WINDOW *local_win);

int game_win_height=30;	
int game_win_width=45;	//游戏窗口的尺寸

int hint_win_height=10;
int hint_win_width=20;	//显示下一个方块形状的窗口的尺寸
WINDOW * game_win, *hint_win ,*score_win;	//3个窗口的指针,游戏,下一个方块,分数
int key;

class Piece				//方块类
{
public:
	int score;			//分数
	int shape; 			//形状
	int next_shape;		//下一个方块形状

	int head_x;			//当前方块首个box的位置,标记位置
	int head_y;

	int size_h;			//当前方块的size
	int size_w;

	int next_size_h;	//下一个方块的size
	int next_size_w;

	int box_shape[4][4];		//当前方块的形状数组4×4,所有7种图形可以在4×4的方框中画出
	int next_box_shape[4][4];	//当前方块的形状数组4×4

	int box_map[30][45];		//用来标记游戏框内的每个box

	bool game_over;				

public:
	void initial();				//初始化函数
	void set_shape(int &cshape, int box_shape[][4],int &size_w, int & size_h);	//设置方块形状

	void score_next();			//显示下一个方块形状以及得分
	void judge();				//判断是否层满
	void move();				//移动函数,通过 ← → ↓ 移动
	void rotate();				//旋转函数
	bool isaggin();				//判断下一次行动是否越界或重合
	bool exsqr(int row);		//判断当前行是否空

	
};

int main()
{

	initscr();						//屏幕初始化,并进入curses模式
	//raw();						//禁止行缓冲,处理挂起、中断或退出等将直接传送给程序去处理而不产生终端信号
	cbreak();						//禁止行缓冲,控制字符将被终端驱动程序解释成其它字符
	noecho();						//禁止输入的字符出现在屏幕上
	curs_set(0);
	keypad(stdscr,TRUE);			//允许使用功能键,为标准屏幕(stdscr)激活了功能键

	refresh();						//刷新终端屏幕
	
	game_win = create_newwin(game_win_height, game_win_width, 0,0);	//创建游戏窗口,设置边框
	wborder(game_win, '*', '*', '*', '*', '*', '*', '*', '*');
	wrefresh(game_win);

	hint_win = create_newwin(hint_win_height, hint_win_width, 0, game_win_width+10);//创建下一个形状提示窗口
	mvprintw(0, game_win_width+10+2,"%s","Next");
	refresh();

	score_win = create_newwin(hint_win_height, hint_win_width, 20, game_win_width+10);//创建分数窗口
	mvprintw(20, game_win_width+10+2,"%s","Score");
	refresh();



	Piece* pp = new Piece;			//创建方块对象
	pp->initial();					//初始化方块


	while(1)
	{
		pp->move();					//移动方块
		if(pp->game_over)			//判断game_over参数是否等于true
			break;
	}

	destory_win(game_win);
	destory_win(hint_win);
	destory_win(score_win);
	delete pp;
	system("clear");

	int row,col;
	getmaxyx(stdscr,row,col);
	mvprintw(row/2,col/2 ,"%s","GAMER OVER ! \n ");
	mvprintw(row/2+2,col/2-2 ,"%s","Wait 5s to return tthe erminal ! \n ");
	refresh();

	sleep(5);
	endwin();
	return 0;
}

WINDOW *create_newwin(int height, int width, int starty, int startx)
{			//参数分别是,窗口的高、宽,窗口的左上角的坐标(起始坐标)
	WINDOW *local_win;
	local_win = newwin(height, width, starty, startx);
	box(local_win,0,0);	//给新创建的窗口画上边框
	wrefresh(local_win);
	return local_win;
}

void destory_win(WINDOW *local_win)
{
	wborder(local_win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
	wrefresh(local_win);
	delwin(local_win);
}


void Piece::initial()
{
	score=0;
	game_over=false;
	for(int i =0;ibox_shape[i][j]==1){
					mvwaddch(game_win,head_y+i,head_x+j,'#');
					wrefresh(game_win);
				}
		}

	}
}

void Piece::move(){		//方块移动
	 fd_set set;
	 FD_ZERO(&set);										//将文件描述符集所有位清零
	 FD_SET(0, &set);									//将文件描述符0置位
	      
	 struct timeval timeout;
	 timeout.tv_sec = 0;
	 timeout.tv_usec= 500000;							//设置超时时间为0.5s
	      
  	if (select(1, &set, NULL, NULL, &timeout) == 0){	//select函数,参数1代表文件描述符范围,最大值加1。超时返回0
		head_y++;
		if(isaggin()){
			head_y--;
			for(int i=0;i=0;i--)
				for(int j=0;jbox_shape[i][j]==1){
						mvwaddch(game_win,head_y-1+i,head_x+j,' ');
						mvwaddch(game_win,head_y+i,head_x+j,'#');

					}
				}
			wrefresh(game_win);
		}

  	}
	      
	if (FD_ISSET(0, &set)) {//检测到按键
	        while ((key = getch()) == -1) ;

		if(key==KEY_LEFT){
			head_x--;
			if(isaggin())
				head_x++; //
			else{
				for(int i=0; ibox_shape[i][j]==1){
							mvwaddch(game_win,head_y+i,head_x+j+1,' ');
							mvwaddch(game_win,head_y+i,head_x+j,'#');

						}
					}
				wrefresh(game_win);
			}
		}

		if(key==KEY_RIGHT){
			head_x++;
			if(isaggin())
				head_x--;
			else{
				for(int i=0; i=0;j--){
						if(this->box_shape[i][j]==1){
							mvwaddch(game_win,head_y+i,head_x+j-1,' ');
							mvwaddch(game_win,head_y+i,head_x+j,'#');

						}
					}
				wrefresh(game_win);
			}
		}

		if(key==KEY_DOWN){								// 按下 ↓ 键 
			head_y++;									//方块的y坐标 +1
			if(isaggin()){								//如果重合或出界,取消这次移动
				head_y--;
				for(int i=0;i=0;i--)
					for(int j=0;jbox_shape[i][j]==1){
							mvwaddch(game_win,head_y-1+i,head_x+j,' ');
							mvwaddch(game_win,head_y+i,head_x+j,'#');

						}
					}
				wrefresh(game_win);
			}
		}

		if(key==KEY_UP)
			rotate();

		if(head_x+size_w+1>game_win_width)
			head_x=game_win_width-size_w-1;
		if(head_x<1)
			head_x=1;
	}
}

bool Piece::isaggin(){
	for(int i=0;i game_win_height-2)		//下面出界
					return true;
				if(head_x+j > game_win_width-2 || head_x+i-1<0)	//左右出界
					return true;
				if(box_map[head_y+i][head_x+j]==1)				//与已占用的box重合
					return true ;
			}
		}
	return false;
}

bool Piece::exsqr(int row){
	for(int j=1;j=2;i--){
		int s=i;
		if(exsqr(i)==0){
			while(s>1 && exsqr(--s)==0);
			for(j=1;jnext_shape=getrand(0,6);
	set_shape(next_shape,next_box_shape,next_size_w,next_size_h);


	for(int i =1;i

你可能感兴趣的:(C++)