毕业设计论文-小游戏贪吃蛇的详细设计.doc
摘要在我们空闲的时候,我们可以用一些我们学过的知识编一些东西,通过这些东西我们可以学习到汇编语言综合应用程序设计方法,还可以提高汇编语言实际应用能力,充分了解计算机硬件和软件,完成理论到实践的推进过程。这个程序就是用我所学过的汇编知识编的一个小游戏,这个游戏的程序主要就是用汇编宏和子程序的知识来编制而成的,我们用宏和子程序定义了很多的模块,模块也就是在我们的程序中直接可以调用的一个独立的程序。所以我们编写程序的时候可以很方便的用到它,所以那些基础知识也是我们编写程序的基础。关键词 汇编 贪吃蛇 小游戏1前言现在有的一些人感觉生活都是很无聊的,特别是我们这些学生,所以有些时候肯定会玩各种各样的游戏的,有一些大的游戏,玩起来会话掉很多的时间,而且也会花掉大量精力的 ,所以在一些闲暇的时候一些小游戏会博得很多人的喜爱,例如:俄罗斯方块,和一些格斗游戏等等。然而这些小游戏的设计方法和软件有很多,所以也有很多不同的效果,本篇设计是采用汇编中宏定义和调用,子程序的调用等一些汇编知识编制而成的一个贪吃蛇小游戏,通过这个小游戏的制作,我们可以得到很多的益处,一方面我们可以不在浪费平时的一些空闲的时间了,而热中于我们自己喜欢的游戏;另一个方面我们制作完游戏还可以给自己或者别人来享受一下,同时自己也会有一种成就感。特别当你用自己学到的知识制作出一个东西的时候,或者克服一个困难的时候你就会发现你自己的价值所在了,而且这还能促进你喜欢学习的念头。目录一、系统分析 二、系统总体设计三、详细设计1、 窗口化程序2、 建立小蛇和食物3、 初始对话框4、 小蛇和食物的位置5、 分配内存空间6、 调整链表大小四、系统测试 1测试方案及用例2.测试结果及软件可靠性分析3.游戏规则五、软件使用说明书六、设计总结参考文献致谢程序清单 一、系统分析这个程序的总体的思想也就是主要用的就是宏和子程序的定义和调用,首先,定义了5个宏它们分别为:屏幕初始化宏定义 在光标位置显示字符和属性定义 显示字符串宏定义 置光标位置宏定义 读光标位置的字符和属性宏定义。它们在程序中起到主要的作用。其次,就是子程序定义了,程序中定义了很多的子程序,其中有:控制子程序 食物子程序,还有记分子程序等。它们首先被主程序调用,然后它们之间再互相调用,这样构成了完整的游戏程序并实现其功能。具体的设计思想是:第一,对数据进行初始化,即对寄存器的初始化,比如对食物的初始化等。第二,开始运行,判断是否符合条件,如果符合赢的条件的话,就会跳转到赢的那个子程序下,然后那个赢的子程序会调用记分的那个子程序,最后显示赢的信息和分数后再转到控制程序执行控制和其后的程序。如果要是输的话,就会跳转到输的那个子程序下,然后那个输的子程序也会调用记分的那个子程序,最后显示得分和信息。如果要是没有赢也没有输的话,那程序会跳到控制的子程序中,等控制完以后程序又会跳到程序判断的那个地方重复的执行。这个就是完成这个游戏程序的整个思想。二、系统总体设计这个程序完成的功能就是和别的游戏一样,最初,给出一个初始化的界面,和一个4个方块组成的小蛇,我们要把那个最初给出那个小蛇穿过那个闪烁的小红黄相间的小方块,然后那个小方块就会变成我们那个小蛇上的组成单元一样的一个小方块,和在别的地方会在出现另一个小方块,我们接下来要做的就是要把那个小方块穿过来,然后我们那个小蛇就会变长了,然后在穿过小方块,就这样重复的做就行了,随着你的穿过你的小蛇就会越来越长了,这是你的得分就会越高,同时你难度也会变大的,因为如果你要碰到四周的变的话,或者你自己的那个小蛇首尾要是相连的话你就会输了,所以当你那个小蛇很长的时候,难度自然就会变大了。开始初始化数据是否成功?LOSEWINNOLOSE显示分数和符号显示成功的符号上下左右的控制结束动画贪吃蛇程序的流程图三详细设计1窗口化程序.data ClassName db"DLGCLASS", 0;"snakeDlg",0 helpMsgdb"Help: Space-Pause or Start | Esc-Exit | Arrow-Direction", 0scoreMsgdb"Length:%d", 0gameoverdb"GAME OVER!", 0BkgndClrdd0000dd00h;0x00bbggrrstatusWidth dd280,350,-1gSnakeSnakeSt<>2建立小蛇和食物InitBmp proc, hWnd:HWNDinvoke GetDC, hWndmov hdc, eax;蛇体画片invoke CreateCompatibleDC, hdcmov hSnkDC, eaxinvoke LoadBitmap, hInstance, SnakeBmpmov hSnkBmp, eaxinvoke SelectObject, hSnkDC, eax;食物画片1invoke CreateCompatibleDC, hdcmov hFdDC1, eaxinvoke LoadBitmap, hInstance, FdBmp1mov hFdBmp1, eaxinvoke SelectObject, hFdDC1, eax;食物画片2invoke CreateCompatibleDC, hdcmov hFdDC2, eaxinvoke LoadBitmap, hInstance, FdBmp2mov hFdBmp2, eax invoke SelectObject, hFdDC2, eax3初始对话框WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAMLOCAL rect:RECTLOCAL ps:PosSt.if uMsg = WM_CLOSEinvoke DestroyWindow, hWnd.elseif uMsg = WM_CREATEinvoke GetWindowRect, hWnd, addr rectinvoke SetWindowPos, hWnd, HWND_NOTOPMOST, rect.left , rect.top, CLIENTW, CLIENTH, SWP_NOZORDER.elseif uMsg = WM_INITDIALOG;此时对话框子控件都已经初始化好了invoke SendDlgItemMessage, hWnd, IDC_SBR1, SB_SETPARTS, 3, offset statusWidthinvoke SendDlgItemMessage, hWnd, IDC_SBR1, SB_SETTEXT, 0, offset helpMsginvoke InitBmp, hWndinvoke InitGame, hWnd4.小蛇与食物的位置push rect.leftpop ps.xpush rect.toppop ps.ymov eax, ps.xmov ebx, ps.y;ps存放的是下一个位置的坐标5.分配内存空间DelFromTail proc, ppNode:dwordpushadassume eax:ptr Node, ebx:ptr Nodemov eax, ppNodemov eax, dword ptr eaxcmp eax, 0je LRET.if eax.next = NULL;只有一个元素,释放内在,将表头置空invoke LocalFree, eaxmov eax, ppNodemov DWORD ptr eax, 0jmp LRET.endifmov ebx, eax.next.while ebx.next != NULLmov eax, eax.nextmov ebx, ebx.next.endwmov eax.next, NULLinvoke LocalFree, ebx6.调整链表大小AddFromHeadproc,ppNode:dword, pPos:dwordpushadassume eax:ptr Node, edx: ptr PosStmov edx, pPospush edxinvoke LocalAlloc, LPTR, sizeof(Node);会改变edx的值pop edxmov ebx, edx.xmov eax.data.x, ebxmov ebx, edx.y mov eax.data.y, ebxmov ebx, ppNodemov ebx, ebxmov eax.next, ebxpush eaxmov eax, ppNodepop DWORD ptr eaxassume eax:nothing, edx:nothingpopadretAddFromHeadendp四系统测试1测试方案及用例 (1)在MASMPlus里编译snack.asm,编译无误后,接下来进行下一步测试。(2)在所创建的窗口化程序里测试小蛇上,下,左,右,和吃食物及碰撞墙壁和自己发生的现象。2. 测试结果及软件可靠性分析测试编译显示无误,出现界面图4.1 界面图测试小蛇吃食物 图4.2吃食物图吃食物成功 图4.3吃食物成功图碰撞墙壁游戏结束 图4.4碰撞墙壁游戏结束小蛇碰撞自己游戏结束 图4.5小蛇碰撞自己游戏结束图3游戏规则贪吃蛇游戏是一款简单的益智类游戏,规则很简单,就是吃屏幕上的食物增加蛇的长度来提高分数,避免蛇撞墙和撞到自己导致游戏结束。五软件使用说明书1、运行程序在我们用的软件MASM32的目录下,我们可以找到snake.exe文件,双击就可以打开了。2、玩游戏我们通过键盘的上下左右键来控制里面我们的那个小蛇的,即键盘上的键,只需要这四个键就可以了。而且有空格键可以暂停或开始游戏,esc为退出游戏。 六设计总结这个小游戏程序主要用的技术包括三个方面:第一个方面就是宏的定义及调用,这个程序当中多次用到宏汇编。这不仅减少了程序的开销,而且还减少了程序运行的时间和一些存储空间。第二个方面就是子程序的调用,这个程序中也有多处用到CALL的调用。使用子程序不仅可以提供模块化程序设计的条件,而且便于程序的调试及修改等。第三个方面就是其中的一些跳转的问题,这个用起来有点麻烦,但是这个用起来比较方便,所以文中很多很多的地方都用到这个跳转。比如:JMP,JNC,JC等。在这个游戏的设计中,其实也遇到很多的困难,比如说一些寄存器使用冲突的问题 ,还有一些是宏的使用问题和当中跳转的问题等。经过这一个小游戏程序的设计,我也深刻体会到这个汇编程序设计的意义所在了,原本在课堂上学的东西自己现在把它运用到现时的生活中的一些小的问题上,那种感觉和意义是无法用言语表达的, 在这个过程当中我也知道了汇编这门课程的重要性了。参考文献1 IBM-PC 汇编语言程序设计 沈美明等 清华大学出版社。 2 8086/8088宏汇编语言程序设计教程 第二版 王正智/编 电子工业出版社。3 80X86汇编语言程序设计教程 杨季文/等编 清华大学出版社。4钱晓捷.汇编语言程序设计(第二版). 电子工业出版社, 2003。5罗云彬.Windows环境下32位汇编语言程序设计(第二版).电子工业出版社, 2006。6 Windows API函数参考手册.人民邮电出版社, 2002。致谢 在这将近一周的汇编语言课程设计里,将我们所学的基础知识加以应用的过程中,在很紧张的时间里完成了这次的课程设计任务。但是在这样很短的时间里完成任务,我们遇到了很多汇编语法知识、程序总体设计思路、程序编程以及程序代码调试困难,幸好在刘树群老师的指导下,将一个个问题都得以解决,再次特别感谢刘老师在这次课设中的帮助。并且要感谢我们小组的另外两名组员,我们各自分工明确并且相互帮助,才完成了这次的课程设计任务。团队是每一个人组成的,只有每一个人分工明确且相互帮助下才能体现出团队的凝聚力,才能更好的完成每一个任务,在这次的课设任务里感谢我们小组以及参与到我们小组的每位成员,谢谢。程序清单.386 .model flat,stdcall option casemap:noneinclude masm32includewindows.incinclude masm32includekernel32.incinclude masm32includeuser32.incinclude masm32includegdi32.incinclude rsrc.inc;resource.hinclude masm32includecomctl32.inc;for status barinclude snake.incinclude list.incinclude d:masmplusincludemasm32.inc;for Randomincludelib masm32libkernel32.libincludelib masm32libuser32.libincludelib masm32libgdi32.libincludelib masm32libcomctl32.libincludelib d:masmpluslibmasm32.libWinMain proto :DWORD,:DWORD,:DWORD,:DWORDAboutProc proto, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAMWndProc proto hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM.data ClassName db"DLGCLASS", 0;"snakeDlg",0 helpMsgdb"Help: Space-Pause or Start | Esc-Exit | Arrow-Direction", 0scoreMsgdb"Length:%d", 0gameoverdb"GAME OVER!", 0BkgndClrdd0000dd00h;0x00bbggrrstatusWidth dd280,350,-1gSnakeSnakeSt<>.data? hInstance HINSTANCE ? CommandLine LPSTR ?hdcdd?hSnkDCdd?hFdDC1dd?hFdDC2dd?hSnkBmpdd?hFdBmp1dd?hFdBmp2dd?hbrBackground dd ?fPausedd?isOverdd?bufferdb100 dup (?).codestart: invoke InitCommonControls invoke GetModuleHandle, NULL mov hInstance,eax invoke GetCommandLine mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT invoke ExitProcess,eaxRandom proc _r0:DWORDmoveax, _r0imul eax, 23addeax, 123andeax, 7FFFHretRandom endp;将改变链表头,没有返回值AddFromHeadproc,ppNode:dword, pPos:dwordpushadassume eax:ptr Node, edx: ptr PosStmov edx, pPospush edxinvoke LocalAlloc, LPTR, sizeof(Node);会改变edx的值pop edxmov ebx, edx.xmov eax.data.x, ebxmov ebx, edx.y mov eax.data.y, ebxmov ebx, ppNodemov ebx, ebxmov eax.next, ebxpush eaxmov eax, ppNodepop DWORD ptr eaxassume eax:nothing, edx:nothingpopadretAddFromHeadendp;删除链表最后一个元素,无返回值DelFromTail proc, ppNode:dwordpushadassume eax:ptr Node, ebx:ptr Nodemov eax, ppNodemov eax, dword ptr eaxcmp eax, 0je LRET.if eax.next = NULL;只有一个元素,释放内在,将表头置空invoke LocalFree, eaxmov eax, ppNodemov DWORD ptr eax, 0jmp LRET.endifmov ebx, eax.next.while ebx.next != NULLmov eax, eax.nextmov ebx, ebx.next.endwmov eax.next, NULLinvoke LocalFree, ebxLRET:assume eax:nothing, ebx:nothingpopadretDelFromTail endpFreeAll proc, ppNode:dwordpush eaxmov eax, ppNodemov eax, eax.while eax != 0push (Node ptr eax).nextinvoke LocalFree, eaxpop eax.endwmov eax, ppNodemov dword ptr eax, 0pop eaxretFreeAllendpIsExistproc, pNode:dword, pPos:dwordpush ebxpush ecxpush edxmov eax, pNodemov edx, pPosassume eax:ptr Node, edx:ptr PosSt.while eax != NULLmov ebx, eax.data.xmov ecx, eax.data.y.if ebx = edx.x && ecx = edx.ymov eax, TRUE.break.endifmov eax, eax.next.endwassume eax:nothing, edx:nothingpop edxpop ecxpop ebxretIsExist endpWinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL wc:WNDCLASSEX LOCAL msg:MSG LOCAL hDlg:HWND mov wc.cbSize,SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra,NULL mov wc.cbWndExtra,DLGWINDOWEXTRA push hInst pop wc.hInstanceinvoke CreateSolidBrush, BkgndClrmov hbrBackground, eax mov wc.hbrBackground,eax mov wc.lpszMenuName, IDR_MENU1 mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,hInstance, SnakeIcon mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax invoke RegisterClassEx, addr wc invoke CreateDialogParam,hInstance, IDD_DLG1,NULL,WndProc,NULL mov hDlg,eax invoke ShowWindow, hDlg,SW_SHOWNORMAL invoke UpdateWindow, hDlg .WHILE TRUE invoke GetMessage, ADDR msg,NULL,0,0 .BREAK .IF (!eax) ;invoke IsDialogMessage, hDlg, ADDR msg ; .IF eax =FALSE invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg ; .ENDIF .ENDW mov eax,msg.wParam ret WinMain endpGetRandNumproc, max:dwordinvoke GetTickCountinvoke Random, eaxmov edx, 0;取余div maxmov eax, edxmov ebx, BOXSIZEmov edx, 0div ebxmul ebxretGetRandNumendpCreateFoodproc, pSnake:dwordinvoke GetRandNum, CLIENTW-BOXSIZEmov ebx, pSnakemov (SnakeSt ptr ebx).food.x, eaxinvoke GetRandNum, CLIENTH-SBR_MEN_CAP-BOXSIZEmov ebx, pSnakemov (SnakeSt ptr ebx).food.y, eaxretCreateFoodendpInitSnakeproc, pSnake:dwordlocal pos:PosStpushadmov eax, pSnakeassume eax:ptr SnakeStmov eax.len, 4mov eax.direct, EASTmov ecx, 0.while ecx < BOXSIZE*4;初始化链表,长度为4mov pos.x, ecxmov pos.y, 60;起始位置lea ebx, posinvoke AddFromHead, addr eax.header, ebxadd ecx, BOXSIZE.endwassume eax:nothingpopadretInitSnakeendpInitBmp proc, hWnd:HWNDinvoke GetDC, hWndmov hdc, eax;蛇体画片invoke CreateCompatibleDC, hdcmov hSnkDC, eaxinvoke LoadBitmap, hInstance, SnakeBmpmov hSnkBmp, eaxinvoke SelectObject, hSnkDC, eax;食物画片1invoke CreateCompatibleDC, hdcmov hFdDC1, eaxinvoke LoadBitmap, hInstance, FdBmp1mov hFdBmp1, eaxinvoke SelectObject, hFdDC1, eax;食物画片2invoke CreateCompatibleDC, hdcmov hFdDC2, eaxinvoke LoadBitmap, hInstance, FdBmp2mov hFdBmp2, eaxinvoke SelectObject, hFdDC2, eaxretInitBmp endpInitGame proc, hWnd:HWNDmov fPause, 0mov isOver, 0invoke FreeAll, offset gSnakeinvoke InitSnake, offset gSnakeinvoke CreateFood, offset gSnakeinvoke wsprintf, offset buffer, offset scoreMsg, gSnake.leninvoke SendDlgItemMessage, hWnd, IDC_SBR1, SB_SETTEXT, 1, offset bufferinvoke KillTimer, hWnd, TIMERIDinvoke SetTimer, hWnd, TIMERID, ELAPSE, NULLinvoke InvalidateRect, hWnd, NULL, TRUEretInitGame endpWndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAMLOCAL rect:RECTLOCAL ps:PosSt.if uMsg = WM_CLOSEinvoke DestroyWindow, hWnd.elseif uMsg = WM_CREATEinvoke GetWindowRect, hWnd, addr rectinvoke SetWindowPos, hWnd, HWND_NOTOPMOST, rect.left , rect.top, CLIENTW, CLIENTH, SWP_NOZORDER.elseif uMsg = WM_INITDIALOG;此时对话框子控件都已经初始化好了invoke SendDlgItemMessage, hWnd, IDC_SBR1, SB_SETPARTS, 3, offset statusWidthinvoke SendDlgItemMessage, hWnd, IDC_SBR1, SB_SETTEXT, 0, offset helpMsginvoke InitBmp, hWndinvoke InitGame, hWnd.elseif uMsg = WM_TIMER.if fPause != 0jmp LRET.elseif isOver != 0not fPauseinvoke MessageBox, hWnd, offset gameover, offset gameover, MB_ICONINFORMATIONinvoke InitGame, hWndjmp LRET.endifmov eax, hFdDC1xchgeax, hFdDC2mov hFdDC1, eaxinvoke BitBlt, hdc, gSnake.food.x, gSnake.food.y, BOXSIZE, BOXSIZE, hFdDC1, 0, 0, SRCCOPYmov eax, gSnake.headerpush (Node ptr eax).data.xpop rect.leftpush (Node ptr eax).data.ypop rect.top.if gSnake.direct = EASTadd rect.left, BOXSIZE.elseif gSnake.direct = SOUTHadd rect.top, BOXSIZE.elseif gSnake.direct = WESTsub rect.left, BOXSIZE.elsesub rect.top, BOXSIZE.endifpush rect.leftpop ps.xpush rect.toppop ps.ymov eax, ps.xmov ebx, ps.y;ps存放的是下一个位置的坐标.if eax = gSnake.food.x && ebx = gSnake.food.yinc gSnake.leninvoke wsprintf, offset buffer, offset scoreMsg, gSnake.leninvoke SendDlgItemMessage, hWnd, IDC_SBR1, SB_SETTEXT, 1, offset bufferinvoke CreateFood, offset gSnake.else.if eax < 0 | eax > CLIENTW | ebx < 0 | ebx > CLIENTH-SBR_MEN_CAP-30;越界mov isOver, 1.elseinvoke IsExist, gSnake.header, addr ps .if eax = TRUEmov isOver, 1.else;/擦除最后一个元素mov eax, gSnake.header.while eax != NULLmov ebx, (Node ptr eax).nextpush ebx.if ebx = NULLpush (Node ptr eax).data.xpop rect.leftpush (Node ptr eax).data.ypop rect.toppush (Node ptr eax).data.xpop rect.rightadd rect.right, BOXSIZEpush (Node ptr eax).data.ypop re