sdk实现的俄罗斯方块

作者在 2011-01-18 14:56:25 发布以下内容
终于自己写了个俄罗斯方块。。
代码还没来的及整理,比较乱。。。
图形的数据结构:每一组表示一类(代码中为shape_num)图形的四种变形(代码中为shape_direction).数字表示第几个方块是图形的组成块。

#ifndef block_h
#define block_h
int shape[7][4][4]=
{
    {
        {0,1,5,9},
        {2,4,5,6},
        {0,4,8,9},
        {0,1,2,4}
    },

    {
        {0,1,4,8},
        {0,1,2,6},
        {1,5,8,9},
        {0,4,5,6}
    },

    {
        {0,1,5,6},
        {1,4,5,8},
        {0,1,5,6},
        {1,4,5,8}
    },

    {
        {1,2,4,5},
        {0,4,5,9},
        {1,2,4,5},
        {0,4,5,9}
    },

    {
        {1,4,5,6},
        {0,4,5,8},
        {0,1,2,5},
        {1,4,5,9}
    },

    {
        {0,1,4,5},
        {0,1,4,5},
        {0,1,4,5},
        {0,1,4,5}
    },

    {
        {0,1,2,3},
        {0,4,8,12},
        {0,1,2,3},
        {0,4,8,12}
    }
};


#endif
函数声明:
#ifndef function_h
#define function_h

LRESULT CALLBACK WndProc(HWND hwnd,UINT mesage,WPARAM wParam, LPARAM lParam);

void Draw_shape(HWND hwnd,int shape_num,int shape_direction,POINT position,COLORREF color);

void Draw_block(HWND hwnd,POINT block,COLORREF color);

void Init_map();

void New_shape(HWND hwnd);

void Down_shape(HWND hwnd);

void Right_shape(HWND hwnd);

void Left_shape(HWND hwnd);

void Change_direction(HWND hwnd);

bool Downable();

bool Rightable();

bool Leftable();

bool Changeable();

void Update_map();

int Full_row();

void Clean_full_row(HWND hwnd,int row);

void Pause();

void Draw_edge(HWND hwnd);

void Pre_to_cur(HWND hwnd);

bool Over();

void Show_over(HWND hwnd);




void Init_frame(HWND hwnd);

void Show_score(HWND hwnd);

void Show_level(HWND hwnd);

void Change_level(HWND hwnd);

void Show_preview(HWND hwnd);







#endif
主程序:
# include<windows.h>
# include<time.h>
# include"block.h"
# include"function.h"

int block_size = 15;//小方块边长

POINT cur_pos = {8,1};//图形当前坐标
int cur_shape_num = 0;//图形当前号码
int cur_shape_direction = 0;//图形当前方向 方向表示同种图形内部的变形变化
int pre_shape_num = 0;
int pre_shape_direction = 0;

#define X_max 20//画图区域宽度
#define Y_max 30//画图区域高度
int map[Y_max][X_max];//画图区域坐标系

COLORREF shape_color = RGB(0,200,200);//图形颜色
COLORREF bg_color = RGB(150,20,20);//背景颜色
COLORREF edge_color = RGB(0,100,100);

int score = 0;
int level = 1;

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPreInstance,
                   PSTR szCmdLine,
                   int iCmdShow)
{

    const int caption_height=GetSystemMetrics(SM_CYCAPTION);//标题栏高度
    const int frame_height=GetSystemMetrics(SM_CYFRAME);//窗口边框高度
    const int frame_width=GetSystemMetrics(SM_CXFRAME);//窗口侧边栏宽度

    static TCHAR classname[]=TEXT("classname");
    MSG msg;
    HWND hwnd;

    WNDCLASS wc;
    wc.style            = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc        = WndProc;
    wc.cbClsExtra        = 0;
    wc.cbWndExtra        = 0;
    wc.hInstance        = hInstance;
    wc.hIcon            = LoadIcon(NULL,IDI_APPLICATION);
    wc.hCursor            = LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground    = CreateSolidBrush(bg_color); ;
    wc.lpszMenuName        = NULL;
    wc.lpszClassName    = classname;
    

    if(!RegisterClass(&wc))
    {
        MessageBox(NULL,TEXT("需要windowsNT"),TEXT("出错啦!"),MB_OK|MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(
        classname,
        TEXT("俄罗斯方块_林语"),
        WS_SYSMENU,
        500,
        200,
        (frame_width*2)+((X_max+5)*block_size),//+5用于显示预览,得分,等级
        (frame_height*2)+(caption_height)+(Y_max*block_size),
        NULL,
        NULL,
        hInstance,
        NULL);

    
    ShowWindow(hwnd,iCmdShow);
//    UpdateWindow(hwnd);
    

    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    return msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam, LPARAM lParam)
{

    switch(message)
    {
    case WM_CREATE:
        Init_map();
        break;
    case WM_PAINT:
        Init_frame(hwnd);
        New_shape(hwnd);
        Pre_to_cur(hwnd);
        Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,shape_color);
        SetTimer(hwnd,1,1000/level,NULL);
        break;
    case WM_TIMER:
        Down_shape(hwnd);
        break;
    case WM_KEYDOWN:
        switch(wParam)
        {
        case VK_UP:
            Change_direction(hwnd);
            break;
        case VK_DOWN:
            Down_shape(hwnd);
            break;
        case VK_LEFT:
            Left_shape(hwnd);
            break;
        case VK_RIGHT:
            Right_shape(hwnd);
            break;
        case VK_SPACE:
            Pause();
            break;
        }
        break;
    case WM_CLOSE:
        KillTimer(hwnd,1);
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd,message,wParam,lParam);;
}
//*******************************************************************************************************************

void Draw_shape(HWND hwnd,int shape_num,int shape_direction,POINT position,COLORREF color)//图形号、方向以及左上角坐标、颜色
{//画图形
    POINT block;
    
    for(int i=0;i<4;++i)
    {
            block.x = position.x + shape[shape_num][shape_direction][i] % 4;
            block.y = position.y + shape[shape_num][shape_direction][i] / 4;
            Draw_block(hwnd,block,color);
    }
}

void Draw_block(HWND hwnd,POINT block,COLORREF color)//小方块左上角坐标及颜色
{//画小方块
    RECT rc;
    SetRect(&rc,
        block.x * block_size + 1,      //作+1 、-1的调整是为了使得方块之间有间隙
        block.y * block_size + 1,
        (block.x + 1) * block_size - 1,
        (block.y + 1) * block_size - 1);

    HDC hdc = GetDC(hwnd);
    HBRUSH brush = (HBRUSH)CreateSolidBrush(color);
    
    FillRect(hdc,&rc,brush);

    DeleteObject(brush);
    ReleaseDC(hwnd,hdc);
}

void Init_map()
{//构造一个开口朝上的半包围结构作为边界

    for(int i = 0;i < Y_max;i++)
    {
        for(int j = 0;j < X_max;j++)
        {
            map[i][j] = 0;
        }
    }

//将边界初始化为1表明此处不可被覆盖
    for(i = 0;i < Y_max;i++)
    {
        map[i][0] = 1;
        map[i][X_max-1] = 1;
    }

    for(i = 0;i < X_max;i++)
    {
        map[Y_max-1][i] = 1;
    }
}
void Init_frame(HWND hwnd)
{//初始化界面,画出方框和信息
    Draw_edge(hwnd);

    HDC hdc = GetDC(hwnd);
    HPEN hpen = CreatePen(PS_SOLID,2,shape_color);
    SelectObject(hdc,hpen);
    TCHAR prev[] = "预览:";//preview
    TextOut(hdc,X_max*block_size,block_size,prev,strlen(prev));
    TCHAR sco[] = "得分:";//score
    TextOut(hdc,X_max*block_size,10*block_size,sco,strlen(sco));
    Show_score(hwnd);
    TCHAR lev[] = "等级:";//level
    TextOut(hdc,X_max*block_size,20*block_size,lev,strlen(lev));
    Show_level(hwnd);
    DeleteObject(hpen);
    ReleaseDC(hwnd,hdc);
}

void New_shape(HWND hwnd)
{//随机生成预览图形并显示
    srand((unsigned)time(NULL));
    pre_shape_num = rand() % 7;
    pre_shape_direction = 0;
    Show_preview(hwnd);
}
void Pre_to_cur(HWND hwnd)
{//将预览图形变为将要出现的图形,并生成新的预览图形
    cur_shape_num = pre_shape_num;
    cur_shape_direction = pre_shape_direction;
    cur_pos.x = 8;
    cur_pos.y = 1;
    New_shape(hwnd);
}

void Down_shape(HWND hwnd)
{//处理图形下移
    if(!Downable())
    {//如果不可以下移、
        Update_map();//在坐标系中记录
        if(Over())//判断是否结束
        {
            KillTimer(hwnd,1);
            Show_over(hwnd);
            return;
        }
        int row;
        while(row = Full_row())//是否有满行
        {
            Clean_full_row(hwnd,row);
        }
        Pre_to_cur(hwnd);//产生新的图形
        Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,shape_color);
        return;
    }

    Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,bg_color);//消除原来的痕迹
    cur_pos.y += 1;//图形的纵坐标+1
    Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,shape_color);//画出下降后的图形
}

void Right_shape(HWND hwnd)
{//处理右移
    if(!Rightable())
    {
        return;
    }
    Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,bg_color);
    cur_pos.x += 1;
    Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,shape_color);
}

void Left_shape(HWND hwnd)
{//处理左移
    if(!Leftable())
    {
        return;
    }    
    Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,bg_color);
    cur_pos.x -= 1;
    Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,shape_color);
}

void Change_direction(HWND hwnd)
{//变形处理
    if(!Changeable())
    {
        return;
    }
    Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,bg_color);
    cur_shape_direction += 1;
    cur_shape_direction %= 4;
    Draw_shape(hwnd,cur_shape_num,cur_shape_direction,cur_pos,shape_color);
}

bool Downable()
{//判断是否可以向下
    POINT down_pos,block_pos;
    down_pos.x = cur_pos.x;
    down_pos.y = cur_pos.y + 1;
    for(int i = 0;i < 4;i++)
    {//分别检查图形中的4个小块是否会与下方重叠
        block_pos.x = down_pos.x + shape[cur_shape_num][cur_shape_direction][i] % 4;
        block_pos.y = down_pos.y + shape[cur_shape_num][cur_shape_direction][i] / 4;
        if(map[block_pos.y][block_pos.x] == 1)
        {
            return false;
        }
    }
    return true;
}

bool Rightable()
{//判断是否可以向右
    POINT down_pos,block_pos;
    down_pos.x = cur_pos.x + 1;
    down_pos.y = cur_pos.y;
    for(int i = 0;i < 4;i++)
    {//分别检查图形中的4个小块是否会与右方重叠
        block_pos.x = down_pos.x + shape[cur_shape_num][cur_shape_direction][i] % 4;
        block_pos.y = down_pos.y + shape[cur_shape_num][cur_shape_direction][i] / 4;
        if(map[block_pos.y][block_pos.x] == 1)
        {
            return false;
        }
    }
    return true;
}

bool Leftable()
{//判断是否可以向左
    POINT down_pos,block_pos;
    down_pos.x = cur_pos.x - 1;
    down_pos.y = cur_pos.y;
    for(int i = 0;i < 4;i++)
    {//分别检查图形中的4个小块是否会与左方重叠
        block_pos.x = down_pos.x + shape[cur_shape_num][cur_shape_direction][i] % 4;
        block_pos.y = down_pos.y + shape[cur_shape_num][cur_shape_direction][i] / 4;
        if(map[block_pos.y][block_pos.x] == 1)
        {
            return false;
        }
    }
    return true;
}

bool Changeable()
{//判断是否可以变形
    int direction = (cur_shape_direction + 1) % 4;
    POINT block_pos;
    for(int i = 0;i < 4;i++)
    {//分别检查图形中的4个小块是否会与周围重叠
        block_pos.x = cur_pos.x + shape[cur_shape_num][direction][i] % 4;
        block_pos.y = cur_pos.y + shape[cur_shape_num][direction][i] / 4;
        if(map[block_pos.y][block_pos.x] == 1)
        {
            return false;
        }
    }
    return true;
}

void Update_map()
{//当图形落到底时更新坐标系
    POINT postion;
    for(int i = 0;i < 4;i++)
    {//将当前图形所在的坐标标记为1
        postion.x = cur_pos.x + shape[cur_shape_num][cur_shape_direction][i] % 4;
        postion.y = cur_pos.y + shape[cur_shape_num][cur_shape_direction][i] / 4;
        map[postion.y][postion.x] = 1;
    }
}

int Full_row()
{//判断是否有满行,有则返回行的坐标,没有返回0
    for(int i = Y_max - 2;i > 0;i--)
    {
        for(int j = 0;j< X_max;j++)
        {
            if(map[i][j]==0)
                break;
        }
        if(j==X_max)
        {
            return i;
        }
    }
    return 0;
}

void Clean_full_row(HWND hwnd,int row)
{//清楚满行
    for(int j = 1;j < X_max - 1;j++)
    {
        map[row][j] = 0;
    }
    POINT block;
    block.y = row;
    for(int i = row - 1;i > 0;i--)
    {//满行以上的所有行下移
        for(j = 1;j <X_max-1;j++)
        {
            if(map[i][j]==1)
            {
                map[i + 1][j] = map[i][j];
                map[i][j] = 0;
            }
        }
    }
    for(i = Y_max - 2;i > 0;i--)
    {//把更新过的坐标系重新画出来
        for(j = 1;j < X_max-1;j++)
        {
            block.x = j;
            block.y = i;
            COLORREF color = bg_color;
            if(map[i][j]==1)
                color = shape_color;
            Draw_block(hwnd,block,color);
        }
    }
    score += 10;//加分并显示
    Show_score(hwnd);
    if(score >= level*100)
    {//判断是否修改等级
        Change_level(hwnd);
    }

}

void Change_level(HWND hwnd)
{//修改等级
    level++;
    Show_level(hwnd);
    //修改速度
    KillTimer(hwnd,1);
    SetTimer(hwnd,1,1000/level,NULL);
}

void Pause()
{//未实现

}

void Draw_edge(HWND hwnd)
{//画出边界
    HDC hdc;
    hdc = GetDC(hwnd);
    HPEN hpen = CreatePen(PS_SOLID,1,edge_color);
    SelectObject(hdc,hpen);
    for(int i = 1;i < Y_max;i++)
    {
        MoveToEx(hdc,block_size-1,i*block_size-1,NULL);
        LineTo(hdc,(X_max-1)*block_size,i*block_size-1);
    }
    for(i = 0;i < X_max;i++)
    {
        MoveToEx(hdc,i*block_size-1,block_size-1,NULL);
        LineTo(hdc,i*block_size-1,(Y_max-1)*block_size-1);
    }
    ReleaseDC(hwnd,hdc);
}

void Show_preview(HWND hwnd)
{//显示预览图形
    POINT postion;
    postion.x = X_max + 1;
    postion.y = 3;
    Draw_shape(hwnd,cur_shape_num,0,postion,bg_color);
    Draw_shape(hwnd,pre_shape_num,pre_shape_direction,postion,shape_color);
}

void Show_score(HWND hwnd)
{//显示得分
    HDC hdc = GetDC(hwnd);
    TCHAR sc[5];
    itoa(score,sc,10);
    TextOut(hdc,(X_max+2)*block_size,13*block_size,sc,strlen(sc));
    ReleaseDC(hwnd,hdc);
}

void Show_level(HWND hwnd)
{//显示等级
    HDC hdc = GetDC(hwnd);
    TCHAR lev[2];
    itoa(level,lev,10);
    TextOut(hdc,(X_max+2)*block_size,23*block_size,lev,strlen(lev));
    ReleaseDC(hwnd,hdc);
}

bool Over()
{//判断游戏是否结束
    for(int i = 1;i < X_max - 1;i++)
    {
        if(map[1][i]==1)
            return true;
    }
    return false;
}

void Show_over(HWND hwnd)
{//这个功能还没完全写好
    RECT rc;
    SetRect(&rc,0,0,(X_max+5)*block_size,Y_max*block_size);
    HDC hdc = GetDC(hwnd);
    HBRUSH hbrush = CreateSolidBrush((bg_color));
    FillRect(hdc,&rc,hbrush);
    MessageBox(hwnd,TEXT("GameOver"),TEXT("GameOver"));
    ReleaseDC(hwnd,hdc);
    DeleteObject(hbrush);

}



默认分类 | 阅读 1202 次
文章评论,共7条
云清f淡
2011-01-19 21:59
1
很强大的
QQ724525146
2011-02-06 23:10
2
怎么用呢????<img src="image/face/24.gif" class="face">
touchsmile
2011-02-21 11:56
3
你学了多长时间C啊?
林语(作者)
2011-03-07 08:35
4
<div class="quote"><span class="q"><b>QQ724525146</b>: 怎么用呢????<img src="image/face/24.gif" class="face"></span></div>编译链接啊
林语(作者)
2011-03-07 08:35
5
<div class="quote"><span class="q"><b>touchsmile</b>: 你学了多长时间C啊?</span></div>上完课程有两年了
变幻小子
2011-03-20 19:46
6
林语(作者)
2011-05-02 17:09
7
其实有很多bug,最近改了两个。在win7上运行比较好,但是在winxp下会有bug
游客请输入验证码
浏览2124次
文章分类