您好,登錄后才能下訂單哦!
這篇文章主要介紹linux環境下C++實現俄羅斯方塊的案例,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
具體內容如下
本程序的運行環境是linux,用到了多線程。創建了一個用來繪圖的線程和一個獲取按鍵的線程。程序中有一些需要改善的地方,比如336-338行定義的全局變量以及聲明的對象。本來聲明的Block和Table對象應該在main函數里面,然后將這兩個對象作為參數傳遞給線程函數getkey。但是好像只能傳遞一個對象參數給線程函數。希望高手能夠對程序進行改進。
ps:由于用到了多線程,而pthread不是linux的默認庫,所以編譯的時候需要指定線程庫。即:g++ -o block -lpthread block.cpp
#include <iostream> #include <cstdlib> #include <pthread.h> #include <time.h> #include<termios.h> #include<fcntl.h> #define TABLE_SIZE 20 #define BLOCK_SIZE 4 #define SLEEP_TIME 500 using namespace std; struct grid{int x; int y;}; //坐標 /////////////////////Block 類////////////////////// class Block { public: enum direct{UP, DOWN, LEFT, RIGHT}; //定義方向 grid g[BLOCK_SIZE]; //方塊的坐標信息 void def_block(grid g1, grid g2, grid g3, grid g4); //定義方塊 void rotate(); //旋轉方塊 void move(int dir); //移動方塊 void set_cen(grid g); //設置方塊旋轉中心 grid get_cen(); //獲取方塊旋轉中心 void set_type(int t); //設置方塊種類 int get_type(); //獲取方塊種類 void back(); //旋轉還原 void creat_block(int x, int y); //隨機生成方塊 private: grid center; //方塊旋轉中心 int type; //方塊類型 }; void Block::def_block(grid g1, grid g2, grid g3, grid g4) { g[0]=g1; g[1]=g2; g[2]=g3; g[3]=g4; } void Block::rotate() { int x, y, i=0; for(i; i<=3; i++) { x=g[i].x-center.x; y=g[i].y-center.y; g[i].x=center.x+y; g[i].y=center.y-x; } } void Block::move(int dir) { int d=dir, i=0; switch(d) { case UP: { for(i; i<=3; i++) g[i].y++; center.y++; break; } case DOWN: { for(i; i<=3; i++) g[i].y--; center.y--; break; } case LEFT: { for(i; i<=3; i++) g[i].x--; center.x--; break; } case RIGHT: { for(i; i<=3; i++) g[i].x++; center.x++; break; } } } void Block::set_cen(grid g) { center=g; } grid Block::get_cen() { return center; } void Block::set_type(int t) { type=t; } int Block::get_type() { return type; } void Block::back() { int x, y, i=0; for(i; i<=3; i++) { x=g[i].x-center.x; y=g[i].y-center.y; g[i].x=center.x-y; g[i].y=center.y+x; } } void Block::creat_block(int x, int y) { //隨機創建方塊 int ran; grid g[BLOCK_SIZE]; ran=1+rand()%7; switch(ran) { //L case 1: { g[0].x=x/2; g[0].y=y-3; g[1].x=g[0].x; g[1].y=g[0].y+1; g[2].x=g[0].x; g[2].y=g[0].y+2; g[3].x=g[0].x+1; g[3].y=g[0].y; set_cen(g[0]); set_type(1); break; } //反L case 2: { g[0].x=x/2; g[0].y=y-3; g[1].x=g[0].x; g[1].y=g[0].y+1; g[2].x=g[0].x; g[2].y=g[0].y+2; g[3].x=g[0].x-1; g[3].y=g[0].y; set_cen(g[0]); set_type(2); break; } //Z case 3: { g[0].x=x/2; g[0].y=y-2; g[1].x=g[0].x; g[1].y=g[0].y+1; g[2].x=g[0].x+1; g[2].y=g[0].y+1; g[3].x=g[0].x-1; g[3].y=g[0].y; set_cen(g[0]); set_type(3); break; } //反Z case 4: { g[0].x=x/2; g[0].y=y-2; g[1].x=g[0].x; g[1].y=g[0].y+1; g[2].x=g[0].x+1; g[2].y=g[0].y+1; g[3].x=g[0].x-1; g[3].y=g[0].y; set_cen(g[0]); set_type(4); break; } //田 case 5: { g[0].x=x/2; g[0].y=y-2; g[1].x=g[0].x; g[1].y=g[0].y+1; g[2].x=g[0].x+1; g[2].y=g[0].y+1; g[3].x=g[0].x+1; g[3].y=g[0].y; set_cen(g[0]); set_type(5); break; } //1 case 6: { g[0].x=x/2; g[0].y=y-3; g[1].x=g[0].x; g[1].y=g[0].y+1; g[2].x=g[0].x; g[2].y=g[0].y+2; g[3].x=g[0].x; g[3].y=g[0].y-1; set_cen(g[0]); set_type(6); break; } //山 case 7: { g[0].x=x/2; g[0].y=y-2; g[1].x=g[0].x; g[1].y=g[0].y+1; g[2].x=g[0].x-1; g[2].y=g[0].y; g[3].x=g[0].x+1; g[3].y=g[0].y; set_cen(g[0]); set_type(7); break; } default: ; } def_block(g[0], g[1], g[2], g[3]); } ///////////////////////////////////////// ////////////////////Table 類////////////////////// class Table { public: Table() { //構造棋盤 height=20; width=10; count=0; init_table(); } Table(int x, int y); int set_block(Block bl); //安設方塊 void clr_block(Block bl); //清除方塊 int clr_line(int y); //消行 int get_h(); //獲取棋盤高度 int get_w(); //獲取棋盤寬度 int if_full(int y); //判定是否滿行 int get_table(int x, int y); //獲取棋盤上點信息 void paint(); //繪制棋盤 void move_line(int y); //整行下移 void set_count(int c); //記錄得分 int get_count(); //獲取得分 private: int table[TABLE_SIZE][TABLE_SIZE];//棋盤 int height, width; //棋盤的高和寬 int count; //得分 void init_table(); //棋盤初始化 }; void Table::init_table() { int i=0, j=0; for(i; i<width; i++) { for(j=0; j<height; j++) { table[i][j]=0; } } } Table::Table(int x, int y) { height=y; width=x; count=0; init_table(); } int Table::set_block(Block bl) { int x, y; int i; for(i=0; i<=3; i++) { x=bl.g[i].x; y=bl.g[i].y; if(table[x][y]!=0 || x>=width || x<0 || y>=height || y<0) { return 0; } } for(i=0; i<=3; i++) { x=bl.g[i].x; y=bl.g[i].y; table[x][y]=1; } return 1; } void Table::clr_block(Block bl) { int x, y; for(int i=0; i<=3; i++) { x=bl.g[i].x; y=bl.g[i].y; table[x][y]=0; } } int Table::clr_line(int y) { if(y<0 || y>=height) return 0; for(int i=0; i<width; i++) { table[i][y]=0; } return 1; } int Table::get_h() { return height; } int Table::get_w() { return width; } int Table::if_full(int y) { int i=0; for(i; i<width; i++) { if(table[i][y]==0) return 0; } return 1; } int Table::get_table(int x, int y) { return table[x][y]; } void Table::paint() { int i, j; for(i=0; i<width+2; i++) cout<<"-"<<flush; cout<<"\n"<<flush; for(i=height-1; i>=0; i--) { cout<<"|"<<flush; for(j=0; j<width; j++) { if(table[j][i]==0) cout<<" "<<flush; else cout<<"?"<<flush; } if(i==10) cout<<"| 得分:"<<get_count()<<endl; else if(i==7) cout<<"| Press 'q' to quit!"<<endl; else cout<<"|"<<endl; } for(i=0; i<width+2; i++) cout<<"-"<<flush; cout<<"\n"<<flush; //cout<<"得分:"<<get_count()<<endl; } void Table::move_line(int y) { int i, j; for(i=y; i<height-1; i++) { for(j=0; j<width; j++) { table[j][i]=table[j][i+1]; } } } void Table::set_count(int c) { count+=c; } int Table::get_count() { return count; } /////////////////////////////////////////////////////// class Mythread { public: void init(); static void *getkey(void *arg);//線程函數在類里面定義必須定義為static型,以去除類指針。 static void *paint_loop(void *arg); }; void Mythread::init() { pthread_t ntid,ntid2; int err,err2; err = pthread_create(&ntid,NULL,getkey,NULL); err2 = pthread_create(&ntid2,NULL,paint_loop,NULL); if(err != 0 || err2 != 0){ cout<<"can't create thread!"<<endl; exit(0); } } unsigned char flag=1,buf[2];//全局變量 Table tab(15, 20); //構造一個15,20的棋盤 Block bl; //構造一個落下方塊 void* Mythread::paint_loop(void *arg) { while(1) { system("clear"); tab.paint(); usleep(50000); //暫停50 MS } } void* Mythread::getkey(void *arg) { struct termios saveterm,nt; fd_set rfds,rs; struct timeval tv; int i=0,q,r,fd=0; tcgetattr(fd,&saveterm); nt=saveterm; nt.c_lflag &= ~ECHO; nt.c_lflag &= ~ISIG; nt.c_lflag &= ~ICANON; tcsetattr(fd,TCSANOW,&nt); FD_ZERO(&rs); FD_SET(fd,&rs); tv.tv_sec=0; tv.tv_usec=0; while(1) { read(0,buf,1); r=select(fd+1,&rfds,NULL,NULL,&tv); if(r<0) { write(1,"select() error.\n",16); } rfds=rs; if(flag==2||buf[0]==113)//游戲結束或者用戶按下'q'鍵,則程序退出 { tcsetattr(0,TCSANOW,&saveterm); exit(0); } if(buf[0]<=68&&buf[0]>=65) flag=0;//如果按的鍵是方向鍵,則將標志位置0并執行相應的處理. if(flag==0) { if(buf[0]==65) { //if(dir!=0) { if(bl.get_type()==5) continue; //如果出現田字形則不作旋轉 tab.clr_block(bl); //清空方塊上一次位置 bl.rotate(); //開始旋轉 if(!tab.set_block(bl)) { //將旋轉后的方塊寫在棋盤上 bl.back(); //如果寫失敗(例如到邊線了,或卡住了)則還原旋轉前位置 continue; tab.set_block(bl); } } //下(加速下落) //dir=GetAsyncKeyState(VK_DOWN); //獲取向下 if(buf[0]==66) { tab.clr_block(bl); //清空方塊上一次位置 bl.move(bl.DOWN); //向下移動一步 if(!tab.set_block(bl)) { //將移動后的方塊寫在棋盤上 bl.move(bl.UP); //如果失敗,則還原到移動前的位置(即上移一步) tab.set_block(bl); } } //左(左移) //dir=GetAsyncKeyState(VK_LEFT); if(buf[0]==68) { tab.clr_block(bl); bl.move(bl.LEFT); if(!tab.set_block(bl)) { bl.move(bl.RIGHT); tab.set_block(bl); } } //右(右移) //dir=GetAsyncKeyState(VK_RIGHT); if(buf[0]==67) { tab.clr_block(bl); bl.move(bl.RIGHT); if(!tab.set_block(bl)) { bl.move(bl.LEFT); tab.set_block(bl); } } flag=1; } } tcsetattr(0,TCSANOW,&saveterm); } ////////////主函數部分/////////////////////// int main() { //Table tab(15, 20); //構造一個15,20的棋盤 //Block bl; //構造一個落下方塊 Mythread thread; thread.init(); int dir,i,c; while(true) { //生成方塊 srand(time(0)); bl.creat_block(tab.get_w(), tab.get_h()); //判斷游戲是否結束 if( !tab.set_block(bl) ) { system("clear"); cout<<"GAME OVER!"<<endl; flag=2; cout<<"PRESS ANY KEY TO CONTINUE!"<<endl; while(1); } ///////////行動按鍵判定 while(true){ usleep(500000); //暫停500 MS /////////////向下移動一格 tab.clr_block(bl); //清空上一次方塊位置 bl.move(bl.DOWN); //向下移動一步 if(!tab.set_block(bl)) { //是否觸底 bl.move(bl.UP); //如果觸底,還原觸底前位置 tab.set_block(bl); break; } } //如果滿行則消行 for(i=0; i<tab.get_h(); i++) { if(tab.if_full(i)) { //是否滿行 tab.clr_line(i); //如果是,消行 tab.move_line(i); //將所消行的上面的棋盤信息下移 i--; //下移后,重新檢查這一行是否滿(可能出現幾行同時消去) tab.set_count(100); //記錄得分 } } } return 0; }
以上是“linux環境下C++實現俄羅斯方塊的案例”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。