| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2405 人关注过本帖
标题:[原创]俄罗斯方块更新至Version2.1,增加更多功能,修正了很多BUG,大家支持一 ...
只看楼主 加入收藏
yuanfeng1129
Rank: 2
等 级:论坛游民
帖 子:62
专家分:31
注 册:2010-8-7
结帖率:0
收藏
 问题点数:0 回复次数:23 
[原创]俄罗斯方块更新至Version2.1,增加更多功能,修正了很多BUG,大家支持一下
俄罗斯方块Tetris version2.1 by yuanfeng1129.rar (360.37 KB)

1.增加速度随等级增高而增加的功能,速度初始化为500毫秒下落一格,每增加一级,时间间隔减少25毫秒,当增加到10级时,速度达到一个峰值,即每250毫秒下落一格;

2.修正画笔变色问题,之前每次打算增加速度变色功能的时候,就会冒出这个问题,尽管尝试了多种算法,但还是有这个BUG,后来发现有次我把速度增加功能删了还是有这个BUG,看来这个BUG应该是由来已久,以前没发觉,但是始终又想不通为什么会这样,为什么每次一玩到600多或700多或800多分的时候,就会出现这个问题,后来我想,会不会是我把画笔通过形参传入进去了才出现的问题,我于是就修正了下每个函数,不让其通过形参传入,直接在函数里面定义画笔,结果还真的好了,真想不通,当然后来还是经过严格大量测试的,因为我要确保方块速度不会一直增加,而是增加到一个峰值截止;

3.修正最小化再重新显示界面时主板重绘而隐藏方块的BUG,究其原因,因为每次最小化或是界面被遮住然后重新显示时,会发送WM_PAINT消息,我只需要修正一下WM_PAINT的内容就轻松解决了,但是解决一个BUG不仅是代码上解决,还要通过大量实例来证明啊,对软件方面,我过分纠结,测试都要进行好多次的,一个文档我都要检查好多遍,尽量连一个错别字都不要有,代码的注释我也尽量全,尽量不出错别字,都要检查好多遍,就是为了让注释全但是又不至于过分冗余,还有尽量不要有错别字,我觉得在这些方面纠结下也没错,因为软件是让大家玩的,出现错误就不好了,一般软件公司发布一个软件,在测试和调试上花的时间往往比编写一个程序的时间更长,还有那些书籍的编者,也是严格检查之后才发行书籍的

4.还增加了一个个性化图标,至于还有没有什么功能,我也想不起来

搜索更多相关主题的帖子: BUG 俄罗斯方块 多功能 
2010-11-06 22:00
yuanfeng1129
Rank: 2
等 级:论坛游民
帖 子:62
专家分:31
注 册:2010-8-7
收藏
得分:0 
程序代码:
#include<windows.h>
#include<time.h>
#include<stdlib.h>
#define W 14 //游戏区域宽度
#define H 26 //游戏区域高度
#define W1 6 //右边状态栏宽度
#define BSIZE 25 //游戏方格边长
#define Y1 6 //放置照片的纵坐标
#define Y2 11 //分数显示栏顶端纵坐标
#define Y3 14 //等级显示栏顶端纵坐标
#define Y4 17 //帮助栏顶端纵坐标
#define Cur_x W/2-1 //游戏方块初始状态左上角横坐标
#define Cur_y 1 //初始状态左上角纵坐标
#define BgColor RGB(0xF5,0xF5,0xDC) //米色
#define FgColor RGB(255,153,204) //淡红色
#define RED RGB(255,0,0)
#define ORANGE RGB(250,128,10)
#define YELLOW RGB(255,255,0)
#define GREEN RGB(0,255,0)
#define CYAN RGB(0,255,255)
#define LIGHT_BLUE RGB(0xA6,0xCA,0xF0) //天蓝色
#define PURPLE RGB(255,0,255)
#define PINK RGB(233,45,143)
#define BLUE RGB(79,195,242)
#define DARKGREEN RGB(0,94,9)
#define GRAY RGB(60,60,60)
#define LIGHTGREEN RGB(114,249,184)
#define MAX_BOX 33 //方块总数
#define MS_NEWBLOCK WM_USER+1  // 消息ID,产生新的【方块】
#define IDI_ICON 100
int score=0,level=0,level_step=100; //分数\等级以及每等级所需分数的定义及初始化
int top=H-1; //最顶端的纵坐标
int x,y; //方块当前位置的横坐标及纵坐标
int cur_boxnum,next_boxnum; //cur_boxnum是当前方块编号,next_boxnum是下一个方块编号
int flag_fullrow=0; //满行标志,初始化为0
int flag_speed_increase=0; //速度增加的标志
int Pause=0; //暂停标志
struct BOARD
{
    int var; //状态,1代表已被占用,0代表未被占用
    int color; //颜色
}board[H][W]; //定义游戏主板,H行W列
struct BLOCK
{
    int a[8][2]; //定义方块形状的数组
    int color; //方块颜色
    int next; //下一个方块的号码
};
struct BLOCK block[MAX_BOX]=
{  //初始化各个游戏方块,-1并不是真正坐标,而是起标识符作用
    {{1,1,1,2,1,3,2,3,-1,-1},RED,1},
    {{0,2,1,2,2,2,0,3,-1,-1},RED,2},
    {{0,1,1,1,1,2,1,3,-1,-1},RED,3},
    {{2,1,0,2,1,2,2,2,-1,-1},RED,0},
    {{1,1,1,2,0,3,1,3,-1,-1},ORANGE,5},
    {{0,1,0,2,1,2,2,2,-1,-1},ORANGE,6},
    {{1,1,2,1,1,2,1,3,-1,-1},ORANGE,7},
    {{0,2,1,2,2,2,2,3,-1,-1},ORANGE,4},
    {{1,1,0,2,1,2,2,2,-1,-1},LIGHT_BLUE,9},
    {{1,1,1,2,2,2,1,3,-1,-1},LIGHT_BLUE,10},
    {{0,2,1,2,2,2,1,3,-1,-1},LIGHT_BLUE,11},
    {{1,1,0,2,1,2,1,3,-1,-1},LIGHT_BLUE,8},
    {{1,1,1,2,2,2,2,3,-1,-1},GREEN,13},
    {{1,2,2,2,0,3,1,3,-1,-1},GREEN,12},
    {{2,1,1,2,2,2,1,3,-1,-1},CYAN,15},
    {{0,2,1,2,1,3,2,3,-1,-1},CYAN,14},
    {{1,0,1,1,1,2,1,3,-1,-1},PURPLE,17},
    {{0,2,1,2,2,2,3,2,-1,-1},PURPLE,16},
    {{1,0,1,1,1,2,1,3,-1,-1},PURPLE,19},
    {{0,2,1,2,2,2,3,2,-1,-1},PURPLE,18},
    {{1,1,2,1,1,2,2,2,-1,-1},YELLOW,20},
    {{0,1,2,1,0,2,1,2,2,2,-1,-1},PINK,22},
    {{1,1,2,1,1,2,1,3,2,3,-1,-1},PINK,23},
    {{0,2,1,2,2,2,0,3,2,3,-1,-1},PINK,24},
    {{0,1,1,1,1,2,0,3,1,3,-1,-1},PINK,21},
    {{0,1,1,1,1,2,1,3,2,3,-1,-1},BLUE,26},
    {{2,1,0,2,1,2,2,2,0,3,-1,-1},BLUE,25},
    {{1,1,2,1,1,2,0,3,1,3,-1,-1},DARKGREEN,28},
    {{0,1,0,2,1,2,2,2,2,3,-1,-1},DARKGREEN,27},
    {{1,1,0,2,2,2,1,3,-1,-1},LIGHTGREEN,29},
    {{0,0,3,0,1,1,2,1,1,2,2,2,0,3,3,3},GRAY,30},//这三个均为炸弹方块
    {{0,0,3,0,1,1,2,1,1,2,2,2,0,3,3,3},GRAY,31},
    {{0,0,3,0,1,1,2,1,1,2,2,2,0,3,3,3},GRAY,32},
};
void Paint(HDC hdc) //此函数用于初始化界面
{
    int i,j;
    HPEN hpen,hpen1; //定义画笔,用于绘制分隔线
    HBRUSH hbrush; //定义画刷
    hpen=CreatePen(PS_SOLID,1,FgColor); //创建画笔,用前景色作画笔
    hpen1=CreatePen(PS_DASHDOTDOT,3,FgColor); //创建画笔,颜色为前景色,线宽为3,双点划线
    SelectObject(hdc,hpen1); //选择画笔
    MoveToEx(hdc,W*BSIZE,0,NULL); //将光标移动到(W*BSIZE,0)处
    LineTo(hdc,W*BSIZE,H*BSIZE); //从光标所在位置画线至(W*BSIZE,H*BSIZE)处
    DeleteObject(hpen1); //删除之前所选用的画笔
    SelectObject(hdc,hpen); //重新选择画笔
    for(i=1;i<H-1;i++)  //绘制游戏区域方格线
        for(j=1;j<W-1;j++)
        {
            hbrush=CreateSolidBrush(board[i][j].color); //画刷颜色与游戏板状态颜色相同
            SelectObject(hdc,hbrush);
            Rectangle(hdc,j*BSIZE,i*BSIZE,(j+1)*BSIZE,(i+1)*BSIZE);
            DeleteObject(hbrush);
        }
    hbrush=GetStockObject(NULL_BRUSH);
    SelectObject(hdc,hbrush);
    for(i=1;i<5;i++)  //绘制右边状态栏游戏预览区域方格线
        for(j=W+1;j<W+W1-1;j++)
            Rectangle(hdc,j*BSIZE,i*BSIZE,(j+1)*BSIZE,(i+1)*BSIZE);
    Rectangle(hdc,(W+1)*BSIZE,Y2*BSIZE,(W+W1-1)*BSIZE,(Y2+2)*BSIZE); //绘制分数栏方格线
    Rectangle(hdc,(W+1)*BSIZE,Y3*BSIZE,(W+W1-1)*BSIZE,(Y3+2)*BSIZE); //绘制等级栏方格线
    Rectangle(hdc,(W+1)*BSIZE,Y4*BSIZE,(W+W1-1)*BSIZE,(Y4+5)*BSIZE); //绘制帮助栏方格线
    TextOut(hdc,(W+2)*BSIZE,(int)((Y2+0.2)*BSIZE),"分    数",8); //输出文字
    TextOut(hdc,(W+2)*BSIZE,(int)((Y3+0.2)*BSIZE),"等    级",8); //同上
    TextOut(hdc,(W+1)*BSIZE,(H-3)*BSIZE,"制作人:袁峰",strlen("制作人:袁峰"));
    TextOut(hdc,(W+1)*BSIZE,(H-2)*BSIZE,"QQ:775141406",strlen("QQ:775141406"));
    DeleteObject(hpen); //删除画笔
    DeleteObject(hbrush); //删除画刷
}
void ShowScore(HDC hdc) //显示分数的函数
{
    char score_str[5]; //定义字符串用于保存分数值
    SetBkColor(hdc,BgColor); //设置文本背景色为窗口背景色
    wsprintf(score_str,"%4d",score); //将数字score转换成字符串后保存到score_str之中
    TextOut(hdc,(int)((W+2.2)*BSIZE),(int)((Y2+1.2)*BSIZE),score_str,4); //在右边状态栏上显示分数
}
void ShowLevel(HDC hdc) //显示等级的,具体同上
{
    char level_str[3];
    SetBkColor(hdc,BgColor);
    wsprintf(level_str,"%2d",level);
    TextOut(hdc,(int)((W+2.7)*BSIZE),(int)((Y3+1.2)*BSIZE),level_str,2);
}
void ShowHelp(HDC hdc) //显示帮助的,该函数只在初始化界面时调用
{
    char help1[]="↑ - 旋转",
         help2[]="↓ - 下移",
         help3[]="← - 左移",
         help4[]="→ - 右移",
         help5[]="空格-暂停";
    TextOut(hdc,(int)((W+1.8)*BSIZE),(int)((Y4+0.2)*BSIZE),help1,9);
    TextOut(hdc,(int)((W+1.8)*BSIZE),(int)((Y4+1.2)*BSIZE),help2,9);
    TextOut(hdc,(int)((W+1.8)*BSIZE),(int)((Y4+2.2)*BSIZE),help3,9);
    TextOut(hdc,(int)((W+1.8)*BSIZE),(int)((Y4+3.2)*BSIZE),help4,9);
    TextOut(hdc,(int)((W+1.8)*BSIZE),(int)((Y4+4.2)*BSIZE),help5,9);
}
void EraseBox(HDC hdc,int x,int y,int num) //清除(x,y)处编号为num的方块
{
    int i;
    HPEN hpen=CreatePen(PS_SOLID,1,FgColor);
    HBRUSH hbrush=CreateSolidBrush(BgColor);
    SelectObject(hdc,hpen);
    SelectObject(hdc,hbrush);
    for(i=0;i<8;i++)   //用背景色填充方块所在区域,使方块隐藏
    {  
        if(block[num].a[i][0]<0) break;
        Rectangle(hdc,(x+block[num].a[i][0])*BSIZE,(y+block[num].a[i][1])*BSIZE,
        (x+block[num].a[i][0]+1)*BSIZE,(y+block[num].a[i][1]+1)*BSIZE);
    }
    DeleteObject(hpen);
    DeleteObject(hbrush);   
}
void ShowBox(HDC hdc,int x,int y,int num) //显示(x,y)处编号为num的方块
{
    int i;
    HPEN hpen=CreatePen(PS_SOLID,1,FgColor);
    HBRUSH hbrush=CreateSolidBrush(block[num].color); //创建画刷,颜色和方块颜色相同
    SelectObject(hdc,hpen);
    SelectObject(hdc,hbrush);
    for(i=0;i<8;i++) //显示方块的过程
    {
        if(block[num].a[i][0]<0) break;
        Rectangle(hdc,(x+block[num].a[i][0])*BSIZE,(y+block[num].a[i][1])*BSIZE,
        (x+block[num].a[i][0]+1)*BSIZE,(y+block[num].a[i][1]+1)*BSIZE);
    }
    DeleteObject(hpen);
    DeleteObject(hbrush);
}
void RePaint(HDC hdc,int org_top)
{
    int i,j;
    HBRUSH hbrush;
    HPEN hpen;
    hpen=CreatePen(PS_SOLID,1,FgColor);
    SelectObject(hdc,hpen);
    if(flag_fullrow) //如果有满行,则重绘主板
    {
        for(i=org_top;i<y+4;i++) //org_top为之前的最顶端
        {
            if(i<=0||i>=H-1) continue; //越界了,就跳出本次循环
            for(j=1;j<W-1;j++)
            { //注意这里绘制主板时,每次都要选择不同的画刷,用完后一定要删除
                hbrush=CreateSolidBrush(board[i][j].color);
                SelectObject(hdc,hbrush);
                Rectangle(hdc,j*BSIZE,i*BSIZE,(j+1)*BSIZE,(i+1)*BSIZE);
                DeleteObject(hbrush);
            }
        }
        flag_fullrow=0;       
    }
    else if(cur_boxnum==MAX_BOX-1||cur_boxnum==MAX_BOX-2||cur_boxnum==MAX_BOX-3) //如果为炸弹方块
    {
        hbrush=CreateSolidBrush(BgColor); //背景色作画刷
        SelectObject(hdc,hbrush);
        for(i=y-2;i<y+6;i++)  //炸弹作用区域为以炸弹为中心的8*8的矩形
        {
            if(i<=0||i>=H-1) continue;
            for(j=x-2;j<x+6;j++)
            {
                if(j<=0||j>=W-1) continue;
                Rectangle(hdc,j*BSIZE,i*BSIZE,(j+1)*BSIZE,(i+1)*BSIZE);
            }
        }
        DeleteObject(hbrush);
    }
    DeleteObject(hpen);
}
void SetFullRow(HDC hdc) //满行处理函数,重置游戏板状态并重绘主板,通过调用Repaint函数重绘
{
    int i,ii,j;
    int k=0;
    int org_top=top; //保存最顶端
    if(cur_boxnum!=MAX_BOX-1&&cur_boxnum!=MAX_BOX-2&&cur_boxnum!=MAX_BOX-3) //如果不是炸弹方块,则执行以下过程
    {
        for(i=y;i<y+4;i++) //从y行开始,从上到下遍历游戏区域
        {
            if(i<=0||i>=H-1) continue; //越界了,就跳出本次循环
            for(j=1;j<W-1;j++)
                if(!board[i][j].var) break; //一旦该行有一个为空,即跳出
            if(j==W-1) //找到满行了
            {
                for(ii=i;ii>=top;ii--) //重置游戏区域各个方格的状态,top为最顶端,i为找到的满行
                    for(j=1;j<W-1;j++)
                        board[ii][j]=board[ii-1][j];
                top++;  //消去1行后,Top加1
                k++; //找到的满行数,每找到一满行,k就加1
                flag_fullrow=1; //满行标志符
            }
        }
        if(k!=0)
        {//以下为增加分数的具体过程
            if(k==1) score+=10; //满行数为1,加10分
            else if(k==2) score+=30; //满行为2加30分
            else if(k==3) score+=50;
            else if(k==4) score+=80;
            ShowScore(hdc); //更新分数
        }
        if(level!=score/level_step) //这里是程序优化部分,也可省略
        {
            level=score/level_step;
            flag_speed_increase=1; //分数增加的标志置1
            ShowLevel(hdc); //更新等级
        }
    }
    RePaint(hdc,org_top); //重绘游戏主板
}
void ChangeVar(void) //改变游戏主板的状态
{
    int i,j;
    if(cur_boxnum==MAX_BOX-1||cur_boxnum==MAX_BOX-2||cur_boxnum==MAX_BOX-3) //如果该方块为炸弹方块
    {
        for(i=y-2;i<y+6;i++)
        {
            if(i<=0||i>=H-1) continue; //越界则跳出本次循环
            for(j=x-2;j<x+6;j++)
            {
                if(j<=0||j>=W-1) continue; //越界
                board[i][j].color=BgColor; //状态置0,颜色恢复为背景色
                board[i][j].var=0;
            }
        }
    }
    else
    {
        for(i=0;i<8;i++)
        {
            if(block[cur_boxnum].a[i][0]<0) break;
            board[y+block[cur_boxnum].a[i][1]][x+block[cur_boxnum].a[i][0]].var=1; //游戏板该位置状态置1
            board[y+block[cur_boxnum].a[i][1]][x+block[cur_boxnum].a[i][0]].color=block[cur_boxnum].color; //游戏板颜色改为方块颜色
        }
    }
}
BOOL CanMove(void) //通过判断新位置是否有方块填充来判断来判断方块是否能够移动
{
    int i;
    for(i=0;i<8;i++)
    {
        if(block[cur_boxnum].a[i][0]<0) break;
        if(board[y+block[cur_boxnum].a[i][1]][x+block[cur_boxnum].a[i][0]].var) //如果该位置有方块填充,则不能移动
            return FALSE;
    }
    return TRUE;
}
BITMAPFILEHEADER * DibLoadImage (PTSTR pstrFileName)   //加载DIB图像到内存之中   
{
    BOOL bSuccess ;
    DWORD dwFileSize,dwHighSize,dwBytesRead;   
    HANDLE hFile;
    BITMAPFILEHEADER *pbmfh;
    hFile=CreateFile(pstrFileName,GENERIC_READ,FILE_SHARE_READ,NULL,       
                     OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
    if(hFile==INVALID_HANDLE_VALUE)
        return NULL;    
    dwFileSize=GetFileSize(hFile,&dwHighSize);
    if(dwHighSize)
    {
        CloseHandle(hFile);
        return NULL ;
    }
    pbmfh=malloc(dwFileSize) ;
    if(!pbmfh)
    {
        CloseHandle(hFile);
        return NULL ;
    }
    bSuccess=ReadFile(hFile,pbmfh,dwFileSize,&dwBytesRead,NULL) ;  
    CloseHandle(hFile);
    if(!bSuccess||(dwBytesRead!=dwFileSize)      
        ||(pbmfh->bfType!=*(WORD *)"BM")
        ||(pbmfh->bfSize!=dwFileSize))
    {
        free(pbmfh);
        return NULL;
    }
    return pbmfh;
}
2010-11-06 22:03
yuanfeng1129
Rank: 2
等 级:论坛游民
帖 子:62
专家分:31
注 册:2010-8-7
收藏
得分:0 
程序代码:
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //窗口过程函数的声明
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hprevInstance,PSTR szCmdLine,int iCmdShow) //入口函数,即主函数
{ //各个形参所代表的意思请自行查阅资料
    int screenwide,screenhight; //定义变量来保存屏幕宽度和高度
    char AppName[]="Tetris"; //定义并初始化窗口类名
    HWND hwnd; //定义窗口句柄
    MSG msg; //定义消息结构体
    WNDCLASSEX wndclass; //定义窗口类
    wndclass.cbSize=sizeof(wndclass); //窗口类大小
    wndclass.style=CS_HREDRAW|CS_VREDRAW; //窗口类风格
    wndclass.lpfnWndProc=WndProc; //窗口过程函数为WndProc
    wndclass.cbClsExtra=0; //窗口类无扩展
    wndclass.cbWndExtra=0; //窗口实例无扩展
    wndclass.hInstance=hInstance; //当前实例句柄为hInstance
    wndclass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON)) ; //加载自定义图标
    wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); //默认光标,光标进入窗口区域时,将显示为箭头
    wndclass.hbrBackground=CreateSolidBrush(BgColor); //窗口背景色
    wndclass.lpszMenuName=NULL; //窗口类无菜单
    wndclass.lpszClassName=AppName; //窗口类名
    wndclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION); //采用默认小图标
    if(!RegisterClassEx(&wndclass)) //窗口类的注册
    {
        MessageBeep(0);
        return FALSE;
    }
    screenwide=GetSystemMetrics(SM_CXFULLSCREEN); //获取屏幕宽度,即横向分辨率
    screenhight=GetSystemMetrics(SM_CYFULLSCREEN); //获取屏幕高度,即纵向分辨率
    hwnd=CreateWindow( //创建窗口
                      AppName, //窗口类名
                     "俄罗斯方块Tetris version2.1 by yuanfeng1129", //窗口实例标题名
                      WS_OVERLAPPEDWINDOW,
                      (screenwide-(W+W1)*BSIZE)/2, //窗口左上角横坐标
                      (screenhight-H*BSIZE)/2, //左上角纵坐标
                      (W+W1)*BSIZE, //窗口宽度
                      (H+1)*BSIZE, //窗口高度,注意包含了标题栏
                       NULL, //窗口无父窗口
                       NULL, //窗口无主菜单
                       hInstance, //当前应用程序实例句柄
                       NULL //“创建参数”指针设置为NULL,可以用这个指针访问以后想要引用的程序中的数据,一般为NULL
                     );
    if(!hwnd) return FALSE; //创建失败则退出程序
    ShowWindow(hwnd,iCmdShow); //显示窗口
    UpdateWindow(hwnd); //刷新窗口
    MessageBox(hwnd," 峰哥哥制作","开始",MB_OK); //弹出框
    SetTimer(hwnd,1,500-25*level,NULL); //设置一个500-25*level毫秒触发一次的定时器,hwnd为窗口句柄,1为定时器标识符
    while(GetMessage(&msg,NULL,0,0)) //消息循环,用于从消息队列中获取消息
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam; //注意这一步不能少
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{ //定义窗口过程函数
    int i,j;
    int old_boxnum; //用于保存之前的方块号
    HDC hdc; //定义DC句柄,DC里包含绘图默认的一些属性
    PAINTSTRUCT ps; //定义绘图结构
    static int cxClient,cyClient,cxDib,cyDib; //cxClient,cyClient为窗口大小改编后窗口的横向宽度和纵向宽度,cxDib,cyDib为DIB图片的像素
    static TCHAR szFileName[MAX_PATH]="MyPhoto.bmp"; //szFileName用来保存DIB文件的路径
    static BITMAPFILEHEADER *pbmfh;   //指向文件头的指针   
    static BITMAPINFO *pbmi; //指向信息头的指针
    static BYTE *pBits; //指向像素位的指针
    switch(iMsg) //消息处理的过程
    {
    case WM_CREATE: /*当一个应用程序使用函数CreateWindow或CreateWindowEx来创建一个窗口时,
  系统将发送该消息给此新建窗口过程。该消息将在创建窗口之后,显示窗口
  之前发送该消息,该消息将在CreateWindow或CreateWindowEx函数返回之前发送。*/
        for(i=1;i<H;i++) //初始化状态,将两竖边状态初始化为1
            board[i][0].var=board[i][W-1].var=1;
        for(j=1;j<W-1;j++) //将最底部状态置1
            board[H-1][j].var=1;
        for(i=1;i<H-1;i++) //将游戏区域状态置0,颜色置为背景色
            for(j=1;j<W-1;j++)
            {
                board[i][j].var=0;
                board[i][j].color=BgColor;
            }
        srand((unsigned)time(NULL)); //初始化随机数发生器
        cur_boxnum=rand()%MAX_BOX; //给当前方块号赋初值
        next_boxnum=rand()%MAX_BOX; //给下一个方块号赋初值
        x=Cur_x; //初始化方块横坐标
        y=Cur_y; //初始化方块纵坐标
        pbmfh=DibLoadImage(szFileName);  // 加载DIB文件至内存中,返回文件头指针
        pbmi=(BITMAPINFO *)(pbmfh+1);
        pBits=(BYTE *)pbmfh+pbmfh->bfOffBits;  
        if(pbmi->bmiHeader.biSize==sizeof(BITMAPCOREHEADER)) //获取DIB文件横向宽度和纵向高度
        {
            cxDib=((BITMAPCOREHEADER *)pbmi)->bcWidth;
            cyDib=((BITMAPCOREHEADER *)pbmi)->bcHeight;
        }
        else
        {
            cxDib=pbmi->bmiHeader.biWidth;
            cyDib=abs(pbmi->bmiHeader.biHeight);
        }
        return 0; //直接退出窗口过程函数
    case WM_SIZE:
        cxClient = LOWORD (lParam) ;//当窗口大小改变时,获取窗口宽度和高度,lparam为附加消息参数,高位字节为高度,低位字节为宽度
        cyClient = HIWORD (lParam) ;//LOWORD函数获取一个字的低位字节,HIWORD相反
        return 0 ;
    case WM_PAINT: //绘制界面,当应用程序适用UpdateWindow刷新窗口时,第一次发送该消息
        hdc=BeginPaint(hwnd,&ps); //给DC句柄赋值
        SetBkColor(hdc,BgColor); //设置文本背景色
        Paint(hdc); //调用Paint函数绘制界面
        ShowScore(hdc); //显示分数
        ShowLevel(hdc); //显示等级
        ShowHelp(hdc); //显示帮助栏
        ShowBox(hdc,x,y,cur_boxnum); //显示游戏区域中的游戏方块
        ShowBox(hdc,W+1,1,next_boxnum); //显示右边状态栏的游戏方块
        if(pbmfh)     //该函数显示DIB图片                                             
            SetDIBitsToDevice(hdc,
                              (W+1)*BSIZE,                     //图片左上角横坐标
                              6*BSIZE,                     // 图片左上角纵坐标
                              cxDib,                 //图片宽度
                              cyDib,                 //图片高度
                              0,                     // xSrc
                              0,                     // ySrc
                              0,                     // first scan line
                              cyDib,                 // number of scan lines
                              pBits,
                              pbmi,
                              DIB_RGB_COLORS);
        EndPaint(hwnd,&ps); //EndPaint函数标记指定窗口的绘画过程结束;这个函数在每次调用BeginPaint函数之后被请求,但仅仅在绘画完成以后。
        return 0;
    case WM_TIMER: //定时器消息,每0.5秒接收到一次
        hdc=GetDC(hwnd); //该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,以后可以在GDI函数中使用该句柄来在设备上下文环境中绘图。
        y++; //y增1
        if(CanMove()) //如果能移动,则擦除原来位置方块,显示新位置方块,相当于是方块下落
           {
            EraseBox(hdc,x,y-1,cur_boxnum);
            ShowBox(hdc,x,y,cur_boxnum);
        }
        else //如果不能移动,则到底了,y恢复之前的值,并发送MS_NEWBLOCK产生新的方块
        {
            y--;
            SendMessage(hwnd,MS_NEWBLOCK,0,0);
        }
        ReleaseDC(hwnd,hdc); //数释放设备上下文环境(DC)供其他应用程序使用
        return 0;
    case WM_KEYDOWN: //当按下键时,会发送该消息
        hdc=GetDC(hwnd);
        switch((int)wParam) //判断具体按下的键
        {
        case VK_UP:
            old_boxnum=cur_boxnum; //保存当前方块号
            cur_boxnum=block[cur_boxnum].next; //方块号变为下一个方块号
            if(CanMove())
            {
                EraseBox(hdc,x,y,old_boxnum);
                ShowBox(hdc,x,y,cur_boxnum);
            }
            else
                cur_boxnum=old_boxnum; //恢复之前的值
            break;
        case VK_DOWN:
            y++;
            if(CanMove())
            {
                EraseBox(hdc,x,y-1,cur_boxnum);
                ShowBox(hdc,x,y,cur_boxnum);
            }
            else
            {
                y--;
                SendMessage(hwnd,MS_NEWBLOCK,0,0); //不能下移,就到底了,产生新的方块
            }
            break;
        case VK_LEFT:
            x--; //横坐标减小1
            if(CanMove()) //如果能移动,则左移,不能移动则恢复之前坐标
            {
                EraseBox(hdc,x+1,y,cur_boxnum);
                ShowBox(hdc,x,y,cur_boxnum);
            }
            else
            {
                x++;
                if((cur_boxnum==MAX_BOX-1||cur_boxnum==MAX_BOX-2||cur_boxnum==MAX_BOX-3)&&x!=1)
                    SendMessage(hwnd,MS_NEWBLOCK,0,0); //当方块为炸弹方块,且在右移时碰到主板方块时,则发送MS_NEWBLOCK消息进行重绘主板,产生新方块
            }
            break;
        case VK_RIGHT: //同上
            x++;
            if(CanMove())
            {
                EraseBox(hdc,x-1,y,cur_boxnum);
                ShowBox(hdc,x,y,cur_boxnum);
            }
            else
            {
                x--;
                if((cur_boxnum==MAX_BOX-1||cur_boxnum==MAX_BOX-2||cur_boxnum==MAX_BOX-3)&&x!=W-5)
                    SendMessage(hwnd,MS_NEWBLOCK,0,0);       
            }
            break;
        case VK_SPACE:
            if(Pause==0)
            {
                Pause=1;
                KillTimer(hwnd,1); //暂停时中止计时器
            }
            else if(Pause==1)
            {
                Pause=0;
                SetTimer(hwnd,1,500-25*level,NULL); //重新开启计时器
            }
            break;
        }
        ReleaseDC(hwnd,hdc);
        return 0;
        case MS_NEWBLOCK:
            hdc=GetDC(hwnd);
            ChangeVar(); //改变游戏主板状态
        /*    for(i=H-2;i>=1;i--)
            {
                for(j=1;j<W-1;j++)
                    if(board[i][j].var) break;
                if(j==W-1)
                {
                    top=i+1;
                    break;
                }
            }*/
            if(top>y+block[cur_boxnum].a[0][1])
                top=y+block[cur_boxnum].a[0][1];
            SetFullRow(hdc); //满行处理
            if(flag_speed_increase==1&&level<=10)
            {
                SetTimer(hwnd,1,500-25*level,NULL);
                flag_speed_increase=0;
            }   
            cur_boxnum=next_boxnum;
            x=Cur_x; //重置方块坐标
            y=Cur_y;
            srand((unsigned)time(NULL)); //初始化随机数发生器
            next_boxnum=rand()%MAX_BOX;
            EraseBox(hdc,W+1,1,cur_boxnum); //清除右边状态栏的方块
            ShowBox(hdc,W+1,1,next_boxnum); //显示右边状态栏的方块
            ShowBox(hdc,Cur_x,Cur_y,cur_boxnum); //显示游戏主板顶部方块
            if(!CanMove()) //刚一开始就不能移动
            {
                if(cur_boxnum!=MAX_BOX-1&&cur_boxnum!=MAX_BOX-2&&cur_boxnum!=MAX_BOX-3) //如果新方块不是炸弹方块,则退出游戏
                {
                    KillTimer(hwnd,1);
                    MessageBox(hwnd,"  退出游戏","退出",MB_OK);
                    PostQuitMessage(0);
                }
                else //如果是炸弹方块,则改变游戏主板状态,并重绘游戏主板,然后发送MS_NEWBLOCK消息
                {
                    ChangeVar();
                    RePaint(hdc,0);
                    SendMessage(hwnd,MS_NEWBLOCK,0,0);
                }
            }
            ReleaseDC(hwnd,hdc);
            return 0;
        case WM_DESTROY: //退出游戏
            if(pbmfh)
                free(pbmfh); //释放文件头指针
            KillTimer(hwnd,1);
            PostQuitMessage(0);
            return 0;
}
return DefWindowProc(hwnd,iMsg,wParam,lParam); //窗口默认处理,当消息处理函数未处理消息时就调用该函数进行处理
}
2010-11-06 22:04
vandychan
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
等 级:贵宾
威 望:18
帖 子:2296
专家分:6418
注 册:2010-8-20
收藏
得分:0 
支持一下你

到底是“出来混迟早要还”还是“杀人放火金腰带”?
2010-11-06 22:23
outsider_scu
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:3
帖 子:430
专家分:1333
注 册:2010-10-21
收藏
得分:0 
真宏伟啊。。。

编程的道路上何其孤独!
2010-11-06 23:51
yu_hua
Rank: 2
等 级:论坛游民
帖 子:222
专家分:95
注 册:2006-8-10
收藏
得分:0 
羡慕楼主!祝贺你!
2010-11-08 18:17
Crack_c_
Rank: 1
来 自:绍兴
等 级:新手上路
帖 子:3
专家分:0
注 册:2010-11-6
收藏
得分:0 
成功属于那些坚持不懈的人
我也正在C的漫漫之路上前行
也是一个人,坚持我的C之路。
加油。。。。。朋友。。。你是最棒的
2010-11-08 19:15
vip1646
Rank: 2
等 级:论坛游民
帖 子:10
专家分:12
注 册:2010-11-10
收藏
得分:0 
哥们,我把你的源码复制在vc里面,编译没错。链接,去错了?怎么回事?我的QQ471872228  真心求你帮助。
2010-11-13 17:06
Alar30
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:10
帖 子:988
专家分:1627
注 册:2009-9-8
收藏
得分:0 
不错哇
支持!
2010-11-13 17:47
jxgjq
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2010-11-15
收藏
得分:0 
和上一个版本一样,编译没问题,连接出错,求解。。
2010-11-15 16:35
快速回复:[原创]俄罗斯方块更新至Version2.1,增加更多功能,修正了很多BUG,大家支 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.034630 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved