《俄罗斯方块C++课程设计报告.doc》由会员分享,可在线阅读,更多相关《俄罗斯方块C++课程设计报告.doc(12页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、课程设计报告题 目 :基于C+俄罗斯方块学 院: 专 业: 学 号: 姓 名: 二一三 年 十二 月经典小游戏设计-俄罗斯方块一、 需求分析。1.1、游戏需求随机给出不同的形状长条形、Z字形、反Z形、田字形、7字形、反7形、T字型下落填充给定的区域,假设填满一条便消掉,假设在游戏中各形状填满了给定区域,为输者,弹出相应提示。1.2、游戏界面需求良好的用户界面,有关信息显示如操作方法、等级等。让方块在一定的区域内运动和变形,该区域用一种颜色说明,即用一种颜色作为背景,本游戏的背景设为黑色。还需用另一种颜色把黑色围起来,宽度适中,要实现美感。而不同的方块用不同的着色表示,使游戏界面更加清晰、有条理
2、。消层时采用一定的时间延迟,增加视觉消行的感官效果。1.3、游戏方块需求良好的方块形状设计,绘制七种常见的根本图形长条形、Z字形、反Z形、田字形、L字形、反L形、T字型以及另外本程序另外参加的点形方块,各个方块要能实现它的变形,可设为顺时针或逆 时针变形,一般为逆时针。为表达游戏的趣味性和扩展性,本游戏象征性的增加了点形方块,其他更多形状的方块可用类似方法增加。1.4、游戏控制的需求游戏控分为多个方面,包括画面绘制,控制命令的获取,控制命令的分配、控制命令的处理,方块的绘制,方块的移动,方块的旋转,方块下落和消层以及计分等。对各个命令的合理处理和综合控制十分重要,一旦出错可能导致整个程序的崩溃
3、,因此需要小心设计。二、 系统设计。2.1、程序流程图:2.2、游戏设计概述从整体上而言,在该游戏可设计一个方块类,其中包括对方块的信息描述(如:ID)、方块的操作如:旋转、下沉。再设计一个控制类,实现各种控制如:获取控制信号,分发控制信号。另定义一个游戏区类,用以处理游戏区绘制等内容。框图如下: 方块类GAME_BLOCK游戏区类Window Private:BLOCKINFO g_CurBlock;(新方块)BLOCKINFO g_NextBlock;下一方块Private:无Public:Void InitWindow()Public:GAME_BLOCK ()GAME_BLOCK ()
4、void NewBlock();/生成方块bool CheckBlock(BLOCKINFO _block);/检测方块能否放下void DrawBlock(BLOCKINFO _block,DRAW_draw=SHOW);void OnRotate();/旋转方块void OnLeft();/ 左移方块void OnRight();/ 右移方块void OnDown();/ 下移方块void OnSink(CGAME &);/ 沉底方块BLOCKINFO &CurBlock();BLOCKINFO &NextBlock();游戏控制类CGamePrivate:Void DispatchCon
5、trol(CTRL);Public:void InitGame();/初始化游戏Void Start_Game();/开场游戏void Game_Over();/游戏完毕void NewGame();/新游戏void Quit_Game();/退出游戏CTRL GetControl(bool _onlyresettimer = false);/获取控制命令在主函数中按照2.1中框图,先通过控制类初始化游戏,再通过随机时间函数获得一个随机数,该随机数确定一个方块,即用该随机数产生一个ID从而确定产生的为方块。然后从键盘取得各种操作信号,通过控类函数对操作信号进展分发、处理,进而控制方块的行为改变
6、。与此同时,监控游戏区中已有方块的状态,一旦满足消行即进展消行控制,同时进展计分和等级划分,而如果游戏区已满那么游戏完毕,弹出提示。而对界面和方块的展现主要通过第三方软件EasyX实现,通过其画图位置的改变与时间的结合到达方块视觉移动的效果。2.3、定义方块的数据构造方块是本游戏的根本要素,对于方块的设计,本游戏用4*4的矩阵画出来,在相应的位置置为1和0以实现各种方块的形状,以“立L形为例如下:0100010001100000而在程序设计中那么赋予各种根本方块一个不同的十六进制ID即可表示该方块,如“立7形其ID为0x4460,再与其其他变形组合和着色分配即可得到各种L形ID的集合0x446
7、0, 0x02E0, 0x0622, 0x0740,MAGENTA;其他各种方块类似设计。具体清单如下:0x0F00, 0x4444, 0x0F00, 0x4444, RED,/ I0x0660, 0x0660, 0x0660, 0x0660, BLUE,/ 口0x4460, 0x02E0, 0x0622, 0x0740, CYAN, / L 蓝绿色0x2260, 0x0E20, 0x0644, 0x0470, GREEN,/ 反L0x0C60, 0x2640, 0x0C60, 0x2640, BROWN,/ Z0x0360, 0x4620, 0x0360, 0x4620, YELLOW,/
8、反Z0x4E00, 0x4C40, 0x0E40, 0x4640, MAGENTA;/ T 品红2.4、方块的变形方块要实现变形,其实就是通过EasyX画出不同的图形来实现的,当然乱画是不行的,而为了控制其变形的情况,必须设定相应的图形描述,本程序使用的是不同图形的不同ID码表示的方法来实在方块的描述的。能过键盘接收变形指令即向上键,将所得信号传递给信号接收函数,再通过信号处理函数改变当前方块的ID值,最后根据新的ID值画出新的图形,此时即实在了方块的变形。2.5、定时处理机制为了提高游戏的易控性和自动性,定时机制是很有必要的。经过定时器的设置后,这里通过利用控制程序跳到定时器的时间的处理函数
9、去实现,当固定时间片间隔到达后,先检测当前下坠物是否已经到达了底部,不是那么进展下坠物向下移动一个单位的操作,是那么到底后产生一个新的“下一个下坠物,并代替旧的,将原先旧的“下一个下坠物用作当前激活状态下正在使用的下坠物,并对使用后的一些状态进展检测:是否马上到达底部,使那么进展销行操作;是否在到达底部的同时到达游戏区域的顶部,从而判定游戏是否因违规而完毕,弹出相应对话框供用户选择是否继续重新开场。图 装载方块 视图类通过不同十六进制ID来记录下坠物的类型,共有七种形状,并从7种方块中随机抽取图形。而ID除了记录下坠物的类型外,还需记录其当前的变形状态。在产生新的下一个下坠物前,需要先将当前状
10、态物的记录和旧的下一个下坠物保存下来,然后用随机函数Random()产生一个最大值不大于指定值的随机正整数,将这个新生成的正整数用作新的“下一个下坠物的形状值。三、关键代码描述。#include #include #include / 定义常量、枚举量、构造体、全局变量#defineWIDTH10/ 游戏区宽度#defineHEIGHT22/ 游戏区高度#defineUNIT20/ 每个游戏区单位的实际像素/ 定义操作类型enum CMDCMD_ROTATE,/ 方块旋转CMD_LEFT, CMD_RIGHT, CMD_DOWN,/ 方块左、右、下移动CMD_SINK,/ 方块沉底CMD_QU
11、IT/ 退出游戏/ 定义绘制方块的方法enum DRAWSHOW,/ 显示方块CLEAR,/ 擦除方块FIX/ 固定方块/ 定义七种俄罗斯方块struct BLOCKWORD dir4;/ 方块的四个旋转状态COLORREF color;/ 方块的颜色g_Blocks7 = 0x0F00, 0x4444, 0x0F00, 0x4444, RED,/ I0x0660, 0x0660, 0x0660, 0x0660, BLUE,/ 口0x4460, 0x02E0, 0x0622, 0x0740, CYAN, / L 蓝绿色0x2260, 0x0E20, 0x0644, 0x0470, GREEN,
12、/ 反L0x0C60, 0x2640, 0x0C60, 0x2640, BROWN,/ Z0x0360, 0x4620, 0x0360, 0x4620, YELLOW,/ 反Z0x4E00, 0x4C40, 0x0E40, 0x4640, MAGENTA;/ T 品红/ 定义当前方块、下一个方块的信息struct BLOCKINFObyte id;/ 方块 IDchar x, y;/ 方块在游戏区中的坐标byte dir:2;/ 方向g_CurBlock, g_NextBlock;/ 定义游戏区BYTE g_WorldWIDTHHEIGHT = 0;/ 函数声明void Init();/ 初始
13、化游戏void Quit();/ 退出游戏void NewGame();/ 开场新游戏void GameOver();/ 完毕游戏CMD GetCmd();/ 获取控制命令void DispatchCmd(CMD _cmd);/ 分发控制命令void NewBlock();/ 生成新的方块bool CheckBlock(BLOCKINFO _block);/ 检测指定方块是否可以放下void DrawUnit(int x, int y, COLORREF c, DRAW _draw);/ 画单元方块void DrawBlock(BLOCKINFO _block, DRAW _draw = SH
14、OW);/ 画方块void OnRotate();/ 旋转方块void OnLeft();/ 左移方块void OnRight();/ 右移方块void OnDown();/ 下移方块void OnSink();/ 沉底方块static int score=0;/ 函数定义/ 主函数void main()Init();CMD c;while(true)c = GetCmd();DispatchCmd(c);/ 按退出时,显示对话框咨询用户是否退出if (c = CMD_QUIT)HWND wnd = GetHWnd();if (MessageBox(wnd, _T(您要退出游戏吗?), _T(
15、提醒), MB_OKCANCEL | MB_ICONQUESTION) = IDOK)Quit();/ 初始化游戏void Init()initgraph(640, 480);srand(unsigned)time(NULL);setbkmode(TRANSPARENT);/ 设置图案填充的背风光为透明/ 显示操作说明settextstyle(14, 0, _T(宋体);outtextxy(20, 330, _T(操作说明:);outtextxy(20, 350, _T(上:旋转);outtextxy(20, 370, _T(下:下移);outtextxy(20, 390, _T(左:左移);
16、outtextxy(20, 410, _T(右:右移);outtextxy(20, 430, _T(空格:沉底);outtextxy(20, 450, _T(ESC:退出);outtextxy(40, 150,_T(score);/ 设置坐标原点setorigin(220, 20);/ 绘制游戏区边界rectangle(-1, -1, WIDTH * UNIT, HEIGHT * UNIT);rectangle(WIDTH + 1) * UNIT - 1, -1, (WIDTH + 5) * UNIT, 4 * UNIT);/ 开场新游戏NewGame();/ 退出游戏void Quit()c
17、losegraph();exit(0);/ 开场新游戏void NewGame()/ 清空游戏区setfillcolor(BLACK);solidrectangle(0, 0, WIDTH * UNIT - 1, HEIGHT * UNIT - 1);ZeroMemory(g_World, WIDTH * HEIGHT);/ 生成下一个方块g_NextBlock.id = rand() % 7;g_NextBlock.dir = rand() % 4;g_NextBlock.x = WIDTH + 1;g_NextBlock.y = HEIGHT - 1;/ 获取新方块NewBlock();/
18、 完毕游戏void GameOver()HWND wnd = GetHWnd();if (MessageBox(wnd, _T(游戏完毕。n想重新来一局吗?), _T(游戏完毕), MB_YESNO | MB_ICONQUESTION) = IDYES)NewGame();elseQuit();/ 获取控制命令DWORD m_oldtime;CMD GetCmd()/ 获取控制值while(true)/ 如果超时,自动下落一格DWORD newtime = GetTickCount();if (newtime - m_oldtime = 500)m_oldtime = newtime;retu
19、rn CMD_DOWN;/ 如果有按键,返回按键对应的功能if (kbhit()switch(getch()case w:case W:return CMD_ROTATE;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:switch(getch()case 72:return CMD_ROTATE;case 75:return CMD_L
20、EFT;case 77:return CMD_RIGHT;case 80:return CMD_DOWN;/ 延时 (降低 CPU 占用率)Sleep(20);/ 分发控制命令void DispatchCmd(CMD _cmd)switch(_cmd)case CMD_ROTATE:OnRotate();break;case CMD_LEFT:OnLeft();break;case CMD_RIGHT:OnRight();break;case CMD_DOWN:OnDown();break;case CMD_SINK:OnSink();break;case CMD_QUIT:break;/ 生
21、成新的方块void NewBlock()g_CurBlock.id = g_NextBlock.id,g_NextBlock.id = rand() % 7;g_CurBlock.dir = g_NextBlock.dir,g_NextBlock.dir = rand() % 4;g_CurBlock.x = (WIDTH - 4) / 2;g_CurBlock.y = HEIGHT + 2;/ 下移新方块直到有局部显示WORD c = g_Blocksg_CurBlock.id.dirg_CurBlock.dir;while(c & 0xF) = 0)g_CurBlock.y-;c = 4;
22、/ 绘制新方块DrawBlock(g_CurBlock);/ 绘制下一个方块setfillcolor(BLACK);solidrectangle(WIDTH + 1) * UNIT, 0, (WIDTH + 5) * UNIT - 1, 4 * UNIT - 1);DrawBlock(g_NextBlock);/ 设置计时器,用于判断自动下落m_oldtime = GetTickCount();/ 画单元方块void DrawUnit(int x, int y, COLORREF c, DRAW _draw)/ 计算单元方块对应的屏幕坐标int left = x * UNIT;int top
23、= (HEIGHT - y - 1) * UNIT;int right = (x + 1) * UNIT - 1;int bottom = (HEIGHT - y) * UNIT - 1;/ 画单元方块switch(_draw)case SHOW:/ 画普通方块setlinecolor(0x006060);roundrect(left + 1, top + 1, right - 1, bottom - 1, 5, 5);setlinecolor(0x003030);roundrect(left, top, right, bottom, 8, 8);setfillcolor(c);setline
24、color(LIGHTGRAY);fillrectangle(left + 2, top + 2, right - 2, bottom - 2);break;case FIX:/ 画固定的方块setfillcolor(RGB(GetRValue(c) * 2 / 3, GetGValue(c) * 2 / 3, GetBValue(c) * 2 / 3);setlinecolor(DARKGRAY);fillrectangle(left + 1, top + 1, right - 1, bottom - 1);break;case CLEAR:/ 擦除方块setfillcolor(BLACK)
25、;solidrectangle(x * UNIT, (HEIGHT - y - 1) * UNIT, (x + 1) * UNIT - 1, (HEIGHT - y) * UNIT - 1);break;/ 画方块void DrawBlock(BLOCKINFO _block, DRAW _draw)WORD b = g_Blocks_block.id.dir_block.dir;int x, y;for(int i = 0; i 16; i+, b = 1)if (b & 0x8000)x = _block.x + i % 4;y = _block.y - i / 4;if (y HEIGH
26、T)DrawUnit(x, y, g_Blocks_block.id.color, _draw);/ 检测指定方块是否可以放下bool CheckBlock(BLOCKINFO _block)WORD b = g_Blocks_block.id.dir_block.dir;int x, y;for(int i = 0; i 16; i+, b = 1)if (b & 0x8000)x = _block.x + i % 4;y = _block.y - i / 4;if (x = WIDTH) | (y 0)return false;if (y HEIGHT) & (g_Worldxy)retu
27、rn false;return true;/ 旋转方块void OnRotate()/ 获取可以旋转的 x 偏移量int dx;BLOCKINFO tmp = g_CurBlock;tmp.dir+;if (CheckBlock(tmp)dx = 0;goto rotate;tmp.x = g_CurBlock.x - 1;if (CheckBlock(tmp)dx = -1;goto rotate;tmp.x = g_CurBlock.x + 1;if (CheckBlock(tmp)dx = 1;goto rotate;tmp.x = g_CurBlock.x - 2;if (CheckB
28、lock(tmp)dx = -2;goto rotate;tmp.x = g_CurBlock.x + 2;if (CheckBlock(tmp)dx = 2;goto rotate;return;rotate:/ 旋转DrawBlock(g_CurBlock, CLEAR);g_CurBlock.dir+;g_CurBlock.x += dx;DrawBlock(g_CurBlock);/ 左移方块void OnLeft()BLOCKINFO tmp = g_CurBlock;tmp.x-;if (CheckBlock(tmp)DrawBlock(g_CurBlock, CLEAR);g_C
29、urBlock.x-;DrawBlock(g_CurBlock);/ 右移方块void OnRight()BLOCKINFO tmp = g_CurBlock;tmp.x+;if (CheckBlock(tmp)DrawBlock(g_CurBlock, CLEAR);g_CurBlock.x+;DrawBlock(g_CurBlock);/ 下移方块void OnDown()BLOCKINFO tmp = g_CurBlock;tmp.y-;if (CheckBlock(tmp)DrawBlock(g_CurBlock, CLEAR);g_CurBlock.y-;DrawBlock(g_Cu
30、rBlock);elseOnSink();/ 不可下移时,执行“沉底方块操作/ 沉底方块void OnSink()int i, x, y;/ 连续下移方块DrawBlock(g_CurBlock, CLEAR);BLOCKINFO tmp = g_CurBlock;tmp.y-;while (CheckBlock(tmp)g_CurBlock.y-;tmp.y-;DrawBlock(g_CurBlock, FIX);/ 固定方块在游戏区WORD b = g_Blocksg_CurBlock.id.dirg_CurBlock.dir;for(i = 0; i 16; i+, b = HEIGHT
31、)/ 如果方块的固定位置超出高度,完毕游戏GameOver();return;elseg_Worldg_CurBlock.x + i % 4g_CurBlock.y - i / 4 = 1;/ 检查是否需要消掉行,并标记BYTE remove = 0;/ 低 4 位用来标记方块涉及的 4 行是否有消除行为for(y = g_CurBlock.y; y = max(g_CurBlock.y - 3, 0); y-)i = 0;for(x = 0; x WIDTH; x+)if (g_Worldxy = 1)i+;if (i = WIDTH)remove |= (1 (g_CurBlock.y -
32、 y);setfillcolor(LIGHTGREEN);setlinecolor(LIGHTGREEN);setfillstyle(BS_HATCHED, HS_DIAGCROSS);fillrectangle(0, (HEIGHT - y - 1) * UNIT + UNIT / 2 - 5, WIDTH * UNIT - 1, (HEIGHT - y - 1) * UNIT + UNIT / 2 + 5);setfillstyle(BS_SOLID);if (remove)/ 如果产生整行消除/ 延时 300 毫秒Sleep(300);/ 擦掉刚刚标记的行IMAGE img;for(i
33、= 0; i = 1)if (remove & 1)for(y = g_CurBlock.y - i + 1; y HEIGHT; y+)for(x = 0; x WIDTH; x+)g_Worldxy - 1 = g_Worldxy;g_Worldxy = 0;getimage(&img, 0, 0, WIDTH * UNIT, (HEIGHT - (g_CurBlock.y - i + 1) * UNIT);putimage(0, UNIT, &img);score+; outtextxy(50, 150,_T(score);/ 产生新方块NewBlock();四、测试结果。程序完成后运行
34、如下,到达预期结果,运行效果良好。成功地完成了方块的显示、旋转、消行功能,游戏可玩性强,且具有封装性、通用性、容错性。五、实验总结。本次C+课程设计前期准备阶段,设想一些设想和主要任务;后期那么是具体功能的实现。这次设计中我遇到了不少困难,本来设想实现双人版对战,美化界面和增加背景音乐等功能,可是由于时间的短促,最终没能实现,心里不免有些遗憾,在实现类的封装和类的继承和多态性时,也遇到了不少问题,通过大家的一起探讨和分析,问题最终一个个迎刃而解,系统开发根本完毕。通过这次课程设计,使我懂得了不少东西。我们在日常的学习中应该注意对所学知识的实践运用,在学习时,应该深入的了解,体会知识,这对我们今后的学习和工作会有很大的帮助。通过此次的实践,我体会到学以致用的乐趣,收获了很多。