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

📄 blockgame.c

📁 单片机版俄罗斯方块游戏
💻 C
字号:
/*-----------------------------------------------------------------俄罗斯方块游戏-*/
/*----------------------------------------------write by codekey, codekey@126.com-*/
/*-------------------------------------------------------------------------2008-3-*/
/*---------------------------------------------欢迎使用和修改,但需保留原作者信息-*/
/*--------------------------------------------------------------------------------*/
#include <reg52.h>
#include <stdlib.h>
#include <STRING.H>
#include "BlockGame.h"
/*--------------------------------------------------------------------------------*/
void InitGame( BLOCK_GAME* pGame )
{	
   	UINT8 i;
	/* 初始化游戏格子 */
	for(i=0;i<GAME_GRID_ROW;i++){
		pGame->GameGrid.Grid[i]=0xE007;	
	} 
	for(i=0;i<3;i++){
		pGame->GameGrid.Grid[i]=0xFFFF;	
		pGame->GameGrid.Grid[GAME_GRID_ROW-i-1]=0xFFFF;
	}
	pGame->GameBlock.nNextBlockType=rand()%7;
}

BOOL NewGame( BLOCK_GAME* pGame )
{
	InitGame(pGame);
	NewBlock(pGame);
	return 0;
}
void GameOver( BLOCK_GAME* pGame )
{
	NewGame(pGame);
}

BOOL NewBlock( BLOCK_GAME* pGame )
{	
	static UINT8 gc=0;

	pGame->GameBlock.nCurBlockType=pGame->GameBlock.nNextBlockType;
	pGame->GameBlock.nCurBlockStatus=0;
	pGame->GameBlock.nNextBlockType=rand()%7;
	if(pGame->GameBlock.nNextBlockType==pGame->GameBlock.nCurBlockType)
		pGame->GameBlock.nNextBlockType=(pGame->GameBlock.nNextBlockType+1)%7;
	gc++;
	if(gc>=6)
	{	
		pGame->GameBlock.nNextBlockType=1;		
		gc=0;
	}
	// need a better algorithm or a better evaluating function 
	// to make cmputer to run as an expert.

	pGame->GameBlock.nFirstBlockRow=GAME_FIRST_ROW-1;
	pGame->GameBlock.nFirstBlockCol=(GAME_LAST_COL-GAME_FIRST_COL+1-4)/2+GAME_FIRST_COL;
	BuildBlocks(pGame);
	return BlockGridConsistent(pGame);
}

/* 判断方格是否可以容纳方块 */
BOOL BlockGridConsistent( BLOCK_GAME* pGame )
{
	UINT8 i;
	UINT16 tmp;
	for(i=0;i<4;i++)
	{	
		tmp=(pGame->GameBlock.BlocksInfo>>(i*4))&0x000F;
		tmp=tmp<<pGame->GameBlock.nFirstBlockCol;
		if( (pGame->GameGrid.Grid[i+pGame->GameBlock.nFirstBlockRow]&tmp)!=0x0 )
		{			
			return 0;
		}
	}
	return 1;
}
 /* 生成方块 */
void BuildBlocks( BLOCK_GAME* pGame )	/*之所以采取这种方式,为了减少ram存储空间*/
{ 
	switch(pGame->GameBlock.nCurBlockType)   
	{
	case 0:	/*一种状态*/
		pGame->GameBlock.BlocksInfo=0x0660;
		break;
	case 1: /*两种状态*/
		switch(pGame->GameBlock.nCurBlockStatus)
		{
		case 0:
		case 2:
			pGame->GameBlock.BlocksInfo=0x00F0;
			break;
		case 1:
		case 3:
			pGame->GameBlock.BlocksInfo=0x2222;
			break;
		}
		break;
	case 2: /*两种状态*/
		switch(pGame->GameBlock.nCurBlockStatus)
		{
		case 0:
		case 2:
			pGame->GameBlock.BlocksInfo=0x4620;
			break;
		case 1:
		case 3:
			pGame->GameBlock.BlocksInfo=0x3600;
			break;
		}
		break;
	case 3: /*两种状态*/
		switch(pGame->GameBlock.nCurBlockStatus)
		{
		case 0:
		case 2:
			pGame->GameBlock.BlocksInfo=0x2640;
			break;
		case 1:
		case 3:
			pGame->GameBlock.BlocksInfo=0x6300;
			break;
		}
		break;
	case 4: /*四种状态*/
		switch(pGame->GameBlock.nCurBlockStatus)
		{
		case 0:
			pGame->GameBlock.BlocksInfo=0x2260;
			break;
		case 1:
			pGame->GameBlock.BlocksInfo=0x0710;
			break;
		case 2:
			pGame->GameBlock.BlocksInfo=0x3220;
			break;
		case 3:
			pGame->GameBlock.BlocksInfo=0x4700;
			break;
		}
		break;
	case 5: /*四种状态*/
		switch(pGame->GameBlock.nCurBlockStatus)
		{
		case 0:
			pGame->GameBlock.BlocksInfo=0x2230;
			break;
		case 1:
			pGame->GameBlock.BlocksInfo=0x1700;
			break;
		case 2:
			pGame->GameBlock.BlocksInfo=0x6220;
			break;
		case 3:
			pGame->GameBlock.BlocksInfo=0x0740;
			break;
		}
		break;
	case 6: /*四种状态*/
		switch(pGame->GameBlock.nCurBlockStatus)
		{
		case 0:
			pGame->GameBlock.BlocksInfo=0x0720;
			break;
		case 1:
			pGame->GameBlock.BlocksInfo=0x2320;
			break;
		case 2:
			pGame->GameBlock.BlocksInfo=0x2700;
			break;
		case 3:
			pGame->GameBlock.BlocksInfo=0x2620;
			break;
		}
		break;
	default: break;
	}
}
/*--移动方块----------------*/
/*  type = eMoveUp     上移 */
/*  type = eMoveDown   下移 */
/*  type = eMoveLeft   左移 */
/*  type = eMoveRigh   右移 */
BOOL MoveBlock( BLOCK_GAME* pGame, UINT8 nMoveMode)
{
	switch((enum eMoveMode)nMoveMode)
	{
	case eMoveUp:
		pGame->GameBlock.nFirstBlockRow--;
		break;
	case eMoveDown:
		pGame->GameBlock.nFirstBlockRow++;

		break;	
	case eMoveRight:
		pGame->GameBlock.nFirstBlockCol++;
		break;
	case eMoveLeft:
		pGame->GameBlock.nFirstBlockCol--;		
		break;
	case eMoveTurn:
		pGame->GameBlock.nCurBlockStatus=(pGame->GameBlock.nCurBlockStatus+1)%4;
		BuildBlocks(pGame);
		break;
	}
	if(!BlockGridConsistent(pGame))
	{
		switch((enum eMoveMode)nMoveMode)
		{
		case eMoveUp:
			pGame->GameBlock.nFirstBlockRow++;
			break;
		case eMoveDown:
			pGame->GameBlock.nFirstBlockRow--;
			break;
		case eMoveLeft:
			pGame->GameBlock.nFirstBlockCol++;
			break;
		case eMoveRight:
			pGame->GameBlock.nFirstBlockCol--;
			break;
		case eMoveTurn:
			pGame->GameBlock.nCurBlockStatus=(pGame->GameBlock.nCurBlockStatus-1+4)%4;
			BuildBlocks(pGame);
			break;
		}
		return 0;
	}	
	return 1;
}

/* 扩展功能-旋转方块,尽可能保证旋转成功 */
BOOL TurnBlock( BLOCK_GAME* pGame )
{
	BOOL bOperated=myTrue;

	if(!MoveBlock(pGame,eMoveTurn)) /*旋转不成功*/
	{
		bOperated = myFalse;
	}
	if(!bOperated)
	{
		if(MoveBlock(pGame,eMoveLeft))
		{
			if(!MoveBlock(pGame,eMoveTurn)) /*左移旋转不成功*/
			{
				bOperated = myFalse;
				MoveBlock(pGame,eMoveRight);
			}
			else
				bOperated = myTrue;
		}
	}

	if(!bOperated)
	{
		if(MoveBlock(pGame,eMoveRight))
		{
			if(!MoveBlock(pGame,eMoveTurn)) /*右移旋转不成功*/
			{
				bOperated = myFalse;
				MoveBlock(pGame,eMoveLeft);
			}
			else
				bOperated = myTrue;			
		}
	}

	if(!bOperated)
	{
		if(MoveBlock(pGame,eMoveDown))
		{
			if(!MoveBlock(pGame,eMoveTurn)) /*下移旋转不成功*/
			{
				bOperated = myFalse;
				MoveBlock(pGame,eMoveUp);
			}
			else
				bOperated = myTrue;			
		}
	}

	if(!bOperated)
	{
		if(MoveBlock(pGame,eMoveUp))
		{
			if(!MoveBlock(pGame,eMoveTurn)) /*上移旋转不成功*/
			{
				bOperated = myFalse;
				MoveBlock(pGame,eMoveDown);
			}
			else
				bOperated = myTrue;			
		}
	}
	
	return bOperated;
}

/*-固定方块在方格上-*/
void FixCurBlock(  BLOCK_GAME* pGame )
{
	UINT8 i;
	UINT16 tmp;
	for(i=0;i<4;i++)
	{
		tmp=pGame->GameBlock.BlocksInfo;
		tmp=(tmp>>i*4)&0x000F;
		tmp=tmp<<pGame->GameBlock.nFirstBlockCol;

		pGame->GameGrid.Grid[pGame->GameBlock.nFirstBlockRow+i] =
			pGame->GameGrid.Grid[pGame->GameBlock.nFirstBlockRow+i]|tmp;
	}
}

/*-消满行-*/
BOOL AdjustGrid( BLOCK_GAME* pGame )
{
	UINT8 i=0,m=0;
	BOOL bAdjusted=0;

	for(i=GAME_FIRST_ROW;i<=GAME_LAST_ROW;i++)
	{
		if(pGame->GameGrid.Grid[i]==0xFFFF)
		{
			for(m=i;m>GAME_FIRST_ROW;m--){
				pGame->GameGrid.Grid[m]=pGame->GameGrid.Grid[m-1];			
			}			
			pGame->GameGrid.Grid[0]=myFalse;	
			bAdjusted=1;
		}
	}
	return bAdjusted;
}

/*--------------------------------------------------------------------------------*/

void CopyGame( BLOCK_GAME* pDestGame, BLOCK_GAME* pSourGame )
{
	memcpy(pDestGame,pSourGame,sizeof(BLOCK_GAME));
}
void CopyGameGrid( GAME_GRID* pDestGrid, GAME_GRID* pSourGrid )
{
	memcpy(pDestGrid,pSourGrid,sizeof(GAME_GRID));
}
void CopyGameBlock( BLOCK_ATTR* pDestBlock, BLOCK_ATTR* pSourBlock )
{
	memcpy(pDestBlock,pSourBlock,sizeof(BLOCK_ATTR));
}
void CopyGridAttr(GRID_ATTR* pDestAttr, GRID_ATTR* pSourAttr )
{
	memcpy(pDestAttr,pSourAttr,sizeof(GRID_ATTR));
}

/*--------------------------------------------------------------------------------*/

void GetGridAttr( BLOCK_GAME* pGame, GRID_ATTR* pGridAttr )
{	
	pGridAttr->nLastBlockFirstRow = pGame->GameBlock.nFirstBlockRow;
	GetFullRow(pGame,pGridAttr);
	GetIdleBank(pGame,pGridAttr);
	GetGridHigh(pGame,pGridAttr);
	GetHighEdge(pGame,pGridAttr);	
}
void GetGridHigh( BLOCK_GAME* pGame, GRID_ATTR* pGridAttr )
{
	UINT8 i=0;
	for(i=GAME_FIRST_ROW;i<=GAME_LAST_ROW;i++)
	{		
		if(pGame->GameGrid.Grid[i]&0x1FF8){			
			break;
		}
	}
	pGridAttr->nGrideHeight = GAME_LAST_ROW-i+1;
}

void GetFullRow( BLOCK_GAME* pGame, GRID_ATTR* pGridAttr )
{
	UINT8 nFullCount=0;
	UINT8 i=0;
	nFullCount=0;
	for(i=GAME_FIRST_ROW;i<=GAME_LAST_ROW;i++)
	{		
		if(pGame->GameGrid.Grid[i]==0xFFFF)
		{			
			nFullCount++;
		}
	}
	pGridAttr->nFullRowCount=nFullCount;	
}

/* 计算无用的空格数 */
void GetIdleBank( BLOCK_GAME* pGame, GRID_ATTR* pGridAttr ) 
{
	UINT8 nIdleBankCount=0;
	UINT8 i=0, j=0;
	nIdleBankCount=0;

	for( j=GAME_FIRST_COL;j<=GAME_LAST_COL;j++)
	{
		i=GAME_FIRST_ROW;
		while(i<=GAME_LAST_ROW 
			&& (0x0000==(pGame->GameGrid.Grid[i]&(0x0001<<j))) ) 
			i++; // 找第一个填充格

		while(i<=GAME_LAST_ROW){
			if( !(pGame->GameGrid.Grid[i++]>>j&0x01) ) nIdleBankCount+=1;
		}
	}
	pGridAttr->nIdleBankCount = nIdleBankCount;
	
}
/* 计算高边 */
void GetHighEdge(BLOCK_GAME* pGame, GRID_ATTR* pGridAttr ) 
{
	UINT8 i, j, m;
	UINT8 EdgeCount;
	UINT8 tmpBankCount;
	UINT8 MostHighEage;
 
	EdgeCount = 0;
	MostHighEage = 0;

	for(j=GAME_FIRST_COL;j<=GAME_LAST_COL;j++)
	{
		i=GAME_FIRST_ROW;		
		while( (i<=GAME_LAST_ROW) 
		       && (0x0==(pGame->GameGrid.Grid[i]&(0x0001<<j))) )i++;
		m = i;
		tmpBankCount=0;   /* 左边 */
		while( (m<=GAME_LAST_ROW)
	 		  && (0x0==(pGame->GameGrid.Grid[m]&(0x0001<<(j-1)))) )
		{
			m++;
			tmpBankCount++;
			MostHighEage=(MostHighEage<tmpBankCount)?tmpBankCount:MostHighEage;
		}
		if(tmpBankCount>2){
			EdgeCount++;
		}
		m = i;
		tmpBankCount=0;   /* 右边 */
		while( (m<=GAME_LAST_ROW)
	 		&& (0x0==(pGame->GameGrid.Grid[m]&(0x0001<<(j+1)))) )
		{
			m++;
			tmpBankCount++;
			MostHighEage=(MostHighEage<tmpBankCount)?tmpBankCount:MostHighEage;
		}
		if(tmpBankCount>2){
			EdgeCount++;
		}
	}
	pGridAttr->nHighEdgeCount=EdgeCount;	
	pGridAttr->nMostHighEdgeHeight=(0==EdgeCount)?0:MostHighEage;	
}
/*--------------------------------------------------------------------------------*/

⌨️ 快捷键说明

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