当前位置:文档之家› 推箱子程序设计报告

推箱子程序设计报告

程序设计报告推箱子通信学院电子信息1204工程班1207050420 郝国成一.设计思路推箱子游戏是一款很有趣味的游戏,其开发过程有一定的技巧和方法,其中涉及到二维数组、键盘操作以及图形化函数等方面的知识。

设计推箱子这个游戏,目的是将箱子推到指定的空位,以完成游戏。

首先,要在窗口上,绘制地图,画出墙和草地。

然后,要保证人和箱子可以移动,这个就用到了case WM_KEYDOWN函数去控制了。

下来,就是要制定游戏规则,根据游戏规则,箱子可以在空地之间、目的地之间、空地和目的地之间来回移动,。

最后,把全部箱子移动到指定位置才算完成本次游戏,因此箱子每移动一次都必须判断全部箱子当前位置是否到达指定坐标。

而且,只要游戏没有结束,就没有时间的限制。

大体思路确定以后就是要去怎么做,怎么去实现自己的想法。

我是采用二维数组绘制地图的原理,把资源图片一张张绘制到窗口DC上,然后记录人物资源的坐标,通过方向键响应,改变人物坐标,达到控制人物移动的目的。

箱子也同样是这个道理。

想好思路以后,就是动手写代码。

这期间我又认识了好多新的Windows的函数,不断的修改,使我更能深刻理解到WIN 32 的作用,收获很大。

二.部分代码// 推箱子.cpp : Defines the entry point for the application.#include "stdafx.h"#include "resource.h"//#include "mmsystem.h"//导入声音头文件//#pragma comment(lib,"winmm.lib")//导入声音头文件库#define MAX_LOADSTRING 100#define width 48#define heigth 48typedef struct{int x;int y;}point;char map1[10][10]=//地图二维数组{" ####"," ### @#"," # b #"," ## # ###"," # # #*#"," # # b*#"," # b *#"," ########"," "};char map2[10][10]=//地图二维数组{"nnnn#####","nnnn# @#","###n#bb #","#*#n# b #","#*### ###","#* ##n","# # #n","#### #","nnn#####"," "};static int bStarted=0;int a = 0;int aimnum_qj=0;int aimnum=0;int boxoknum_qj=0;char map_mid[10][10];char map[10][10];point man_mid;RECT map_bg[10][10];RECT ManDes;void DrawMap(HWND hWnd,char **Dmap,int m,int n);//加载地图void DrawPicture(HWND hWnd,HBITMAP hBmp,RECT spot);void keydown_up(HWND hWnd);void keydown_left(HWND hWnd);void keydown_down(HWND hWnd);void keydown_right(HWND hWnd);void up_result();void left_result();void right_result();void down_result();LPCTSTR szFileName0="man.bmp";//HBITMAP hBmp_man=(HBITMAP)LoadImage(NULL,szFileName0,IMAGE_BITMAP,0,0, //LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);HBITMAP hBmp_man=(HBITMAP)LoadImage(NULL,szFileName0,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);LPCTSTR szFileName1="box.bmp";HBITMAP hBmp_box=(HBITMAP)LoadImage(NULL,szFileName1,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);LPCTSTR szFileName2="wall.bmp";HBITMAP hBmp_wall=(HBITMAP)LoadImage(NULL,szFileName2,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);LPCTSTR szFileName3="aim.bmp";HBITMAP hBmp_aim=(HBITMAP)LoadImage(NULL,szFileName3,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);LPCTSTR szFileName4="ground.bmp";HBITMAP hBmp_ground=(HBITMAP)LoadImage(NULL,szFileName4,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);// Global Variables:HINSTANCE hInst;// current instanceTCHAR szTitle[MAX_LOADSTRING];// The title bar text TCHAR szWindowClass[MAX_LOADSTRING];// The title bar text// Foward declarations of functions included in this code module:ATOM MyRegisterClass(HINSTANCE hInstance);BOOL InitInstance(HINSTANCE, int);LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACK About(HWND,UINT,WPARAM,LPARAM);LRESULT CALLBACK Start(HWND,UINT,WPARAM,LPARAM);INT_PTR CALLBACK Help(HWND,UINT,WPARAM,LPARAM);int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){// TODO: Place code here.UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);MSG msg;HACCEL hAccelTable;// Initialize global stringsLoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// Perform application initialization:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MY);// Main message loop:while (GetMessage(&msg, NULL, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){TranslateMessage(&msg);DispatchMessage(&msg);}}return msg.wParam;}//// FUNCTION: MyRegisterClass()//// PURPOSE: Registers the window class.//// COMMENTS://// This function and its usage is only necessary if you want this code// to be compatible with Win32 systems prior to the 'RegisterClassEx'// function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated// with it.//ATOM MyRegisterClass(HINSTANCE hInstance){//wcex.lpfnWndProc= (WNDPROC)WndProc;//wcex.hIcon= LoadIcon(hInstance, (LPCTSTR)IDI_PUSHBOX); //wcex.lpszMenuName= (LPCSTR)IDC_PUSHBOX;//wcex.hIconSm= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); WNDCLASSEX wcex;wcex.cbSize=sizeof(WNDCLASSEX);wcex.style=CS_HREDRAW|CS_VREDRAW;//wcex.style=CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc=WndProc;wcex.cbClsExtra=0;wcex.cbWndExtra=0;wcex.hInstance=hInstance;wcex.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDC_MY));wcex.hCursor=LoadCursor(NULL,IDC_ARROW);wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName= MAKEINTRESOURCE(IDC_MY);wcex.lpszClassName=szWindowClass;wcex.hIconSm=LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));return RegisterClassEx(&wcex);return RegisterClassEx(&wcex);}//// FUNCTION: InitInstance(HANDLE, int)//// PURPOSE: Saves instance handle and creates main window//// COMMENTS://// In this function, we save the instance handle in a global variable and // create and display the main program window.//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){HWND hWnd;hInst = hInstance; // Store instance handle in our global variablehWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 300, 30, 680, 600, NULL, NULL, hInstance, NULL);if (!hWnd){return FALSE;}ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return TRUE;}//// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)//// PURPOSE: Processes messages for the main window.//// WM_COMMAND- process the application menu// WM_PAINT - Paint the main window// WM_DESTROY- post a quit message and return////LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;//TCHAR szHello[MAX_LOADSTRING];//LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);int winnum=0;int i,j;for(i=0;i<10;i++)//设置矩形数组,为画图作准备for(j=0;j<10;j++){map_bg[i][j].left=i*width;map_bg[i][j].top=j*heigth;map_bg[i][j].right=(i+1)*width;map_bg[i][j].bottom=(j+1)*heigth;}switch (msg){case WM_COMMAND:wmId=LOWORD(wParam);wmEvent=HIWORD(wParam);//分析菜单选项switch(wmId){case IDM_ABOUT:DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUTBOX),hWnd,(DLGPROC)About);break;case IDM_HELP://帮助对话框DialogBox(hInst,MAKEINTRESOURCE(IDM_HELP),hWnd,(DLGPROC)Help);break;case IDM_start://菜单开始选项winnum=0;aimnum_qj=0;for(i=0;i<10;i++)for(j=0;j<10;j++){map[i][j]=map1[i][j];}DrawMap(hWnd,(char **)map1,10,10);//加载原始地图aimnum=aimnum_qj;memcpy(map_mid,map1,sizeof(map1));//将原始地图复制到运行中的地图for(i=0;i<10;i++)for(j=0;j<10;j++)if(map_mid[i][j]=='@'){map_mid[i][j]=' ';}// PlaySound(TEXT("音乐名"),NULL,SND_SYNC);//开始音乐bStarted=1;break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd,msg,wParam,lParam);}break;case WM_KEYDOWN://相应方向键switch(wParam){case VK_UP://PlaySound(TEXT("声音名"),NULL,SND_SYNC);//按键音keydown_up(hWnd);break;case VK_LEFT://PlaySound(TEXT("声音名"),NULL,SND_SYNC);//按键音keydown_left(hWnd);break;case VK_RIGHT://PlaySound(TEXT("声音名"),NULL,SND_SYNC);keydown_right(hWnd);break;case VK_DOWN://PlaySound(TEXT("声音名"),NULL,SND_SYNC);keydown_down(hWnd);break;}case WM_PAINT:hdc=BeginPaint(hWnd,&ps);//系统重绘if(bStarted){boxoknum_qj=0;DrawMap(hWnd,(char **)map_mid,10,10);DrawPicture(hWnd,hBmp_man,ManDes);if((boxoknum_qj==aimnum)&&(winnum==0)&&(a == 0))//判断结束{winnum=1;if(IDYES==MessageBox(hWnd,TEXT("你赢了!是否进入下一关?"),TEXT("恭喜:"),MB_YESNO)){winnum=0;a++;aimnum_qj=0;for(i=0;i<10;i++)for(j=0;j<10;j++){map[i][j]=map2[i][j];}DrawMap(hWnd,(char **)map,10,10);//加载原始地图aimnum=aimnum_qj;memcpy(map_mid,map2,sizeof(map2));//将原始地图复制到运行中的地图/*for(i=0;i<10;i++)for(j=0;j<10;j++)if(map_mid[i][j]=='@'){map_mid[i][j]=' ';}hdc=BeginPaint(hWnd,&ps);//系统重绘boxoknum_qj=0;DrawMap(hWnd,(char **)map_mid,10,10);DrawPicture(hWnd,hBmp_man,ManDes);if((boxoknum_qj==aimnum)&&(winnum==0))//判断结束{winnum=1;MessageBox(hWnd,TEXT("你赢了!"),TEXT("恭喜:"),MB_SYSTEMMODAL|MB_OK);}EndPaint(hWnd,&ps);*/}}else if((boxoknum_qj==aimnum)&&(winnum==0)&&(a==1))//判断结束{MessageBox(hWnd,TEXT("哈哈!你通关了!"),TEXT("恭喜:"),MB_SYSTEMMODAL|MB_OK);}}EndPaint(hWnd,&ps);break;case WM_DESTROY:PostQuitMessage(0);break;case WM_CLOSE:if(IDYES==MessageBox(hWnd,"你确定要退出!!!","结束",MB_YESNO)){DestroyWindow(hWnd);}break;default:return DefWindowProc(hWnd, msg, wParam, lParam);}return 0;}// Mesage handler for about box.//****************************************************//函数名称:LRESULT CALLBACK About(HWND,UINT,WPARAM,LPARAM)//函数目的:处理主窗口的消息//注释://****************************************************LRESULT CALLBACK About(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){UNREFERENCED_PARAMETER(lParam);switch(msg){case WM_INITDIALOG:return (INT_PTR)TRUE;case WM_COMMAND:if(LOWORD(wParam)==IDOK||LOWORD(wParam)==IDCANCEL) {EndDialog(hDlg,LOWORD(wParam));return(INT_PTR)FALSE;}break;}return (INT_PTR)FALSE;}//****************************************************//函数名称:LRESULT CALLBACK Help(HWND,UINT,WPARAM,LPARAM) //函数目的:处理主窗口的消息//注释://**************************************************** LRESULT CALLBACK Help(HWND hDlg, // handle to windowUINT msg, // message identifierWPARAM wParam, // first message parameterLPARAM lParam // second message parameter){switch(msg){case WM_INITDIALOG:return(INT_PTR)TRUE;case WM_COMMAND:if(LOWORD(wParam)==IDOK||LOWORD(wParam)==IDCANCEL) {EndDialog(hDlg,LOWORD(wParam));return(INT_PTR)TRUE;}break;}return (INT_PTR)FALSE;}//****************************************************//函数名称:DrawPicture(HWND hWnd,HBITMAP hBmp,RECT spot) //函数目的:加载图片//注释://**************************************************** void DrawPicture(HWND hWnd,HBITMAP hBmp,RECT spot){HDC hdc,hdcMemory;HBITMAP hOldBmp;BITMAP bmp;hdc=GetDC(hWnd);hdcMemory=CreateCompatibleDC(hdc);hOldBmp=(HBITMAP)SelectObject(hdcMemory,hBmp);GetObject(hBmp_aim,sizeof(BITMAP),&bmp);BitBlt(hdc,spot.left,spot.top,spot.right-spot.left,spot.bottom-spot.top,hdcMemory,0, 0,SRCCOPY);//DeleteObject(SelectObject(hdcMemory,hOldBmp));DeleteDC(hdcMemory);ReleaseDC(hWnd,hdc);}/////////////////////////////////////////////////////////////////void DrawMap(HWND hWnd,char **Dmap,int m,int n)//加载地图{int x=0,y=0,k=0;for(y=0;y<n;++y){for(x=0;x<m;++x){switch(*((char*)Dmap+n*y+x)){case '#'://墙壁DrawPicture(hWnd,hBmp_wall,map_bg[x][y]);break;case '*'://目的地DrawPicture(hWnd,hBmp_aim,map_bg[x][y]);aimnum_qj++;break;case '@'://工人DrawPicture(hWnd,hBmp_man,map_bg[x][y]);man_mid.x=x;man_mid.y=y;ManDes.left=x*width;//设置工人的矩阵参数ManDes.top=y*heigth;ManDes.right=(x+1)*width;ManDes.bottom=(y+1)*heigth;break;case 'b'://箱子DrawPicture(hWnd,hBmp_box,map_bg[x][y]);break;case 'q'://箱子在目的地上DrawPicture(hWnd,hBmp_box,map_bg[x][y]);boxoknum_qj++;//统计多少箱子就位break;case' '://草地for(k=0;k<x;k++){if(*((char*)Dmap+n*y+k)=='#'){DrawPicture(hWnd,hBmp_ground,map_bg[x][y]);}}break;}}}}////////////////////////////////////////////////////////////////////////void keydown_up(HWND hWnd){switch(map_mid[man_mid.y-1][man_mid.x]){case '#'://上面为墙壁break;case ' '://草地case '*'://上面是目的地up_result();break;case 'b': //上面为箱子case 'q'://上面为箱子在目的地状态下switch(map_mid[man_mid.y-2][man_mid.x]){case '#'://上面为墙壁case 'b'://上面两格为箱子break;case ' '://上面两格为草地up_result();map_mid[man_mid.y-1][man_mid.x]='b';//将箱子向上放一格在目的地break;case '*'://上面两格为目的地up_result();map_mid[man_mid.y-1][man_mid.x]='q';//将向上放一格在目的地//这是我加的,黄老师书上原没有,结果老出错,下面都是map_mid[man_mid.y][man_mid.x]='b';break;}}}////////////////////////////////////////////////////////////////////////void keydown_left(HWND hWnd){switch(map_mid[man_mid.y][man_mid.x-1]){case '#'://左面右墙壁break;case ' '://草地case '*'://左面是目的地left_result();break;case 'b': //为箱子case 'q'://左面为箱子在目的地状态下switch(map_mid[man_mid.y][man_mid.x-2]){case '#'://左面为墙壁case 'b'://左面两格为箱子break;case ' '://左面两格为草地left_result();map_mid[man_mid.y][man_mid.x-1]='b';//将箱子向上放一格在目的地break;case '*'://左面两格为目的地left_result();map_mid[man_mid.y][man_mid.x-1]='q';//将向左放一格在目的地map_mid[man_mid.y][man_mid.x]='b';break;}}}////////////////////////////////////////////////////////////////////////void keydown_right(HWND hWnd){switch(map_mid[man_mid.y][man_mid.x+1]){case '#'://右面右墙壁break;case ' '://草地case '*'://右面是目的地right_result();break;case 'b': //为箱子case 'q'://右面为箱子在目的地状态下switch(map_mid[man_mid.y][man_mid.x+2]){case '#'://右面为墙壁case 'b'://右面两格为箱子break;case ' '://右面两格为草地right_result();map_mid[man_mid.y][man_mid.x+1]='b';//将箱子向上放一格在目的地break;case '*'://右面两格为目的地right_result();map_mid[man_mid.y][man_mid.x+1]='q';//将向左放一格在目的地map_mid[man_mid.y][man_mid.x]='b';break;}}}////////////////////////////////////////////////////////////////////////void keydown_down(HWND hWnd){switch(map_mid[man_mid.y+1][man_mid.x]){case '#'://下面下墙壁break;case ' '://草地case '*'://下面是目的地down_result();break;case 'b': //为箱子case 'q'://下面为箱子在目的地状态下switch(map_mid[man_mid.y+2][man_mid.x]){case '#'://下面为墙壁case 'b'://下面两格为箱子break;case ' '://下面两格为草地down_result();map_mid[man_mid.y+1][man_mid.x]='b';break;case '*'://下面两格为目的地down_result();map_mid[man_mid.y+1][man_mid.x]='q';//将向左放一格在目的地map_mid[man_mid.y][man_mid.x]='b';break;}}}void up_result(){if(map[man_mid.y][man_mid.x]!='*')//当工人位置以前不是目的地时{map_mid[man_mid.y][man_mid.x]=' ';//工人向上走后原位置为草地}else if(map[man_mid.y][man_mid.x]=='*')//当工人位置以前是目的地时{map_mid[man_mid.y][man_mid.x]='*'; //工人走后原位置为目的地}man_mid.y=man_mid.y-1;//修改工人坐标ManDes.bottom=ManDes.bottom-heigth;//修改工人矩形参数ManDes.top=ManDes.top-heigth;}void left_result(){if(map[man_mid.y][man_mid.x]!='*')//当工人位置以前不是目的地时{map_mid[man_mid.y][man_mid.x]=' '; //工人向上走后原位置为草地}else if(map[man_mid.y][man_mid.x]=='*'){map_mid[man_mid.y][man_mid.x]='*';}man_mid.x=man_mid.x-1;//修改工人坐标ManDes.left=ManDes.left-width;//修改工人矩形参数ManDes.right=ManDes.right-width;}void right_result(){if(map[man_mid.y][man_mid.x]!='*')//当工人位置为前不是目的地时{map_mid[man_mid.y][man_mid.x]=' ';//工人向上走后原位置为草地}else if(map[man_mid.y][man_mid.x]=='*'){map_mid[man_mid.y][man_mid.x]='*';}man_mid.x=man_mid.x+1;//修改工人坐标ManDes.left=ManDes.left+width;//修改工人矩形参数ManDes.right=ManDes.right+width;}void down_result(){if(map[man_mid.y][man_mid.x]!='*')//当工人位置以前不是目的地时{map_mid[man_mid.y][man_mid.x]=' '; //工人向上走后原位置为草地}else if(map[man_mid.y][man_mid.x]=='*'){map_mid[man_mid.y][man_mid.x]='*';}man_mid.y=man_mid.y+1;//修改工人坐标ManDes.bottom=ManDes.bottom+heigth;//修改工人矩形参数ManDes.top=ManDes.top+heigth;}三.游戏截图四.心得体会大二下学期通过这一次c语言课程设计我们可以更好的熟悉自己的专业知识,在编写游戏程序的同时也可以愉悦身心,在程序设计的后期内心始终充斥着一种自豪感。

相关主题