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

57 篇文章 0 订阅

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

  • 空间

本程序的运行环境是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 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;

}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值