俄罗斯方块----Ubuntu终端游戏
2016-07-10 14:55
781 查看
我最近在看C++和linux,为了能够更加牢靠的掌握自己的学到的知识,所以采用写小游戏的方法来帮助自己巩固学习。在这篇代码中我用到的C++和linux知识有:
C++知识:
1. 类的创建
2. 内联函数
3. pthread线程
linux知识:
1. 进入root模式
2. 给文件增加权限
3. 查看和使用系统的外设
有三点要特别说明:
1. 本代码不适用于所有linux系统,如果照搬的话可能会运行失败。如果要保证此代码编译的程序能在另一台机器上运行,需要先查看该机器的键盘是对应哪一个event文件,并将代码中的打开event文件的名称改掉。
2. 因为打开event文件需要很高的权限,所以需要在root模式下运行
3. 要编译此程序需要在链接是加入pthread库,即编译时需要g++ -lpthread *.cpp
具体代码如下:
C++知识:
1. 类的创建
2. 内联函数
3. pthread线程
linux知识:
1. 进入root模式
2. 给文件增加权限
3. 查看和使用系统的外设
有三点要特别说明:
1. 本代码不适用于所有linux系统,如果照搬的话可能会运行失败。如果要保证此代码编译的程序能在另一台机器上运行,需要先查看该机器的键盘是对应哪一个event文件,并将代码中的打开event文件的名称改掉。
2. 因为打开event文件需要很高的权限,所以需要在root模式下运行
3. 要编译此程序需要在链接是加入pthread库,即编译时需要g++ -lpthread *.cpp
具体代码如下:
RussiaBlock.h #ifndef RUSSIA_BLOCK_H #define RUSSIA_BLOCK_H #include <iostream> #include <ctime> #include <stdexcept> #include <unistd.h> #include <pthread.h> #include <cstdlib> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/select.h> #include <errno.h> #include <linux/input.h> using namespace std; typedef struct Pos { unsigned char x; unsigned char y; } Pos; typedef struct Block { Pos pos[4]; bool Droping; short shape; } Block; class RussiaBlock { private: enum {TIAN_BLOCK=0,L_BLOCK,T_BLOCK,FL_BLOCK,I_BLOCK,HI_BLOCK,Z_BLOCK,FZ_BLOCK}; bool gameFail; bool dropToEnd; bool Rotating; unsigned int score; unsigned char screenWidth; unsigned char screenHeight; Block currentBlock; Block nextBlock; unsigned char map[100][100]; public: void GameStart(void); //开始游戏 RussiaBlock(unsigned char, unsigned char = 80); private: Block TianBlock(void); //田型方块 void FailNotice(void); //游戏失败提示 Block LBlock(void); //L型方块 void KeyOperate(void); //按键操作 void ShowScreen(void); //显示游戏区域 Block CreatNewBlock(void); //创建一个新的方块 void ShowNextBlock(void); //显示下一个方块提示 private: Block TBlock(); //T型方块 Block FLBlock(); //反L型方块 Block IBlock(); //I型方块 Block HIBlock(); //横I型方块 Block ZBlock(); //Z型方块 Block FZBlock(); //反Z型方块 void AutoDrop(void *); //自动下降线程 static void *Thread_func(void *); static void *Thread_Key(void *); void MoveRight(); //右移 void MoveLeft(); //左移 void DropEnd(); //下降到底 void RotateBlock(); //旋转方块 void DeleteLines(); //清除游戏区域内多行内容 bool DropOneLine(); //下降一行 void DeleteOneLine(); //删除一行 bool AtTheEnd(); //判断是否在可降落的最低点 inline bool ThisLineIsFull(int index) { for(int i=0;i<screenWidth;i++) { if(map[i][index] == 0) return false; } return true; } inline void DeleteOneLine(int index) { for(int i=index;i>0;i--) { for(int j=0;j<screenWidth;j++) { map[j][i] = map[j][i-1]; } } for(int j=0;j<screenWidth;j++) { map[j][0] = 0; } } }; #endif
RussiaBlock.cpp #include "RussiaBlock.h" #include <iostream> using namespace std; RussiaBlock::RussiaBlock(unsigned char width, unsigned char height) { gameFail = false; screenWidth = width; screenHeight= height; score = 0; for(int i=0;i != 100;i++) for(int j=0;j!=100;j++) { map[i][j] = 0; } srand(time(0)); nextBlock = CreatNewBlock(); Rotating = false; } Block RussiaBlock::CreatNewBlock(void) { short blockShape = 0; blockShape = (short)(rand()%8); Block newBlock; switch(blockShape) { case 0: newBlock = TianBlock();break; case 1: newBlock = LBlock();break; case 2: newBlock = TBlock();break; case 3: newBlock = FLBlock();break; case 4: newBlock = IBlock();break; case 5: newBlock = HIBlock();break; case 6: newBlock = ZBlock();break; case 7: newBlock = FZBlock();break; } newBlock.shape = blockShape; return newBlock; } void RussiaBlock::ShowScreen() { system("clear"); for(int i=0;i<screenWidth+2;i++) cout << "_"; cout <<endl; for(int i(0);i<screenHeight;i++) { cout << "|"; for(int j(0);j<screenWidth;j++) { if(map[j][i] == 0) cout<<" "; else if(map[j][i] == 1 || map[j][i] == 2) cout<<"#"; else cout<<map[j][i]; } cout << "|"; cout<<endl; } for(int i=0;i<screenWidth+2;i++) cout << "-" ; cout << endl; ShowNextBlock(); cout << "score:" << score<<endl; } void RussiaBlock::ShowNextBlock(void) { bool have = false; for(int r=0;r<4;r++) { for(int c=0;c<4;c++) { have = false; for(int blk=0;blk<4;blk++) { if(nextBlock.pos[blk].x == c&& nextBlock.pos[blk].y == r) { have = true; cout << "#"; } } if(have==false) cout<<" "; } cout << endl; } } void RussiaBlock::GameStart(void) { pthread_t id_auto,id_key; try { int ret = pthread_create(&id_auto,NULL,&Thread_func,this); if(ret != 0) throw runtime_error("start game fail"); ret = pthread_create(&id_key,NULL,&Thread_Key,this); if(ret != 0) throw runtime_error("start game fail"); } catch(runtime_error err) { cout << err.what() <<endl; return; } gameFail = false; while(!gameFail) { dropToEnd = false; currentBlock = nextBlock; nextBlock = CreatNewBlock(); for(int i=0;i<4;i++) { currentBlock.pos[i].x += (screenWidth/2); map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1; } while(!dropToEnd) { if(AtTheEnd()) { dropToEnd = true; for(int i=0;i<4;i++) map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 2; DeleteLines(); } } for(int i=0;i<screenWidth;i++) { if(map[i][0] == 2) { gameFail = true; break; } } } pthread_join(id_auto,NULL); pthread_join(id_key,NULL); FailNotice(); } bool RussiaBlock::AtTheEnd(void) { for(int i=0;i<4;i++) { if(map[currentBlock.pos[i].x][currentBlock.pos[i].y + 1] == 2|| currentBlock.pos[i].y ==screenHeight - 1) return true; } return false; } void RussiaBlock::FailNotice(void) { string failStr("Game Over!"); for(int i=0;i!=failStr.size();i++) { map[i][screenHeight/2] = failStr[i]; } ShowScreen(); } void RussiaBlock::KeyOperate(void) { struct input_event ev_key; int btn_fd = open("/dev/input/event3",O_RDWR); if(btn_fd < 0) { cerr << btn_fd <<endl; cerr << "Game initial fail!" << endl; return; } while(!gameFail) { int count = read(btn_fd,&ev_key,sizeof(struct input_event)); //for(int i=0;i<(int)count/sizeof(struct input_event);i++) if(EV_KEY == ev_key.type && ev_key.value == 1) { switch(ev_key.code) { case KEY_A:MoveLeft();break; case KEY_S:DropEnd();break; case KEY_D:MoveRight();break; case KEY_W:RotateBlock();break; } } ShowScreen(); } close(btn_fd); } void RussiaBlock::DeleteLines(void) { for(int i=0;i<screenHeight;i++) { if(ThisLineIsFull(i)) { DeleteOneLine(i); score++; } } } void RussiaBlock::DropEnd(void) { bool getEnd = false; while(1) { for(int i=0;i<4;i++) { if(map[currentBlock.pos[i].x][currentBlock.pos[i].y + 1] == 2|| currentBlock.pos[i].y ==screenHeight - 1) { getEnd = true; break; } } if(!getEnd) { for(int i=0;i<4;i++) { map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0; currentBlock.pos[i].y++; map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1; } } else break; } } void RussiaBlock::MoveRight(void) { for(int i=0;i<4;i++) { if(currentBlock.pos[i].x + 1 == screenWidth || map[currentBlock.pos[i].x+1][currentBlock.pos[i].y] == 2) { return ; } } for(int i=0;i<4;i++) { map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0; currentBlock.pos[i].x++; } for(int i=0;i<4;i++) map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1; } void RussiaBlock::MoveLeft(void) { for(int i=0;i<4;i++) { if(currentBlock.pos[i].x - 1 < 0 || map[currentBlock.pos[i].x-1][currentBlock.pos[i].y] == 2) { return ; } } for(int i=0;i<4;i++) { map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0; currentBlock.pos[i].x--; map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1; } } void RussiaBlock::RotateBlock(void) { short blockShape = currentBlock.shape; if(blockShape == TIAN_BLOCK) return; if(blockShape == I_BLOCK) { Pos pos[4] = {0}; for(int i=0;i<4;i++) { pos[i].y = currentBlock.pos[2].y; pos[i].x = currentBlock.pos[2].x + i-1; } for(int i=0;i<4;i++) { if(map[pos[i].x][pos[i].y] == 2 || pos[i].y >= screenHeight || pos[i].y < 0 || pos[i].x >= screenWidth || pos[i].x < 0) return ; } for(int i=0;i<4;i++) { map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0; currentBlock.pos[i] = pos[i]; map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1; } currentBlock.shape = HI_BLOCK; return ; } if(blockShape == HI_BLOCK) { Pos pos[4] = {0}; for(int i=0;i<4;i++) { pos[i].x = currentBlock.pos[1].x; pos[i].y = currentBlock.pos[1].y + i-1; } for(int i=0;i<4;i++) { if(map[pos[i].x][pos[i].y] == 2 || pos[i].y >= screenHeight || pos[i].y < 0 || pos[i].x >= screenWidth || pos[i].x < 0) return ; } for(int i=0;i<4;i++) { map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0; currentBlock.pos[i] = pos[i]; map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1; } currentBlock.shape = I_BLOCK; return ; } unsigned char maxX = currentBlock.pos[0].x,maxY = currentBlock.pos[0].y,minX = currentBlock.pos[0].x, minY = currentBlock.pos[0].y; for(int i=1;i<4;i++) { if(maxX < currentBlock.pos[i].x) maxX = currentBlock.pos[i].x; if(minX > currentBlock.pos[i].x) minX = currentBlock.pos[i].x; if(maxY < currentBlock.pos[i].y) maxY = currentBlock.pos[i].y; if(minY > currentBlock.pos[i].y) minY = currentBlock.pos[i].y; } unsigned char X = ((maxX-minX) == 2)?maxX-1:maxX; unsigned char Y = ((maxY-minY) == 2)?maxY-1:maxY; unsigned char arr[3][3] = {0}; short arrX=0,arrY=0; for(int i=Y-1;i<=Y+1;i++) { arrX = 0; for(int j=X-1;j<=X+1;j++) { arr[arrX++][arrY] = map[j][i]; if(map[j][i] == 2) return ; } arrY++; } //转置并换行 for(int i=0;i<3;i++) { for(int j = 0;j<=i;j++) { unsigned char temp = arr[j][i]; arr[j][i] = arr[i][j]; arr[i][j] = temp; } } for(int j=0;j<3;j++) { unsigned char temp = arr[j][0]; arr[j][0] = arr[j][2]; arr[j][2] = temp; } arrY = 0; int index = 0; for(int i=Y-1;i<=Y+1;i++) { arrX = 0; for(int j=X-1;j<=X+1;j++) { map[j][i] = arr[arrX++][arrY]; if(map[j][i] == 1) { currentBlock.pos[index].x = j; currentBlock.pos[index++].y = i; } } arrY++; } } Block RussiaBlock::TianBlock(void) { Block NewBlock = {0}; NewBlock.pos[0].x = 0; NewBlock.pos[0].y = 0; NewBlock.pos[1].x = 1; NewBlock.pos[1].y = 0; NewBlock.pos[2].x = 0; NewBlock.pos[2].y = 1; NewBlock.pos[3].x = 1; NewBlock.pos[3].y = 1; return NewBlock; } Block RussiaBlock::LBlock(void) { Block NewBlock = {0}; NewBlock.pos[0].x = 0; NewBlock.pos[0].y = 0; NewBlock.pos[1].x = 0; NewBlock.pos[1].y = 1; NewBlock.pos[2].x = 0; NewBlock.pos[2].y = 2; NewBlock.pos[3].x = 1; NewBlock.pos[3].y = 2; return NewBlock; } Block RussiaBlock::TBlock(void) { Block NewBlock = {0}; NewBlock.pos[0].x = 0; NewBlock.pos[0].y = 0; NewBlock.pos[1].x = 1; NewBlock.pos[1].y = 0; NewBlock.pos[2].x = 2; NewBlock.pos[2].y = 0; NewBlock.pos[3].x = 1; NewBlock.pos[3].y = 1; return NewBlock; } Block RussiaBlock::FLBlock(void) { Block NewBlock = {0}; NewBlock.pos[0].x = 0; NewBlock.pos[0].y = 0; NewBlock.pos[1].x = 1; NewBlock.pos[1].y = 0; NewBlock.pos[2].x = 2; NewBlock.pos[2].y = 0; NewBlock.pos[3].x = 2; NewBlock.pos[3].y = 1; return NewBlock; } Block RussiaBlock::IBlock(void) { Block NewBlock = {0}; NewBlock.pos[0].x = 0; NewBlock.pos[0].y = 0; NewBlock.pos[1].x = 0; NewBlock.pos[1].y = 1; NewBlock.pos[2].x = 0; NewBlock.pos[2].y = 2; NewBlock.pos[3].x = 0; NewBlock.pos[3].y = 3; return NewBlock; } Block RussiaBlock::HIBlock(void) { Block NewBlock = {0}; NewBlock.pos[0].x = 0; NewBlock.pos[0].y = 0; NewBlock.pos[1].x = 1; NewBlock.pos[1].y = 0; NewBlock.pos[2].x = 2; NewBlock.pos[2].y = 0; NewBlock.pos[3].x = 3; NewBlock.pos[3].y = 0; return NewBlock; } Block RussiaBlock::ZBlock(void) { Block NewBlock = {0}; NewBlock.pos[0].x = 0; NewBlock.pos[0].y = 0; NewBlock.pos[1].x = 1; NewBlock.pos[1].y = 0; NewBlock.pos[2].x = 1; NewBlock.pos[2].y = 1; NewBlock.pos[3].x = 2; NewBlock.pos[3].y = 1; return NewBlock; } Block RussiaBlock::FZBlock(void) { Block NewBlock = {0}; NewBlock.pos[0].x = 1; NewBlock.pos[0].y = 0; NewBlock.pos[1].x = 2; NewBlock.pos[1].y = 0; NewBlock.pos[2].x = 0; NewBlock.pos[2].y = 1; NewBlock.pos[3].x = 1; NewBlock.pos[3].y = 1; return NewBlock; } void *RussiaBlock::Thread_func(void *param) { RussiaBlock *p = (RussiaBlock *)param; p->AutoDrop(NULL); } void RussiaBlock::AutoDrop(void *ptr) { while(!gameFail) { int tim = time(0); while(tim == time(0)) ; DropOneLine(); ShowScreen(); } } bool RussiaBlock::DropOneLine(void) { for(int i=0;i<4;i++) { if(map[currentBlock.pos[i].x][currentBlock.pos[i].y + 1] ==2 ||currentBlock.pos[i].y == screenHeight -1) { return false; } } for(int i=0;i<4;i++) { map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 0; currentBlock.pos[i].y++; } for(int i=0;i<4;i++) map[currentBlock.pos[i].x][currentBlock.pos[i].y] = 1; return true; } void *RussiaBlock::Thread_Key(void *param) { RussiaBlock *p = (RussiaBlock *)param; p->KeyOperate(); }
main.cpp #include <iostream> #include "RussiaBlock.h" using namespace std; int main() { RussiaBlock blk(10,10); blk.GameStart(); return 0; }
makefile RussiaBlock: main.o RussiaBlock.o g++ -lpthread main.o RussiaBlock.o -o RussiaBlock main.o: main.cpp RussiaBlock.h g++ -c main.cpp RussiaBlock.o: RussiaBlock.cpp g++ -c RussiaBlock.cpp
相关文章推荐
- Linux socket 初步
- 使用C++实现JNI接口需要注意的事项
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- 关于指针的一些事情