处女作 俄罗斯方块

来源:互联网 发布:如何查看本机端口号 编辑:程序博客网 时间:2024/06/16 08:57

#include<windows.h>#include<stdlib.h>#include<time.h>#include"definition.h"#include"function.h"LRESULT CALLBACK MyFirstProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){HWND hwnd;MSG msg;srand((unsigned)time(NULL));//这里是埋下随机数种子WNDCLASS wndclass;wndclass.cbClsExtra=0;wndclass.cbWndExtra=0;wndclass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);wndclass.hInstance=hInstance;wndclass.lpfnWndProc=MyFirstProc;wndclass.lpszMenuName=NULL;wndclass.lpszClassName="cc";wndclass.style=CS_HREDRAW|CS_VREDRAW;RegisterClass(&wndclass);hwnd=CreateWindow("cc","处女作",WS_OVERLAPPEDWINDOW &~WS_MAXIMIZEBOX &~WS_THICKFRAME&~WS_OVERLAPPED,400,0,(COLUMN+1)*23-9,(ROW+2)*23-9,NULL,NULL,hInstance,NULL);//23是位图的像素高度和宽度 可通过 char tm[100];sprintf(tm,"像素是:%d",bm.bmWidth);MessageBox(hwnd,tm,"像素",                                                                                                //                  MB_OK),来查看ShowWindow(hwnd,SW_SHOWNORMAL);UpdateWindow(hwnd);Myrand();收获随机数种子并初始化boxwhile(GetMessage(&msg,NULL,0,0)){if(!JudgeFull())//判断是否到顶了{if(!JudgeFall(x,y))//判断是否到达底端{Puton(x,y);//用小盒子box填充大盒子StateClearLine();//判断满行并销行InvalidateRect(hwnd,NULL,TRUE);//发送WM_PAINT重绘窗口x=0;y=COLUMN/2;Myrand();}}elsePostMessage(hwnd,WM_CLOSE,0,0);//到顶了发送消息结束程序DispatchMessage(&msg);//装换消息TranslateMessage(&msg);//派遣消息}return msg.wParam;}LRESULT CALLBACK MyFirstProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam){int i,j,temp;PAINTSTRUCT ps;HDC hdc;HDC hdcmem;HBITMAP hbitmap;BITMAP bm;switch(uMsg){case WM_CREATE:SetMap();//初始化地图x=0;y=COLUMN/2;SetTimer(hwnd,ID_DOWN,250,NULL);break;case WM_TIMER:if(ID_DOWN==wParam){temp=x;    temp++;if(Test(temp,y,box,State))x++;InvalidateRect(hwnd,NULL,TRUE);}break;case WM_PAINT:hdc=BeginPaint(hwnd,&ps);//获取设备描述表hbitmap=(HBITMAP)LoadImage(NULL,"blockunit.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);//加载位图大家可以找一个方块位图命名为"blockunit.bmp就可以了 当然像                                                                                                                                                                                  //素的大小要调一下,可以通过前面介绍的方法获取方块像素大小hdcmem=CreateCompatibleDC(hdc);//创建内存设备描述表 兼容DCGetObject(hbitmap,sizeof(bm),&bm);获取位图信息hbitmap=(HBITMAP)SelectObject(hdcmem,hbitmap);//将位图选入设备描述表for(i=0;i<4;i++)//画小盒子for(j=0;j<4;j++){if(box[i][j]==1)BitBlt(hdc,(y+j-1)*bm.bmWidth,(x+i)*bm.bmHeight,bm.bmWidth,bm.bmHeight,hdcmem,0,0,SRCCOPY);}    for(i=0;i<ROW+1;i++)//画大盒子for(j=1;j<COLUMN+2;j++)if(State[i][j]==1){BitBlt(hdc,(j-1)*bm.bmWidth,i*bm.bmHeight,bm.bmWidth,bm.bmHeight,hdcmem,0,0,SRCCOPY);}EndPaint(hwnd,&ps);DeleteDC(hdcmem);DeleteDC(hdc);break;case WM_KEYDOWN://效应按键消息{switch(wParam)//判断按键消息种类虚拟键{case VK_LEFT:temp=y;temp--;   if(Test(x,temp,box,State))y--;InvalidateRect(hwnd,NULL,TRUE);break;case VK_RIGHT:temp=y;temp++;   if(Test(x,temp,box,State))y++;InvalidateRect(hwnd,NULL,TRUE);break;    case VK_UP:   if(TestRoll(x,y,box)==1)UpRoll(box,box);   InvalidateRect(hwnd,NULL,TRUE);     break;case VK_DOWN:temp=x;temp++;if(Test(temp,y,box,State))x++;InvalidateRect(hwnd,NULL,TRUE);break;}}break;case WM_CLOSE:if(MessageBox(hwnd,"Game over","退出游戏",MB_OK))DestroyWindow(hwnd);//摧毁窗口 注意此时并没有关闭应用程序只是摧毁了窗口 发送WM_DESTROYbreak;case WM_DESTROY:PostQuitMessage(0);发送WM_QUIT关闭应用程序break;default:return DefWindowProc(hwnd,uMsg,wParam,lParam);} }void Myrand()//获取随机数{int type;int i,j;type=rand()%7;for(i=0;i<4;i++)for(j=0;j<4;j++)box[i][j]=BlockState[type][i][j];}void UpRoll(int boxOut[][4],int boxIn[][4])//方块翻转{int i,j;int temp[4][4]={0};for(i=0;i<4;i++)for(j=3;j>=0;j--){temp[j][3-i]=boxIn[i][j];}for(i=0;i<4;i++)for(j=0;j<4;j++){boxOut[i][j]=temp[i][j];}}int Test(int cx,int cy,int cbox[][4],int cState[][COLUMN+2])//测试方块是否到达边缘{int i,j;for(i=0;i<4;i++)for(j=0;j<4;j++){if(1==cState[i+cx][j+cy]&&cbox[i][j])return 0;}return 1; }void Puton(int cx,int cy)//box填充State{int i,j;for(i=0;i<4;i++)for(j=0;j<4;j++){   if(box[i][j]==1)State[i+cx][j+cy]=box[i][j];}}int JudgeFull(){int i;int flag=0;for(i=1;i<COLUMN;i++)if(State[0][i]){flag=1;return 1;}return 0;}void ClearLine()//销行{int i,j;int flag;int cx,cy;for(i=0;i<ROW;i++){flag=1;for(j=1;j<COLUMN;j++){if(!State[i][j]){flag=0;break;}}if(1==flag){for(cx=i;cx>=1;cx--)  for(cy=1;cy<COLUMN;cy++)  {  State[cx][cy]=State[cx-1][cy];  }  for(cy=1;cy<COLUMN;cy++) State[0][cy]=0;}}}void SetMap()//初始化地图{int i,j;for(i=0;i<ROW+1;i++)for(j=0;j<COLUMN+2;j++){if(j==0||j==COLUMN+1||i==ROW)//这是一个很巧妙的方法让大盒子的最左最右最下端让State[][]初始化为1始方块不能越过这三条边界,起到了围墙的作用State[i][j]=1;else State[i][j]=0;}}int TestRoll(int cx,int cy,int cbox[][4])//判断方块是否能翻转{int testbox[4][4]={0};UpRoll(testbox,cbox);if(Test(cx,cy,testbox,State))return 1;return 0;}int JudgeFall(int cx,int cy)//判断方块是否到底部{int temp;temp=x;temp++;if(Test(temp,cy,box,State))return 1;elsereturn 0;}--------------------------------------------------------------------------------------------definition.h#define ROW 25#define COLUMN 16#define TYPE 7#define ID_DOWN 1int x,y;//记录小方块坐标int State[ROW+1][COLUMN+2]={0};int box[4][4]={0};int BlockState[TYPE][4][4]={//方块七种形态{0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0},{0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0},{0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0},{0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0},{0,0,0,0,0,0,1,1,0,1,1,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,1,0,0,1,1,1,0,0,0,0,0}};---------------------------------------------function.hvoid Myrand();void ClearLine();int JudgeFull();int JudgeFall(int,int);int Test(int,int,int[][4],int[][COLUMN+2]);void SetMap();void UpRoll(int boxOut[][4],int boxIn[][4]);void Puton(int,int);int TestRoll(int,int,int[][4]);



--------------------------------------------------------------
用到的主要API函数 多看看加强记忆

函数原型

  int MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT UType);

编辑本段参数

  hWnd:标识将被创建的消息框的拥有窗口。如果此参数为NULL,则消息框没有拥有窗口。
  lpText:指向一个以NULL结尾的、含有将被显示的消息的字符串的指针。
  lpCaption:指向一个以NULL结尾的、用于对话框标题的字符串的指针。
  uType:指定一个决定对话框的内容和行为的位标志集。缺省值为MB_OK;

函数原型

  BOOL UpdateWindow(
  HWND hWnd // 窗口的句柄
  );如果窗口更新的区域不为空,UpdateWindow函数通过发送一个WM_PAINT消息来更新指定窗口的客户区。函数绕过应用程序的消息队列,直接发送WM_PAINT消息给指定窗口的窗口过程,如果更新区域为空,则不发送消息。

函数原型

void srand(unsigned seed);经常这样用 srand((unsigned) time(NULL))来埋下种子

SetTimer函数的用法

  1.1 用WM_TIMER来设置定时器
  先请看SetTimer这个API函数的原型
  UINT_PTR SetTimer(
  HWND hWnd, // 窗口句柄
  UINT_PTR nIDEvent, // 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器
  UINT uElapse, // 时间间隔,单位为毫秒
  TIMERPROC lpTimerFunc // 回调函数,设置了回调函数WM_TIMER直接发送到该函数不经过应用程序消息队列
  );


LoadImage

目录

简介
参数

编辑本段简介

  函数功能:该函数装载图标,光标,或位图。
  函数原型:HANDLE LoadImage(
  HINSTANCE hinst,
  LPCTSTR lpszName,
  UINT uType,
  int cxDesired,
  int cyDesired,
  UINT fuLoad
  );

编辑本段

GetObject

目录

函数简介
程序示例

编辑本段函数简介

  函数功能:该函数得到指定图形对象的信息,根据图形对象,函数把填满的或结构,或表项(用于逻辑调色板)数目放入一个指定的缓冲区。
  函数原型:int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
  参数:
  hgdiobj:指向感兴趣的图形对象的句柄,它可以是这样的一个句柄:一个逻辑位图、一个刷子、一种字体、一个调色板、笔或通过调用CreateDIBsection函数创建的与设备无关位图。
  cbBuffer:指定将要写到缓冲区的信息的字节数目。
  lpvObject:指向一个缓冲区的指针,该缓冲区将要检索指定图形对象的信息。




SelectObject

  CPen* SelectObject( CPen* pPen );
  CBrush* SelectObject( CBrush* pBrush );
  virtual CFont* SelectObject( CFont* pFont );
  CBitmap* SelectObject( CBitmap* pBitmap );
  int SelectObject( CRgn* pRgn );
  CGdiObject* SelectObject( CGdiObject* pObject );
  函数功能:该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象。
  函数原型:HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj);//返回值是被取代的对象句柄




编辑本段函数原型

  BOOL BitBlt(HDC hdcDest,int nXDest,int nYDest,int nWidth,int nHeight,HDC hdcSrc,int nXSrc,int nYSrc,DWORD dwRop);

函数功能

  该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境。

编辑本段参数

  hdcDest:指向目标设备环境的句柄。
  nXDest:指定目标矩形区域左上角的X轴逻辑坐标。
  nYDest:指定目标矩形区域左上角的Y轴逻辑坐标。
  nWidth:指定源和目标矩形区域的逻辑宽度。
  nHeight:指定源和目标矩形区域的逻辑高度。
  hdcSrc:指向源设备环境的句柄。
  nXSrc:指定源矩形区域左上角的X轴逻辑坐标。
  nYSrc:指定源矩形区域左上角的Y轴逻辑坐标。
  dwRop:指定光栅操作代码。这些代码将定义源矩形区域的颜色数据,如何与目标矩形区域的颜色数据组合以完成最后的颜色。



PostQuitMessage

  函数功能:该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息。
  函数原型:VOID PostQuitMessage(int nExitCode);
  参数:
  nExitCode:指定应用程序退出代码。此值被用作消息WM_QUIT的wParam参数。
  返回值:无。

函数原型

  HWND CreateWindow(
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x,
  int y,
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMENU hMenu,
  HANDLE hlnstance,
  LPVOID lpParam);

编辑本段参数

lpClassName

  指向一个空结束的字符串或整型数atom。如果该参数是一个整型量,它是由此前调用theGlobalAddAtom函数产生的全局量。这个小于0xC000的16位数必须是lpClassName参数字的低16位,该参数的高位必须是0。
  如果lpClassName是一个字符串,它指定了窗口的类名。这个类名可以是任何用函数RegisterClassEx注册的类名,或是任何预定义的控制类名。请看说明部分的列表。

LPWindowName

  指向一个指定窗口名的空结束的字符串指针。
  如果窗口风格指定了标题条,由lpWindowName指向的窗口标题将显示在标题条上。当使用Createwindow函数来创建控制例如按钮,选择框和静态控制时,可使用lpWindowName来指定控制文本。

dwStyle

  指定创建窗口的风格。该参数可以是下列窗口风格的组合再加上说明部分的控制风格。风格意义:
  WS_BORDER:创建一个单边框的窗口。
  WS_CAPTION:创建一个有标题框的窗口(包括WS_BODER风格)。
  WS_CHILD:创建一个子窗口。这个风格不能与WS_POPUP风格合用。
  WS_CHLDWINDOW:与WS_CHILD相同。
  WS_CLIPCHILDREN:当在父窗口内绘图时,排除子窗口区域。在创建父窗口时使用这个风格。
  WS_CLlPBLINGS;排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到WM_PAINT消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口。如果未指定WS_CLIPSIBLINGS风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口。
  WS_DISABLED:创建一个初始状态为禁止的子窗口。一个禁止状态的窗口不能接受来自用户的输入信息。
  WS_DLGFRAME:创建一个带对话框边框风格的窗口。这种风格的窗口不能带标题条。
  WS_GROUP:指定一组控制的第一个控制。这个控制组由第一个控制和随后定义的控制组成,自第二个控制开始每个控制,具有WS_GROUP风格,每个组的第一个控制带有WS_TABSTOP风格,从而使用户可以在组间移动。用户随后可以使用光标在组内的控制间改变键盘焦点。
  WS_HSCROLL:创建一个有水平滚动条的窗口。
  WS_ICONIC:创建一个初始状态为最小化状态的窗口。与WS_MINIMIZE风格相同。
  WS_MAXIMIZE:创建一个初始状态为最大化状态的窗口。
  WS_MAXIMIZEBOX:创建一个具有最大化按钮的窗口。该风格不能与WS_EX_CONTEXTHELP风格同时出现,同时必须指定WS_SYSMENU风格。
  WS_OVERLAPPED:产生一个层叠的窗口。一个层叠的窗口有一个标题条和一个边框。与WS_TILED风格相同。
  WS_OVERLAPPEDWINDOW:创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXIMIZEBOX风格的层叠窗口,与WS_TILEDWINDOW风格相同。
  WS_POPUP;创建一个弹出式窗口。该风格不能与WS_CHLD风格同时使用。
  WS_POPUPWINDOW:创建一个具有WS_BORDER,WS_POPUP,WS_SYSMENU风格的窗口,WS_CAPTION和WS_POPUPWINDOW必须同时设定才能使窗口某单可见。
  WS_SIZEBOX:创建一个可调边框的窗口,与WS_THICKFRAME风格相同。
  WS_SYSMENU:创建一个在标题条上带有窗口菜单的窗口,必须同时设定WS_CAPTION风格。
  WS_TABSTOP:创建一个控制,这个控制在用户按下Tab键时可以获得键盘焦点。按下Tab键后使键盘焦点转移到下一具有WS_TABSTOP风格的控制。
  WS_THICKFRAME:创建一个具有可调边框的窗口,与WS_SIZEBOX风格相同。
  WS_TILED:产生一个层叠的窗口。一个层叠的窗口有一个标题和一个边框。与WS_OVERLAPPED风格相同。
  WS_TILEDWINDOW:创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU, WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXMIZEBOX风格的层叠窗口。与WS_OVERLAPPEDWINDOW风格相同。
  WS_VISIBLE创建一个初始状态为可见的窗口。
  WS_VSCROLL:创建一个有垂直滚动条的窗口。
  X
  指定窗口的初始水平位置。对一个层叠或弹出式窗口,X参数是屏幕坐标系的窗口的左上角的初始X坐标。对于子窗口,x是子窗口左上角相对父窗口客户区左上角的初始X坐标。如果该参数被设为CW_USEDEFAULT则系统为窗口选择缺省的左上角坐标并忽略Y参数。CW_USEDEFAULT只对层叠窗口有效,如果为弹出式窗口或子窗口设定,则X和y参数被设为零。
  Y
  指定窗口的初始垂直位置。对一个层叠或弹出式窗日,y参数是屏幕坐标系的窗口的左上角的初始y坐标。对于子窗口,y是子窗口左上角相对父窗口客户区左上角的初始y坐标。对于列表框,y是列表框客户区左上角相对父窗口客户区左上角的初始y坐标。如果层叠窗口是使用WS_VISIBLE风格位创建的并且X参数被设为CW_USEDEFAULT,则系统将忽略y参数。

nWidth

  以设备单元指明窗口的宽度。对于层叠窗口,nWidth或是屏幕坐标的窗口宽度或是CW_USEDEFAULT。若nWidth是CW_USEDEFAULT,则系统为窗口选择一个缺省的高度和宽度:缺省宽度为从初始X坐标开始到屏幕的右边界,缺省高度为从初始X坐标开始到目标区域的顶部。CW_USEDEFAULT只对层叠窗口有效;如果为弹出式窗口和子窗口设定CW_USEDEFAULT标志则nWidth和nHeight被设为零。

nHeight

  以设备单元指明窗口的高度。对于层叠窗口,nHeight是屏幕坐标的窗口宽度。若nWidth被设为CW_USEDEFAULT,则系统忽略nHeight参数。

hWndParent

  指向被创建窗口的父窗口或所有者窗口的句柄。若要创建一个子窗口或一个被属窗口,需提供一个有效的窗口句柄。这个参数对弹出式窗口是可选的。Windows NT 5.0;创建一个消息窗口,可以提供HWND_MESSAGE或提供一个己存在的消息窗口的句柄。

hMenu

  菜单句柄,或依据窗口风格指明一个子窗口标识。对于层叠或弹出式窗口,hMenu指定窗口使用的菜单:如果使用了菜单类,则hMenu可以为NULL。对于子窗口,hMenu指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的。

hlnstance

  与窗口相关联的模块事例的句柄。

lpParam

  指向一个值的指针,该值传递给窗口 WM_CREATE消息。该值通过在IParam参数中的CREATESTRUCT结构传递。如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。
  返回值:如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL。若想获得更多错误信息,请调用GetLastError函数。

备注

  在返回前,CreateWindow给窗口过程发送一个WM_CREATE消息。对于层叠,弹出式和子窗口,CreateWindow给窗口发送WM_CREATE,WM_GETMINMAXINFO和WM_NCCREATE消息。消息WM_CREATE的IParam参数包含一个指向CREATESTRUCT结构的指针。如果指定了WS_VISIBLE风格,CreateWindow向窗口发送所有需要激活和显示窗口的消息。




  











原创粉丝点击