C语言图形编程--俄罗斯方块制作(二)源代码
所有源代码文件,此为本人2年前所作,设计上还有些缺陷。希望大家不吝指正。
设计详解点击这里
下面是头文件head.h
/************************ (C) COPYRIGHT 2013 yang_yulei ************************
* File Name : head.h
* Author : yang_yulei
* Date First Issued : 12/18/2013
* Description :
*
*
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _HEAD_H_
#define _HEAD_H_ /* Includes ------------------------------------------------------------------*/
#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>/* Macro ---------------------------------------------------------------------*/
#define TRUE 1
#define FALSE 0//GUI游戏界面相关的参数
#define GUI_WALL_SQUARE_WIDTH 10 //外围围墙小方格的宽度(单位:像素)
#define GUI_xWALL_SQUARE_NUM 30 //横向(x轴方向)围墙小方格的数量(必须是偶数)
#define GUI_yWALL_SQUARE_NUM 46 //纵向(y轴方向)围墙小方格的数量(必须是偶数)
#define GUI_WALL_WIDTH_PIX (GUI_WALL_SQUARE_WIDTH*GUI_xWALL_SQUARE_NUM)
#define GUI_WALL_HIGH_PIX (GUI_WALL_SQUARE_WIDTH*GUI_yWALL_SQUARE_NUM) #define WINDOW_WIDTH 480 //窗口的宽度
#define WINDOW_HIGH GUI_WALL_HIGH_PIX //窗口高度//俄罗斯方块相关的参数
//移动的方向
#define DIRECT_UP 3
#define DIRECT_DOWN 2
#define DIRECT_LEFT -1
#define DIRECT_RIGHT 1 //每一个小方块的大小(是围墙小方格宽度的2倍)
#define ROCK_SQUARE_WIDTH (2*GUI_WALL_SQUARE_WIDTH)
//横向能容纳小方格的数量
#define X_ROCK_SQUARE_NUM ((GUI_xWALL_SQUARE_NUM-2)/2)
//纵向能容纳小方格的数量
#define Y_ROCK_SQUARE_NUM ((GUI_yWALL_SQUARE_NUM-2)/2) /* Exported types ------------------------------------------------------------*/
typedef int BOOL ; //布尔值类型/*数据结构-线性表(结构体数组)*/
typedef struct ROCK
{//用来表示方块的形状(每一个字节是8位,用每4位表示方块中的一行)unsigned int rockShapeBits ; int nextRockIndex ; //下一个方块,在数组中的下标
} RockType ;//方块在图形窗口中的位置(即定位4*4大块的左上角坐标)
typedef struct LOCATE
{int left ; int top ;
} RockLocation_t ;/* Function prototypes -------------------------------------------------------*/
//源文件play.c中
void PlayGame(void) ;//源文件init.c中
int InitProcParameters(void) ;//源文件GUI.c中
void DrawRock(int, const struct LOCATE *, BOOL) ;
void DrawGameGUI(void) ;
void UpdataScore(void) ;
void UpdataGrade(int) ;#endif /* _HEAD_H_ *//*********************** (C) COPYRIGHT 2013 yang_yulei *********END OF FILE****/
下面是源文件main.cpp
/************************ (C) COPYRIGHT 2013 yang_yulei ************************
* File Name : main.cpp
* Author : yang_yulei
* Date First Issued : 1/16/2012
* Description : 开发环境 VC++ 6.0 含EasyX图形库(http://www.easyx.cn)
* 俄罗斯方块
*
*
********************************************************************************
* History:
* 1/16/2012 : V0.1
* 12/18/2013 : V0.2
********************************************************************************
*
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "head.h"
#include <windows.h>
#include <dos.h>/* Typedef -------------------------------------------------------------------*/
/* Variables -----------------------------------------------------------------*/
//全局变量-游戏板的状态描述(即表示当前界面哪些位置有方块)
//0表示没有,1表示有(多加了两行和两列,形成一个围墙,便于判断方块是否能够移动)
char g_gameBoard[Y_ROCK_SQUARE_NUM+2][X_ROCK_SQUARE_NUM+2] = {0} ;
//统计分数
int g_score = 0 ;
//等级
int g_grade = 0 ;int g_rockTypeNum = 0 ; //共有多少种俄罗斯方块
RockType rockArray[50] = {(0,0)} ;/*******************************************************************************
* Function Name : main
* Description : Main program
* Input : None
* Output : None
* Return : None
*******************************************************************************/
int
main(void)
{//画出游戏界面initgraph(WINDOW_WIDTH, WINDOW_HIGH) ; //初始化图形窗口cleardevice() ;DrawGameGUI() ; //使用 API 函数修改窗口名称HWND hWnd = GetHWnd();SetWindowText(hWnd, "俄罗斯方块");//初始化参数InitProcParameters() ;//游戏过程PlayGame() ;closegraph() ;return 0 ;
}
下面是源文件init.cpp---游戏运行前 初始化的一些方法
/************************ (C) COPYRIGHT 2013 yang_yulei ************************
* File Name : init.cpp
* Author : yang_yulei
* Date First Issued : 12/18/2013
* Description :
*
********************************************************************************
*
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "head.h"/* Variables -----------------------------------------------------------------*/
extern char g_gameBoard[][X_ROCK_SQUARE_NUM+2] ;
extern int g_rockTypeNum ;
extern RockType rockArray[] ;/* Function prototypes -------------------------------------------------------*/
static int ReadRockShape(void) ;
static unsigned int ShapeStr2uInt(char* const);/*******************************************************************************
* Function Name : InitProcParameters
* Description : 在正式开始运行游戏前,初始化一些参数:g_gameBoard从配置文件中读取系统中俄罗斯方块的形状
* Be called : main
* Input : None
* Output : g_gameBoard rockArray
* Return : None
*******************************************************************************/
//初始化程序参数
int
InitProcParameters(void)
{int i ;//初始化游戏板(把这个二维数组的四周置1,当作围墙,用于判断边界)for (i = 0; i < X_ROCK_SQUARE_NUM+2; i++){g_gameBoard[0][i] = 1 ;g_gameBoard[Y_ROCK_SQUARE_NUM+1][i]= 1 ;}for (i = 0; i < Y_ROCK_SQUARE_NUM+2; i++){g_gameBoard[i][0] = 1 ;g_gameBoard[i][X_ROCK_SQUARE_NUM+1]= 1 ;}//从配置文件中读取游戏中所有方块的形状点阵ReadRockShape() ;return 0 ;
}/*******************************************************************************
* Function Name : ReadRockShape
* Description : 从配置文件中读取系统中俄罗斯方块的形状 把它记录在rockArray中
* Be called : InitProcParameters
* Input : rockshape.ini
* Output : rockArray
* Return : 成功返回0 失败返回1
*******************************************************************************/
int
ReadRockShape(void)
{FILE* fp ;int i = 0 ;int len = 0 ;int rockArrayIdx = 0 ;int shapeNumPerRock = 0 ; //一种方块的形态数目(用于计算方块的nextRockIndex)char rdBuf[128] ;char rockShapeBitsStr[128] = {0};unsigned int shapeBits = 0 ;g_rockTypeNum = 0 ;//打开配置文件 从中读取方块的形状fp = fopen(".\\rockshape.ini", "r") ;if (fp == NULL){perror("open file error!\n") ;return 1 ;}while (fgets(rdBuf, 128, fp) != NULL){len = strlen(rdBuf) ;rdBuf[len-1] = '\0' ;switch (rdBuf[0]){case '@': case '#':strcat(rockShapeBitsStr, rdBuf) ;break ;case 0 : //一个方块读取结束shapeBits = ShapeStr2uInt(rockShapeBitsStr) ;rockShapeBitsStr[0] = 0 ;shapeNumPerRock++ ;rockArray[rockArrayIdx].rockShapeBits = shapeBits ;rockArray[rockArrayIdx].nextRockIndex = rockArrayIdx + 1 ;rockArrayIdx++ ;g_rockTypeNum++ ; //记录方块数量的全局变量+1break ;case '-'://一种方块读取结束(更新其nextRockIndex值)rockArray[rockArrayIdx-1].nextRockIndex = rockArrayIdx - shapeNumPerRock ;shapeNumPerRock = 0 ;break ;default :break ;}}//while()return 0 ;
}/*******************************************************************************
* Function Name : ShapeStr2uInt
* Description : 把配置文件中的描述方块形状的字符串 转化为 unsigned int型
* Be called :
* Input : shapeStr 描述方块形状的字符串(从文件中读取的)
* Output : None
* Return : unsigned int型的方块形状点阵(用其低16位表示)
*******************************************************************************/
unsigned int
ShapeStr2uInt(char* const shapeStr)
{unsigned int shapeBitsRet = 0 ;char* p = shapeStr ;for (p += 15; p >= shapeStr; p--){if (*p == '@'){shapeBitsRet |= ((unsigned int)1 << (&shapeStr[15]-p)) ;}}return shapeBitsRet ;
}
下面是源文件GUI.cpp---一些关于在界面上画出界面的一些方法
/************************ (C) COPYRIGHT 2013 yang_yulei ************************
* File Name : GUI.cpp
* Author : yang_yulei
* Date First Issued : 12/18/2013
* Description :
*
********************************************************************************
*
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "head.h"/* Variables -----------------------------------------------------------------*/
//预览区位置
RockLocation_t previewLocation = {GUI_WALL_SQUARE_WIDTH*GUI_xWALL_SQUARE_NUM+70, 50} ; extern RockType rockArray[] ;/*******************************************************************************
* Function Name : DrawRock
* Description : 在游戏区画出编号为rockIndex的方块
* Be called : PlayGame()
* Input : rockIndex :currentLocatePtr: 此方块的位置displayed : 此方块是否显示
* Output : None
* Return : None
*******************************************************************************/
void
DrawRock(int rockIndex, const struct LOCATE * currentLocatePtr, BOOL displayed)
{int i ;int mask ;int rockX ; //俄罗斯方块的4*4模型的左上角点x轴的坐标int rockY ; //俄罗斯方块的4*4模型的左上角点y轴的坐标int spaceFlag ; //占位标记(用于g_gameBoard,1表示某处有方块 0表示此处无方块)int color ; //画出的方块的颜色//若此方块是用于显示的,则设置其颜色为白色,其占位标记设为1//否则设置其颜色为黑色(背景色),占位标记设为0displayed ? (color = WHITE,spaceFlag = 1) : (color = BLACK,spaceFlag = 0) ;setcolor(color) ; //设置画笔颜色setlinestyle(PS_SOLID, NULL, 2) ; //设置线形为1像素的实线rockX = currentLocatePtr->left ;rockY = currentLocatePtr->top ;//逐位扫描由unsigned int的低2字节//16个位组成的俄罗斯方块形状点阵(其代表4*4的方块形状)mask = (unsigned int)1 << 15 ;for (i=1; i<=16; i++){//与掩码相与为1的 即为方块上的点if ((rockArray[rockIndex].rockShapeBits & mask) != 0){//在屏幕上画出此方块rectangle(rockX+2, rockY+2, rockX+ROCK_SQUARE_WIDTH-2, rockY+ROCK_SQUARE_WIDTH-2) ; }//每4次 换行 转到下一行继续画i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left): rockX += ROCK_SQUARE_WIDTH ;mask >>= 1 ;}
}/*******************************************************************************
* Function Name : DrawGameGUI
* Description : 画出游戏界面
* Be called : main()
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void
DrawGameGUI(void)
{int i = 0 ;int wallHigh = GUI_yWALL_SQUARE_NUM * GUI_WALL_SQUARE_WIDTH ;//围墙的高度(像素)setcolor(RED) ; //设置围墙的颜色setlinestyle(PS_SOLID, NULL, 0) ; //设置围墙方格的线形(1像素的实线)//画出围墙(画矩形是 先确定左上顶点的坐标,再确定右下顶点坐标)//先画出上下墙for (i = GUI_WALL_SQUARE_WIDTH; i <= GUI_WALL_WIDTH_PIX; i += GUI_WALL_SQUARE_WIDTH){rectangle(i-GUI_WALL_SQUARE_WIDTH,0,i,GUI_WALL_SQUARE_WIDTH) ; //上墙rectangle(i-GUI_WALL_SQUARE_WIDTH,wallHigh-GUI_WALL_SQUARE_WIDTH, i,wallHigh) ; //下墙}//再画出左右墙for (i = 2*GUI_WALL_SQUARE_WIDTH; i <= wallHigh-GUI_WALL_SQUARE_WIDTH; i += GUI_WALL_SQUARE_WIDTH){rectangle(0,i-GUI_WALL_SQUARE_WIDTH, GUI_WALL_SQUARE_WIDTH,i) ; //左墙rectangle(GUI_WALL_WIDTH_PIX-GUI_WALL_SQUARE_WIDTH,i-GUI_WALL_SQUARE_WIDTH, GUI_WALL_WIDTH_PIX,i) ; //右墙}//画分隔线setcolor(WHITE) ; //设置画笔颜色setlinestyle(PS_DASH, NULL, 2) ; //设置线形为2像素的虚线line(GUI_WALL_WIDTH_PIX+20,0,GUI_WALL_WIDTH_PIX+20,wallHigh) ; //在偏移右围墙的20处画线//画右边统计分数及版权信息栏//先设置字体LOGFONT f ; //定义字体属性结构体getfont(&f) ; //获得当前字体f.lfHeight = 18 ; //设置字体高度为 38(包含行距)strcpy(f.lfFaceName, "黑体") ; //设置字体为“黑体”f.lfQuality = ANTIALIASED_QUALITY ; //设置输出效果为抗锯齿 setfont(&f) ; //设置字体样式//1,显示预览outtextxy(GUI_WALL_WIDTH_PIX+80 , 20 , "预览") ;//2,显示等级栏outtextxy(GUI_WALL_WIDTH_PIX+80 , 140 , "等级") ;//3,显示得分栏outtextxy(GUI_WALL_WIDTH_PIX+80 , 190 , "得分") ;//4,显示操作说明 outtextxy(GUI_WALL_WIDTH_PIX+65 , 255 , "操作说明") ;getfont(&f) ;strcpy(f.lfFaceName, "宋体") ;f.lfHeight = 15 ; setfont(&f) ;outtextxy(GUI_WALL_WIDTH_PIX+45 , 290 , "w.a.s.d控制方向") ;outtextxy(GUI_WALL_WIDTH_PIX+45 , 313 , "回车键 暂停") ;outtextxy(GUI_WALL_WIDTH_PIX+45 , 336 , "空格键 快速下落") ;//5.版权信息line(GUI_WALL_WIDTH_PIX+20 , wallHigh-65 , WINDOW_WIDTH , wallHigh-65) ;outtextxy(GUI_WALL_WIDTH_PIX+40 , wallHigh-50 , " 杨溢之 作品") ;outtextxy(GUI_WALL_WIDTH_PIX+40 , wallHigh-30 , " QQ:702080167") ;//显示等级,得分信息setcolor(RED) ; outtextxy(GUI_WALL_WIDTH_PIX+90 , 163 , "1") ;outtextxy(GUI_WALL_WIDTH_PIX+90 , 223 , "0") ;
}/*******************************************************************************
* Function Name : UpdataScore
* Description : 增加一次得分,并把游戏界面的得分区显示 更新
* Be called : ProcessFullRow()
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void
UpdataScore(void)
{char scoreStr[5] ; //用字符串的形式存储得分extern int g_score ;extern int g_grade ;//分数的增长的单位是10g_score += 10 ;//得分是100的倍数,则等级加1 (等级在5级以上的就 保持不变)if (g_score == (g_score/100)*100 && g_grade < 5)UpdataGrade(++g_grade) ;//删除原先信息setfillstyle(BLACK) ; bar(GUI_WALL_WIDTH_PIX+90,220,GUI_WALL_WIDTH_PIX+99,229) ;//显示信息setcolor(RED) ; sprintf(scoreStr , "%d" , g_score) ;outtextxy(GUI_WALL_WIDTH_PIX+90 , 223 , scoreStr) ;
}/*******************************************************************************
* Function Name : UpdataGrade
* Description : 增加一次等级,并把游戏界面的等级区显示 更新
* Be called :
* Input : grade :新的等级值
* Output : None
* Return : None
*******************************************************************************/
void
UpdataGrade(int grade)
{char gradeStr[5] ; //删除原先信息setfillstyle(BLACK) ; bar(GUI_WALL_WIDTH_PIX+90,160,GUI_WALL_WIDTH_PIX+99,169) ;//显示信息setcolor(RED) ; sprintf(gradeStr , "%d" , grade) ;outtextxy(GUI_WALL_WIDTH_PIX+90 , 163 , gradeStr) ;
}
下面是源文件play.cpp---控制游戏的重要方法
/************************ (C) COPYRIGHT 2013 yang_yulei ************************
* File Name : play.cpp
* Author : yang_yulei
* Date First Issued : 12/18/2013
* Description :
*
********************************************************************************
*
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "head.h"/* Variables -----------------------------------------------------------------*/
extern char g_gameBoard[][X_ROCK_SQUARE_NUM+2] ;
extern int g_rockTypeNum ;
extern RockType rockArray[] ;/* Function prototypes -------------------------------------------------------*/
static BOOL MoveAble(int, const struct LOCATE *, int) ;
static void SetOccupyFlag(int, const struct LOCATE *) ;
static void ProcessFullRow(void) ;
static BOOL isGameOver() ;
static void ProccessUserHit(int, int*, struct LOCATE*) ;
static void FastFall(int, struct LOCATE *, struct LOCATE *) ;
static void DelFullRow(int f_row) ;/*******************************************************************************
* Function Name : PlayGame
* Description : 此程序的主要设计逻辑
* Be called : main
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void
PlayGame(void)
{int userHitChar ; //用户敲击键盘的字符int currentRockIndex ; //当前方块在rockArray数组中下标int nextRockIndex ; //准备的下个方块的下标BOOL moveAbled = FALSE ;//记录方块能否落下DWORD oldtime = 0;extern int g_grade ;//当前方块位置RockLocation_t currentRockLocation ; //初始方块位置(由当中开始下落)RockLocation_t initRockLocation = {(GUI_xWALL_SQUARE_NUM/2-4)*GUI_WALL_SQUARE_WIDTH, GUI_WALL_SQUARE_WIDTH}; //预览区位置extern RockLocation_t previewLocation ;//为第一次下落,初始化参数//随机选择当前的俄罗斯方块形状 和下一个俄罗斯方块形状srand(time(NULL)) ;currentRockIndex = rand()%g_rockTypeNum ;nextRockIndex = rand()%g_rockTypeNum ;currentRockLocation.left = initRockLocation.left ;currentRockLocation.top = initRockLocation.top ;while(1){ DrawRock(currentRockIndex, ¤tRockLocation, TRUE) ; FlushBatchDraw(); //用批绘图功能,可以消除闪烁//判断能否下落moveAbled = MoveAble(currentRockIndex, ¤tRockLocation, DIRECT_DOWN) ;//如果不能下落则生成新的方块if (!moveAbled) { //设置占位符(此时方块已落定)SetOccupyFlag(currentRockIndex, ¤tRockLocation) ;//擦除预览DrawRock( nextRockIndex, &previewLocation, FALSE) ; //生成新的方块currentRockIndex = nextRockIndex ;nextRockIndex = rand()%g_rockTypeNum ;currentRockLocation.left = initRockLocation.left ;currentRockLocation.top = initRockLocation.top ;}//显示预览DrawRock(nextRockIndex, &previewLocation, TRUE) ;//如果超时(且能下落),自动下落一格// 这个超时时间400-80*g_grade 是本人根据实验自己得出的// 一个速度比较适中的一个公式(g_grade不会大于等于5)DWORD newtime = GetTickCount(); if (newtime - oldtime >= (unsigned int)(400-80*g_grade) && moveAbled == TRUE){oldtime = newtime ;DrawRock(currentRockIndex, ¤tRockLocation, FALSE) ; //擦除原先位置currentRockLocation.top += ROCK_SQUARE_WIDTH ; //下落一格}//根据当前游戏板的状况判断是否满行,并进行满行处理ProcessFullRow() ;//判断是否游戏结束if (isGameOver()){ MessageBox( NULL,"游戏结束", "GAME OVER", MB_OK ) ;exit(0) ;}//测试键盘是否被敲击if (kbhit()){ userHitChar = getch() ; ProccessUserHit(userHitChar, ¤tRockIndex, ¤tRockLocation) ;}Sleep(20) ; //降低CPU使用率}//结束外层while(1)}/*******************************************************************************
* Function Name : ProccessUserHit
* Description : 处理用户敲击键盘
* Be called : PlayGame()
* Input : userHitChar 用户敲击键盘的ASCII码rockIndexPtr 当前俄罗斯方块在rockArray中的下标rockLocationPtr 当前方块在游戏界面中的位置* Output : rockIndexPtr 响应用户敲击后 新方块的下标rockLocationPtr 响应用户敲击后 新方块的位置
* Return : None
*******************************************************************************/
void
ProccessUserHit(int userHitChar, int* rockIndexPtr, struct LOCATE* rockLocationPtr)
{switch (userHitChar){case 'w' : case 'W' : //“上”键//检查是否能改变方块形状 if (MoveAble(rockArray[*rockIndexPtr].nextRockIndex, rockLocationPtr, DIRECT_UP)){DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ;*rockIndexPtr = rockArray[*rockIndexPtr].nextRockIndex ;}break ;case 's' : case 'S' : //“下”键DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ; //擦除原先位置rockLocationPtr->top += ROCK_SQUARE_WIDTH ; break ;case 'a' : case 'A' : //“左”键if (MoveAble(*rockIndexPtr, rockLocationPtr, DIRECT_LEFT)){DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ; rockLocationPtr->left -= ROCK_SQUARE_WIDTH ;} break ;case 'd' : case 'D' : //“右”键if (MoveAble(*rockIndexPtr, rockLocationPtr, DIRECT_RIGHT)){ DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ;rockLocationPtr->left += ROCK_SQUARE_WIDTH ;} break ;case ' ' : //空格(快速下落)DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ;FastFall(*rockIndexPtr, rockLocationPtr, rockLocationPtr) ; break ;case 13 : //回车键(暂停)while(1){ userHitChar = getch() ;if (userHitChar==13)break ;}break ;default : break ;}}/*******************************************************************************
* Function Name : MoveAble
* Description : 判断编号为rockIndex 在位置currentLocatePtr的方块能否向direction移动
* Be called :
* Input : None
* Output : None
* Return : TRUE 可以移动FALSE 不可以移动
*******************************************************************************/
BOOL
MoveAble(int rockIndex, const struct LOCATE* currentLocatePtr, int f_direction)
{int i ;int mask ; int rockX ;int rockY ;rockX = currentLocatePtr->left ;rockY = currentLocatePtr->top ;mask = (unsigned int)1 << 15 ;for (i=1; i<=16; i++){//与掩码相与为1的 即为方块上的点if ((rockArray[rockIndex].rockShapeBits & mask) != 0){//判断能否移动(即扫描即将移动的位置 是否与设置的围墙有重叠)//若是向上(即翻滚变形)if( f_direction == DIRECT_UP ){//因为此情况下传入的是下一个方块的形状,故我们直接判断此方块的位置是否已经被占if (g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1][(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] == 1)return FALSE ; }//如果是向下方向移动else if( f_direction == DIRECT_DOWN ){if (g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+2][(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] ==1) return FALSE ;}else //如果是左右方向移动{ //f_direction的DIRECT_LEFT为-1,DIRECT_RIGHT为1,故直接加f_direction即可判断。if (g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1][(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1+f_direction] ==1) return FALSE ;}}//每4次 换行 转到下一行继续i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left): rockX += ROCK_SQUARE_WIDTH ;mask >>= 1 ;}return TRUE ;
}/*******************************************************************************
* Function Name : SetOccupyFlag
* Description : 更新游戏板状态(把一些位置设置为已占用)
* Be called :
* Input : rockIndex 方块的下标(定位了方块的形状)currentLocatePtr 方块的位置(用来设定已占用标识)
* Output : None
* Return : None
*******************************************************************************/
void
SetOccupyFlag(int rockIndex, const struct LOCATE * currentLocatePtr)
{int i ;int mask ; int rockX ;int rockY ;rockX = currentLocatePtr->left ;rockY = currentLocatePtr->top ;mask = (unsigned int)1 << 15 ;for (i=1; i<=16; i++){//与掩码相与为1的 即为方块上的点if ((rockArray[rockIndex].rockShapeBits & mask) != 0){g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1][(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] = 1 ;}//每4次 换行 转到下一行继续画i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left): rockX += ROCK_SQUARE_WIDTH ;mask >>= 1 ;}
}/*******************************************************************************
* Function Name : ProcessFullRow
* Description : 检查是否有满行,若有,则删除满行(并更新得分信息)
* Be called :
* Input : g_gameBoard
* Output : None
* Return : None
*******************************************************************************/
void
ProcessFullRow(void)
{int i = 1 ;int cnt = 0 ;BOOL rowFulled = TRUE ;int rowIdx = Y_ROCK_SQUARE_NUM ; //从最后一行开始往上检查while (cnt != X_ROCK_SQUARE_NUM) //直到遇到是空行的为止{rowFulled = TRUE ;cnt = 0 ;//判断是否有满行 并消除满行for (i = 1; i <= X_ROCK_SQUARE_NUM; i++){if( g_gameBoard[rowIdx][i] == 0 ){rowFulled = FALSE ;cnt++ ;}}if (rowFulled) //有满行 (并更新得分信息){ DelFullRow(rowIdx) ; //更新得分信息UpdataScore() ;rowIdx++ ;} rowIdx-- ;}
}/*******************************************************************************
* Function Name : DelFullRow
* Description : 删除游戏板的第rowIdx行
* Be called :
* Input : g_gameBoardrowIdx 要删除的行 在g_gameBoard中的下标
* Output : None
* Return : None
*******************************************************************************/
void
DelFullRow(int rowIdx)
{int cnt = 0 ;int i ;//把此行擦除setcolor(BLACK) ;for (i=1; i<=X_ROCK_SQUARE_NUM; i++){rectangle(GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*rowIdx-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*rowIdx-2) ; }//把此行之上的游戏板方块全向下移动一个单位while (cnt != X_ROCK_SQUARE_NUM) //直到遇到是空行的为止{cnt =0 ; for (i=1; i<=X_ROCK_SQUARE_NUM; i++){g_gameBoard[rowIdx][i] = g_gameBoard[rowIdx-1][i] ;//擦除上面的一行setcolor(BLACK) ;rectangle( GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*(rowIdx-1)-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*(rowIdx-1)-2 ) ; //显示下面的一行if (g_gameBoard[rowIdx][i] ==1){setcolor(WHITE) ;rectangle( GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-ROCK_SQUARE_WIDTH+2,GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*rowIdx-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-2,GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*rowIdx-2 ) ; }if (g_gameBoard[rowIdx][i] == 0)cnt++ ; //统计一行是不是 都是空格}//forrowIdx-- ;}
}/*******************************************************************************
* Function Name : FastFall
* Description : 让编号为rockIndex 且初始位置在currentLocatePtr的方块 快速下落到底部
* Be called :
* Input : rockIndex currentLocatePtr
* Output : endLocatePtr 下落后方块的位置
* Return : None
*******************************************************************************/
void
FastFall
(int rockIndex, struct LOCATE * currentLocatePtr, struct LOCATE * endLocatePtr)
{int i ;int mask ; //掩码,用于判断方块的形状int rockX ; //方块的坐标(4*4方格的左上角点的x轴坐标)int rockY ; //方块的坐标(4*4方格的左上角点的y轴坐标)while (currentLocatePtr->top <= GUI_WALL_SQUARE_WIDTH+Y_ROCK_SQUARE_NUM*ROCK_SQUARE_WIDTH){rockX = currentLocatePtr->left ;rockY = currentLocatePtr->top ;mask = (unsigned int)1 << 15 ;for (i=1; i<=16; i++){//与掩码相与为1的 即为方块上的点if ((rockArray[rockIndex].rockShapeBits & mask) != 0){if(g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1][(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] == 1) //遇到底部{endLocatePtr->top = currentLocatePtr->top-ROCK_SQUARE_WIDTH ;return ;} }//每4次 换行 转到下一行继续画i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left): rockX += ROCK_SQUARE_WIDTH ;mask >>= 1 ;}currentLocatePtr->top += ROCK_SQUARE_WIDTH ;}//while()
}/*******************************************************************************
* Function Name : isGameOver
* Description : 判断是否游戏结束
* Be called :
* Input : None
* Output : None
* Return : TRUE 游戏结束FALSE 游戏继续
*******************************************************************************/
BOOL
isGameOver()
{ int i ;BOOL topLineHaveRock = FALSE ; //在界面的最高行有方块的标记BOOL bottomLineHaveRock = FALSE ; //在界面的最低行有方块的标记for (i=1; i<=X_ROCK_SQUARE_NUM; i++){if( g_gameBoard[1][i] == 1 )topLineHaveRock = TRUE ;if( g_gameBoard[Y_ROCK_SQUARE_NUM][i] == 1 )bottomLineHaveRock = TRUE ;}//若底层行和顶层行都有方块 则说明在所有行都有方块,游戏结束if (topLineHaveRock && bottomLineHaveRock)return TRUE ;elsereturn FALSE ;
}
下面是配置文件rockshape.ini
@###
@###
@@##
####@@@#
@###
####
####@@##
#@##
#@##
######@#
@@@#
####
####-----
#@##
#@##
@@##
####@###
@@@#
####
####@@##
@###
@###
####@@@#
##@#
####
####-----
@###
@@##
#@##
#####@@#
@@##
####
####-----
#@##
@@##
@###
####@@##
#@@#
####
####-----
#@##
@@@#
####
####@###
@@##
@###
####@@@#
#@##
####
#####@##
@@##
#@##
####-----
#@##
#@##
#@##
#@##@@@@
####
####
####-----
####
@@##
@@##
####-----
C语言图形编程--俄罗斯方块制作(二)源代码相关推荐
- C语言如何让图形的眼睛动起来,C语言图形编程--俄罗斯方块制作(一)详解
效果图 用C语言实现俄罗斯方块,需要先解决下面几个问题: 1.如何用C语言绘制图形界面 EasyX图形库(http://www.easyx.cn)即TC的图形库在VC下的移植. 包含库#include ...
- c语言二维图形变换程序,C语言图形编程(五、二维图形变换-01)(国外英文资料).doc...
C语言图形编程(五.二维图形变换-01)(国外英文资料) C语言图形编程(五.二维图形变换-01)(国外英文资料) The first user coordinates to the screen c ...
- C语言图形编程(绘图函数部分),C语言图形编程(三、绘图函数-02)12
C语言图形编程(三.绘图函数-02)12 } 84. putimage() 输出图像函数 功能: 函数putimage()将一个先前保存在内存中的图像输出到屏幕上. 用法: 此函数调用方式为void ...
- C++语言图形编程基本函数
文章目录 说明 工具及环境 基本图形绘制 生成图形窗口 绘制点 绘制线 绘制矩形 绘制圆 文字输出 贴图操作 声明 IMAGE 类型变量 载入图片 输出图片 其他补充 媒体控制 多线程 批处理绘制 时 ...
- c 语言绘图函数,c语言图形编程(三、绘图函数-)(C language graphics programming (three, drawing function -)).doc...
c语言图形编程(三.绘图函数-)(C language graphics programming (three, drawing function -)).doc c语言图形编程(三.绘图函数-01) ...
- c语言编程基础课件,第7章_C语言图形编程基础课件
第7章_C语言图形编程基础课件 狭义的组织变革是指组织根据外部环境的变化和内部情况的变化及时地改变自己的内在组织结构,以适应客观发展的需要. 狭义的组织变革是指组织根据外部环境的变化和内部情况的变化及 ...
- c语言代码运行成图指令代码,C语言图形编程代码.doc
C语言图形编程代码 C语言图形编程代码 自己以前编写的C语言图形编程代码 自己以前编写的图形编程代码实现DOS下256BMP图片显示,中文注释,中文汉字显示 写的不好,给大家交流与学习,TC3.0与T ...
- C语言图形编程(绘图函数部分)
一.屏幕和视口设置与清除函数 setviewport() 设置图形视口函数 clearviewport()清除图形视口函数 cleardevice() 清除屏幕函数 getviewsettings() ...
- c语言中编程称量十二个小球的质量,c语言题:现有十二个小球,其中一个小球的重量与其... 有12个外观相同的小球,其中11个是标准球,质量完......
导航:网站首页 > c语言题:现有十二个小球,其中一个小球的重量与其... 有12个外观相同的小球,其中11个是标准球,质量完... c语言题:现有十二个小球,其中一个小球的重量与其... 有1 ...
最新文章
- PHP的is_numeric is_int is_integer ctype_digit
- 最新建账年(over partition by)的研究
- mysql没有写入权限_MySQL的权限系统
- Java操作mongoDB2.6的常见API使用方法
- 服务器系统如用pe和做镜像,PE如何使用?
- 在计算机网络拓扑结构中目前最常用的是,常用的计算机网络拓扑结构.docx
- 帝国cms ajax,帝国CMS注册体验加强 ajax检测用户名和密码
- SGE安装部署完整过程-基于CentOS7
- 投影、坐标系统、基准面和椭圆体、空间参考几个概念的详述
- uniapp app内使用微信H5支付
- AT-SURF-F437 3D Test
- R语言基于mediation包行中介效应分析(2)
- 【GStreamer 】3-1 gstreamer插件之 videotestsrc 介绍
- Java随机位数的验证码的生成(详解)
- 服务器检测到恶意发送文件,微软认证:文件服务器上与恶意文件夹的战争
- JVM_01 内存结构(深入理解+图解)
- 2.Docker容器学习之新生入门必备基础知识
- Paint的setStrokeCap、setStrokeJoin、setPathEffect
- Haptic feedback
- 将十六进制数提取出来进行bit位解析完成代码