用VC++设计与实现俄罗斯方块游戏时间:2010-09-26 18:07来源:未知作者:admin 点击:482次
目录 1 引言6 1.1 游戏的历史6 1.2 Windows编程特点7 1.3 V isual C++ 6.0编程特点8 1.4 课程设计目的8 2 需求分析9 2.1 游戏需求9 2.2 软硬件需求9 2.3 接口控制10 3 概要设计10 3.1 定义方块的数据结构10 3.2 游戏设计分析11 3.3游戏流程图13 4 详细设计14 4.1 总目录
1 引言6
1.1 游戏的历史6
1.2 Windows编程特点7
1.3 V isual C++ 6.0编程特点8
1.4 课程设计目的8
2 需求分析9
2.1 游戏需求9
2.2 软硬件需求9
2.3 接口控制10
3 概要设计10
3.1 定义方块的数据结构10
3.2 游戏设计分析11
3.3游戏流程图13
4 详细设计14
4.1 总体设计14
4.2 创建界面的主框架15
4.3 正常流程的设计16
4.4 中断操作流程的实现23
4.5 游戏区域绘图的实现27
4.6 功能的完善27
4.7 游戏演示29
参考文献30
摘要本课程设计主要解决利用V isual C++设计与实现俄罗斯方块游戏的算法、游戏内部功能、游戏区域的绘图的程序设计。在课程设计中,系统开发平台为Windows 2000,程序设计设计语言采用Visual C++ 6.0,程序运行平台为Windows 98/2000/XP。对于每个俄罗斯方块各自的形态变换改变到下一个形态利用数组来实现,在程序设计中,采用MFC机制来实现,并且直接从架构的其中一个类对象中继承下来,将它完善而变成有某功能特性的物件对象。
关键词俄罗斯方块;MFC;算法;数组
1 引言
俄罗斯方块是个老幼皆宜的小游戏,它实现由四块正方形的色块组成,然后存储在一个数组的四个元素中,计算机随机产生不同七种类型的方块,根据计算机时钟控制它在一定的时间不停的产生,用户根据键盘的四个方向键控制翻转、向左、向右和向下操作,(控制键的实现是由键盘的方向键的消息函数实现)。然后程序根据这七种方块堆叠成各种不同的模型。
1.1 游戏的历史
俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏,它曾经造成的轰动与造成的经
济价值可以说是游戏史上的一件大事。这款游戏最初是由苏联的游戏制作人Alex Pajitnov 制作的,它看似简单但却变化无穷,令人上瘾。相信大多数用户都还记得为它痴迷得茶不思饭不想的那个俄罗斯方块时代。
究其历史,俄罗斯方块最早还是出现在PC机上,而我国的用户都是通过红白机了解、喜欢上它的。现在联众又将重新掀起这股让人沉迷的俄罗斯方块风潮。对一般用户来说,它的规则简单,容易上手,且游戏过程变化无穷,而在"联众俄罗斯方块"中,更有一些联众网络游戏所独有的魅力――有单机作战与两人在线对战两种模式,用户可任选一种进行游戏。网络模式还增加了积分制,使用户既能感受到游戏中的乐趣,也给用户提供了一个展现自己高超技艺的场所[1]。
图 1.1 俄罗斯方块
1.2 Windows编程特点
(1)图形用户界面
Windows为用户提供了独立于应用程序的图形设备接口,利用这个接口,程序员可以在应用程序中显示文本和图形;所有的硬件设备都由Windows的设备驱动程序来管理。
(2)多任务
在传统的MS-DOS环境中,每次只能够执行一个任务,只有从一个任务中退出才能执行下一任务,这样在客观上就浪费了很多的资源。但是在Windows操作环境中,多个应用程序可以同时运行,每个应用程序在屏幕上都有一个显示的窗口,即为Windows的多任务环境。(3)资源共享
在windows操作系统中,应用程序之间共享资源的方式共有三种:剪贴板、DDE和OLE。
1.3 V isual C++ 6.0编程特点
Visual C++6.0是微软公司推出的开发Win32应用程序(Windows 95/98/2000/XP/NT)的、面向对象的可视化集成工具。它的最大优点就是提供了功能强大的MFC类库,MFC是一个很大的C++类层次结构,其中封装了大量的类及其函数,很多Windows程序所共有的标准内容可以由MFC的类来提供,MFC类为这些内容提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓,这将简化编程工作,大大的减少程序员编写的代码数量,使编程工作变得更加轻松容易。
1.4 课程设计目的
综合运用所学理论知识和技能,设计开发俄罗斯方块,使自己熟悉应用系统的开发过程,培养独立思考能力,检验学习效果和动手能力,提高工程实践能力,为将来实际工作打下坚实的基础。
2 需求分析
2.1 游戏需求
随机给出不同的形状(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型)下落填充给定的区域,若填满一条便消掉,记分,当达到一定的分数时,过关,设置六关,每关方块下落的速度不同,若在游戏中各形状填满了给定区域,为输者。游戏功能要求如下:游戏界面需求:良好的用户界面,有关数显示和分数显示。让方块在一定的区域内运动和变形,该区域用一种颜色表明,既用一种颜色作为背景,最好设为黑色。还需用另一种颜色把黑色围起来,宽度适中,要实现美感。
游戏形状(方块)需求:良好的方块形状设计,绘制七种常见的基本图形(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),各个方块要能实现它的变形,可设为顺时针或逆时针变形,一般为逆时针。
键盘处理事件:方块下落时,可通过键盘方向键(上、下、左、右键)对该方块进行向上(变
形),向下(加速)、向左、向右移动。
显示需求:当不同的方块填满一行时可以消行,剩余方块向下移动并统计分数。当达到一定的分数时过关。设置六关,每关方块下落的速度不同。
2.2 软硬件需求
操作系统Windows98/me/2000/XP/2003
内存容量64MB
显卡要求8M
声卡要求支持DirectX 8.0 音效卡
交互工具键盘/鼠标
CPU 奔腾133以上
光驱8倍速以上
硬盘空间400MB
显示器VGA以上显示器
开发软件Java可视化编程3.0以上版本
2.3 接口控制
本软件需求通过键盘进行操作,在Windows的操作系统下,利用键盘的上、下、左、右键对方块进行移动变形,要使用键盘的接口事件。
3 概要设计
3.1 定义方块的数据结构
对于方块在某一瞬间的位置标识,我们采用一个4×2的小数组标识出来,即用4个存储单位空间存储当前下坠物的每一子块的位置,也就是说,用4个存储单位空间存储当前下坠物的每一子块的位置来对整个下坠物件的位置进行标识,而每个存储空间的大小就是一个典的坐标值(x,y),而每个方块按照从左到右的方式进行编号,并且在编号过程中对于同一列的方块实行从上到下进行编号[2] 。
图3.1 方块编号
ActiveStatus[0][0]和ActiveStatus[0][1]则是第0号方块的横坐标x和纵坐标y ;ActiveStatus[2][0]和ActiveStatus[2][1]则是第2号方块的横坐标x和纵坐标y。
3.2 游戏设计分析
有前面的功能描述可知,我先虚拟出俄罗斯方块游戏的类对象,并抽象出核心的数据属性和操作方法等,然后再作细化,最后将整个虚拟类的外壳脱掉,再移植到视图类中去,其实现如下:
CRectGameView : public CView
{
//内部存取数据结构
int m_stateMap[MAX_ROW][MAX_COL];
//初始化操作
GameInitnal(); //游戏的初始化
//用于判断数据相关状态的操作
IsLeftLimit(); //下坠物件是否可向左移动
IsRightLitmit(); //
IsBottom(); //是否已经到达了底部
IsGameEnd(); //是否游戏已经结束
//方块物件下坠过程中的操作
RectChange(); //下坠物件变形
RectDown(); //下坠物件正常下落
RectArrow(); //下坠物件方向移动(左,右,下加速)
//状态控制操作
GameStart(); //游戏开始
GamePause(); //游戏暂停
GameEnd(); //游戏结束
}
通过上面的代码可以看出,在虚拟类中抽象出了核心的内部数据和一些基本的操作函数。对于操作函数,可以把它们分为内部实现的基本核心操作(如判断操作)以及明显提供给外部使用的整体模块外部操作(如状态控制操作)。而内部的基本操作又可以分为判断操作和执行操作这样两种类型[3]。
图3.1 正常流程的设计
图3.2 中断流程的设计
4 详细设计
4.1 总体设计
序号方法名作用
1 Main() 定义窗口
2 Rectview() 创建变量
3 Gamestart() 游戏开始
4 DrawGame() 游戏界面初始化
5 RectDown() 当前方块下降
6 invalidatecurrent () 刷新指定区域
7 OnTimer () 承担所有驱动
8 GamePaush () 游戏暂停
9 OnDraw () 绘制屏幕
10 IsBottom() 处理到达后的图形,进行加分,满行判断及消行处理等
11 KeyDown() 控制按键信息
12 Rectchange() 控制图形变化
13 GameEnd () 游戏结束
表4.1 涉及函数
图4.1 程序运行调用图
4.2 创建界面的主框架
首先建立一个项目工程,名为skyblue_Rect,并在AppWizard的架构选择过程中选择单文档方式,其他保持默认选项。其项目的架构类视图信息如图所示:
在构架类视图中是MFC基本架构组合:App(应用程序)类、Document(文档)类、V iew(视图)类、Frame(框架)类和用于提示关于作者的对话框CAboutDlg类,至于COptionDlg类是用作俄罗斯方块参数选择的对话框类对象
图 4.2 主框架图
4.3 正常流程的设计
(1)定时制机制
从分析游戏的特性可以知道,定时器的产生与生效应该在游戏开始的时候,而在游戏暂停或者游戏结束时则将已经设定的定时器失效/销亡(对于暂停的情况,使它销亡,当游戏从暂停状态又进入游戏状态时候,则重新创建一个定时器并激活它的运作),所以分别在游戏的开始函数、暂停函数已经结束函数中实现定时器的激活与去激活工作。这里,先在资源编辑器菜单资源里面添加三个菜单选项,分别是游戏的“开始”、“暂停”、和“结束”,然后利用ClassWizard直接在视图类对象Cskyblue_RectView中为它们添加空白的处理函数,具体如表2所示。
表 4.3 菜单选项功能对应表
菜单选项名称快捷键资源ID 响应处理函数
开始游戏&S ID_GAME_START OnGameStart()
暂停游戏&P ID_GAME_PAISH OnGamePaush()
结束游戏&E ID_GAME_END OnGameEnd()
(2)定时处理
经过定时器的设置后,这里通过利用ClassWizard跳到定时器到时候的处理函数OnTimer()去实现,当固定时间片间隔到达后,先检测当前下坠物是否已经到达了底部,不是则进行RectDown()下坠物向下移动一个单位的操作,是则到底后产生一个新的“下一个下坠物”,并代替旧的,将原先旧的“下一个下坠物”用作当前激活状态下正在使用的下坠物,并对使用后的一些状态进行检测:是否马上到达底部,使则进行销行操作
;是否在到达底部的同时到达游戏区域的顶部,从而判定游戏是否因违规而结束。
图 4.3 装载方块
视图类创建了m_icurrentStatus和m_inextStatus两个成员变量来记录下坠物的类型,共有七种形状,并从7种方块中随机抽取图形。而m_currentRect除了记录下坠物的类型外,还需记录其当前的变形状态,最多用两位表示,第1位用作类型标识(1~7),第2位用作同种类型的不同表现方式,最多有4种状态(1~4)。
在产生新的下一个下坠物前,需要先将当前状态物的记录和旧的下一个下坠物保存下来,然后用随机函数Random()产生一个最大值不大于指定值的随机正整数,将这个新生成的正整数用作新的“下一个下坠物”的形状值。
(3)底部到达的判断与销行的实现
图4.4 处理方块到达图
将新的下坠物放置到游戏区域中去,这时可能出现马上到达底部的情况,因此需要对它进行判断,如果是到达底部,则进行销行处理,并且修改相应的数据状态。而判断是否已经到达了底部,可以通过当前下坠物件所对应的接触面的方块位置为被占用状态(MAP_STA TE_NOT_EMPTY=1)来确定,利用数组InterFace[74][4]记录1~7种下坠物的1~4种形态的接触面信息。
统计分数:在消行处理里面有一个专门用来统计消行数的变量,然后根据变量的值决定分数的多少,程序统计分数是:消一行得100分,同时消2行得400分,销掉x行,则分数为:x*(x*100)。如果总分数达到过关条件就过关,改变游戏速度,游戏初始化,开启新的一关,然后再加载方块。没有达到过关分数或者没有满行,则加载下一个方块继续游戏。
图 4.5 判断满行及销行图
检测游戏区域中的所有行,,并对每行的所有纵列状态进行检测,如果其中有一列是空闲状态则不可以销行。如果可以销行的话,将增加单位分数,并且将该行清空,再将该行上面的所有物件都向下偏移一个单位,以填充该行的空缺。
例销行与积分
if (m_isBottom)
{
//判断是否已得分
for (i=0;i { m_bIsSucced = TRUE; for (j=0;j if (GameStatus[i][j]==MAP_STA TE_EMPTY) m_bIsSucced = FALSE; //如果得分,则销掉此行 if (m_bIsSucced) { for (k=i;k>0;k--) for (j=0;j GameStatus[k][j] = GameStatus[k-1][j]; //第1行清零 for (j=0;j GameStatus[0][j]=MAP_STA TE_EMPTY; m_iMuch += 1; } } 图 4.6 显示控制 在视图类对象中增加了成员变量m_iStartX和m_iStartY,分别为视图窗口的左上角起点的坐标偏移值。如果检测到有销行操作的话,经过一系列内部核心数据的修改后,应该将销行后的区域以及分数显示区域的部分进行重绘。所以函数体分别先计算出这两个小矩形区域的位置,然后再调用InvalidateRect()函数对这两个区域宣布重绘,从而触发视图的重绘。 4.4 中断操作流程的实现 (1)处理键盘事件 关于按键命令消息的响应,可以通过对WM_KEYDOWN消息的处理函数进行截获并重写来实现,下面是对该处理函数OnKeyDown()的重写。 // 功能:处理用户的输入,方块的左,右移,加速及变形 void CSkyblue_RectV iew::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch(nChar) { case VK_LEFT: RectArrow(LEFT); break; case VK_RIGHT: RectArrow(RIGHT); break; case VK_UP: RectChange(); break; case VK_DOWN: RectArrow(DOWN); break; } CView::OnKeyDown(nChar, nRepCnt, nFlags); } 图 4.7 键盘事件功能图 当方块要进行上(变形)、下、左、右变化时,先对方块将要移动到的位置进行判断,判断是否有障碍,有则保持原来的位置不变,没有则根据所按的键执行相关的操作。再把方块的位置显示在屏幕上。方块的移动其实也只是对行或列坐标的增减而己。 (2)变形的实现 图4.8 方块变化 当按下向上键时,将会执行方块变化事件(change())。常见的方块有7种(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),所有图形都是用两个一维数组来统计它的横坐标和纵坐标,每个方块有4种不同的变化形状。 例计算变形后的小方块的坐标和显示的状态值 //变形后位置在数组中的存放顺序仍需遵循先左后右,在同一列中先上后下 xx1=x1; xx2=x2; xx3=x3; xx4=x4; yy1=y1; yy2=y2; yy3=y3; yy4=y4; switch(m_currentRect) { case 1: xx1=x1+1; yy1=y1-1; xx3=x3-1; yy3=y3+1; xx4=x4-2; yy4=y4+2; m_lscurrentRect = 11; break; case 11: xx1=x1-1; yy1=y1+1; xx3=x3+1; yy3=y3-1; xx4=x4+2; yy4=y4-2; m_lscurrentRect = 1; break; …… //省略部分为同类实现的变形后小方块坐标的计算代码 case 73: xx2=x2+1; yy2=y2-1; xx3=x3+2; yy3=y3-2; xx4=x4-1; yy4=y4-1; m_lscurrentRect = 7; break; } 4.5 游戏区域绘图的实现 首先将外部位图文件rect.bmp中的位图动态导入(映射)到内存位图里面,根据游戏区域中的二维数组GameStatus[MAX_ROW][MAX_COL]中的内部数据将所有数据状态中为被占用状态MAP_STA TE_NOT_EMPTY的小方块区域用指定的小方块图样类型来填充,然后将已经绘制好的游戏区域图像一次性的拷贝到与屏幕关联的设备环境中,从而达到屏幕的显示。4.6 功能的完善 为了使得游戏功能更加健全,另外为用户提供了一些附加功能,如表3所示。 表 4.6 附加功能描述列表 功能名称选项其他描述 游戏等级选择初级......顶级对游戏快慢难度的设定 方块图案样式选择深蓝......条纹对下坠物的小方块图案样式选择 游戏区域大小选择小、中、大对游戏区域的行列数选择 网格的选用有、无是否需要在游戏区域绘制网格 背景音乐的选用有、无在游戏过程中是否播放背景音乐 先将这些目标功能通过资源编辑器在主菜单条进行添加,将前面已有的菜单选项补全,再通过ClassWizard添加对应的响应处理函数。其最终效果如图 1 图 4.9 游戏设置 游戏是用来给大家娱乐的,所以要能在使用的过程中给大家带来快乐,消除大家的疲劳,所以我在游戏中添加了漂亮的场景和动听的背景音乐,设置了个性化的工具栏快捷键,激发大家的娱乐激情。 4.7 游戏演示 游戏主界面如图所示。 图4.10 俄罗斯方块游戏运行主界面 结束语 在本次课程设计中,我从指导老师颜宏文身上学到了很多东西。老师认真负责的工作态度,严谨的治学精神和深厚的理论水平都使我收益匪浅。她无论在理论上还是在实践中,都给与我很大的帮助,使我得到不少的提高这对于我以后的工作和学习都有一种巨大的帮助,感她耐心的辅导。另外,在游戏开发过程中谢中科老师也给于我们很大的帮助,帮助解决了不少的难点,使得游戏能及时开发完成,还有所有的同学同样给与我不少帮助,这里一并表示感谢。 参考文献 [1]Ben Sawyer. 游戏软件设计与开发指南[M].北京:人民邮电出版社,1998.8~46 [2]钦科技. V isual C++游戏设计[M]. 北京:科海电子出版社,2003.1~211 [3]坂本千寻.V isual C++专业游戏程序设计[M]. 北京:中国铁道出版社,2004 附录1:主程序源程序清单 CSkyblue_RectView::CSkyblue_RectView() { //第一次开始游戏 m_bFistPlay = TRUE; //缺省为不是游戏暂停状态 m_bGamePaush = FALSE; //缺省为不插放背景音乐 m_bMusic = FALSE; //缺省为画网格线 m_bDrawGrid = TRUE; //总分值清零 m_iPerformance = 0; //测试值:为12行,10列 m_iRow = 12; m_iCol = 10; //左上角X,Y坐标 m_iStartX = 10; m_iStartY = 10; //缺省级别为3级 m_iLevel = 2; //第一种样式 m_iBlockSytle = 0; //缺省方块大小为m_iLarge个象素 m_iLarge = 30; //缺省游戏是结束的 m_bGameEnd = TRUE; int i,j; //赋初值 for (i=0;i<100;i++) for (j=0;j<100;j++) GameStatus[i][j]=0; //各种形状方块的接触面数据,参见设计书的接触面表格, //如果某种形状的方块没有4个接触面,则后面的数据填-1 for (i=0;i<74;i++) for (j=0;j<4;j++) InterFace[i][j] = -1; /* 1 ---- */ InterFace[1][0] = 3; InterFace[11][0] = 0; InterFace[11][1] = 1; InterFace[11][2] = 2; InterFace[11][3] = 3; /* 2 -- */ InterFace[2][0] = 1; InterFace[2][1] = 3; /* 3 - --- */ InterFace[3][0] = 0; InterFace[3][1] = 2; InterFace[3][2] = 3; InterFace[31][0] = 2; InterFace[31][1] = 3; InterFace[32][0] = 0; InterFace[32][1] = 2; InterFace[32][2] = 3; InterFace[33][0] = 0; InterFace[33][1] = 3; /* 4 -- -- */ InterFace[4][0] = 1; InterFace[4][1] = 3; InterFace[41][0] = 0; InterFace[41][1] = 2; InterFace[41][2] = 3; /* 5 -- -- */ InterFace[5][0] = 1; InterFace[5][1] = 3; InterFace[51][0] = 0; InterFace[51][1] = 2; InterFace[51][2] = 3; /* 6 -- - - */ InterFace[6][0] = 0; InterFace[6][1] = 3; InterFace[61][0] = 1; InterFace[61][1] = 2; InterFace[61][2] = 3; InterFace[62][0] = 2; InterFace[62][1] = 3; InterFace[63][0] = 0; InterFace[63][1] = 1; InterFace[63][2] = 3; /* 7 -- - - InterFace[7][0] = 2; InterFace[7][1] = 3; InterFace[71][0] = 1; InterFace[71][1] = 2; InterFace[71][2] = 3; InterFace[72][0] = 0; InterFace[72][1] = 3; InterFace[73][0] = 0; InterFace[73][1] = 1; InterFace[73][2] = 3; } // 功能:承担所有驱动工作 void CSkyblue_RectV iew::OnTimer(UINT nIDEvent) { //如果原来的方块已到底或游戏刚开始,则掉下一个新的方块 int i,j,k; if (m_isBottom) { //1.产生下一个随机下坠物 m_icurrentStatus = m_inextStatus; m_inextStatus = Random(7); //得到下一次的方块样式 // if (m_inextStatus==0) m_inextStatus++; //2.修改新的“下一下坠物” RectStatusToNextStatus( m_inextStatus ); // CRect rect(m_iStartY+320, m_iStartX, m_iStartY+440, m_iStartX+160); // InvalidateRect(&rect); // Invalidate(FALSE); //3.将旧的“下一下坠物”用作当前使用 m_currentRect = m_icurrentStatus; //根据当前下坠物的形状去初始化激活状态下的下坠物坐标RectStatusToActiveStatus( m_icurrentStatus ); //将当前动态数组中的数据反映到大数组中ActiveStatusToGameStatus(); m_isBottom = FALSE; //4.判断当前方块是否已到底 IsBottom(); //5.判断游戏是否已结束: 碰了底,且第1行有小方块 if (m_isBottom) for (i=0;i if (GameStatus[0][i]) { KillTimer(1); AfxMessageBox("游戏已结束!"); for (j=0;j for (k=0;k GameStatus[j][k]=0; Invalidate(FALSE); m_bGameEnd = TRUE; break; } } else //当前方块下降 { RectDown(); } CView::OnTimer(nIDEvent); } // 函数:产生一个最大值不大于指定值的随机正整数(Random) // 参数:MaxNumber : 随机数的上限 // 返回值: 产生的随机数 int CSkyblue_RectView::Random(int MaxNumber) { //布下随机种子 srand( (unsigned)time( NULL ) ); //产生随机数 int random = rand() % MaxNumber; //保证非0 if(random == 0 ) random++; return random; } //内部函数:初始掉落时,将根据方块的样式决定下一次将要掉下来的动态数组的值void CSkyblue_RectV iew::RectStatusToNextStatus(int m_which) { switch(m_which) { case 1: NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 1; NextStatus[1][1] = 1; NextStatus[2][0] = 2; NextStatus[2][1] = 1; NextStatus[3][0] = 3; NextStatus[3][1] = 1; break; case 2: NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 1; NextStatus[1][1] = 1; NextStatus[2][0] = 0; NextStatus[2][1] = 2; NextStatus[3][0] = 1; NextStatus[3][1] = 2; break; case 3: NextStatus[0][0] = 1; NextStatus[0][1] = 0; NextStatus[1][0] = 0; NextStatus[1][1] = 1; NextStatus[2][0] = 1; NextStatus[2][1] = 1; NextStatus[3][0] = 1; NextStatus[3][1] = 2; break; case 4: NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 1; NextStatus[1][1] = 1; NextStatus[2][0] = 1; NextStatus[2][1] = 2; NextStatus[3][0] = 2; NextStatus[3][1] = 2; break; case 5: NextStatus[0][0] = 1; NextStatus[0][1] = 1; NextStatus[1][0] = 2; NextStatus[1][1] = 1; NextStatus[2][0] = 0; NextStatus[2][1] = 2; NextStatus[3][0] = 1; NextStatus[3][1] = 2; break; case 6: NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 0; NextStatus[1][1] = 2; NextStatus[2][0] = 1; NextStatus[2][1] = 2; NextStatus[3][0] = 2; NextStatus[3][1] = 2; break; case 7: NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 1; NextStatus[1][1] = 1; NextStatus[2][0] = 2; NextStatus[2][1] = 1; NextStatus[3][0] = 0; NextStatus[3][1] = 2; break; } } void CSkyblue_RectV iew::RectStatusToActiveStatus(int m_which) { switch(m_which) { case 1: ActiveStatus[0][0] = 0; ActiveStatus[0][1] = 5; ActiveStatus[1][0] = 1; ActiveStatus[1][1] = 5; ActiveStatus[2][0] = 2; ActiveStatus[2][1] = 5; ActiveStatus[3][0] = 3; ActiveStatus[3][1] = 5; break; …… } } // 内部函数:将当前下坠物的位置映射到游戏区域地图数组中去 void CSkyblue_RectV iew::ActiveStatusToGameStatus() { int x1,x2,x3,x4,y1,y2,y3,y4; x1 = ActiveStatus[0][0]; x2 = ActiveStatus[1][0]; x3 = ActiveStatus[2][0]; x4 = ActiveStatus[3][0]; y1 = ActiveStatus[0][1]; y2 = ActiveStatus[1][1]; y3 = ActiveStatus[2][1]; y4 = ActiveStatus[3][1]; GameStatus[x1][y1]=MAP_STA TE_NOT_EMPTY; GameStatus[x2][y2]=MAP_STA TE_NOT_EMPTY; GameStatus[x3][y3]=MAP_STA TE_NOT_EMPTY; GameStatus[x4][y4]=MAP_STA TE_NOT_EMPTY; } // 内部函数:判断当前方块是否已到底,并且销行等相关的工作 void CSkyblue_RectV iew::IsBottom() { //到底有两种概念:1是已到底部,2是下面碰到了另外的方块 int x1,x2,x3,x4; int x,xx,yy,i; x1 = ActiveStatus[0][0]; x2 = ActiveStatus[1][0]; x3 = ActiveStatus[2][0]; x4 = ActiveStatus[3][0]; //是否为底部的判断 //1。到达游戏区域的底部 //2。与接触面正下方的小方块区域为被占用状态 if (x1>=m_iRow-1 || x2>=m_iRow-1 || x3>=m_iRow-1 || x4>=m_iRow-1) m_isBottom = TRUE; else { for (i=0;i<4;i++) { if (InterFace[m_currentRect][i] > -1) {//取当前下坠物有接触面的方块 //获取有接触面的小方块的编号 x=InterFace[m_currentRect][i]; //根据编号获取ActiveStatus中该小方块的整下方的坐标 xx=ActiveStatus[x][0]+1; yy=ActiveStatus[x][1]; //判断该接触面整下方的小方块区域是否为被占用状态 if (GameStatus[xx][yy]==MAP_STA TE_NOT_EMPTY) m_isBottom = TRUE; } } } BOOL m_bIsSucced; int k,j; int m_iMuch=0; //本次销掉的行数 //计分规则:一次销掉一行,加100分,一次销掉两行,加400分,三行,900分//例如销掉x行,则分数为:x*(x*100) if (m_isBottom) { //判断是否已得分 for (i=0;i { m_bIsSucced = TRUE; for (j=0;j if (GameStatus[i][j]==MAP_STA TE_EMPTY) m_bIsSucced = FALSE; //如果得分,则销掉此行 if (m_bIsSucced) { for (k=i;k>0;k--) for (j=0;j GameStatus[k][j] = GameStatus[k-1][j]; //第1行清零 for (j=0;j GameStatus[0][j]=MAP_STA TE_EMPTY; m_iMuch += 1; } } if (m_iMuch>0) { m_iPerformance += m_iMuch * m_iMuch * 100; //刷新游戏区域 CRect rect1(m_iStartY, m_iStartX, m_iStartY+300, m_iStartX+360); //InvalidateRect(&rect1); //刷新分数区域 CRect rect2(m_iStartY+320, m_iStartX+180, m_iStartY+440, m_iStartX+200); //InvalidateRect(&rect2); Invalidate(FALSE); } } } // 内部函数:当前方块下降 void CSkyblue_RectV iew::RectDown() { IsBottom(); if (!m_isBottom) { //清除以前的方块 int x1,x2,x3,x4,y1,y2,y3,y4; x1 = ActiveStatus[0][0]; x2 = ActiveStatus[1][0]; x3 = ActiveStatus[2][0]; x4 = ActiveStatus[3][0]; y1 = ActiveStatus[0][1]; y2 = ActiveStatus[1][1]; y3 = ActiveStatus[2][1]; y4 = ActiveStatus[3][1]; GameStatus[x1][y1]=MAP_STA TE_EMPTY; GameStatus[x2][y2]=MAP_STA TE_EMPTY; GameStatus[x3][y3]=MAP_STA TE_EMPTY; GameStatus[x4][y4]=MAP_STA TE_EMPTY; InvalidateCurrent(); //方块下落 ActiveStatus[0][0] += 1; ActiveStatus[1][0] += 1; ActiveStatus[2][0] += 1; ActiveStatus[3][0] += 1; GameStatus[x1+1][y1]=MAP_STA TE_NOT_EMPTY; GameStatus[x2+1][y2]=MAP_STA TE_NOT_EMPTY; GameStatus[x3+1][y3]=MAP_STA TE_NOT_EMPTY; GameStatus[x4+1][y4]=MAP_STA TE_NOT_EMPTY; InvalidateCurrent(); } } //内部函数:刷新当前的区域 void CSkyblue_RectV iew::InvalidateCurrent() { int i; for (i=0;i<4;i++) { CRect rect(m_iStartX+ActiveStatus[i][1]*m_iLarge, m_iStartY+ActiveStatus[i][0]*m_iLarge, m_iStartX+(ActiveStatus[i][1]+1)*m_iLarge+5, m_iStartY+(ActiveStatus[i][0]+1)*m_iLarge); //InvalidateRect(&rect); Invalidate(FALSE); } } // 功能:处理用户的输入,方块的左,右移,加速及变形 void CSkyblue_RectV iew::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch(nChar) { case VK_LEFT: RectArrow(LEFT); break; case VK_RIGHT: RectArrow(RIGHT); break; case VK_UP: RectChange(); case VK_DOWN: RectArrow(DOWN); break; } CView::OnKeyDown(nChar, nRepCnt, nFlags); } // 内部函数:当前方块下降加速,左移,右移 void CSkyblue_RectV iew::RectArrow(int m_Type) { //获取当前下坠物4个小方块的位置坐标 int x1,x2,x3,x4,y1,y2,y3,y4; x1 = ActiveStatus[0][0]; x2 = ActiveStatus[1][0]; x3 = ActiveStatus[2][0]; x4 = ActiveStatus[3][0]; y1 = ActiveStatus[0][1]; y2 = ActiveStatus[1][1]; y3 = ActiveStatus[2][1]; y4 = ActiveStatus[3][1]; //对不同的移动命令指示进行分类实现 switch(m_Type) { case LEFT: //对每种不同的移动命令指示特性作相应的可移动分析 if ( (ActiveStatus[0][1]>0) && IsLeftLimit() && !m_isBottom) { //清原来的方块 GameStatus[x1][y1]=MAP_STA TE_EMPTY; GameStatus[x2][y2]=MAP_STA TE_EMPTY; GameStatus[x3][y3]=MAP_STA TE_EMPTY; GameStatus[x4][y4]=MAP_STA TE_EMPTY; //添加新的移动后数据状态 ActiveStatus[0][1] -= 1; ActiveStatus[1][1] -= 1; ActiveStatus[2][1] -= 1; ActiveStatus[3][1] -= 1; GameStatus[x1][y1-1]=MAP_STA TE_NOT_EMPTY; GameStatus[x2][y2-1]=MAP_STA TE_NOT_EMPTY; GameStatus[x3][y3-1]=MAP_STA TE_NOT_EMPTY; GameStatus[x4][y4-1]=MAP_STA TE_NOT_EMPTY; InvalidateCurrent(); } case RIGHT: if ( (ActiveStatus[3][1]< m_iCol-1) && IsRightLitmit() && !m_isBottom) { //清原来的方块 GameStatus[x1][y1]=MAP_STA TE_EMPTY; GameStatus[x2][y2]=MAP_STA TE_EMPTY; GameStatus[x3][y3]=MAP_STA TE_EMPTY; GameStatus[x4][y4]=MAP_STA TE_EMPTY; //添加新的移动后数据状态 ActiveStatus[0][1] += 1; ActiveStatus[1][1] += 1; ActiveStatus[2][1] += 1; ActiveStatus[3][1] += 1; GameStatus[x1][y1+1]=MAP_STA TE_NOT_EMPTY; GameStatus[x2][y2+1]=MAP_STA TE_NOT_EMPTY; GameStatus[x3][y3+1]=MAP_STA TE_NOT_EMPTY; GameStatus[x4][y4+1]=MAP_STA TE_NOT_EMPTY; InvalidateCurrent(); } break; case DOWN: RectDown(); break; } } // 内部函数:方块是否还可以左移 BOOL CSkyblue_RectView::IsLeftLimit() { int x1,x2,x3,x4,y1,y2,y3,y4; x1 = ActiveStatus[0][0]; x2 = ActiveStatus[1][0]; x3 = ActiveStatus[2][0]; x4 = ActiveStatus[3][0]; y1 = ActiveStatus[0][1]; y2 = ActiveStatus[1][1]; y3 = ActiveStatus[2][1]; y4 = ActiveStatus[3][1]; //根据当前下坠物的具体形态,分析判断其是否有向左移动的空间switch(m_currentRect) { /* | | | "1"字形形态类型,判断其四个方块的正左边都没有任何物件(空间没有被占据) | */ case 1: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1] || GameStatus[x4][y4-1]) return FALSE; break; case 11: if (GameStatus[x1][y1-1]) return FALSE; break; case 2: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1]) return FALSE; break; case 3: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1]) return FALSE; break; case 31: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1]) return FALSE; break; case 32: if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1]) return FALSE; break; case 33: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x4][y4-1]) return FALSE; break; case 4: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x4][y4-1]) return FALSE; break; case 41: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1]) return FALSE; break; case 5: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1]) return FALSE; break; case 51: if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1]) return FALSE; break; case 6: if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1] || GameStatus[x4][y4-1]) return FALSE; break; case 61: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1]) return FALSE; break; case 62: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1]) return FALSE; break; case 63: if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1]) return FALSE; break; case 7: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1]) return FALSE; break; case 71: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1]) return FALSE; break; case 72: if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1]) return FALSE; break; case 73: if (GameStatus[x1][y1-1] || GameStatus[x4][y4-1]) return FALSE; break; } return TRUE; } // 内部函数:方块的变形 void CSkyblue_RectV iew::RectChange() { //先预先变形,然后判断变形后的方块是否有空间,如有足够空间,则进行实际变形,否则不变 /*学无止境*/ #include void Init(); void Down(); void GoOn(); void ksdown(); void Display(int color); void Give(); int Touch(int x,int y,int dx,int dy); int GeyKey(); void Select(); void DetectFill(); void GetScores(); void Fail(); void Help(); void Quit(); void DrawBox(int x,int y,int Color); void OutTextXY(int x,int y,char *String); void DispScore(int x,int y,char Ch); void DrawNext(int Color); int Heng=12,Shu=20; /*横竖*/ int Position[MAX][MAX]; int middle[MAX][MAX]; int ActH,ActS; 课程设计 俄罗斯方块改进 2016年4月20 日 设计题目 学号 专业班级 学生姓名 指导教师 目录 1. 课程设计目的错误!未定义书签。 2. 功能分析错误!未定义书签。 3. 程序设计实现过程错误!未定义书签。 程序总体设计结构错误!未定义书签。 界面设计错误!未定义书签。 重要数据的数据结构设计错误!未定义书签。函数设计错误!未定义书签。 4. 运行效果错误!未定义书签。 5. 源代码详解错误!未定义书签。 6. 参考文献错误!未定义书签。 俄罗斯方块改进 1. 课程设计问题 据百度百科,俄罗斯方块(Tetris)是一款由俄罗斯人阿列克谢·帕基特诺夫于1984年6月发明的休闲游戏。游戏的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。 要求支持键盘操作和7种不同类型方块的旋转变换,并且界面上显示下一个方块的提示以及当前的玩家的得分,随着游戏的进行,等级越高,游戏难度越大,即方块的下落速度越快,相应的等级,等级越高,消去一行所得到的分数越高,为玩家提供了不同的选择。 2. 功能分析 俄罗斯方块游戏需要解决的问题包括: ⑴按任意键开始游戏,随机产生方块并自动下移 ⑵用Esc键退出游戏。 ⑶用键变换方块 ⑷用键和键左右移动方块 ⑸用键使方块加速下移 ⑹用空格键使方块暂停 ⑺能正确判断满行并消行、计分、定级别 ⑻设定游戏方块为不同形状重点: *游戏面包的数据结构:二维数组 *7种形状方块的数据结构:结构体保存每种形状方块的坐标 3. 程序设计实现过程 程序总体设计结构 首先初始化进入图形模式,进入欢迎界面,玩家按任意进入主菜单界面,按键进入游戏界面,键然后设置新的时钟中断。开始游戏后,进入该程序最核心的部分——处理和实现进行过程中的各种事件和函数。在处理中判断游戏是否结束,如果没有结束,则重新开始游戏,否则结束游戏。 详解如下: (1)游戏方块预览功能。在游戏过程中,当在游戏底板中出现一个游戏方块时,必须在游戏方块预览区域中出现下一个游戏方块,这样有利于游戏玩家控制游戏的策略。由于在此游戏中存在19种不同的游戏方块,所以在游戏方块预览区域中需要显示随机生成的游戏方块。 【转载】88行代码实现俄罗斯方块游戏(含讲解) 来源:https://www.doczj.com/doc/4817195725.html,/p/8 在正式阅读本文之前,请你记得你应该用娱乐的心态来看, 本代码所使用到的技巧,在工作了的人眼里会觉得很纠结,很蛋疼,很不可理喻,很丑, 注意,是你蛋疼,不关我的事 通常,写一个俄罗斯方块,往往动不动就几百行,甚至上千行,而这里只有88行 正所谓头脑风暴,打破常规。这里将使用很多不平常的手段来减少代码 以下是Win-TC可以成功编译并执行的代码(代码保证单行长度不超过80字符,如果你是Win7系统,那请看后文): 程序代码: #include"graphics.h" #include 1、新建“.h”头文件,将“头文件” 代码粘贴至其中, 2、新建“.c”源文件,将“源代码” 代码粘贴到其中。 3、新建空白工程,将头文件和源代码 添加进去,调试使用。 //头文件 //1.自定义枚举类型,定义7种形态的游戏方块 typedef enum tetris_shape { ZShape=0, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape }shape; //2.函数声明 //(1)操作方块函数 int maxX();//取得当前方块的最大x坐标 int minX();//取得当前方块的最小x坐标 void turn_left();//当前方块逆时针旋转90度 void turn_right(); int out_of_table(); void transform(); int leftable(); int rightable(); int downable(); void move_left(); void move_right(); //(2)操作游戏桌面的函数 int add_to_table(); void remove_full(); //(3)控制游戏函数 void new_game(); void run_game(); void next_shape(); int random(int seed); //(4)绘图函数 void paint(); void draw_table(); //(5)其他功能函数 void key_down(WPARAM wParam); void resize(); void initialize(); void finalize(); //(6)回调函数,用来处理Windows消息 LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM); //源代码 //1.文件包含 #include C语言课程设计报告 俄罗斯方块程序设计报告 一、问题描述 俄罗斯方块(Tetris,俄文:Тетрис)是一款电视游戏机和掌上游戏机游戏,它由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。 在本次设计中,要求支持键盘操作和若干种不同类型方块的旋转变换,并且界面上显示下一个方块的提示以及当前的玩家的得分,随着游戏的进行,等级越高,游戏难度越大,即方块的下落速度越快,相应的等级,等级越高,为玩家提供了不同的选择。 二、功能分析 I、俄罗斯方块游戏需要解决的问题包括: ⑴、随机产生方块并自动下移 ⑵、用Esc键退出游戏 ⑶、用键变体 ⑷、用键和键左右移动方块 ⑸、用空格键使游戏暂停 ⑹、能正确判断满行并消行、计分、定级别 ⑺、设定游戏为不同级别,级别越高难度越大 II、俄罗斯方块游戏需要设计的功能函数包括: ⑴、声明俄罗斯方块的结构体 ⑵、函数原型声明 ⑶、制作游戏窗口 ⑷、制作俄罗斯方块 ⑸、判断是否可动 ⑹、随机产生俄罗斯方块类型的序号 ⑺、打印俄罗斯方块 ⑻、清除俄罗斯方块的痕迹 ⑼、判断是否满行并删除满行的俄罗斯方块 三、程序设计 1、程序总体结构设计 (1)、游戏方块预览功能。在游戏过程中,游戏界面右侧会有预览区。由于在此游戏中存在多种不同的游戏方块,所以在游戏方块预览区域中显示随机生成的游戏方块有利于游戏玩家控制游戏的策略。 (2)、游戏方块控制功能。通过各种条件的判断,实现对游戏方块的左移、右移、自由下落、旋转功能,以及行满消除行的功能。 (3)、游戏数据显示功能。在游戏玩家进行游戏过程中,需要按照一定的游戏规则给玩家计算游戏分数。例如,消除一行加100分,游戏分数达到一定数量 来如鹏挺长时间了,受益很多希望更多的朋学加入进来 做俄罗斯方块是因为无意中在杨老师的帖子看到说最少也要能做出俄罗斯方块这样的东西出来,我想这个意思能做出俄罗斯方块就说明水平到了一个层次了吧。 刚才注意到音乐播放器居然下载超过400次!我反醒我上传的代码很少解释 而且做的都是没有趣味的东西。 俄罗斯方块如鹏已经有好几个同学做出来了,但是我想还有很多同学做不出来,我抛砖引玉,其实俄罗斯方块并不复杂 今天先告诉大家第一步, 在屏幕上把方块显示出来 cfree 新建一个工程选窗口程序显示helloworld的 win32的 api 图形函数都要用到 HDC 这是一个保存窗口图形的数据的句柄 比如我要画一个正方形可以用 Rectangle (hdc,标X,左上角坐标y,右下角坐标x,右下角坐标y); 为了方便我们直接在 switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // 这个下面添加代码 Rectangle (hdc,50,50,100,100); 然后编译运行 这是效果就是一个正方形没别的东西?别着急哈,慢慢来。 俄罗斯方块每块都是四部分的所以要画4个 这里面需要一小点数学知识 把这些复制到刚才的位置看一下效果 { int x,y; const int size=50;//方块大小 x=y=50;//从窗口的左上角位置开始画 //第一个方块 Rectangle (hdc,x,y,x+size,y+size); x+=size; //向右一块位置画第二个方块 Rectangle (hdc,x,y,x+size,y+size); x+=size; //向右一块位置画第三个方块 Rectangle (hdc,x,y,x+size,y+size); //最后一个方块 //相对于第三个方块左下角的位置 x-=50;y-=50; Rectangle (hdc,x,y,x+size,y+size); } 这个画好像很麻烦我们可以自定义一个函数huafangkuai 专门负责画这个正方形以后所有的其他函数也必须经过他才能画正方形 这个类似于win32 api的封装思想 void huafangkuai(int x,int y,int color); x y是方块的坐标color 就是color 函数原理是x y 是相对于游戏里的坐标而不是屏幕坐标 屏幕坐标要经过函数自己转换这样我们就可以把心关注在游戏的事情而不必分心了void huafangkuai(HDC hdc,int x,int y,int color) { const int BEGINX= 50;//游戏图形的开始位置 const int BEGINY= 50 ; const int FSIZE= 35 ; //方块大小 int screenx=BEGINX +x*FSIZE; //方块左上角的坐标是x乘方块大小再加上起始位置 int screeny=BEGINY +y*FSIZE; Rectangle (hdc,screenx,screeny,screenx+FSIZE,screeny+FSIZE); } 这样我们再画就四个就容易多了 color 先不管 int x,y; x=5;y=5; huafangkuai(hdc,x,y,0); huafangkuai(hdc,x+1,y,0); huafangkuai(hdc,x+2,y,0); ````````` 学院:数计学院 班级:13级数媒班 学号: 姓名: 摘要 …………………………………………………………………………………………………….. 关键字: 目录 第一部分设计总概........................................................................................................................... 摘要………………………………………………………………………………………………… 一、设计目的............................................................................................................................. 二、设计要求............................................................................................................................. 三、设计内容............................................................................................................................. 四、系统分析与设计................................................................................................................. 第二部分数据结构设计................................................................................................................... 第三部分功能实现与程序调试………………………………………………………………….第四部分完成设计........................................................................................................................... 一、实习日记............................................................................................................................. 二、实习总结............................................................................................................................. 三、教师评语............................................................................................................................. 四、程序使用说明书…………………………………………………………………………. 第一部分设计总概 一、设计目的 二、设计要求 三、设计内容 四、系统分析与设计 其中的主要逻辑有: (1)由于c的随机性函数不好,所以每次游戏开始根据bios时间设置种子。 (2)得分越高,方块下降速度越快(每200分为单位)。 (3)每下落一个方块加1分,每消除一行加10分,两行加30分,三行加70分,四行加150分。初试分数为100分。 游戏控制: up-旋转;空格-下落到底;左右下方向键-控制方向。P-开始或暂停游戏。ESC-退出。 特点: (1)由于tc不支持中文,所以基本都是英文注释。 (2)函数命名尽可能规范的表达其内部处理目的和过程。 (3)代码加上注释仅有577行。(我下载过的两个俄罗斯方块代码一个在1087行,一个在993行,我的比它们代码少)。 (4)除了消除空格时算法比较复杂,其他算法都比较简单易读。 (5)绘图效率和局部代码效率扔有待提高。 (6)FrameTime参数可能依据不同硬件环境进行具体设置,InitGame需要正确的TC路径。 俄罗斯方块源于大约9年前上大一时的一个梦,我们在学习c语言时,我的同寝室友邀请我合作一起完成俄罗斯方块(课外作业性质),但是当时限于我们的水平比较菜和学习状态比较懒散,我们没有完成。大一的时候我在机房里无意发现别人留下的俄罗斯方块程序,运行,老师发现后激动的问我是我写的吗,我惭愧的摇摇头。那时看到别人做c的大程序深感羡慕(自己只是写几十行的程序)。数年后我仍然看到有不同样式的实现,但是我一直没有实现它,知道今天忽然有这个想法去做,算是弥补多年前的遗憾和心愿吧。 --------------------------------------------- Q&A: ---------------------------------------------- Q:我编译时出现错误:fatal error C1083: Cannot open include file: 'bios.h': Nosuch file or directory,该如何解决? A:正文中的代码,是使用Borland公司的TC2.0编译的,编译结果运行在Windows的16位虚拟机上。bi os.h是属于TC的头文件,在VC或者其他编译器中可能没有这个头文件。因此会产生这个错误。 解决办法: (1)可以下载附件中的压缩包,是使用VC6.0进行编译的版本,编译结果是Windows程序,运行在wind ows 32系统上。两者之间的算法完全一致,区别仅仅是绘图时采用的接口不同,TC下采用BGI(进入图形模式),VC下采用的是GDI(使用DC进行绘图)。 (2)下载TC2.0进行编译。 Q:使用TC3.0进行编译时,提示未能初始化图形模式,请使用initgraph函数。 A:这是因为TC3.0的BGI文件的路径和TC2.0有所不同。TC2.0的BGI文件位于TC路径下。而TC3.0的BGI文件位于BGI文件夹中。请把initgame函数中的initgraph函数中的第三个参数设置为正确的路径。例如:initgraph(&..,&..,"C:\\TC\\BGI"); Q:编译后运行时,弹出错误对话框报告16位虚拟机遇到不可执行的指令,点击确定后退出。 A:该问题在某些环境中出现,可能是基于软件或者硬件环境造成,具体原因暂时未知。为避免该问题,请加载附件中的压缩包VC6.0版本。 /*学无止境*/ #include <> #include <> #include <> #define ESC 27 #define UP 328 #define DOWN 336 #define LEFT 331 #define RIGHT 333 #define BLANK 32 #define BOTTOM 2 #define CANNOT 1 #define CAN 0 #define MAX 30 #define F1 315 #define ADD 43 #define EQUAL 61 #define DEC 45 #define SOUNDs 115 #define SOUNDS 83 #define PAUSEP 80 #define PAUSEp 112 void Init(); void Down(); void GoOn(); void ksdown(); void Display(int color); void Give(); int Touch(int x,int y,int dx,int dy); int GeyKey(); void Select(); void DetectFill(); void GetScores(); void Fail(); void Help(); void Quit(); void DrawBox(int x,int y,int Color); void OutTextXY(int x,int y,char *String); void DispScore(int x,int y,char Ch); void DrawNext(int Color); int Heng=12,Shu=20; /*横竖*/ int Position[MAX][MAX]; int middle[MAX][MAX]; int ActH,ActS; #include #include C语言之游戏 俄罗斯方块课程设计报告 专业:[] 学生姓名:[] 指导教师:[] 完成时间: 目录 一、需求分析 ................................. 错误!未定义书签。 二、概要设计 ................................. 错误!未定义书签。 三、详细设计 ................................. 错误!未定义书签。 四、调试分析 (19) 五、用户手册 (20) 六、测试数据 ................................. 错误!未定义书签。 七、附录..................................... 错误!未定义书签。 一、需求分析 1.该程序是完成一个简易的俄罗斯方块的任务,其要完成几个重要的功能:界面,方块下落,旋转,判断是否还能下落,左右移动,分数,速度设置,清楚满的每行,下个方块的预览等; 2.可用#include 课程名称《数据结构》课程设计指导老师 所在学院 专业年级 提交日期 成绩 小组成员表 课程设计实验 一、需求分析 我们对俄罗斯方块这个游戏一点也不陌生,知道游戏的玩法和实现后,我们很快就着手开干。游戏要有出现场景、方块、消除方块得分、判断游戏结束等几个大功能。结构清晰简洁便于分工。 二、算法原理介绍 游戏主要使用了数组这个数据结构。不过与以往的程序不同,这个游戏有一个大数组包含很多个小数组,大数组不断的吸收小数组内的元素,达到条件得分。 三、概要设计 1、功能块各函数列表 2、场景的设置 int map[28][17]={ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1}, {0,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1}, {0,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1}, {0,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} }; void showmap() { int i,j; for(i=5;i<28;i++) { for(j=1;j<17;j++) { gotoxy(2*j,i); if(j==1||j==2||j==15||j==16) {printf("┃");} else if(i==26||i==27) {printf("━");} else if(map[i][j]==1) printf("■"); else if(map[i][j]==0) printf("□"); } } } 一个c语言写的俄罗斯方块的代码#include <stdlib.h> #include <graphics.h> #include <bios.h> #define mDRAW 5 #define mLINE 6 #define mADOWN 7 #define mGEN 8 #define mLEFT 75 #define mRIGHT 77 #define mSPACE 57 #define mESC 1 #define TIMEINT 2 #define MAXX 9 #define MAXY 30 #define BACKCOLOR BLACK #define WINX 50 #define WINY 470 #define GAP 6 #define AREAX (WINX+GAP) #define AREAY (WINY-GAP) int oldarea[MAXY+1][MAXX]; int area[MAXY+1][MAXX]; int actW,actH,actX,actY; int curX,curY,curColor,curW,curH; int newX,newY,newColor,newW,newH; int active; int box[4][4]; int FORCOLOR; int MESSAGE; int BOX[7][4][4]={ { {1,1,1,1}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} },{ {1,1,1,0}, {1,0,0,0}, {0,0,0,0}, {0,0,0,0} },{ > #include <> #include <> #include <> __cplusplus #define __CPPARGS ... #else #define __CPPARGS #define MINBOXSIZE 15 /* 最小方块的尺寸*/ #define BGCOLOR 7 /* 背景着色*/ #define GX 200 #define GY 10 #define SJNUM 10000 /* 每当玩家打到一万分等级加一级*/ /* 按键码*/ #define VK_LEFT 0x4b00 #define VK_RIGHT 0x4d00 #define VK_DOWN 0x5000 #define VK_UP 0x4800 #define VK_HOME 0x4700 #define VK_END 0x4f00 #define VK_SPACE 0x3920 #define VK_ESC 0x011b #define VK_ENTER 0x1c0d /* 定义俄罗斯方块的方向(我定义他为4种)*/ #define F_DONG 0 #define F_NAN 1 #define F_XI 2 #define F_BEI 3 #define NEXTCOL 20 /* 要出的下一个方块的纵坐标*/ #define NEXTROW 12 /* 要出的下一个方块的横从标*/ #define MAXROW 14 /* 游戏屏幕大小*/ #define MAXCOL 20 #define SCCOL 100 /*游戏屏幕大显示器上的相对位置*/ #define SCROW 60 int gril[22][16]; /* 游戏屏幕坐标*/ int col=1,row=7; /* 当前方块的横纵坐标*/ int boxfx=0,boxgs=0; /* 当前寺块的形壮和方向*/ int nextboxfx=0,nextboxgs=0,maxcol=22;/*下一个方块的形壮和方向*/ int minboxcolor=6,nextminboxcolor=6; int num=0; /*游戏分*/ int dj=0,gamedj[10]={18,16,14,12,10,8,6,4,2,1};/* 游戏等级*/ /* 以下我用了一个3组来纪录方块的最初形状和方向*/ int boxstr[7][4][16]={{ C语言课程设计报告 主标题: C语言课程设计 副标题:俄罗斯方块游戏 ----界面设计 姓名:卢文俊 指导教师:刘慧 院系:信息工程学院 专业:计算机科学与技术 班级: 11计本(二)班 小组成员:卢文俊,齐伟,陈龙 提交日期: 2012-6-7 俄罗斯方块程序设计报告 一、问题描述: 要求支持键盘操作和7种不同类型方块的旋转变换,并且界面上显示下一个方块的提示以及当前的玩家的得分,随着游戏的进行,等级越高,游戏难度越大,即方块的下落速度越快,相应的等级,等级越高,消去一行所得到的分数越高,为玩家提供了不同的选择。 二、功能分析: 俄罗斯方块游戏需要解决的问题包括: ⑴按任意键开始游戏,随机产生方块并自动下移 ⑵用Esc键退出游戏。 ⑶用键变换方块 ⑷用键和键左右移动方块 ⑸用键使方块加速下移 ⑹用空格键使方块直接下移 ⑺能正确判断满行并消行、计分、定级别 ⑻能正确计时 ⑼设定游戏为不同级别,级别越高难度越大 重点: *游戏面包的数据结构:二维数组 *7种形状方块的数据结构:结构体保存每种形状方块的坐标、颜色 三、程序设计: 1、程序总体设计结构:首先初始化进入图形模式,进入欢迎界面,玩家按 任意进入主菜单界面,按键进入游戏界面,键然后设置新的时钟中断。开始游戏后,进入该程序最核心的部分——处理和实现进行过程中的各种事件和函数。在处理中判断游戏是否结束,如果没有结束,则重新开始游戏,否则结束游戏。详解如下: (1)、游戏方块预览功能。在游戏过程中,当在游戏底板中出现一个游戏方块时,必须在游戏方块预览区域中出现下一个游戏方块,这样有利于游戏玩家控制游戏的策略。由于在此游戏中存在19种不同的游戏方块,所以在游戏方块预览区域中需要显示随机生成的游戏方块。 (2)、游戏方块控制功能。通过各种条件的判断,实现对游戏方块的左移、右移、快速下移、自由下落、旋转功能,以及行满消除行的功能。 俄罗斯方块游戏 初始化图形模式 (欢迎界面) 进入菜单选项 开 始新游戏游 戏 帮 助 游 戏 说 明 退 出 游 戏 游 戏 排 名 开始游戏 C语言编写的《俄罗斯方块》详解.txt铁饭碗的真实含义不是在一个地方吃一辈子饭,而是一辈子到哪儿都有饭吃。就算是一坨屎,也有遇见屎壳郎的那天。所以你大可不必为今天的自己有太多担忧。335280641 Tc2.0 编写俄罗斯方块游戏 很多编程爱好者都编写过俄罗斯方块的游戏程序。很久以前,我用Tc2.0也做过一个;最近有好些朋友看见我以前的俄罗斯方块的程序后, 问我是怎么做的。我一直想把这个程序的整个过程写一份详细的东西,与各位编程爱好者分享,一直没空。正好现在放假了, 而且离回家还有几天。于是我就把这个程序重新写了一遍,尽量使程序的结构比较清晰好懂一些。同时写了下面的这份东西。 俄罗斯方块游戏的程序中用到了一些方法。为了比较容易理解这些方法,我在讲述的同时写了些专门针对这些方法的示例程序。 这些示例程序力求短小,目的是用最小的代码能够清楚的示例所用的方法。这些示例程序都经过tc2.0测试。 最后还附了完整的俄罗斯方块游戏的源代码,和最终的可执行程序。如果你看了这份东东,有什么意见和想法,请发电子邮件告诉我。 我将会继续更新这分东东,最新的版本可以在我的个人主页上下载。 下面的问题是有关俄罗斯方块程序的,其中有些是朋友问我的,有些是我认为可能会被问到的。我尽量按问题从易到难排列这些问题。 关于俄罗斯方块程序的一些问题: ****************************************************** Tc2.0中怎么样设置图形显示? Tc2.0中常用图形函数的用法? 怎样获取鍵盘输入? 怎样控制方块的移动? 怎样控制时间间隔(用于游戏中控制形状的下落)? 游戏中的各种形状及整个游戏空间怎么用数据表示? 游戏中怎么判断左右及向下移动的可能性? 游戏中怎么判断某一形状旋转的可能性? 按向下方向键时加速某一形状下落速度的处理? 怎么判断某一形状已经到底? 怎么判断某一已经被填满? 怎么消去已经被填满的一行? 怎么消去某一形状落到底后能够消去的所有的行?(如长条最多可以消去四行) 怎样修改游戏板的状态? 怎样统计分数? 怎样处理升级后的加速问题? 怎样判断游戏结束? 关于计分板设计的问题。 关于“下一个”形状取法的问题。 C语言课程设计报告 I、俄罗斯方块游戏需要解决的问题包括: ⑴、随机产生方块并自动下移 ⑵、用Esc键退出游戏 ⑶、用键变体 ⑷、用键和键左右移动方块 ⑸、用空格键使游戏暂停 ⑹、能正确判断满行并消行、计分、定级别 ⑺、设定游戏为不同级别,级别越高难度越大 II、俄罗斯方块游戏需要设计的功能函数包括: ⑴、声明俄罗斯方块的结构体 ⑵、函数原型声明 ⑶、制作游戏窗口 (2)、游戏方块控制功能。通过各种条件的判断,实现对游戏方块的左移、右移、自由下落、旋转功能,以及行满消除行的功能。 (3)、游戏数据显示功能。在游戏玩家进行游戏过程中,需要按照一定的游戏规则给玩家计算游戏分数。例如,消除一行加100分,游戏分数达到一定数量 之后,需要给游戏者进行等级的上升,每上升一个等级,游戏方块的下落速度将加快,游戏的难度将增加。以上游戏数据均会在游戏界面右侧显示以提示玩家。 (4)、游戏信息提示功能。玩家进入游戏后,将有对本游戏如何操作的友情提示。 (5)、游戏结束退出功能。判断游戏结束条件,通过Esc键进行退出。 游戏是否结束 是 关闭游戏界面返回程序 游戏执行主流程图 2、界面设计 分为左右两个部分: *左边为游戏面板 *右边有三部分:游戏数据提示框、下一个方块提示框和功能提示框 3、重要功能函数设计 1)、声明俄罗斯方块的结构体 struct Tetris { int x; //中心方块的x轴坐标 int y; //中心方块的y轴坐标 int flag; //标记方块类型的序号 int next; //下一个俄罗斯方块类型的序号 void del_full(HANDLE hOut,struct Tetris *); //开始游戏 void start_game(); 3)、制作游戏窗口 void make_frame() { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //定义显示器句柄变量gotoxy(hOut,FrameX+Frame_width-5,FrameY-2); //打印游戏名称C语言俄罗斯方块游戏源代码
C语言课程设计报告 俄罗斯方块改进版
俄罗斯方块C语言代码
C语言课程设计俄罗斯方块源代码
俄罗斯方块C语言程序设计报告
教你用c语言写俄罗斯方块
C语言编写俄罗斯方块实验报告
C语言程序设计-俄罗斯方块源程序
C语言俄罗斯方块游戏源代码
C语言俄罗斯方块(详解..)
c语言俄罗斯方块代码
c语言俄罗斯方块实验报告
c语言数据结构程序设计俄罗斯方块
一个c语言写的俄罗斯方块的代码
俄罗斯方块C语言代码
c语言俄罗斯方块游戏程序设计报告
C语言编写的《俄罗斯方块》详解
俄罗斯方块C语言程序设计报告