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

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

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <time.h>
#include <unistd.h>#include<termios.h>
#include<fcntl.h>#define TABLE_SIZE 20
#define BLOCK_SIZE 4
#define SLEEP_TIME 500using 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) {//Lcase 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;}//反Lcase 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;}//Zcase 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;}//反Zcase 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;}//1case 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;elsecout<<"|"<<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;
}

C++俄罗斯方块(linux环境)相关推荐

  1. C++俄罗斯方块(linux环境)-转 感觉非常好

    C++俄罗斯方块(linux环境)-转 感觉非常好 空间 本程序的运行环境是linux,用到了多线程.创建了一个用来绘图的线程和一个获取按键的线程.程序中有一些需要改善的地方,比如336-338行定义 ...

  2. 俄罗斯方块linux服务器,C++俄罗斯方块(linux环境)(比较简单的实现)

    #include #include #include #include #include #include #include #define TABLE_SIZE 20 #define BLOCK_S ...

  3. Linux 环境配置的最佳实践

    Linux 环境配置的最佳实践 Linux 基础知识 硬链接 & 软链接 Linux 目录 基本指令 Linux 环境配置 安装 zsh 和 oh-my-zsh 开发环境安装(必用) nvm ...

  4. linux环境下nacos的安装+启动,阿里云服务器安装nacos

    nacos安装+启动(linux环境): 基础:安装java环境 官网下载压缩包:如 nacos-server-1.2.1.tar.gz 放在自定义目录下 # 解压 tar -xvf nacos-se ...

  5. Linux环境变量说明与配置

    相关的配置文件说明: /etc/profile 范围:对所有用户生效 作用: a.定义USER变量 b.定义LOGNAME变量 c.定义MAIL变量 d.定义PATH变量 e.定义HOSTNAME变量 ...

  6. linux svn更换数据仓库,Linux环境下SVN数据仓库迁移

    上一篇文章介绍了Windows环境下SVN数据的备份与还原,这篇文章介绍下Linux环境下数据迁移. 一准备工作 1安装环境 1 centOS7 2可上网 2软件需求 1 winSCP 2 PuTTy ...

  7. Linux环境下的网络编程

    本文介绍了在Linux环境下的socket编程常用函数用法及socket编程的一般规则和客户/服务器模型的编程应注意的事项和常遇问题的解决方法,并举了具体代  码实例.要理解本文所谈的技术问题需要读者 ...

  8. [.Net跨平台]部署DTCMS到Jexus遇到的问题及解决思路---Linux环境搭建

    最近朋友托我帮忙研究如何把一个DTCMS部署到Linux下,经过1天的研究,部署基本成功,可能有些细节还未注意到,现在把心得分享一下.过程比预期的要简单 身为.Net程序员,这个问题的第一步可能就是如 ...

  9. Linux 环境变量配置

    linux 环境,用户通过shell 操作时,系统会为用户初使化环境变量, 比如系统公共资源路径: path , include , bin 等目录. shell 模式下,执行 export , 查看 ...

最新文章

  1. centos 安装php5.6
  2. Oracle时间函数
  3. 三、hbase JavaAPI
  4. 交换机与路由器在网路中所扮演的角色—Vecloud微云
  5. oracle tns 代理配置_oracle数据库tns配置方法详解
  6. 双足机器人简单步态生成
  7. python 弹窗不阻断线程_Javascript 如何阻断程序的运行
  8. 「刷新 CTO」微软与 CSDN 的 CTO 转型思想汇
  9. VSCODE: 快速生成html框架
  10. linux shell脚本 main,Linux shell启动Java Main函数脚本
  11. 物联网控制的智能LED灯带(1):WS2812灯带控制(WS2812/2811,ESP32,NODE-RED)
  12. 组合体计算机绘图的实验原理,《机械制图及计算机绘图》实验教案.pdf
  13. ARCGIS之土地报备坐标(报盘数据)txt批量导出工具简介
  14. 客户分段模型(Customer Segmentation Models)
  15. 【DPD数字预失真】射频功放的Volterra级数数字预失真系统开发
  16. 微信小程序自定义组件/插件等解析
  17. ios 去除字符串首尾空格、换行
  18. Java基础知识点总结(面试版)
  19. PostgreSQL CAST 转换数据类型
  20. DML语句(delete,insert,update)

热门文章

  1. Zabbix的mysql到Tidb分布式数据库的替换
  2. 蓝牙耳机哪个款式好用?好用蓝牙耳机款式推荐
  3. 美通社日历 | 媒体关注、会展信息、企业财报发布,节假日备忘(2月1日—2月7日)...
  4. 计算机专业海报排版设计,【平面设计必看干货:海报设计排版构图篇】- 环球网校...
  5. Netty网络聊天(一) 聊天室实战
  6. 支付宝和蚂蚁花呗的技术架构及实践
  7. 淘宝的数据库,主键是如何设计的?
  8. AudioTrack: releaseBuffer() track 0xe5c6bc00 disabled due to previous underrun, restarting
  9. micropython中断优先级_中断管理 - RT-Thread 文档中心
  10. Java手机忘了密码怎么办_忘记Linux密码怎么办