武汉电力职业技术学院《C语言程序设计》课程实习指导书黄逵中2015.5C语言程序设计课程实习for14241一、实习时间2015.6.23~2015.6.26(第16周)二、实习地点计算机中心50508三、实习内容编码实现“俄罗斯方块”游戏程序四、实习计划时间内容要求第一天上午程序设计方案及代码编写方法第一天下午阅读理解设计方案写出自己理解的设计方案第二天输入、调试已给定的代码仔细阅读,并写出对函数的理解第三天上午编写、调试待编函数写出设计思路、算法第三天下午编写、调试待编函数写出设计思路、算法第四天上午给所有函数重要(主要)语句添加注解第四天下午编写实习报告提交报告五、指导教师黄逵中、谢光良六、程序设计方案1.图形及其形态的表示a)图形的外观形状5形态1形态2形态3形态4形状2形状1形状3形状41/20C语言程序设计课程实习for14241b)图形及其形态的表示共有5种不同形状的图形,其展现出来的形态分别有1、2、4种,共有15种图形形态;每一种图形都由4个方块构成。为了方便起见,可以将所有图形及其不同形态统一地看作是4*4的大方格,每一个大方格填涂其中4个小方格。因此,每一个图形形态都可以用一个4*4的二维数组来表示,没有填涂的小方格用0值表示,填涂的小方格用非0值的表示。例如形状1的形态1:{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}}形状1的形态2:{{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}}由于图形不止一种形态,最多有4种,因此,每一种图形可以用4*4*4的三维数组来表示每一种图形的各个不同的形态。例如,图形1{{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},{{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}},{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}当然,表示所有图形的所有形态,可以一个5*4*4*4的四维数组来表示。但是,由于并不是所有的图形都有4种形态,为了处理形态变化的方便,还必须用一个一维数组来保存5种图形的形态数。即{2,1,4,4,4}方法一:图形数组:intShapes[图形数][形态数][大方块行数][大方块列数]图形形态数数组:intStateCount[图形数]方法二:由于图形及其形态是一个整体,因此使用结构体来表示图形更合理。定义图形结构体类型typedefstruct_Shape{intStateCount;intBlocks[4][4][4];}Shape;图形数组:ShapeShapes[图形数];2.方块堆积区的表示方块堆积区即图形可移动、方块堆积的平面区域。显然可以一个二维数组来表示。unsignedshortRoom[行数][列数],其元素的值表示位置是否有方块堆积,0表示没有,非0值表示有。3.图形的显示游戏的过程中,图形的形状、形态、位置是变化的,因此,程序(1)必须能实现定位显示(2)在新位置或形状显示之前,必须先擦除旧位置或旧形状的图形2/20C语言程序设计课程实习for14241a)定位显示Windows控制台C运行库提供如下函数BOOLSetConsoleCursorPosition(HANDLE控制台句柄,COORD屏幕坐标);HANDLEGetStdHandle(STD_OUTPUT_HANDLE);typedefstruct_COORD{SHORTX;SHORTY;}COORD,*PCOORD;b)将光标定位到可移动区域内的相对坐标(x,y)voidGotoXY(intx,inty)区域的相对坐标(x,y)变换成控制台坐标(sx,sy):sxx+x0;syy+y0调用SetConsoleCursorPositionc)在可移动区域(x,y)处显示图形shape的s形态voidShowShape(void)r0当r4c0当c4shape.blocksT[s][r][c]非0F定位到(x+c,y+r)显示方块(‘\xdb’)c++r++XY■(x,y)Ox0y0sxsyO3/20C语言程序设计课程实习for14241d)擦除当前位置(x,y)上的当前图形(当前状态s)voidEraseShape(void)r0当r4c0当c4shape.blocksT[s][r][c]非0F定位到(x+c,y+r)显示空白(‘\x20’)c++r++4.创建图形s随机产生0~4当前图形CurrentShapeShapes[s];c随机产生0~3当前图形颜色CurrentColorcolors[c];当前图形纵坐标CurrectY0;当前图形横坐标CurrentX堆积窗中间当前图形形态CurrentState05.移动图形voidMoveShapeDown(void);voidMoveShapeLeft(void);voidMoveShapeRight(void);当前图形可以T移动到新位置F擦除当前位置的图形改变当前位置坐标在当前位置显示图形6.改变图形形态voidRotateShape(void);下一形态sn(当前形态s+1)%shape.stateCount当前图形sn形态(即当前图形T能在当前位置能变换形态)F擦除当前位置的图形改变当前的形态ssn在当前位置显示图形4/20C语言程序设计课程实习for142417.图形可移动到新位置(x,y)/图形能否在(x,y)位置变换形态intCanMoveTo(intstate,intx,inty);r0当r4c0当c4shape.blocks并且roomT[state][r][c]非0[x+r][y+c]非0F返回0c++r++返回18.创建图形当前图形:shape,图形形态:state,当前位置:(x,y)voidFreezeShape(void)r0当r4c0当c4shape.blocksT[state][r][c]非0Froom[y+r][x+c]shape.blocks[state][r][c]c++r++5/20C语言程序设计课程实习for142419.判断方块堆积是否成行,成行则消除成行方块当前图形坐标(x,y)lines[4]{0};count0r3当r=0c0当c堆积窗宽度room[y+r]T[x+c]==0F退出循环c++c==堆积T窗宽度F记录成行行号:lines[count]y+rcount++r--countT0Fi0当icountrlines[i]当r0c0当c堆积窗宽度room[r][c]room[r-1][c]c++r--ji+1当jcountlines[j]++j++i++6/20C语言程序设计课程实习for1424110.主函数设置屏幕模式初始化room、初始化随机函数种子等创建图形显示图形显示分数永真循环图形不能下移并且T图形在最顶部F游戏结束key01秒钟T内有击键Fkey扫描码是ESCT键(key==27)F退出无击键T或向下箭头键(key==80)F可以T下移F向左T箭头键(key==75)F下移一行左移一列向右T箭头键(key==77)F还可T以再下移F右移一列向上T箭头键(key==72)F固定图形变换形态是空格键(key==32)方块T成行F直落到底消除成行方块消除成行方块记分记分创建图形创建图形显示图形显示图形7/20C语言程序设计课程实习for14241七、系统函数1.获取控制台句柄HANDLEWINAPIGetStdHandle(__inDWORDnStdHandle//要获取有的标准设备);2.设置控制台显示模式BOOLWINAPISetConsoleDisplayMode(__inHANDLEhConsoleOutput,//控制台句柄__inDWORDdwFlags,//显示模式PCOORDlpNewScreenBufferDimensions//屏幕缓冲区大小指针);3.设置控制台显示代码页BOOLWINAPISetConsoleCP(__inUINTwCodePageID//代码页标识437为美国英文,);//936为简体中文4.设置控制台光标位置BOOLWINAPISetConsoleCursorPosition(__inHANDLEhConsoleOutput,//控制台句柄__inCOORDdwCursorPosition//光标位置);5.线程暂停VOIDWINAPISleep(__inDWORDdwMilliseconds//暂停毫秒数);6.系统时钟“嘀哒”数DWORDWINAPIGetTickCount(void);//返回系统启动至今的毫秒数7.设置随机种子voidsrand(unsignedintseed//种子);8.随机函数intrand(void);//返回0~32767范围内的随机数9.检测是否有击键int_kbhit(void);//有击键返回非0,否则返回010.获取击键值int_getch(void);//获取击键的扫描码8/20C语言程序设计课程实习for14241八、参考程序(部分)#includestdio.h#includestdlib.h#includewindows.h#includeconio.h#includectype.h#includewincon.h//定义符号常量#defineFRM_WIDTH20//堆积窗宽度#defineFRM_HEIGHT20//堆积窗高度#defineBLOCK'\xdb'//方块字符#defineSPACE'\x20'//空白字符//类型定义typedefBOOL(WINAPI*PROCSETCONSOLEDISPLAYMODE)(HANDLE,DWORD,PCOORD);PROCSETCONSOLEDISPLAYMODESetConsoleDisplayMode;typedefstruct_shape//形状类型{intStateCount;//图形形态数intBlocks[4][4][4];//不同形态的方块}Shape;//全局函数声明voidCreateShape(void);//创建图形voidShowShape(void);//显示图形intCanMoveTo(intstate,intx,inty);//可将图形的形态state移动到(x,y)处?voidMoveShapeDown(void);//向下移动图形一行voidMoveShapeLeft(void);//向左移动图形一列voidMoveShapeRight(void);//向右移动图形一列voidRotateShape(void);//旋转图形—变换图形形态voidDropShape(void);//图形直接坠落到底voidShowFrame(void);//显示堆积窗边框voidEraseShape(void)//擦除当前图形voidFreezeShape(void);//固定图形voidRemoveLines(void);//消除连成行的方块voidShowScores(void);//显示分数voidClearGame(void);//清理游戏voidGotoXY(intx,inty);//光标定位到堆积窗(x,y)voidShowOperateHelp(void);//显示操作帮助intGameOver(void);//显示“GameOver!”,返回值是否继续9/20C语言程序设计课程实习for14241//全局变量定义ShapeShapes[5]=//五种图形{{2,{{{1,1,1,1}},{{1},{1},{1},{1}}}},{1,{{{1,1},{1,1}}}},{4,{{{1,1,1},{0,1}},{{1},{1,1},