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

📄 russia.c

📁 基于C语言的俄罗斯方块游戏机程序,可以很方便的应用到各种游戏机中去.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*========================================================================
 *
 *  版权所有  2003-2004 吴柏建. All Rights Reserved.
 *
 *  文件:       russia.c
 *  内容:		演示应用SSS库功能制作窗口游戏——俄罗斯方块。
 *  作者:			吴柏建。
 *  制作日期:		2003.3.8-2003.3.11
 *  修改日期:		2003..
 *
 *========================================================================*/
#include <windows.h>
#include "resource.h"

#include "sss.h"
#pragma comment(lib,"sss.lib")

static HINSTANCE g_hInstance;

/*======================================================================
---消息宏---
======================================================================*/
#define RKEY_LEFT   0
#define RKEY_RIGHT  1
#define RKEY_DOWN   2
#define RKEY_CIRCLE 3
#define RKEY_START  4
#define RKEY_PAUSE  5
#define RMSG_TIME   6
#define RMSG_PAINT  7

#define RKEY_SPEEDUP     8
#define RKEY_SPEEDDOWN   9

/*======================================================================
---消息队列函数---
======================================================================*/
#define MSG_QUEUE_SIZE 16    /*定义队列中容纳的消息数量*/
int MsgQueue[MSG_QUEUE_SIZE];/*定义全局的消息队列*/
int MsgWrite = 0;            /*消息队列的写入位置*/
int MsgRead = 0;             /*消息队列的读出位置*/

void SendMsg( int msg )
{
	int i = (1+MsgWrite)%MSG_QUEUE_SIZE;
	MsgQueue[MsgWrite] = msg;
	MsgWrite = i;
	if( i == MsgRead )MsgRead = (++MsgRead)%MSG_QUEUE_SIZE;
}
BOOL GetMsg( int *msg )
{
	if( MsgRead != MsgWrite )
	{
		*msg = MsgQueue[MsgRead];
		MsgRead = ((++MsgRead)%MSG_QUEUE_SIZE);
		return 1;
	}
	return 0;
}
void ClearMsg( void )
{
	MsgRead = MsgWrite;
}

/*======================================================================
---常量数据---
======================================================================*/
// ■■  ■■  ■■  ■■
// ■■  ■■  ■■  ■■
const char gBlock0[4][2][2]=
{
	{ {1,1,},{1,1,}, },
	{ {1,1,},{1,1,}, },
	{ {1,1,},{1,1,}, },
	{ {1,1,},{1,1,}, },
};


// ○○○○  ○■○○  ○○○○  ○■○○
// ■■■■  ○■○○  ■■■■  ○■○○
// ○○○○  ○■○○  ○○○○  ○■○○
// ○○○○  ○■○○  ○○○○  ○■○○
const char gBlock1[4][4][4]=
{
	{ {0,0,0,0,},{1,1,1,1,},{0,0,0,0,},{0,0,0,0,}, },
	{ {0,1,0,0,},{0,1,0,0,},{0,1,0,0,},{0,1,0,0,}, },
	{ {0,0,0,0,},{1,1,1,1,},{0,0,0,0,},{0,0,0,0,}, },
	{ {0,1,0,0,},{0,1,0,0,},{0,1,0,0,},{0,1,0,0,}, },
};

// ○■○  ○■○  ○○○  ○■○
// ■■■  ○■■  ■■■  ■■○
// ○○○  ○■○  ○■○  ○■○
const char gBlock2[4][3][3]=
{
	{ {0,1,0,},{1,1,1,},{0,0,0,}, },
	{ {0,1,0,},{0,1,1,},{0,1,0,}, },
	{ {0,0,0,},{1,1,1,},{0,1,0,}, },
	{ {0,1,0,},{1,1,0,},{0,1,0,}, },
};

// ○■○  ○○○  ○■○  ○○○
// ■■○  ■■○  ■■○  ■■○
// ■○○  ○■■  ■○○  ○■■
const char gBlock3[4][3][3]=
{
	{ {0,1,0,},{1,1,0,},{1,0,0,}, },
	{ {0,0,0,},{1,1,0,},{0,1,1,}, },
	{ {0,1,0,},{1,1,0,},{1,0,0,}, },
	{ {0,0,0,},{1,1,0,},{0,1,1,}, },
};

// ■○○  ○○○  ■○○  ○○○
// ■■○  ○■■  ■■○  ○■■
// ○■○  ■■○  ○■○  ■■○
const char gBlock4[4][3][3]=
{
	{ {1,0,0,},{1,1,0,},{0,1,0,}, },
	{ {0,0,0,},{0,1,1,},{1,1,0,}, },
	{ {1,0,0,},{1,1,0,},{0,1,0,}, },
	{ {0,0,0,},{0,1,1,},{1,1,0,}, },
};

// ■○○  ○■■  ○○○  ○■○
// ■■■  ○■○  ■■■  ○■○
// ○○○  ○■○  ○○■  ■■○
const char gBlock5[4][3][3]=
{
	{ {1,0,0,},{1,1,1,},{0,0,0,}, },
	{ {0,1,1,},{0,1,0,},{0,1,0,}, },
	{ {0,0,0,},{1,1,1,},{0,0,1,}, },
	{ {0,1,0,},{0,1,0,},{1,1,0,}, },
};

// ○○○  ■■○  ○○■  ○■○
// ■■■  ○■○  ■■■  ○■○
// ■○○  ○■○  ○○○  ○■■
const char gBlock6[4][3][3]=
{
	{ {0,0,0,},{1,1,1,},{1,0,0,}, },
	{ {1,1,0,},{0,1,0,},{0,1,0,}, },
	{ {0,0,1,},{1,1,1,},{0,0,0,}, },
	{ {0,1,0,},{0,1,0,},{0,1,1,}, },
};

const int gBlockSize[7] = { 2,4,3,3,3,3,3, };
const void *gBlockAddr[7] = { gBlock0,gBlock1,gBlock2,gBlock3,gBlock4,gBlock5,gBlock6,};

typedef struct _RUSSIADATA
{
	int Flag;         //状态标志:0:初始化状态 1:运行状态 2:暂停状态 3:结束状态。
	int XinWnd,YinWnd;//显示起点。
	int Speed;        //飞行速度。
	int Score;        //得分。
	int FlyBlock;     //飞行块的标志 0:NULL   1 ~ 7 : gBlock1 ~ gBlock7
	int FlyX,FlyY;    //飞行块的在map[24][10]中的位置。
	int FlyF;         //飞行块的方向。0~3
	int NextFlyBlock; //下一个飞行块的标志。
	int NextFlyX,NextFlyY;//下一个飞行块的在map[24][10]中的位置。
	int NextFlyF;     //下一个飞行块的方向。0~3
	int w,h;          //块的宽与高。
	LPBMP pBmpBlock;  //一个块的显示图象。
	LPBMP pBmpNoBlock;//一个块的背景显示图象。
	LPBMP pBmpNumber; //数字图象。
	LPBMP pBmpBuffer; //显示缓冲,用于防止闪烁。宽度=10*w,高度=20*h。
	LPBMP pBmpBoard;  //预告区背景图象。
	/*
	//不可见部分。
	00	○○○○○○○○○○
	01	○○○○○○○○○○
	02	○○○○○○○○○○
	03	○○○○○○○○○○

	//可见部分。
	04	○○○○○○○○○○
	05	○○○○○○○○○○
	06	○○○○○○○○○○
	07	○○○○○○○○○○
	08	○○○○○○○○○○
	09	○○○○○○○○○○
	10	○○○○○○○○○○
	11	○○○○○○○○○○
	12	○○○○○○○○○○
	13	○○○○○○○○○○
	14	○○○○○○○○○○
	15	○○○○○○○○○○
	16	○○○○○○○○○○
	17	○○○○○○○○○○
	18	○○○○○○○○○○
	19	○○○○○○○○○○
	20	○○○○○○○○○○
	21	○○○○○○○○○○
	22	○○○○○○○○○○
	23	○○○○○○○○○○
	*/
	char map[24][10]; //块的显示表。
	char map2[24][10];

}RUSSIADATA;

/*======================================================================
---功能函数---
======================================================================*/
void IntTime( int ID )
{
	SendMsg( RMSG_TIME );
	SSS_Cpu_Interrupt( 0 );
}

BOOL InitRussia( RUSSIADATA * p )
{
	RECT sRC, dRC;
	LPBMP pBmp;
	memset( p, 0, sizeof(RUSSIADATA) );
	memset( p->map, 1, 24*10 );
	memset( p->map2, -1, 24*10 );

	p->XinWnd = 10;
	p->YinWnd = 10;
	p->Speed = 50;
	p->Score = 0;
	p->w = 10;
	p->h = 10;

	pBmp = SSS_Bmp_Load( MAKEINTRESOURCE(IDB_BLOCK) );

	p->pBmpBlock = SSS_Bmp_Create( p->w, p->h );
	p->pBmpNoBlock = SSS_Bmp_Create( p->w, p->h );
	p->pBmpNumber = SSS_Bmp_Load( MAKEINTRESOURCE(IDB_NUMBER) );
	p->pBmpBuffer = SSS_Bmp_Create( p->w*10, p->h*20 );
	p->pBmpBoard = SSS_Bmp_Create( 47, 47 );

	if( !( pBmp && p->pBmpBlock && p->pBmpNoBlock && p->pBmpBuffer ) )return 0;

	SetRect( &dRC, 0, 0, p->w, p->h );
	SetRect( &sRC, p->w, 0, p->w*2, p->h );
	SSS_Bmp_ShowInBmp( &dRC, p->pBmpBlock, &dRC, pBmp, 0 );
	SSS_Bmp_ShowInBmp( &dRC, p->pBmpNoBlock, &sRC, pBmp, 0 );

	SetRect( &dRC, 0, 0, 47, 47 );
	SSS_Bmp_ShowInBmp( &dRC, p->pBmpBoard, &sRC, pBmp, 0 );

	SSS_Bmp_Release( pBmp );

	return 1;
}

void DrawRussia( RUSSIADATA * p )
{
	RECT sRC, dRC;
	int i,j,x,y,k;
	LPBMP pBmp;
	char *s;

	//显示游戏区。
	SetRect( &sRC, 0, 0, p->w, p->h );

	for( j=4; j<24; j++ )for( i=0; i<10; i++ )
	{
		if( p->map2[j][i] != p->map[j][i] )
		{
			p->map2[j][i] = p->map[j][i];
			pBmp = p->map[j][i] ? p->pBmpBlock : p->pBmpNoBlock;
			SetRect( &dRC, p->w*i, p->h*(j-4), p->w*(i+1), p->h*(j-3) );
			SSS_Bmp_ShowInBmp( &dRC, p->pBmpBuffer, &sRC, pBmp, 0 );
		}
	}

	SetRect( &sRC, 0, 0, p->w*10, p->h*20 );
	dRC = sRC;
	OffsetRect( &dRC, p->XinWnd, p->YinWnd );
	SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpBuffer, 0 );

	//预告区显示。
	if( p->Flag != 1 && p->Flag != 2 )//显示速度。
	{
		j = (p->Speed/5)/10;
		i = (p->Speed/5)%10;
		SetRect( &sRC, j*13, 0, (j+1)*13, 23 );
		SetRect( &dRC, 177, 61, 190, 84 );
		SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpNumber, 0 );
		SetRect( &sRC, i*13, 0, (i+1)*13, 23 );
		SetRect( &dRC, 190, 61, 203, 84 );
		SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpNumber, 0 );
	}
	else//显示下一个块。
	{

		//清除预告区域,注意直接缩放图形显示到窗口时DIRECTX导致窗口在屏幕边缘的剪切会有问题。
		SetRect( &sRC, 0, 0, 47, 47 );
		dRC = sRC;
		OffsetRect( &dRC, 166, 49 );
		SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpBoard, 0 );

		//画预告区域。
		SetRect( &sRC, 0, 0, p->w, p->h );
		k = gBlockSize[p->NextFlyBlock];
		s = (char *)gBlockAddr[p->NextFlyBlock];
		s += p->NextFlyF*k*k;
		x = 169+(4-k)*p->w/2;
		y = 52+(4-k)*p->h/2;
		for( j=0; j<k; j++ )for( i=0; i<k; i++ )
		{
			if( s[j*k+i] )
			{
				SetRect( &dRC, x+i*p->w, y+j*p->h, x+(i+1)*p->w, y+(j+1)*p->h );
				SSS_Bmp_ShowInWnd( &dRC, &sRC, p->pBmpBlock, 0 );
			}
		}
	}
}

void StepRussia( RUSSIADATA * p )
{
	//  0       1        2       3       4       5       6  
	// ■■  ○○○○  ○■○  ○■○  ■○○  ■○○  ○○○
	// ■■  ■■■■  ■■■  ■■○  ■■○  ■■■  ■■■
	//       ○○○○  ○○○  ■○○  ○■○  ○○○  ■○○

	//                  0  1  2  3  4  5  6
	//                  9 13 12  8  8 10 10
	static int X[7] = { 9,22,34,42,50,60,70, };
	int i = (rand()%70), j;
	p->FlyBlock = p->NextFlyBlock;
	p->FlyX = p->NextFlyX;
	p->FlyY = p->NextFlyY;
	p->FlyF = p->NextFlyF;
	//p->NextFlyBlock = (rand()%7);
	for( j=0;;j++ )if( i<X[j] )break;
	p->NextFlyBlock = j;
	p->NextFlyX = (10-gBlockSize[p->NextFlyBlock])/2;
	p->NextFlyY = 0;
	p->NextFlyF = (rand()%4);
}

void StartRussia( RUSSIADATA * p )
{
	if( p->Flag == 1 )return;
	if( p->Flag != 2 )
	{
		StepRussia( p );
		StepRussia( p );
		memset( p->map, 0, 24*10 );
		DrawRussia( p );
	}
	p->Flag = 1;
	SSS_Timer_Init( RMSG_TIME, (100-p->Speed)*2/3, IntTime );
}

void PauseRussia( RUSSIADATA * p )
{
	if( p->Flag == 1 )
	{
		 p->Flag = 2;
		 SSS_Timer_Out( RMSG_TIME );
	}
}
BOOL BlockIn( RUSSIADATA * p )
{
	int i,j,w,h,x,y;
	char *s;
	
	s = (char *)gBlockAddr[ p->FlyBlock ];
	w = h = gBlockSize[ p->FlyBlock ];
	for( j=0; j<h; j++ )for( i=0; i<w; i++ )
	{
		if( s[ p->FlyF*w*h+j*w+i ] !=0 )
		{
			x = p->FlyX+i;
			y = p->FlyY+j;
			if( y < 0 || y >= 24 || x < 0 || x >= 10 )return 0;
			if( p->map[ y ][ x ] == 1 )return 0;
		}
	}
	for( j=0; j<h; j++ )for( i=0; i<w; i++ )
	{
		if( s[ p->FlyF*w*h+j*w+i ] !=0 )
		{
			p->map[ p->FlyY+j ][ p->FlyX+i ] = 1;
		}
	}
	return 1;
}
void BlockOut( RUSSIADATA * p )
{
	int i,j,w,h;
	char *s;
	
	s = (char *)gBlockAddr[ p->FlyBlock ];
	w = h = gBlockSize[ p->FlyBlock ];
	for( j=0; j<h; j++ )for( i=0; i<w; i++ )
	{
		if( s[ p->FlyF*w*h+j*w+i ] !=0 )
		{
			p->map[ p->FlyY+j ][ p->FlyX+i ] = 0;
		}

⌨️ 快捷键说明

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