标题:第三个游戏俄罗斯方块出来了
取消只看楼主
Fisher~
Rank: 4
等 级:业余侠客
帖 子:93
专家分:222
注 册:2012-11-10
结帖率:100%
 问题点数:0 回复次数:3 
第三个游戏俄罗斯方块出来了
看了三天,昨天写了一天有问题没弄出来,今天下午重写一下午完成,当然还有之前看的基础才能一气呵成,所有的代码和exe还有工程文件都在压缩包里,有兴趣看看把,这是连接地址L:
http://pan.baidu.com/share/link?shareid=4198653437&uk=2988506976
这是截图
程序代码:
/*************************************
** 程序名称:俄罗斯方块                **
** 编译环境:vs2012                    **
** 编辑作者:往事随风<1034882113>    **
** 最后修改:2013-07-24                **
** 项目类型:win32控制台程序        **
**************************************/

#include<graphics.h>
#include<conio.h>        // _kbhit() _getch()
#include<time.h>

/****************** 宏定义区   **********************/
#define GAME_ROW    20            // 游戏区行数
#define GAME_COL    10            // 游戏区列数
#define BLOCK_SIZE    20            // 每个游戏区单位像素大小
#define MENU_LEN    400            // 菜单界面长度
#define MENU_WIDE    440            // 菜单界面宽度

/****************** 数据类型定义区 ******************/
enum CMD
{
    CMD_UP,                                // 上方向键
    CMD_LEFT,CMD_RIGHT,CMD_DOWN,        // 左右下方向将
    CMD_SINK,                            // 沉底(空格)
    CMD_QUIT                            // 退出
};

enum DRAW
{
    SHOW,        // 显示
    HIDE,        // 隐藏
    FIX            // 固定
};

struct block
{
    WORD dir[4];        // 16位短整形 存储四个变形
    COLORREF color;
}Block[7] = {    {0x0F00, 0x4444, 0x0F00, 0x4444, RED},        // I
{0x0660, 0x0660, 0x0660, 0x0660, BLUE},        //
{0x4460, 0x02E0, 0x0622, 0x0740, MAGENTA},    // L
{0x2260, 0x0E20, 0x0644, 0x0470, YELLOW},    // 反L
{0x0C60, 0x2640, 0x0C60, 0x2640, CYAN},        // Z
{0x0360, 0x4620, 0x0360, 0x4620, GREEN},    // 反Z
{0x4E00, 0x4C40, 0x0E40, 0x4640, BROWN}};    // T;

struct blockinfo
{
    byte id;        // 确定基本形状
    char x,y;        // 在游戏区的坐标
    byte dir:2;        // 四个变形
}Cur_Block,Next_Block;

byte Block_Map[GAME_ROW][GAME_COL];

/****************** 全局变量区 **********************/
static int Sc_length = BLOCK_SIZE*(GAME_COL+8)+10;    // 屏幕总长    // 窗口边框占了10像素
static int Sc_height = BLOCK_SIZE*GAME_ROW+10;        // 屏幕总高
IMAGE img_border[2];                                // 屏幕中的边框    (0:左边框右边框 1:右边横边框)
IMAGE img_bk;                                        // 屏幕中的背景图片
IMAGE img_block[2];                                    // 方格图片
IMAGE img_nextbk;                                    // 预览方块背景
IMAGE img_menu;
IMAGE img_textbk;
DWORD old_time;                                        //
int    score = 0;                                        // 分数
DWORD speed = 500;                                    // 速度                        

/****************** 函数声明区 **********************/
void print_tips();
void gameOption();
void gameDeclare(void);
void getMouse(POINT *point);
void print_menu(void);
void init_img();
void init_window();
void quit_game();
void game_over();
void new_game();
void new_block();
void draw_block(blockinfo _block,DRAW draw = SHOW);
bool check_border(blockinfo _block);
CMD get_cmd();
void DispatchCmd(CMD _cmd);
void click_left();
void click_right();
void click_up();
void click_down();
void click_space();
void game_begin();
void game_score(int count);
void print_score(int score);

/****************** 函数定义区 **********************/

/* 打印分数 */
void print_score(int score)
{
    char cscore[5] = "0";
    char cspeed[4] = "0";
    int i = 0;

    _itoa(score,cscore,10);
    _ltoa(speed,cspeed,10);
    // 显示分数
    putimage(BLOCK_SIZE*(GAME_COL+1),BLOCK_SIZE*7,&img_textbk);
    settextcolor(MAGENTA);
    setbkmode(TRANSPARENT);                    // 设置文字背景透明
    outtextxy(BLOCK_SIZE*(GAME_COL+2),BLOCK_SIZE*10,_T("分数:"));
    outtextxy(BLOCK_SIZE*(GAME_COL+2),BLOCK_SIZE*14,_T("速度:"));
    while (cscore[i])
        outtextxy(BLOCK_SIZE*(GAME_COL+3)+8*i,BLOCK_SIZE*12,cscore[i++]);
    i = 0;
    while (cspeed[i])
    outtextxy(BLOCK_SIZE*(GAME_COL+3)+8*i,BLOCK_SIZE*16,cspeed[i++]);
}

/* 计算游戏分数并设置游戏速度 */
void game_score(int count)
{
    switch (count)
    {
    case 1:    score += 10; break;
    case 2:    score += 20; break;
    case 3:    score += 40; break;
    case 4: score += 80; break;
    }
    if (score >= 1000)
        speed = 200;
    if (speed >= 5000)
        speed = 100;
    print_score(score);
}

/* 开始游戏 */
void game_begin()
{
    CMD c;   
    init_window();
    while (true)
    {
        c = get_cmd();
        DispatchCmd(c);
        if (c == CMD_QUIT)   
        {
            HWND wnd = GetHWnd();
            if (MessageBox(wnd, _T("您要退出游戏吗?"), _T("提醒"),
            MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
            quit_game();
        }
    }
}

/* 空格键沉底 */
void click_space()
{
    int x =0,y = 0,i = 0;

    // 连续下移方块
    draw_block(Cur_Block,HIDE);
    blockinfo tmp = Cur_Block;        //
    tmp.y++;
    while (check_border(tmp))
    {   
        Cur_Block.y++;
        tmp.y++;
    }
    draw_block(Cur_Block,FIX);

    // 固定在游戏区
    WORD b = Block[Cur_Block.id].dir[Cur_Block.dir];    // 确定形状
    for (i = 0; i < 16; i++)
    {
        if (b & 0x8000)
        {
            x = Cur_Block.x + i%4;
            y = Cur_Block.y + i/4;
            if (y < 0)
            {
                game_over();
                return;
            }
            else Block_Map[y][x] = 1;        /*******************/
        }
        b <<= 1;
    }

    // 判断是否可以消行并标记
    int row[4] = {0};
    bool bRow = false;
    for (y = Cur_Block.y; y <= max(Cur_Block.y + 3,GAME_ROW); y++)    // 每一行
    {
        i = 0;
        for (x = 0; x < GAME_COL; x++)    // 每一列
            if (Block_Map[y][x])
                i++;
        if (i == GAME_COL)
        {
            bRow = true;
            row[y - Cur_Block.y] = 1;        // 从上往下消行
        }
    }

    // 取消标记
    if (bRow)
    {
        Sleep(200);
        IMAGE img;        // 截图
        int count = 0;
        for (i = 0; i < 4; i++)
        {
            if (row[i])
            {
                count++;        // 判断消得行数
                for (y = Cur_Block.y+i-1; y > 0; y--)
                    for (x = 0; x < GAME_COL; x++)
                    {
                        Block_Map[y+1][x] = Block_Map[y][x];        //
                        Block_Map[y][x] = 0;
                    }
                    getimage(&img,0,0,BLOCK_SIZE*GAME_COL,BLOCK_SIZE*(Cur_Block.y+i));    //
                    putimage(0,BLOCK_SIZE,&img);
            }
        }
        game_score(count);
    }
    new_block();
}

/* 上方向键 */
void click_up()
{
    blockinfo tmp = Cur_Block;        //
    int dx = 0;

    tmp.dir++;                    if (check_border(tmp))    { dx = 0;  goto rota; }
    tmp.x = Cur_Block.x + 1;    if (check_border(tmp))    { dx = 1;  goto rota; }
    tmp.x = Cur_Block.x - 1;    if (check_border(tmp))    { dx = -1; goto rota; }
    tmp.x = Cur_Block.x + 2;    if (check_border(tmp))    { dx = 2;  goto rota; }
    tmp.x = Cur_Block.x - 2;    if (check_border(tmp))    { dx = -2; goto rota; }
    return;

rota:
    draw_block(Cur_Block,HIDE);
    Cur_Block.dir++;
    Cur_Block.x += dx;
    draw_block(Cur_Block);
}

/* 下方向键 */
void click_down()
{
    blockinfo tmp = Cur_Block;        //
    tmp.y++;
    if (check_border(tmp))
    {
        draw_block(Cur_Block,HIDE);
        Cur_Block.y++;
        draw_block(Cur_Block);
    }
    else click_space();
}

/* 右方向键 */
void click_right()
{
    blockinfo tmp = Cur_Block;        //
    tmp.x++;
    if (check_border(tmp))
    {
        draw_block(Cur_Block,HIDE);
        Cur_Block.x++;
        draw_block(Cur_Block);
    }
}

/* 左方向键 */
void click_left()
{
    blockinfo tmp = Cur_Block;        //
    tmp.x--;
    if (check_border(tmp))
    {
        draw_block(Cur_Block,HIDE);
        Cur_Block.x--;
        draw_block(Cur_Block);
    }
}

// 分发控制命令
void DispatchCmd(CMD _cmd)
{
    switch(_cmd)
    {
    case CMD_UP:        click_up();            break;
    case CMD_LEFT:        click_left();        break;
    case CMD_RIGHT:        click_right();        break;
    case CMD_DOWN:        click_down();        break;
    case CMD_SINK:        click_space();        break;
    case CMD_QUIT:        break;
    }
}

/* 获取控制命令 */
CMD get_cmd()
{
    // 获取控制值
    while(true)
    {
        // 如果超时,自动下落一格
        DWORD new_time = GetTickCount();
        if (new_time - old_time >= speed)
        {
            old_time = new_time;
            return CMD_DOWN;
        }

        // 如果有按键,返回按键对应的功能
        if (_kbhit())
        {
            switch(_getch())
            {
            case 'w':
            case 'W':    return CMD_UP;
            case 'a':
            case 'A':    return CMD_LEFT;
            case 'd':
            case 'D':    return CMD_RIGHT;
            case 's':
            case 'S':    return CMD_DOWN;
            case 27:    return CMD_QUIT;
            case ' ':    return CMD_SINK;
            case 0:
            case 0xE0:
                /* 这个是标识一次按键将会返回两个16位整数的特殊值。一旦你扫描键盘按键,
                返回值(比如_getch()的返回值)是0xE0的话,那么预示着后面还有一个整数等
                待返回,你需要再调用一次_getch()获得那个返回值,前后两个返回值合并构成
                一个32位的整数值,才是那个按键的完整代码。通常是按下控制键时会出现这个
                现象,比如Ctrl+键、PgUp/PgDn等,都会这样。也就是说,键盘按键,有些键是
                返回16位整数的,有些是返回32位整数的,后者的高位必定是0xE0。这跟汉字的
                编码与ASCII编码有区别,是同一个道理。在C语言编程中,如果使用_getch()函
                数接收键盘按键,那么就要分析其返回值是否0xE0,如果是,则必须再调用一
                次_getch(),否则缓冲区中会残留数据,也影响程序的正常运作 */
                switch(_getch())
                {
                case 72:    return CMD_UP;
                case 75:    return CMD_LEFT;
                case 77:    return CMD_RIGHT;
                case 80:    return CMD_DOWN;
                }
            }
        }
        // 延时 (降低 CPU 占用率)
        Sleep(20);
    }
}

/* 判断越界 */
bool check_border(blockinfo _block)
{
    WORD tmp = Block[_block.id].dir[_block.dir];    // 确定具体形状
    int x = 0, y = 0;

    for (int i = 0; i < 16; i++)
    {
        if (tmp & 0x8000)
        {
            x = _block.x + i%4;
            y = _block.y + i/4;

            if (x < 0 || x >= GAME_COL || y >= GAME_ROW)
                return false;
            if (y >= 0 && Block_Map[y][x])            //
                return false;
        }
        tmp <<= 1;
    }
    return true;
}

/* 画出一个方块 */
void draw_block(blockinfo _block,DRAW draw)
{
    WORD tmp = Block[_block.id].dir[_block.dir];    // 确定具体形状
    int x = 0,y = 0;                // 记录临时坐标

    for (int i = 0; i < 16; i++)
    {
        if (tmp & 0x8000)            // 此行都为0没有方块
        {
            x = _block.x + i%4;
            y = _block.y + i/4;
            if (y >= 0)
            {
                if (draw == HIDE)    // 擦除
                    putimage(x*BLOCK_SIZE,y*BLOCK_SIZE,&img_block[1]);
                else putimage(x*BLOCK_SIZE,y*BLOCK_SIZE,&img_block[0]);
            }
        }
        tmp <<= 1;
    }
}

/* 产生新的方块 */
void new_block()
{
    // 产生当前屏幕中要出现的方块
    Cur_Block.id = Next_Block.id;
    Cur_Block.dir = Next_Block.dir;
    Cur_Block.x = (GAME_COL-4)/2;
    Cur_Block.y = -3;

    // 产生新的预览方块
    Next_Block.id = rand()%7;
    Next_Block.dir = rand()%4;

    // 下移方块直到显示局部
    WORD tmp = Block[Cur_Block.id].dir[Cur_Block.dir];
    while ((tmp & 0xF) == 0)
    {
        Cur_Block.y++;
        tmp >>= 4;
    }

    // 画出屏幕中的方块
    draw_block(Cur_Block);

    // 画出新的预览方块
    putimage((GAME_COL+1)*BLOCK_SIZE,0,&img_nextbk);
    draw_block(Next_Block);

    // 设置计时器判断方块下落
    old_time = GetTickCount();
}

/* 新的游戏 */
void new_game()
{
    // 初始化游戏
    putimage(0,0,&img_bk);                            // 清空游戏屏幕
    ZeroMemory(Block_Map,GAME_ROW*GAME_COL);        // 重置地图标志

    // 产生新的预览方块
    Next_Block.id = rand()%7;
    Next_Block.dir = rand()%4;
    Next_Block.x = GAME_COL+2;
    Next_Block.y = 1;

    // 画出新的预览方格
    draw_block(Next_Block);

    // 产生新的方块
    new_block();
}

/* 游戏失败 */
void game_over()
{
    HWND wnd = GetHWnd();
    if (MessageBox(wnd, _T("游戏结束。\n您想重新来一局吗?"), _T("游戏结束"),
        MB_YESNO | MB_ICONQUESTION) == IDYES)
        new_game();
    else
        quit_game();
}

/* 退出游戏 */
void quit_game()
{
    closegraph();
    exit(0);
}

/* 初始化游戏窗口数据 */
void init_window()
{
    initgraph(Sc_length,Sc_height);       
    setbkcolor(DARKGRAY);
    cleardevice();

    srand((unsigned)time(NULL));

    putimage(BLOCK_SIZE,0,&img_bk);                                    // 输出背景图片
    putimage(0,0,&img_border[0]);                                    // 输出最左边边界
    putimage(BLOCK_SIZE*(GAME_COL+1),0,&img_border[0]);                // 输出右边边界
    putimage(BLOCK_SIZE*(GAME_COL+2),BLOCK_SIZE*6,&img_border[1]);    // 输出右边横边框

    setorigin(BLOCK_SIZE,0);        // 设置坐标原点
    print_score(score);
    new_game();
}

/* c初始化图片资源 */
void init_img()
{   
    loadimage(&img_block[0],_T("./res/tetris0.bmp"),BLOCK_SIZE,BLOCK_SIZE,true);
    loadimage(&img_block[1],_T("./res/tetris1.jpg"),BLOCK_SIZE,BLOCK_SIZE,true);
    loadimage(&img_bk,_T("./res/bk.jpg"),BLOCK_SIZE*GAME_COL,BLOCK_SIZE*GAME_ROW,true);   
    loadimage(&img_border[0],_T("./res/border.bmp"),BLOCK_SIZE,BLOCK_SIZE*GAME_ROW,true);   
    loadimage(&img_border[1],_T("./res/dborder.bmp"),BLOCK_SIZE*6,BLOCK_SIZE,true);
    loadimage(&img_nextbk,_T("./res/nextbk.jpg"),BLOCK_SIZE*6,BLOCK_SIZE*6,true);
    loadimage(&img_menu,_T("./res/menu.jpg"),MENU_LEN,MENU_WIDE,true);
    loadimage(&img_textbk,_T("./res/textbk.jpg"),BLOCK_SIZE*6,BLOCK_SIZE*13,true);
}

/* 输出提示信息 */
void print_tips()
{
    outtextxy(150,400,_T("按任意键返回"));
    _getch();
}

/* 游戏版本信息 */
void gameOption()
{
    int x = 140,y = 50;

    putimage(0,0,&img_menu);
    setcolor(BLUE);                                // 设置字体颜色
    outtextxy(x,y,_T("俄罗斯方块"));
    outtextxy(x,y+80,_T("版本:1.0"));
    outtextxy(x-60,y+120,_T("由往事随风<1034882113>制作"));
    print_tips();
}

/* 游戏说明 */
void gameDeclare(void)
{
    int x = 140,y = 80;

    putimage(0,0,&img_menu);
    outtextxy(170,40,_T("游戏说明"));
    outtextxy(x,y,_T("↑:变换形状"));
    outtextxy(x,y+40,_T("↓:加速向下移动"));
    outtextxy(x,y+80,_T("←:向左移动"));
    outtextxy(x,y+120,_T("→:向右移动"));
    print_tips();
}

/* 得到鼠标坐标 */
void getMouse(POINT *point)
{
    HWND hwnd = GetHWnd();        // 获取绘图窗口句柄
    MOUSEMSG msg;

    FlushMouseMsgBuffer();
    while (true)                                    // 等待鼠标点击
    {
        msg = GetMouseMsg();
        if (msg.uMsg ==WM_LBUTTONDOWN)
        {
            GetCursorPos(point);                    // 获取鼠标指针位置(屏幕坐标)
            ScreenToClient(hwnd,point);                // 将鼠标指针位置转换为窗口坐标
            break;
        }
    }
}

/* 输出游戏菜单 */
void print_menu(void)
{
    int x  = MENU_LEN / 3,y = MENU_WIDE / 5;

    initgraph(MENU_LEN,MENU_WIDE);
    putimage(0,0,&img_menu);

    setfillcolor(RED);
    fillrectangle(x,y,x * 2,y * 4);

    setbkmode(TRANSPARENT);                    // 设置文字背景透明
    outtextxy(x+60,y + 40,_T("菜单"));        // x为133,y为88
    outtextxy(x+30,y+80,_T("开始新游戏"));    // 一个字占的长宽分别为15
    outtextxy(x+40,y+120,_T("游戏说明"));
    outtextxy(x+40,y+160,_T("关于游戏"));
    outtextxy(x+40,y+200,_T("退出游戏"));
}

/****************** 主函数区   **********************/
void main()
{
    POINT point;                                // 存储坐标位置

    init_img();
    srand((unsigned)time(NULL));                // 产生随机种子

    while (true)
    {       
        print_menu();
        getMouse(&point);
        if (point.x > 163 && point.x < 238)        // 菜单范围
        {
            if (point.y >168 && point.y < 182)    // 开始游戏
            {
                closegraph();
                game_begin();
            }           
            else if (point.y > 208 && point.y < 222)    // 游戏说明
                gameDeclare();
            else if (point.y >248 && point.y < 262)        // 关于游戏
                gameOption();
            else if (point.y > 288 && point.y < 305)    // 退出游戏
                {
                    HWND wnd = GetHWnd();
                    if (MessageBox(wnd, _T("您要退出游戏吗?"), _T("提醒"),
                        MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
                        quit_game();
                }
        }
        else ;        /*********键盘操作*******/
    }
}


[ 本帖最后由 Fisher~ 于 2013-7-24 02:23 编辑 ]
搜索更多相关主题的帖子: 俄罗斯方块 压缩包 
2013-07-24 02:22
Fisher~
Rank: 4
等 级:业余侠客
帖 子:93
专家分:222
注 册:2012-11-10
得分:0 
回复 2楼 丶弱水彡千
让有兴趣的帮忙测试一下看有什么bug,一个人能想到的毕竟有限
2013-07-24 10:14
Fisher~
Rank: 4
等 级:业余侠客
帖 子:93
专家分:222
注 册:2012-11-10
得分:0 
回复 4楼 岁月如刀
额mfc我一直想学可惜没有学,那个还是挺高端的,我这比较简单
2013-07-24 13:50
Fisher~
Rank: 4
等 级:业余侠客
帖 子:93
专家分:222
注 册:2012-11-10
得分:0 
回复 9楼 thomashj
点击relase版的exe因为我用的是vs2012版本比较高,你们机子上没有,或者你可以把代码复制一份重新建个工程编译,还有就是可以下载那个dll文件放在system32文件夹下
2013-07-29 12:37



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-417860-1-1.html




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

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