Chinaunix首页 | 论坛 | 博客
  • 博客访问: 894670
  • 博文数量: 299
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2493
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-21 10:07
个人简介

Linux后台服务器编程。

文章分类

全部博文(299)

文章存档

2015年(2)

2014年(297)

分类: C/C++

2014-06-09 16:44:30

本程序的运行环境是linux,用到了多线程。创建了一个用来绘图的线程和一个获取按键的线程。程序中有一些需要改善的地方,比如336-338行定义的全局变量以及声明的对象。本来声明的Block和Table对象应该在main函数里面,然后将这两个对象作为参数传递给线程函数getkey。但是好像只能传递一个对象参数给线程函数。希望高手能够对程序进行改进。

ps:由于用到了多线程,而pthread不是linux的默认库,所以编译的时候需要指定线程库。即:g++ -o block -pthread block.cpp


  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5.   
  6. #include  
  7. #include 
  8. #include
  9.   
  10.   
  11. #define TABLE_SIZE 20  
  12. #define BLOCK_SIZE 4  
  13. #define SLEEP_TIME 500  
  14.   
  15. using namespace std;  
  16.   
  17. struct grid{int x; int y;};        //坐标  
  18.   
  19. /////////////////////Block 类//////////////////////  
  20. class Block  
  21. {  
  22. public:  
  23.     enum direct{UP, DOWN, LEFT, RIGHT};                 //定义方向  
  24.     grid g[BLOCK_SIZE];                                 //方块的坐标信息  
  25.   
  26.     void def_block(grid g1, grid g2, grid g3, grid g4); //定义方块  
  27.     void rotate();                                      //旋转方块  
  28.     void move(int dir);                                 //移动方块  
  29.     void set_cen(grid g);                               //设置方块旋转中心  
  30.     grid get_cen();                                     //获取方块旋转中心  
  31.     void set_type(int t);                               //设置方块种类  
  32.     int get_type();                                     //获取方块种类  
  33.     void back();                                        //旋转还原  
  34.     void creat_block(int x, int y);                     //随机生成方块  
  35.   
  36. private:  
  37.     grid center;                                        //方块旋转中心  
  38.     int type;                                           //方块类型  
  39.       
  40.   
  41. };  
  42.   
  43. void Block::def_block(grid g1, grid g2, grid g3, grid g4) {  
  44.     g[0]=g1; g[1]=g2; g[2]=g3; g[3]=g4;  
  45. }  
  46.   
  47. void Block::rotate() {  
  48.     int x, y, i=0;  
  49.   
  50.     for(i; i<=3; i++) {  
  51.         x=g[i].x-center.x; y=g[i].y-center.y;  
  52.         g[i].x=center.x+y; g[i].y=center.y-x;  
  53.     }  
  54. }  
  55.   
  56. void Block::move(int dir) {  
  57.     int d=dir, i=0;  
  58.   
  59.     switch(d) {  
  60.     case UP: {   
  61.         for(i; i<=3; i++) g[i].y++;  
  62.         center.y++; break;  
  63.              }  
  64.     case DOWN: {  
  65.         for(i; i<=3; i++) g[i].y--;  
  66.         center.y--; break;  
  67.                }  
  68.     case LEFT: {  
  69.         for(i; i<=3; i++) g[i].x--;  
  70.         center.x--; break;  
  71.                }  
  72.     case RIGHT: {  
  73.         for(i; i<=3; i++) g[i].x++;  
  74.         center.x++; break;  
  75.                 }  
  76.     }  
  77. }  
  78.   
  79. void Block::set_cen(grid g) {  
  80.     center=g;  
  81. }  
  82.   
  83. grid Block::get_cen() {  
  84.     return center;  
  85. }  
  86.   
  87. void Block::set_type(int t) {  
  88.     type=t;  
  89. }  
  90.   
  91. int Block::get_type() {  
  92.     return type;  
  93. }  
  94.   
  95. void Block::back() {  
  96.     int x, y, i=0;  
  97.   
  98.     for(i; i<=3; i++) {  
  99.         x=g[i].x-center.x; y=g[i].y-center.y;  
  100.         g[i].x=center.x-y; g[i].y=center.y+x;  
  101.     }  
  102. }  
  103.   
  104. void Block::creat_block(int x, int y) {   //随机创建方块  
  105.     int ran;  
  106.     grid g[BLOCK_SIZE];  
  107.   
  108.       
  109.     ran=1+rand()%7;  
  110.     switch(ran) {  
  111.     //L  
  112.     case 1: {  
  113.         g[0].x=x/2; g[0].y=y-3;  
  114.         g[1].x=g[0].x; g[1].y=g[0].y+1;  
  115.         g[2].x=g[0].x; g[2].y=g[0].y+2;  
  116.         g[3].x=g[0].x+1; g[3].y=g[0].y;   
  117.         set_cen(g[0]); set_type(1); break;  
  118.             }  
  119.     //反L  
  120.     case 2: {  
  121.         g[0].x=x/2; g[0].y=y-3;  
  122.         g[1].x=g[0].x; g[1].y=g[0].y+1;  
  123.         g[2].x=g[0].x; g[2].y=g[0].y+2;  
  124.         g[3].x=g[0].x-1; g[3].y=g[0].y;   
  125.         set_cen(g[0]); set_type(2); break;  
  126.             }  
  127.     //Z  
  128.     case 3: {  
  129.         g[0].x=x/2; g[0].y=y-2;  
  130.         g[1].x=g[0].x; g[1].y=g[0].y+1;  
  131.         g[2].x=g[0].x+1; g[2].y=g[0].y+1;  
  132.         g[3].x=g[0].x-1; g[3].y=g[0].y;   
  133.         set_cen(g[0]); set_type(3); break;  
  134.             }  
  135.     //反Z  
  136.     case 4: {  
  137.         g[0].x=x/2; g[0].y=y-2;  
  138.         g[1].x=g[0].x; g[1].y=g[0].y+1;  
  139.         g[2].x=g[0].x+1; g[2].y=g[0].y+1;  
  140.         g[3].x=g[0].x-1; g[3].y=g[0].y;   
  141.         set_cen(g[0]); set_type(4); break;  
  142.             }  
  143.     //田  
  144.     case 5: {  
  145.         g[0].x=x/2; g[0].y=y-2;  
  146.         g[1].x=g[0].x; g[1].y=g[0].y+1;  
  147.         g[2].x=g[0].x+1; g[2].y=g[0].y+1;  
  148.         g[3].x=g[0].x+1; g[3].y=g[0].y;   
  149.         set_cen(g[0]); set_type(5); break;  
  150.             }  
  151.     //1  
  152.     case 6: {  
  153.         g[0].x=x/2; g[0].y=y-3;  
  154.         g[1].x=g[0].x; g[1].y=g[0].y+1;  
  155.         g[2].x=g[0].x; g[2].y=g[0].y+2;  
  156.         g[3].x=g[0].x; g[3].y=g[0].y-1;   
  157.         set_cen(g[0]); set_type(6); break;  
  158.             }  
  159.     //山  
  160.     case 7: {  
  161.         g[0].x=x/2; g[0].y=y-2;  
  162.         g[1].x=g[0].x; g[1].y=g[0].y+1;  
  163.         g[2].x=g[0].x-1; g[2].y=g[0].y;  
  164.         g[3].x=g[0].x+1; g[3].y=g[0].y;   
  165.         set_cen(g[0]); set_type(7); break;  
  166.             }  
  167.     default: ;  
  168.     }  
  169.     def_block(g[0], g[1], g[2], g[3]);  
  170. }  
  171.   
  172.   
  173. /////////////////////////////////////////  
  174.   
  175. ////////////////////Table 类//////////////////////  
  176. class Table  
  177. {  
  178. public:  
  179.       
  180.     Table() {                         //构造棋盘  
  181.         height=20; width=10; count=0;  
  182.         init_table();  
  183.     }  
  184.     Table(int x, int y);  
  185.     int set_block(Block bl);          //安设方块  
  186.     void clr_block(Block bl);         //清除方块  
  187.     int clr_line(int y);              //消行  
  188.     int get_h();                      //获取棋盘高度  
  189.     int get_w();                      //获取棋盘宽度  
  190.     int if_full(int y);               //判定是否满行  
  191.     int get_table(int x, int y);      //获取棋盘上点信息  
  192.     void paint();                     //绘制棋盘  
  193.     void move_line(int y);            //整行下移  
  194.     void set_count(int c);            //记录得分  
  195.     int get_count();                  //获取得分  
  196.   
  197. private:  
  198.     int table[TABLE_SIZE][TABLE_SIZE];//棋盘  
  199.     int height, width;                //棋盘的高和宽  
  200.     int count;                        //得分  
  201.   
  202.     void init_table();                //棋盘初始化  
  203.   
  204. };  
  205.   
  206. void Table::init_table() {  
  207.     int i=0, j=0;  
  208.   
  209.     for(i; i
  210.         for(j=0; j
  211.             table[i][j]=0;  
  212.         }  
  213.     }  
  214. }  
  215.   
  216. Table::Table(int x, int y) {  
  217.     height=y; width=x; count=0;  
  218.     init_table();  
  219. }  
  220.   
  221. int Table::set_block(Block bl) {  
  222.     int x, y;  
  223.     int i;  
  224.     for(i=0; i<=3; i++) {  
  225.         x=bl.g[i].x; y=bl.g[i].y;  
  226.         if(table[x][y]!=0 || x>=width || x<0 || y>=height || y<0) {  
  227.             return 0;  
  228.         }  
  229.     }  
  230.     for(i=0; i<=3; i++) {  
  231.         x=bl.g[i].x; y=bl.g[i].y;  
  232.         table[x][y]=1;  
  233.     }  
  234.     return 1;  
  235. }  
  236.   
  237. void Table::clr_block(Block bl) {  
  238.     int x, y;  
  239.   
  240.     for(int i=0; i<=3; i++) {  
  241.         x=bl.g[i].x; y=bl.g[i].y;  
  242.         table[x][y]=0;  
  243.     }  
  244. }  
  245.   
  246. int Table::clr_line(int y) {  
  247.     if(y<0 || y>=height) return 0;  
  248.     for(int i=0; i
  249.         table[i][y]=0;  
  250.     }  
  251.     return 1;  
  252. }  
  253.   
  254. int Table::get_h() {  
  255.     return height;  
  256. }  
  257.   
  258. int Table::get_w() {  
  259.     return width;  
  260. }  
  261.   
  262. int Table::if_full(int y) {  
  263.     int i=0;  
  264.   
  265.     for(i; i
  266.         if(table[i][y]==0) return 0;  
  267.     }  
  268.     return 1;  
  269. }  
  270.   
  271. int Table::get_table(int x, int y) {  
  272.     return table[x][y];  
  273. }  
  274.   
  275. void Table::paint() {  
  276.     int i, j;  
  277.   
  278.     for(i=0; i"-"<
  279.     cout<<"\n"<
  280.     for(i=height-1; i>=0; i--) {  
  281.         cout<<"|"<
  282.         for(j=0; j
  283.             if(table[j][i]==0) cout<<" "<
  284.             else cout<<"?"<
  285.         }  
  286.         if(i==10)  
  287.             cout<<"|    得分:"<
  288.         else if(i==7)  
  289.             cout<<"|    Press 'q' to quit!"<
  290.         else  
  291.             cout<<"|"<
  292.     }  
  293.     for(i=0; i"-"<
  294.     cout<<"\n"<
  295.     //cout<<"得分:"<  
  296. }  
  297.   
  298. void Table::move_line(int y) {  
  299.     int i, j;  
  300.   
  301.     for(i=y; i
  302.         for(j=0; j
  303.             table[j][i]=table[j][i+1];  
  304.         }  
  305.     }  
  306. }  
  307.   
  308. void Table::set_count(int c) {  
  309.     count+=c;  
  310. }  
  311.   
  312. int Table::get_count() {  
  313.     return count;  
  314. }  
  315.   
  316. ///////////////////////////////////////////////////////  
  317. class Mythread  
  318. {  
  319. public:  
  320.     void init();  
  321.     static void *getkey(void *arg);//线程函数在类里面定义必须定义为static型,以去除类指针。  
  322.     static void *paint_loop(void *arg);  
  323. };  
  324.   
  325. void Mythread::init()  
  326. {  
  327.     pthread_t ntid,ntid2;  
  328.     int err,err2;         
  329.     err = pthread_create(&ntid,NULL,getkey,NULL);  
  330.     err2 = pthread_create(&ntid2,NULL,paint_loop,NULL);  
  331.     if(err != 0 || err2 != 0){  
  332.         cout<<"can't create thread!"<
  333.         exit(0);  
  334.     }  
  335. }  
  336.   
  337. unsigned char flag=1,buf[2];//全局变量  
  338. Table tab(15, 20);  //构造一个15,20的棋盘  
  339. Block bl;           //构造一个落下方块  
  340. void* Mythread::paint_loop(void *arg)  
  341. {  
  342.     while(1)  
  343.     {  
  344.         system("clear");  
  345.         tab.paint();  
  346.         usleep(50000);       //暂停50 MS  
  347.     }  
  348. }  
  349. void* Mythread::getkey(void *arg)  
  350. {  
  351.     struct termios saveterm,nt;  
  352.     fd_set rfds,rs;  
  353.     struct timeval tv;  
  354.     int i=0,q,r,fd=0;  
  355.     tcgetattr(fd,&saveterm);  
  356.     nt=saveterm;  
  357.   
  358.     nt.c_lflag &= ~ECHO;  
  359.     nt.c_lflag &= ~ISIG;  
  360.     nt.c_lflag &= ~ICANON;  
  361.   
  362.     tcsetattr(fd,TCSANOW,&nt);  
  363.   
  364.     FD_ZERO(&rs);  
  365.     FD_SET(fd,&rs);  
  366.     tv.tv_sec=0;  
  367.     tv.tv_usec=0;  
  368.     while(1)  
  369.     {     
  370.         read(0,buf,1);  
  371.         r=select(fd+1,&rfds,NULL,NULL,&tv);  
  372.         if(r<0)  
  373.         {  
  374.             write(1,"select() error.\n",16);  
  375.         }  
  376.         rfds=rs;  
  377.         if(flag==2||buf[0]==113)//游戏结束或者用户按下'q'键,则程序退出  
  378.         {  
  379.             tcsetattr(0,TCSANOW,&saveterm);  
  380.             exit(0);  
  381.         }  
  382.         if(buf[0]<=68&&buf[0]>=65) flag=0;//如果按的键是方向键,则将标志位置0并执行相应的处理.  
  383.         if(flag==0)  
  384.         {  
  385.             if(buf[0]==65) {  
  386.             //if(dir!=0) {  
  387.                 if(bl.get_type()==5) continue//如果出现田字形则不作旋转  
  388.                 tab.clr_block(bl);           //清空方块上一次位置  
  389.                 bl.rotate();                 //开始旋转  
  390.                 if(!tab.set_block(bl)) {     //将旋转后的方块写在棋盘上  
  391.                     bl.back();              //如果写失败(例如到边线了,或卡住了)则还原旋转前位置  
  392.                     continue;  
  393.                     tab.set_block(bl);         
  394.                 }  
  395.             }  
  396.             //下(加速下落)  
  397.             //dir=GetAsyncKeyState(VK_DOWN);   //获取向下  
  398.             if(buf[0]==66) {  
  399.                 tab.clr_block(bl);          //清空方块上一次位置  
  400.                 bl.move(bl.DOWN);           //向下移动一步  
  401.                 if(!tab.set_block(bl)) {    //将移动后的方块写在棋盘上  
  402.                     bl.move(bl.UP);         //如果失败,则还原到移动前的位置(即上移一步)  
  403.                     tab.set_block(bl);  
  404.                 }  
  405.             }  
  406.             //左(左移)  
  407.             //dir=GetAsyncKeyState(VK_LEFT);  
  408.             if(buf[0]==68) {  
  409.                 tab.clr_block(bl);  
  410.                 bl.move(bl.LEFT);  
  411.                 if(!tab.set_block(bl)) {  
  412.                     bl.move(bl.RIGHT);  
  413.                     tab.set_block(bl);  
  414.                 }  
  415.             }  
  416.             //右(右移)  
  417.             //dir=GetAsyncKeyState(VK_RIGHT);  
  418.             if(buf[0]==67) {  
  419.                 tab.clr_block(bl);  
  420.                 bl.move(bl.RIGHT);  
  421.                 if(!tab.set_block(bl)) {  
  422.                     bl.move(bl.LEFT);  
  423.                     tab.set_block(bl);  
  424.                 }  
  425.             }  
  426.             flag=1;  
  427.         }  
  428.     }  
  429.     tcsetattr(0,TCSANOW,&saveterm);  
  430. }  
  431.   
  432. ////////////主函数部分///////////////////////  
  433.   
  434. int main()  
  435. {  
  436.     //Table tab(15, 20);  //构造一个15,20的棋盘  
  437.     //Block bl;           //构造一个落下方块  
  438.     Mythread thread;  
  439.     thread.init();  
  440.     int dir,i,c;  
  441.     while(true) {  
  442.         //生成方块  
  443.         srand(time(0));  
  444.         bl.creat_block(tab.get_w(), tab.get_h());  
  445.         //判断游戏是否结束  
  446.         if( !tab.set_block(bl) ) {  
  447.             system("clear");  
  448.             cout<<"GAME OVER!"<
  449.             flag=2;  
  450.             cout<<"PRESS ANY KEY TO CONTINUE!"<
  451.             while(1);  
  452.         }  
  453.         ///////////行动按键判定  
  454.         while(true){  
  455.             usleep(500000);       //暂停500 MS  
  456.             /////////////向下移动一格  
  457.             tab.clr_block(bl);       //清空上一次方块位置  
  458.             bl.move(bl.DOWN);        //向下移动一步  
  459.             if(!tab.set_block(bl)) {     //是否触底  
  460.                 bl.move(bl.UP);       //如果触底,还原触底前位置  
  461.                 tab.set_block(bl);  
  462.                 break;  
  463.             }  
  464.         }  
  465.         //如果满行则消行  
  466.         for(i=0; i
  467.             if(tab.if_full(i)) {  //是否满行  
  468.                 tab.clr_line(i);  //如果是,消行  
  469.                 tab.move_line(i); //将所消行的上面的棋盘信息下移  
  470.                 i--;           //下移后,重新检查这一行是否满(可能出现几行同时消去)  
  471.                 tab.set_count(100); //记录得分  
  472.             }  
  473.         }  
  474.           
  475.     }  
  476.     return 0;  
  477. }  
阅读(1641) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~