| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2798 人关注过本帖
标题:俄罗斯方块游戏
只看楼主 加入收藏
gtxuq
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2008-6-12
收藏
 问题点数:0 回复次数:13 
俄罗斯方块游戏
我们以控制台程序的字符界面来实现这个游戏,规定游戏区域为10×20个单元格,宽为10,高为20,在屏幕上用20行×10列个字符(如*和空格)来代表这些单元格,每次将整个游戏区域输出,然后等待用户输入一个命令,按命令的要求进行方块的移动、旋转、清行等动作,并把新的游戏区域重新输出(输出之前清除屏幕),游戏结束后给出提示,用户可重新开始或退出程序。
要求用OO技术来进行游戏的设计:
1、 方块类:每个方块都要记录自己的ID、形状。形状采用4对整数坐标来表示,分别记录其4个小方块的相对位置
方块类主要操作:
 构造函数:参数至少有:ID和参考点初始坐标。
 填充:把自己填充到指定的游戏区域中。返回填充成功或失败的信息。
 清除:把自己从指定的游戏区域中清除。
 移动:在指定的游戏区域中移动,包括向左、右、下移动,以1个单元格为单位。返回是否移动成功的信息。
 旋转:在指定的游戏区域中旋转一次,然后在指定的游戏区域中重新填充自己
 获得占用行:返回本方块4个小方块所占用的各行
2、 游戏区域类
其主要属性:游戏区域数据,状态:游戏未开始(初态)和游戏已开始。
主要操作为:
 游戏区域读写:指定游戏区域的一个单元格坐标后,返回或设置单元格的值。
 绘制:清除屏幕后将游戏区域绘制出来。
 命令处理:命令为一个字符串,格式自定。要求实现如下命令:
 游戏开始:当接收到此命令时,将状态切换为游戏已开始。
 方块左移、右移、旋转:对活动方块调用相应的操作,不论是否能移动成功都重新绘制本游戏区域,如果移动失败绘制完毕后给出文字提示信息。为增加游戏难度,可以在执行几次左右移或旋转后自动执行“方块下移”命令。
 方块下移:对活动方块调用相应的操作,如果移动成功,则重新绘制本游戏区域后操作结束,如果移动失败,则说明方块已经掉到最下面,需要执行方块落地操作。
方块落地:
 先执行清行操作:获得活动方块占用了哪些行的信息,然后逐行进行扫描:可以每清除一行就重新绘制一次游戏区域,获得动画效果。
 执行完清行操作后,要产生下一个方块,此时要把活动方块指定为新产生的方块,而且还要检查新产生的方块是否能成功填充,如果填充失败,说明游戏结束,此时将游戏区域状态恢复为游戏未开始,抛出异常通知游戏结束(类型自定),但在本类内不处理该异常,让类的使用者处理。
3、 程序总体流程
程序运行后,生成一个游戏区域类对象,然后不停地接收用户输入的命令,并进行处理,格式自定。
 游戏开始命令。此命令被转发给游戏区域处理。
 退出命令。用户可直接退出程序。
 方块左移、右移、旋转、下移命令:转发给游戏区域处理。注意,由于此时游戏区域对象的函数可能会抛出异常表示游戏结束,所以需要捕获这些异常。捕获到异常时说明游戏结束,此时提问用户是退出还是继续游戏,用户要求退出则退出程序,如果要求继续游戏则执行一次“ 游戏开始命令”即可。
4、 如果有兴趣可加上分数的计算功能。

请问哪位大哥可以帮着设计一下?
搜索更多相关主题的帖子: 俄罗斯方块 游戏 
2008-06-12 20:29
gtxuq
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2008-6-12
收藏
得分:0 
咋没个人帮忙一下?
2008-06-13 22:46
sunkaidong
Rank: 4
来 自:南京师范大学
等 级:贵宾
威 望:12
帖 子:4496
专家分:141
注 册:2006-12-28
收藏
得分:0 
你到c区看看前几天有人写过。。。

学习需要安静。。海盗要重新来过。。
2008-06-13 23:01
Elten
Rank: 1
来 自:洛阳
等 级:新手上路
威 望:1
帖 子:27
专家分:4
注 册:2007-11-23
收藏
得分:0 
试试

divide and conquer  ;  stepwise refinement
2008-06-13 23:13
wanghepeng10
Rank: 1
等 级:新手上路
帖 子:41
专家分:0
注 册:2008-5-7
收藏
得分:0 
嗨,小的初学啊,想写简直是登天啊。
2008-06-14 01:24
liuyc
Rank: 1
等 级:新手上路
帖 子:29
专家分:0
注 册:2008-6-12
收藏
得分:0 
有同感!
2008-06-14 15:33
gtxuq
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2008-6-12
收藏
得分:0 
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <assert.h>
#include <limits.h>

#ifdef _DEBUG
#define verify(f)    assert(f)
#else
#define verify(f)    ((void)(f))
#endif

class Console // 控制台
{
    friend class Window;
public:
    // title: 控制台标题
    // point: 控制台宽度和高度
    void Open( const char* title, COORD wl )
    {
        assert( wl.X>0 && wl.Y>0 );
        verify( (hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE ); // 获得输出句柄
        verify( SetConsoleTitle( title ) );                        // 设置标题
        CONSOLE_CURSOR_INFO cci = { 25, FALSE };
        verify( SetConsoleCursorInfo( hStdOutput, &cci ) );        // 去处光标
        SMALL_RECT wrt = { 0, 0, wl.X-1, wl.Y-1 };
        verify( SetConsoleWindowInfo( hStdOutput, TRUE, &wrt ) );  // 设置窗体尺寸
        coord = wl;                                      
        verify( SetConsoleScreenBufferSize( hStdOutput, coord ) ); // 设置缓冲尺寸
    }
private:
    HANDLE hStdOutput;
    COORD  coord;
};

class Window // 窗体是控制台的一个子部分
{
public:
    // wrect: 窗体左上角坐标,右下角坐标
    void Open( Console& console, SMALL_RECT wrect )
    {
        assert( wrect.Left < wrect.Right && wrect.Top < wrect.Bottom );
        assert( wrect.Left>=0 && wrect.Right<=console.coord.X );
        assert( wrect.Top>=0 && wrect.Bottom<=console.coord.Y );
        pcon = &console;
        wrt = wrect;
    }
    // x,y: 相对于窗体的坐标
    // color: 字体和背景颜色
    // str: 欲输出字符串,遇0或达到len数量则结束,没考虑控制字符,比如\r等
    void Output( short x, short y, WORD color, const char* str, size_t len=INT_MAX )
    {
        assert( x>=0 && x<=wrt.Right-wrt.Left && y>=0 && y<=wrt.Bottom-wrt.Top );
        COORD c = { wrt.Left+x, wrt.Top+y };
        DWORD n = 0;
        WORD cs[2] = { color, color };
        for( const char* p=str; len!=0 && *p!=0; --len,++p,++c.X  )
        {
            if( c.X >= wrt.Right ) // 换行
            {
                c.X = wrt.Left+x;
                ++c.Y;
                assert( c.Y < wrt.Bottom );
            }
            if( *p > 0 ) // 单字节字符
            {
                verify( WriteConsoleOutputCharacter( pcon->hStdOutput, p, 1, c, &n ) && n==1 );
                verify( WriteConsoleOutputAttribute( pcon->hStdOutput, cs, 1, c, &n ) && n==1 );
            }
            else // 双字节字符
            {
                assert( len>=2 && *(p+1)!=0 && (c.X+1)<wrt.Right );
                verify( WriteConsoleOutputCharacter( pcon->hStdOutput, p, 2, c, &n ) && n==2 );
                verify( WriteConsoleOutputAttribute( pcon->hStdOutput, cs, 2, c, &n ) && n==2 );
                --len,++p,++c.X;
            }
        }
    }
private:
    Console*  pcon;
    SMALL_RECT wrt;
};
2008-06-15 23:53
gtxuq
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2008-6-12
收藏
得分:0 
class RussiaDiamonds
{
public:
    // x,y: 左上角坐标,右下角坐标
    RussiaDiamonds( Console& console, short x, short y )
    {
        SMALL_RECT wrect = { x, y, x+38, y+21 };
        win.Open( console, wrect );
    }

    // 分别是 开始,暂停,声效,变形,左移,右移,下移,落地 键的键码, 声效频率, 延续时间
    // Example:
    //  A   键为 0x41,      用0x00000041 表示
    //  F1  键为 0x00,0x3B, 用0x00003800 表示
    //  F11 键为 0xE0,0x85, 用0x000085E0 表示
    void Open( int ctrlkeys[8], char ctrlkeydecs[8][5], DWORD frequency, DWORD duration )
    {
        memcpy( keys, ctrlkeys, sizeof(keys) );
        memcpy( decs, ctrlkeydecs, sizeof(decs) );
        freq = frequency, dura =duration;

        gameover = false;
        pause = true;
        voice = true;
        score = 0, level = 0;
        memset( data, 0, sizeof(data) );
        srand( time(0) );
        next = rand()%7;
        x=4, y=-2, c=-1, z=0;

        win.Output( 0, 0, COLOR_B, bg+0, 38 );
        for( int i=1; i<20; ++i )
        {
            win.Output( 0, i, COLOR_B, bg+38*i+0, 2 );
            win.Output( 2, i, COLOR_C, bg+38*i+2, 22 );
            win.Output( 24, i, COLOR_B, bg+38*i+24, 14 );
        }
        win.Output( 0, 20, COLOR_B, bg+38*20, 38 );
        for( int j=0; j<8; ++j )
            win.Output( 33, j+7, COLOR_B, decs[j], 4 );

        DrawNext();
    }

    bool IsRun() const
    {
        return !gameover && !pause;
    }
    int Level() const
    {
        return level;
    }

    bool Down( void )
    {
        return MessageDeal( keys[6] );
    }
2008-06-15 23:54
gtxuq
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2008-6-12
收藏
得分:0 
// 游戏结束返回 false
    bool MessageDeal( const int k )
    {
        if( gameover )
        {
            if( k == keys[0] ) // 重新开始
            {
                Open( keys, decs,freq, dura );
                return true;
            }
            return false;
        }

        if( pause ) // 暂停
        {
            if( k == keys[0] )      // 开始
            {
                pause = false;
                if( c == -1 )
                {
                    c = next;
                    next = rand()%7;
                    DrawNext();
                }
            }
            else if( k == keys[2] ) // 声效
                voice = !voice;
            else
                return true;
            VoiceBeep();
            return true;
        }

        if( k == keys[1] )      // 暂停
            pause = true;
        else if( k == keys[3] ) // 变形
            MoveTrans();
        else if( k == keys[4] ) // 左移
            MoveLeft();
        else if( k == keys[5] ) // 右移
            MoveRight();
        else if( k == keys[6] ) // 下移
            { if( 0 == MoveDown() ) return false; }
        else if( k == keys[7] ) // 落地
            { if( !MoveDownDown() ) return false; }
        else if( k == keys[2] ) // 声效
            voice = !voice;
        else
            return true;
        VoiceBeep();
        return true;
    }

private:
    void VoiceBeep( void ) // 声效
    {
        if( voice ) Beep( freq, dura );
    }
    void DrawScoreLevel( void ) // 绘制得分
    {
        char tmp[6];
        sprintf( tmp, "%05d", score );
        win.Output( 31, 19, COLOR_B, tmp, 5 );
        sprintf( tmp, "%1d", level );
        win.Output( 28, 19, COLOR_B, tmp, 1 );
    }
    void DrawNext( void )  // 绘制 "next框" 中的图形
    {
        for( int i=0; i<2; ++i )
            for( int j=0; j<4; ++j )
                win.Output( 28+j*2, 1+i, COLOR_B, bk[next][0][i][j]==0?" ":"■", 2 );
    }
    void DrawOver( void )  // 游戏结束
    {
        win.Output( 28, 1, COLOR_B, "GAME" );
        win.Output( 28, 2, COLOR_B, "OVER" );
    }
    void Draw( WORD color )
    {
        for( int i=0; i<4; ++i )
        {
            if( y+i<0 || y+i>= 19 ) continue;
            for( int j=0; j<4; ++j )
                if( bk[c][z][i][j] == 1 )
                    win.Output( 2+x*2+j*2, 1+y+i, color, "■", 2 );
        }
    }
2008-06-16 00:11
gtxuq
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2008-6-12
收藏
得分:0 
bool IsFit( int x, int y, int c, int z ) // 给定的x,y,c,z是否可行
    {
        for( int i=0; i<4; ++i )
        {
            for( int j=0; j<4; ++j )
            {
                if( bk[c][z][i][j]==1 )
                {
                    if( y+i < 0 ) continue;
                    if( y+i>=19 || x+j<0 || x+j>=11 || data[y+i][x+j]==1 ) return false;
                }
            }
        }
        return true;
    }
    void RemoveRow( void ) // 消行
    {
        const char FULLLINE[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
        int linecount = 0;
        for( int i=0; i<19; ++i )
        {
            if( 0 == memcmp( data[i], FULLLINE, 11 ) )
            {
                ++linecount;
                for( int m=0; m<11; ++m )
                {
                    for( int n=i; n>1; --n )
                    {
                        data[n][m] = data[n-1][m];
                        win.Output( 2+m*2, 1+n, data[n][m]==1?COLOR_B:COLOR_C, "■", 2 );
                    }
                    data[0][m] = 0;
                    win.Output( 2+m*2, 1, COLOR_C, "■", 2 );
                }
            }
        }
        char data[19][11] = { 0 };

        if( linecount == 0 ) return;
        int _score = 0;
        switch( linecount )
        {
        case 1: _score =  100; break;
        case 2: _score =  300; break;
        case 3: _score =  700; break;
        case 4: _score = 1500; break;
        }
        score += _score;
        if( score > 99999 ) score = 99999;
        level = score/10000;
        DrawScoreLevel();
    }
2008-06-16 00:12
快速回复:俄罗斯方块游戏
数据加载中...
 
   



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

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