源代码下载地址:http://download.csdn.net/detail/qq_29187355/9855657

1 题目要求

设计一个双人俄罗斯方块游戏

2 功能需求

(1)   实现双人俄罗斯方块

(2)   实现下一个砖块预测功能

(3)  隐藏工具栏、状态栏

(4)  实现难度可以选择

(5)   添加游戏说明菜单 添加作者菜单 添加网址超链接

(6)   实现砖块三维化

(7)   实现总分统计功能,和每步消除所得分数显示

(8)   实现背景音乐播放功能

(9)   暂停功能

(10) 增加了新的方块类
(11) 设置窗口大小,禁用最大化按钮,禁止鼠标拖动改变窗口大小。

3 总体设计

1.矩形框类的设计:

设计CBin类描述Tetris游戏的矩形框,用image的二维数组来描述这个矩形框。设置不同的值显示不同颜色的矩形,若没有砖块则为0。

2.砖块的设计:

设计CBrick抽象类来设计砖块,应用多态性的原理,其他不同类型的砖块类继承CBrick,来设计不同的砖块。

3.砖块在面板中的显示设计:

在视图类中设计并显示砖块。

4 详细设计

CBin类:

函数名称

函数说明

CBin(unsigned int w, unsigned int h)

构造函数,用来初始化数据成员

width  和 height ,并为image 分配空间并初始化。

~CBin()

析构函数,删除在构造函数中为

image分配的空间。

void getImage(unsigned char**

destImage)

将image 的数据拷贝到 destImage.

你可以假设destImage 指向的空间足够容纳image

void setImage(unsigned char**

srcImage)

把srcImage  中的数据拷贝到image.

你可以假设srcImage 是一个合法的指针

unsigned int removeFullLines()

检查image ,如果任何一行完全填

满,则删除这一行,并让上面行的

数据下移一行,返回删除的总行数。

详细代码:

#include"stdafx.h"
#include "bin.h"  //" "从自己编写的头文件中找,<>从系统自带头文件中找.
CBin
CBin::CBin(unsigned int w, unsigned int h)
{
width=w;
height=h;
image = new unsigned char* [height];
for (unsigned int i = 0; i0; m--)
{
for (j=0; j

CBrick类

设计CBrick抽象类来设计砖块。

CBrick类的成员函数:

        virtual int shiftLeft(CBin*bin)=0;      //将砖块在游戏的矩形框内左移一位       

        virtual int shiftRight(CBin* bin)=0;     //将砖块在游戏的矩形框内右移一位

        virtual int shiftDown(CBin* bin)=0;     //将砖块在游戏的矩形框内下移

        virtual int rotateClockwise(CBin* bin)=0;           //将砖块在游戏的矩形框内顺时针旋转

        virtual int checkCollision(CBin* bin)=0;          //检查砖块是否冲突

        virtual void operator>>(unsigned char**binImage)=0;     //重载运算符>>,通过设置映射到游戏矩形的二维数组binImage,设置砖块的颜色,这里假设binimage是一个合适的二维数组。

      virtual void putAtTop(int newOrient, int newPosX)=0;   //置顶

应用多态性的原理,其他不同类型的砖块类继承CBrick,来设计不同的砖块

共设计了七种不同类型的砖块。

可视化设计:

在视图类中设计并显示砖块。

(1).定义相关的变量并在构造函数中初始化。

部分代码如下:

public:
CNewTetrisDoc* GetDocument();
COLORREF GetLightColor(COLORREF m_crBody);
COLORREF GetDarkColor(COLORREF m_crBody);
面板 1///
CBin*bin;       //定义游戏矩形框指针
CBrick*activeBrick;      //定义指向当前下落砖块的指针
int gameOver;      //判断游戏是否结束
int brickInFlight;          //判断砖块是否处于下落状态
int brickType;       //砖块类别
unsigned int initOrientation;      //初始状态
int notCollide;       //冲突否
unsigned int numLines;      //消的行数
unsigned char**outputImage;
int difficulty;  //定义难度
void DrawImage(CBin*bin,CBin *bin2,unsigned char** image,unsigned char** image2,unsigned char**imageY1,
unsigned char **imageY2,CDC *pDC);
(初始化省略)

(2).添加DrawImage(CBin *bin,CBin *bin2,unsignedchar** image,unsigned char** image2,unsigned char **imageY1,unsigned char**imageY2,CDC *pDC)函数,用来绘制游戏砖块。

部分代码如下:

unsigned intwidth,i,j; unsigned int height; width=bin->getWidth();height=bin->getHeight();
int nSize = 20; //砖块大小
CRect rect;
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP3); //加载位图
CBrush brush;
brush.CreatePatternBrush(&bitmap);
GetClientRect(&rect);
pDC->FillRect(rect,&brush);
/*       pDC->FillSolidRect(rect,RGB(255,255,255));       //绘制背景色*/
/*       pDC->Rectangle(100,0,300,400); */
char buf[100];
sprintf(buf,"玩家一:分数:%d",numLines*10);
pDC->TextOut(300,20,buf);
/*       pDC->Rectangle(450,0,650,400); */
char buf2[100];
sprintf(buf2,"玩家二:分数:%d",numLines2*10);
pDC->TextOut(850,20,buf2);
CRect rc,rc2;
CRect rcY1;
CRect rcY2;              //定义矩形区
COLORREFBrickColor[8]={0xFFFFFF,0xFF0000,0x00FF00,0x0000FF,0x00FFFF,0xFFFF00,0x800000,0x800080};
/游戏界面显示
for (i=0; iFillRect(rc,&CBrush(BrickColor[image[i][j]]));                       //画临时砖块(运动中)
pDC->Draw3dRect(rc,GetLightColor(BrickColor[image[i][j]]),GetDarkColor(BrickColor[image[i][j]]));
}

(3)在菜单中添加

ID_Game_Start    开始(&S)

难度(&D)属性选择pop-up,子菜单为:

ID_DIFF_EASY   容易

ID_DIFF_MID     中等

ID_DIFF_SUP     高级

暂停(&P)属性选择pop-up,子菜单为:

IDD_Pause   暂停

IDD_Restart 开始

为其分别添加消息响应函数:

void CNewTetrisView::OnGameStart()
{
//TODO: Add your command handler code here
gameOver=0; brickInFlight=0; numLines=0;
for(unsigned int i = 0; i<20; i++)
{
for(unsigned int j = 0; j<10; j++)
{
outputImage[i][j]=0;
}
}
bin->setImage(outputImage);
SetTimer(0,difficulty,NULL);   //设置定时器
}
void CNewTetrisView::OnDiffEasy()
{
//TODO: Add your command handler code here
difficulty=500;
OnGameStart();
}
void CNewTetrisView::OnDiffMid()
{
//TODO: Add your command handler code here
difficulty=350;
OnGameStart();
}
void CNewTetrisView::OnDiffSup()
{
//TODO: Add your command handler code here
difficulty=150;
OnGameStart();
}

暂停功能的实现:

按下暂停键的时候停止定时器,按下重新开始键开启定时器就行了。

voidCNewTetrisView::OnPause()
{
// TODO: Add your commandhandler code here
KillTimer(0);
}
voidCNewTetrisView::OnRestart()
{
// TODO: Add your commandhandler code here
SetTimer(0,difficulty,NULL);
}

(4)为视图类添加WM_TIMER的消息响应函数。初始化面板,并设置定时器。

(这里省略代码,最终版代码在下面)

(5)在OnDraw()函数中调用DrawImage函数,显示面板。

(这里省略代码,最终版代码在下面)

(6)添加WM_KEYDOWON的消息响应函数,以响应用户按键。

void CNewTetrisView::OnKeyDown(UINT nChar, UINTnRepCnt, UINT nFlags)
{
//控制面板1
if(nChar == VK_RIGHT) activeBrick->shiftRight(bin);
elseif (nChar == VK_LEFT) activeBrick->shiftLeft(bin);
elseif (nChar == VK_UP)  activeBrick->rotateClockwise(bin);
elseif (nChar == VK_DOWN) activeBrick->shiftDown(bin);
Invalidate();
CView::OnKeyDown(nChar,nRepCnt, nFlags);
}

这样一个基本的单人版俄罗斯方块游戏就做好了

进一步完善和改进:

双人版功能的实现:

就是把前面的代码重新写一遍再显示在另一个区域,用另一个定时器。

(1).定义相关的变量并在构造函数中初始化。

(2)在DrawImage函数中绘制游戏砖块,显示在另一个区域。

部分代码如下:

//2
if(0 != imageY2[i][j])
{
pDC->FillRect(rcY2,&CBrush(BrickColor[imageY2[i][j]]));//画临时砖块(运动中)
pDC->Draw3dRect(rcY2,GetLightColor(BrickColor[imageY2[i][j]]),GetDarkColor(BrickColor[imageY2[i][j]]));
}

(3)在OnDraw()函数中调用DrawImage函数,显示面板。代码省略。

( 4)  修改WM_TIMER的消息响应函数。初始化面板,并设置另一个定时器。

(5)修改ID_Game_Start的消息响应函数,初始化面板,启动定时器。这里省略代码

(6)修改WM_KEYDOWON的消息响应函数,以响应用户按键。

部分代码如下:

 //控制面板1
if (nChar == VK_RIGHT) activeBrick->shiftRight(bin);
else if (nChar == VK_LEFT) activeBrick->shiftLeft(bin);
else if (nChar == VK_UP)   activeBrick->rotateClockwise(bin);
else if (nChar == VK_DOWN) activeBrick->shiftDown(bin);
Invalidate();

(7)修改暂停和开始的消息响应函数,这里省略代码。

预显示功能的实现:

在生成砖块的时候,一次生成两块,一块显示,一块下落。

(1)定义flag用于标记是不是第一次下落,并初始化。

(2)在DrawImage函数中绘制游戏砖块,显示在相应的区域。

部分代码如下:

//预显示
for (i = 0; i < 4; ++i)//一行一行的画砖块
{
for (j = 2; j < 8; ++j)
{
rcY1 = CRect((j-2)*nSize+380, i*nSize+250, (j+1-2)*nSize+380, (i+1)*nSize+250);
rcY2 = CRect((j-2)*nSize+530, i*nSize+250, (j+1-2)*nSize+530, (i+1)*nSize+250);
//绘制面板
//1
if (0 != imageY1[i][j])
{
pDC->FillRect(rcY1, &CBrush(BrickColor[imageY1[i][j]]));//画临时砖块(运动中)
pDC->Draw3dRect(rcY1,GetLightColor(BrickColor[imageY1[i][j]]),GetDarkColor(BrickColor[imageY1[i][j]]));
}
//2
if (0 != imageY2[i][j])
{
pDC->FillRect(rcY2, &CBrush(BrickColor[imageY2[i][j]]));//画临时砖块(运动中)
pDC->Draw3dRect(rcY2,GetLightColor(BrickColor[imageY2[i][j]]),GetDarkColor(BrickColor[imageY2[i][j]]));
}
}
}

(3)在OnDraw()函数中调用DrawImage函数,显示面板。

代码如下:

  int m_nWidth,m_nHeight;
CDC m_memDC;
CBitmap m_memBmp;
/*  m_memBmp.LoadBitmap(IDB_BITMAP2); //装载位图*/
//1.用于映射屏幕的内存设备环境
//获取游戏窗口的大小用于下面设置内存位图的尺寸
CRect windowRect;
GetClientRect(&windowRect);
m_nWidth = windowRect.Width();
m_nHeight = windowRect.Height();
//内存设备环境与屏幕设备环境关联(兼容)
m_memDC.CreateCompatibleDC(pDC);
//内存位图与与屏幕关联(兼容),大小为游戏窗口的尺寸
/*  m_memBmp.CreateCompatibleBitmap(pDC,m_nWidth,m_nHeight); */
m_memDC.FillSolidRect(windowRect,RGB(0,0,0));
//内存设备环境与内存位图关联,以便通过m_memDC 在内存位图上作画
m_memDC.SelectObject(&m_memBmp);
DrawImage(bin,bin2,outputImage,outputImage2,outputImageY1,outputImageY2,pDC);
//把内存DC 上的图形拷贝到电脑屏幕
pDC->BitBlt(0,0,m_nWidth,m_nHeight,&m_memDC,0,0,SRCCOPY);
m_memDC.DeleteDC(); //删除DC
m_memBmp.DeleteObject(); //删除位图

界面的美化:

修改标题:在doc类中OnNewDocument()函数修改

BOOL CNewTetrisDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
SetTitle(_T("俄罗斯方块"));
return TRUE;
}

设置标题栏图标: 首先在资源视图引入ICON文件

然后在CMainFrame中的OnCreate()函数中添加如下代码:

//设置标题栏的图标
HICON m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
SetIcon(m_hIcon,TRUE);
SetIcon(m_hIcon,FALSE);
return 0;

工具栏、菜单栏、状态栏的隐藏,最大化按钮的禁用,窗口大小的设定:

在CMainFrame中的OnCreate()函数中添加如下代码:

 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
/*  SetMenu(NULL);//菜单栏的隐藏*/
ShowControlBar(&m_wndToolBar,FALSE,FALSE);//工具栏的隐藏
ShowControlBar(&m_wndStatusBar,FALSE,FALSE);//状态栏的隐藏

在CMainFrame中的PreCreateWindow函数中添加如下代码:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
//  the CREATESTRUCT cs
cs.cx = 1024;//设定窗口的大小       (窗口大小可以用QQ截图获得)
cs.cy = 571;
cs.style &= ~WS_THICKFRAME;//使窗口不能用鼠标改变大小
cs.style &= ~WS_MAXIMIZEBOX; //禁止窗口最大化
return TRUE;
}

背景位图的插入:

首先在资源视图导入文件(bmp格式)

然后在DrawImage函数中添加如下代码:

CRect rect;
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP3); //加载位图
CBrush brush;
brush.CreatePatternBrush(&bitmap);  //创建位图画刷
GetClientRect(&rect);       //获得客户区大小
pDC->FillRect(rect,&brush);   //将矩形区域用位图填充

添加背景音乐功能:

首先先把你要添加的音乐用格式工厂转化为WAV格式,然后放入res文件夹。将VC98文件夹下的WINMM.LIB文件放入res文件夹。

然后添加lib文件 选择 Project->Add to Project->Files ,然后找到WINMM,添加进去。因为后面要用到PlaySound函数。

然后在资源中插入 WAVE 命名为 IDR_WAVE3 。

然后在CNewTetrisView类实现文件中引入mmsystem.h

然后在Gamestart函数中添加

PlaySound((LPCTSTR)IDR_WAVE3,AfxGetInstanceHandle(),SND_RESOURCE |SND_ASYNC |SND_LOOP);

帮助对话框的添加:

首先插入对话框资源,然后为它对应一个类 HelpDialog.h

在视图类实现文件中添加#include "HelpDialog.h"

为帮助 菜单添加消息响应函数:

HelpDialog dlg;

dlg.DoModal();

超文本链接的添加:

(1)    在资源中插入光标文件 ID设为IDC_HAND

(2)    在Dialog中加入静态文本控件,并更改其ID为IDC_LINK。

(3)    在对话框头文件中加入数据成员:

protected:

RECT m_pRectLink;              //用于保存静态文本框的屏幕坐标

(4)    在对话类成员函数OnInitDialog()中添加以下代码

GetDlgItem(IDC_LINK)->GetWindowRect(&m_pRectLink);//将静态文本的屏幕坐标存放在m—pRectLink中

ScreenToClient(&m_pRectLink);//将屏幕坐标转换为客户坐标

(5)变换鼠标形状

为对话框添加OnMouseMove函数 添加如下代码:

 //下面设置鼠标在静态文本区时,将光标设成小手状
if (point.x>m_pRectLink.left&&point.xm_pRectLink.top&&point.yLoadCursor(IDC_HAND);
//将鼠标设为小手状
SetCursor(hCursor);
}

(6)  添加鼠标单击响应事件, 为Dialog类添加OnLButtonDown函数  添加如下代码:

void HelpDialog::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (point.x>m_pRectLink.left&&point.xm_pRectLink.top&&point.y

5 测试与实现


VC版双人PK版俄罗斯方块相关推荐

  1. Qt版双人俄罗斯方块游戏

    Qt版双人俄罗斯方块游戏 转载请标明出处:牟尼的专栏 http://blog.csdn.net/u012027907     之前写过<VC版双人俄罗斯方块>,将其在Qt下又重写了一遍,核 ...

  2. C++猜数字小游戏1.0.1版猜数字1.1---国庆特版(双人战斗版)

    (回忆上一篇开头--) 国庆在家,你觉得无聊吗???                                                                          ...

  3. c语言编程vcwin7,vc++6.0 win7版

    vc++6.0 win7版经测试可完美运行且兼容性良好,大学生朋友们在宿舍用笔记本都可以进行程序开发了.vc++6.0是一款功能强悍的可视化编程工具,是一款优秀专业的C++编译器,简单易用,十分容易上 ...

  4. VC++ 2010(学习版) 安装教程—图文详解

    VC++ 2010 (学习版)安装教程 将压缩包下载完后 如图操作: 等待中..... 然后打开 开始菜单,在 最近添加 可以找到应用 把它拖到桌面上生成快捷方式: 安装就算完成啦!over! 安装包 ...

  5. 热血传奇手机版法师PK怎么样 热血传奇法师PK技巧

    更多信息请点击:手机游戏免费下载:http://www.zhuoyi.com/ 热血传奇手机版法师PK怎么样 热血传奇法师PK心得.法师是个争议很大的职业,特别是在PK的时候,用的好以一当十,用的不好 ...

  6. 关于VC++6.0 绿色版不能用的修改意见

    本人于2013年6月份传送了一个资源 VC++6.0 绿色版 http://download.csdn.net/detail/joshgu958/5515751 但是将其安装在自己的机子上不能用.查看 ...

  7. 复旦数院专业情诗微博走红 医学物理C++各版大PK

    复旦三行情诗大赛,目前已征集到270余条"三行情诗".即使用最严谨的科学符号,也能写下最炽热的情诗.不少网友唏嘘不已:没学高数,连情书都看不懂了!除传统数学版外,医学版.物理版.程 ...

  8. 同时生成 Release版和Debug版DLL的方法

    同时生成 Release版和Debug版DLL的方法 warning LNK4070的解决办法 重命名了一个MFC常规DLL的工程文件(VS C++ 2005编译环境),结果在编译时出现这样的警告:1 ...

  9. 计算机网络教程第五版|微课版 - 第四章 网络层 - 习题【补充】

    第四章.网络层[补充] 本章的习题 请简述网络层的转发和选路两个重要功能的区别和联系 转发:分组在单一的路由器的一条输入链路中,由路由器将该分组移动到合适的输出链路 路由选择:一个网络中,分组从发送方 ...

最新文章

  1. tnsping通oracle连不上,写正确了tnsnames文件却tnsping无法ping通
  2. python中%r和%s的区别
  3. 手写体识别(数据挖掘入门与实践-实验11)
  4. java 中的路径问题总结(绝对路径与相对路径) .
  5. JZOJ 5776. 【NOIP2008模拟】小x游世界树
  6. 文件如何存储c语言,急求如何将下列C语言程序数据存储到文件中?
  7. 暖通中级工程师计算机考试题库,暖通工程师试题(含答案)
  8. 多个点 最远距离 java_Java实现的计算最大下标距离算法示例
  9. torch.cat;Pytorch nn.MaxPool1d
  10. XcodeGhost事件冷思考:智能时代的达摩克利斯之剑
  11. oracle离散度,统计学基础知识之数据离散程度描述
  12. 计网实验(一):IP子网划分
  13. Android 音频系统
  14. 搜狗输入法的桌面图标消失,无法打开设置怎么办
  15. C语言程序设计现代方法第二版,第八章课后编程题——第9题生成贯穿10乘10字符组的随机步法
  16. DaVinci Resolve Studio 15(达芬奇调色软件) Mac永久破解激活方法
  17. 360度全景图是如何生成的?
  18. USB OVER Network的使用(共享usb端口)
  19. 扇贝开发:国内NFT平台运营主要合规问题
  20. 五个最好的压缩软件下载

热门文章

  1. 人脸图像质量评价 SER
  2. 2022年最新安徽建筑安全员考试题库及答案
  3. python语言是多模型语言-Python的语言特点
  4. 绘画工具研究笔记(不定期更新)-1月13日加入史明克24色专业水彩和白夜水彩...
  5. 轻松筹 html模板,轻松筹怎么写最感人标题?有没有模板?劝你千万别生搬硬套...
  6. 顺德美食-嘉信京华食街
  7. ZYNQ7000 SDK开发使用
  8. 同一电脑上安装且使用vue2.0和vue3.0版本
  9. G711转AAC代码总结【转】
  10. 蜜雪冰城饮品商城系统