⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qgamewidget.cpp

📁 linux 下的 仿联众版俄罗斯方块游戏。qt3 实现。 具有 人机交互功能。 具有 对战模式。 喜欢玩俄罗斯方块的朋友们
💻 CPP
字号:
/*********************************************************************** * * *    linux版仿联众俄罗斯方块 v1.0 *    该软件在GPL(GNU通用公共许可证)下发布 * *    Copyright (C)   <codeky@126.com> * *   This source code is licensed under the GNU General Public License * ************************************************************************/#include <qapplication.h>#include <qpainter.h>#include <qdrawutil.h>#include <qpixmap.h>#include "config.h"#include "qmainwidget.h"#include "qgamewidget.h"#include "qgamethread.h"#define gamelock() gameAccessMutex.lock()#define gameunlock() gameAccessMutex.unlock()extern char curPath[];static QMutex gameAccessMutex;  //访问 BLOCK_GAME game 的锁// 访问,修改 都应该加琐,因为存在线程QGameWidget::QGameWidget( QWidget *parent, const char *name )        : QWidget( parent, name ){	InitGame(&game); // 初始状态不必加琐	bPlayMode = ePlaySinle; // 默认为自由模式	bComputerRun = false;	clrLastBlockRect();	bRefresh = true;	brcolor[0] = Qt::darkRed; 		brcolor[1] = Qt::red;	brcolor[2] = Qt::blue; 			brcolor[3] = Qt::darkCyan;	brcolor[4] = Qt::darkMagenta; 	brcolor[5] = Qt::darkYellow;	brcolor[6] = Qt::darkGreen; 	egcolor = Qt::lightGray;	gamePix = new QPixmap( DEF_GAME_WIDTH,DEF_GAME_HEIGHT );	nextPix = new QPixmap( DEF_BLOCK_SIZE*4,DEF_BLOCK_SIZE*4 );	blockSize = DEF_BLOCK_SIZE ;	if(!gamePix) exit(-1);	connect( this, SIGNAL(SelPainSignal(int)),        SLOT(drawGame(int)) );	setPalette( QPalette( lightGray ));}// 必然是 开始 运行 后 才会调用该 函数void QGameWidget::overDriveDownBlock(){	gamelock();	FixCurBlock(&game);	_bS8 n = AdjustGrid(&game);	bool newSuccess=true;	if(!NewBlock(&game)){		GameOver(&game);		newSuccess=false;		if(bPlayMode!=ePalyVS) palyAufile("au/lost_attacked.au");		// 对战模式说verygood	}	gameunlock();	if(!newSuccess){		if( bPlayMode==ePalyVS) emit NoticeOtherWinGame();	}else{ // 游戏仍然继续		if(n==0)			palyAufile("au/normal_downed.au");		else if(n==1)			palyAufile("au/normal_full_row.au");		else if(n>1)			palyAufile("au/multiple_full_row.au");	}	emit AddOtherLine(n);	emit SelPainSignal(1); // 无论如何都要重绘	clrLastBlockRect();	bRefresh = true;}// 充分利用系统命令~~void QGameWidget::palyAufile(const char * filename){	extern char curPath[];	char cmd[PATH_MAX+50];	sprintf(cmd,"cat %s%s > /dev/audio 2> /dev/null &",curPath,filename);	system(cmd);}void QGameWidget::gameAddLine(_bS8 n){	if(bPlayMode!=ePalyVS || n>4 || n<=0 )	return;	gamelock();	AddLine(&game,n-1);	gameunlock();	emit SelPainSignal(1); //~~}int QGameWidget::gameStatus(){	gamelock();	int s = game.nGameStatus;	gameunlock();	return s;}void QGameWidget::startGame(){	gamelock();	NewGame(&game);	gameunlock();	drawGame(1);}void QGameWidget::setPlayMode(int mode){	bPlayMode = mode; //}void QGameWidget::setGamePause(bool p){	gamelock();	if(p){		game.nGameStatus = eGamePause;	}else{		game.nGameStatus = eGameRun;	}	gameunlock();	if(p){		drawGame(1);	}}void QGameWidget::iWinTheGame() // 自己赢了{	gamelock();	WinGame(&game);	gameunlock();	drawGame(1);	palyAufile("au/very_good.au");}void QGameWidget::handleKeyEvent( int key){	if(bComputerRun) return;	int s= gameStatus();	if(s==eGameRun)	{		bool b = false;		switch(key){			case eMoveTurn:				gamelock();				b = MoveBlock(&game,eMoveTurn);				gameunlock();				if(b)drawGame(0);				break;			case eMoveLeft:				gamelock();				b = MoveBlock(&game,eMoveLeft);				gameunlock();				if(b)drawGame(0);				break;			case eMoveRight:				gamelock();				b = MoveBlock(&game,eMoveRight);				gameunlock();				if(b)drawGame(0);				break;			case eMoveSDown:				gamelock();				b = MoveBlock(&game,eMoveDown);				gameunlock();				if(!b)	overDriveDownBlock(); // 自己有锁				drawGame(0);				break;			case eMoveDown:				gamelock();				while(MoveBlock(&game,eMoveDown));				gameunlock();				overDriveDownBlock();				drawGame(0);				break;		}	}}void QGameWidget::resizeEvent ( QResizeEvent * e){	int c = e->size().width()/GAME_COL; // 列宽	int r = e->size().height()/GAME_ROW;// 行高	blockSize = (c > r) ? r: c; // 选小的	setGeometry(x(),y(),blockSize*GAME_COL,blockSize*GAME_ROW);	// 居然这样能行,可能是当下次resize之前,先进行了判断。	gamePix->resize(blockSize*GAME_COL,blockSize*GAME_ROW);	bRefresh = true;}void QGameWidget::drawGame(int rBack){	painter_lock();	QPainter p(gamePix);	if(rBack | bRefresh){		drawBackGrid(&p);		bRefresh = false; // 免得重绘背景,绘图耗时	}	switch(gameStatus()){		case eGameRun:		case eGamePause:			drawClrLastBlock(&p);			drawCurBlock(&p);			break;		case eGameLost:			drawOverShow(&p,0);			break;		case eGameWin:			drawOverShow(&p,1);			break;	}	p.end();	p.begin( this );	p.drawPixmap(0,0, *gamePix );	painter_unlock();	drawNextBlock();}void QGameWidget::paintEvent( QPaintEvent * ){	drawGame(1); // 这样就不怕系统刷新了}void QGameWidget::drawOverShow( QPainter *p ,int type ){	char tmpName[PATH_MAX];	if(type==0){		sprintf(tmpName,"%simages/lost.bmp",curPath);	}else{		sprintf(tmpName,"%simages/win.bmp",curPath);	}	QPixmap t(tmpName);	int a = t.width();	int b =blockSize*GAME_COL;	int c = t.height();	int h = blockSize*GAME_ROW; //新高度	QRect r;	if(a>b){  // 图像宽于框框,只考虑这中情况,简单点		b-=6; // 不要压在边框上了		h = c*b/a;		if(h)			r.setRect(3,(blockSize*GAME_ROW-h)/2,b,h);	}else{		r.setRect((b-a)/2,(h-c)/2,a,c);	}	p->drawPixmap(r,t);}void QGameWidget::drawBackGrid( QPainter *p ){	QRect BlockRect;	_bS8 i, j;	gamelock();	for(i=GAME_FIRST_ROW;i<=GAME_LAST_ROW;i++) {		for(j=GAME_FIRST_COL;j<=GAME_LAST_COL;j++) {			BlockRect.setRect((j-GAME_FIRST_COL)*blockSize,							   (i-GAME_FIRST_ROW)*blockSize, blockSize,+blockSize);			if(0!=game.GameGrid.Grid[i][j].bFillBlock) {			//	p->setBrush( brcolor[game.GameGrid.Grid[i][j].nBlockType] );			//	p->drawRect(BlockRect);				QBrush br(brcolor[game.GameGrid.Grid[i][j].nBlockType]);				qDrawShadeRect(p,BlockRect,colorGroup(),false,1,0,&br);			} else {				//p->eraseRect(BlockRect);				p->fillRect(BlockRect,QBrush(Qt::black));			}		}	}	gameunlock();}void QGameWidget::drawNextBlock(){	QRect BlockRect;	if(!nextPix)		nextPix = new QPixmap(DEF_BLOCK_SIZE*4,DEF_BLOCK_SIZE*4);	nextPix->fill(Qt::black);	painter_lock();	QPainter p( nextPix );	int s = gameStatus();	if(s==eGameRun || s== eGamePause){		gamelock();		for(int i=0;i<4;i++)		for(int j=0;j<4;j++) {			if(GameBlock[game.GameBlock.nNextBlockType][0][i][j]){			 	BlockRect.setRect(j*DEF_BLOCK_SIZE,	i*DEF_BLOCK_SIZE,							DEF_BLOCK_SIZE, DEF_BLOCK_SIZE );				QBrush br(brcolor[game.GameBlock.nNextBlockType]);				qDrawShadeRect(&p,BlockRect,colorGroup(),false,1,0,&br);			}		}		gameunlock();	}	p.end();	painter_unlock();	emit PaintNextSignal(nextPix);}void QGameWidget::drawCurBlock( QPainter *p ){	QRect BlockRect;	int nCount=0;	gamelock();	for(int i=0;i<4;i++) {		for(int j=0;j<4;j++) {			if(GameBlock[game.GameBlock.nCurBlockType][game.GameBlock.nCurBlockStatus][i][j]){			 	BlockRect.setRect( (game.GameBlock.CurFirstBlock.col+j-GAME_FIRST_COL)*blockSize,				(game.GameBlock.CurFirstBlock.row+i-GAME_FIRST_ROW)*blockSize,				blockSize, blockSize );				QBrush br(brcolor[game.GameBlock.nCurBlockType]);				qDrawShadeRect(p,BlockRect,colorGroup(),false,1,0,&br);				LastBlockRect[nCount++]=BlockRect;			}		}	}	gameunlock();}void QGameWidget::clrLastBlockRect(){	LastBlockRect[0]		=LastBlockRect[1]		=LastBlockRect[2]		=LastBlockRect[3]	=QRect(0,0,0,0);}void QGameWidget::drawClrLastBlock( QPainter *p ){	for(int i=0;i<4;i++)		//p->eraseRect(LastBlockRect[i]);		p->fillRect(LastBlockRect[i],QBrush(Qt::black));}//-----------------------------------------------------------// 这是一组电脑运行相关的程序,void QGameWidget::setComputerRun(bool r){	bComputerRun = r;}bool QGameWidget::ComputerRun(){	GAME_GRID  GridBack;	GAME_BLOCK BlockBack;	BLOCK_GAME GameBack;	BLOCK_GAME CmpGame;	GRID_ATTR CurGridAttr;	GRID_ATTR BestGridAttr;	if( !bComputerRun ) return false;	if(gameStatus()!=eGameRun) return false;	gamelock();	CopyGame(&GameBack, &game);	gameunlock();	_bS8 i=0,j=0;	_bS8 TurnCount=0; //需要旋转的次数	_bS8 BestCol=GameBack.GameBlock.CurFirstBlock.col;	 // 最好状态所在列	unsigned int timer0 = GameBack.nGameTimer;	CopyGame(&CmpGame, &GameBack);	BestGridAttr.nFullRowCount=-1; // 保证比较不出问题	for(i=0;i<4;i++)	{		for(j=0;j<i;j++) TurnBlock(&CmpGame); // 旋转i次		while(MoveBlock(&CmpGame,eMoveLeft)); // 移到最左边		do{			CopyGameGrid(&GridBack,&CmpGame.GameGrid); // 保存格子			CopyGameBlock(&BlockBack,&CmpGame.GameBlock); // 保存方块			j=CmpGame.GameBlock.CurFirstBlock.col;			while(MoveBlock(&CmpGame,eMoveDown)); // 落下			FixCurBlock(&CmpGame);	 // 固定			GetGridAttr(&CmpGame,&CurGridAttr); // 获取属性			if(judgeBetterAttr(CurGridAttr,BestGridAttr)){				CopyGridAttr(&BestGridAttr,&CurGridAttr);				TurnCount=i;				BestCol=j;			}			CopyGameGrid(&CmpGame.GameGrid,&GridBack); // 恢复格子			CopyGameBlock(&CmpGame.GameBlock,&BlockBack); // 恢复方块		}while(MoveBlock(&CmpGame,eMoveRight)); // 单步向右移动		CopyGame(&CmpGame,&GameBack);	// 恢复为初时状态	}	/*****************************************************************/	gamelock();	unsigned int timer1 = game.nGameTimer;	gameunlock();	if(timer0 != timer1)		return false;	return driveBlockRun(TurnCount,BestCol);}#define HaveNewGame_OR_Dirtied() \do{ \	if(timer0!=timer1){ \			return false; \	} \	if(dirty){ \		gamelock(); \		game.bDirty = _bFalse; \		gameunlock(); \		return false; \	} \}while(0)bool QGameWidget::driveBlockRun(int status, int col){	gamelock();	unsigned int timer0 = game.nGameTimer;	_bBool dirty = game.bDirty;	gameunlock();	unsigned int timer1 = timer0;	while(status-->0)	{		gamelock();		timer1 = game.nGameTimer;		dirty = game.bDirty;		gameunlock();		HaveNewGame_OR_Dirtied();		gamelock();		TurnBlock(&game);		gameunlock();		emit SelPainSignal(0);		QGameThread::msleep(100);	};	_bBool b = _bTrue;	while(1){		gamelock();		timer1 = game.nGameTimer;		dirty = game.bDirty;		b = game.GameBlock.CurFirstBlock.col>col;		gameunlock();		HaveNewGame_OR_Dirtied();		if(!b) break;		gamelock();		MoveBlock(&game,eMoveLeft);		gameunlock();		emit SelPainSignal(0);		QGameThread::msleep(100);	};	while(1){		gamelock();		b = game.GameBlock.CurFirstBlock.col<col;		timer1 = game.nGameTimer;		dirty = game.bDirty;		gameunlock();		HaveNewGame_OR_Dirtied();		if(!b) break;		gamelock();		MoveBlock(&game,eMoveRight);		gameunlock();		emit SelPainSignal(0);		QGameThread::msleep(100);	};	do{		gamelock();		timer1 = game.nGameTimer;		dirty = game.bDirty;		gameunlock();		HaveNewGame_OR_Dirtied();		gamelock();		b = MoveBlock(&game,eMoveDown);		gameunlock();		emit SelPainSignal(0);		QGameThread::msleep(50);	}while(b);	overDriveDownBlock(); // 自己有锁	emit SelPainSignal(1);	return true;}bool QGameWidget::judgeBetterAttr(const GRID_ATTR& CurAttr,                       const GRID_ATTR& BestAttr){	if(CurAttr.nFullRowCount>BestAttr.nFullRowCount){		return true;	}	else if(CurAttr.nFullRowCount==BestAttr.nFullRowCount	        || BestAttr.nFullRowCount==1){		if(CurAttr.nIdleBankCount<BestAttr.nIdleBankCount){			return true;		}else if(CurAttr.nIdleBankCount		         ==BestAttr.nIdleBankCount){			if(CurAttr.nLastBlockFirstRow			   >BestAttr.nLastBlockFirstRow){				return true;			}else if(CurAttr.nLastBlockFirstRow			         ==BestAttr.nLastBlockFirstRow)	{				if(CurAttr.nMostHighEdgeHeight				   <BestAttr.nMostHighEdgeHeight)					return true;				else if(CurAttr.nMostHighEdgeHeight				        ==BestAttr.nMostHighEdgeHeight)	{					if(CurAttr.nHighEdgeCount					   <=BestAttr.nHighEdgeCount){						return true;					}				}			}		}	}	return false;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -