gusucode.com > 基于VC++编程war3连连看源码程序 > war3连连看/源代码/linkView.cpp
// linkView.cpp : implementation of the CLinkView class // #include "stdafx.h" #include "link.h" #include "linkDoc.h" #include "linkView.h" #include "windows.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CLinkView IMPLEMENT_DYNCREATE(CLinkView, CView) BEGIN_MESSAGE_MAP(CLinkView, CView) //{{AFX_MSG_MAP(CLinkView) ON_WM_LBUTTONDOWN() ON_WM_PAINT() ON_WM_ERASEBKGND() ON_WM_MOUSEMOVE() ON_WM_CHAR() ON_WM_CANCELMODE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CLinkView construction/destruction CLinkView::CLinkView() { // TODO: add construction code here } CLinkView::~CLinkView() { } BOOL CLinkView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CLinkView drawing void CLinkView::OnDraw(CDC* pDC) { CLinkDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here } ///////////////////////////////////////////////////////////////////////////// // CLinkView diagnostics #ifdef _DEBUG void CLinkView::AssertValid() const { CView::AssertValid(); } void CLinkView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CLinkDoc* CLinkView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CLinkDoc))); return (CLinkDoc*)m_pDocument; } #endif //_DEBUG //声明外部变量theApp extern CLinkApp theApp; //进入新的关卡 void NewStage( CDC * pDC ) { srand(time(0)); int i , j ; for( i = 0 ;i<leny ; ++i ) for( j =0 ; j<lenx ; ++j ) theApp.PicArray[i][j].visible = false ; int x , y ; //每关出现lenx种图形,每种图形各有leny个 ,本程序中lenx=10 ,leny = 8 for( i=0; i<lenx-1 ; ++i ) { for( j =0 ; j<leny ; ++j ) { bool re = true ; while( re ) { y = rand()%leny ; x = rand()%lenx ; if( theApp.PicArray[y][x].visible == false ) { theApp.PicArray[y][x].type = i ; theApp.PicArray[y][x].visible = true ; theApp.PicArray[y][x].x = x ; theApp.PicArray[y][x].y = y ; re = false ; } } } } for( i = 0; i<leny ; ++i ) //剩下最后一种图片就不用随机了 for( j =0 ; j<lenx ; ++j ) if( theApp.PicArray[i][j].visible == false ) { theApp.PicArray[i][j].type = lenx-1 ; theApp.PicArray[i][j].visible = true ; theApp.PicArray[i][j].x = j ; //千万注意对应关系!! theApp.PicArray[i][j].y = i ; } CString str ; str.Format( "您的得分是 %u ,共%d关,现在是第 %d 关", theApp.score ,totalStage,theApp.stage) ; pDC->TextOut( 150 , 15 , str) ; theApp.PaintPicture(pDC); } /*在图片a与图片b间画线 * CClientDC & dc为当前的dc */ void draw_line( picture & a , picture & b , CClientDC & dc ) //CClientDC类不能作按值传递参数 { CPoint p1( theApp.margin + a.x * 64 + 64 / 2 , theApp.margin + a.y * 64 + 64 / 2 ) ; CPoint p2( theApp.margin + b.x * 64 + 64/ 2 , theApp.margin + b.y * 64 + 64 / 2 ) ; dc.MoveTo( p1 ); dc.LineTo( p2 ) ; } //将图片a从当前窗口中抹去 void paint_black( picture a , CDC *pDC ) { CBrush backBrush(RGB(0, 0, 0)); CBrush* pOldBrush = pDC->SelectObject(&backBrush); CRect rect; pDC->GetClipBox(&rect); pDC->PatBlt(theApp.margin + width * a.x , theApp.margin + width * a.y, width , width , PATCOPY); pDC->SelectObject(pOldBrush); } //判断图片a与图片b能否直接相连(a、b间连线的转角数为0 ) bool match_direct( picture a , picture b , CClientDC & dc ) { //a、b的x或y坐标必须有且只有一个相同才能直接相连 if (! ( a.x==b.x || a.y == b.y ) ) return false ; //判断a、b间是否有其他图片阻隔 int i ; bool match_x = false ; if( a.x == b.x ) { match_x = true ; if( a.y > b.y ) for( i=a.y-1 ; i>b.y ; --i ) if( theApp.PicArray[ i][ a.x ].visible == true ) match_x = false ; if( b.y > a.y ) for( i = b.y -1 ; i>a.y ; --i ) if( theApp.PicArray[ i][ a.x ].visible == true ) match_x = false ; } bool match_y = false ; if( a.y == b.y ) { match_y = true ; if( a.x > b.x ) for( i = a.x - 1 ; i>b.x ; --i ) if( theApp.PicArray[ a.y ][ i ].visible == true ) match_y = false ; if( b.x > a.x ) for( i = b.x -1 ; i>a.x ; --i ) if( theApp.PicArray[ a.y ][ i ].visible == true ) match_y = false ; } if( match_x || match_y ) { // draw_line( a , b , dc ) ; //不能写在这里,否则match_one_corner会不正常 return true ; } return false ; } //判断a、b间能否通过只有一个转角的折线相连 bool match_one_corner( picture a , picture b , CClientDC & dc) { if( theApp.PicArray[ b.y ][ a.x ].visible == false &&\ match_direct( a , theApp.PicArray[ b.y ][ a.x ] , dc) && \ match_direct( b , theApp.PicArray[ b.y ][ a.x ] ,dc) ) { draw_line( a , theApp.PicArray[ b.y ][ a.x ] ,dc ) ; draw_line( b , theApp.PicArray[ b.y ][ a.x ] ,dc) ; return true ; } if( theApp.PicArray[ a.y ][ b.x ].visible == false &&\ match_direct( a , theApp.PicArray[ a.y ][ b.x ] ,dc ) && \ match_direct( b , theApp.PicArray[ a.y ][ b.x ] ,dc) ) { draw_line( a , theApp.PicArray[ a.y ][ b.x ] ,dc ) ; draw_line( b , theApp.PicArray[ a.y ][ b.x ] ,dc) ; return true ; } return false ; } //判断a、b能否通过有2个转角的折线相连 bool match_two_corner( picture a , picture b , CClientDC & dc ) { int i ; //转化为a与c能直接相连,而c与b可以通过有一个转角的折线相连的情况 for( i=a.x -1 ; i>=0 ; --i ) if( theApp.PicArray[a.y][i].visible == true ) break; else if( match_one_corner( theApp.PicArray[a.y][i] , b ,dc) ) { draw_line( a , theApp.PicArray[a.y][i] ,dc ) ; return true ; } for( i = a.x +1 ; i<lenx ; ++i ) if( theApp.PicArray[a.y][i].visible == true ) break; else if( match_one_corner( theApp.PicArray[a.y][i] , b ,dc ) ) { draw_line( a , theApp.PicArray[a.y][i] ,dc ) ; return true ; } for( i = a.y - 1 ; i>=0 ; --i ) if( theApp.PicArray[i][a.x].visible == true ) break; else if( match_one_corner( theApp.PicArray[i][a.x] ,b ,dc) ) { draw_line( a , theApp.PicArray[i][a.x] ,dc ) ; return true ; } for( i = a.y + 1 ; i<leny ; ++i ) if( theApp.PicArray[i][a.x].visible == true ) break; else if( match_one_corner( theApp.PicArray[i][a.x] ,b ,dc) ) { draw_line( a , theApp.PicArray[i][a.x] ,dc ) ; return true ; } return false ; } //判断a与b能否相连(条件:a与b类型相同,且能用转角不超过3个的折线相连 bool match( picture a , picture b , CClientDC & dc ) { if( a.type != b.type ) return false ; //直接相连 if( match_direct( a, b , dc ) ) { draw_line( a , b , dc ) ; Sleep(500) ; //连线在窗口中显示0.5 s 后消失 for( int i=0 ;i<leny ; ++i ) for( int j =0 ;j<lenx ; ++j ) if( theApp.PicArray[i][j].visible == false ) paint_black( theApp.PicArray[i][j] , &dc ) ; return true ; } //通过一个或两个转角相连的情况 if( match_one_corner( a , b ,dc ) || match_two_corner( a, b ,dc) ) { Sleep(500) ; for( int i=0 ;i<leny ; ++i ) for( int j =0 ;j<lenx ; ++j ) if( theApp.PicArray[i][j].visible == false ) paint_black( theApp.PicArray[i][j] , &dc ) ; return true ; } return false ; } //点击左键时判断前后点击的图片能否消去 void CLinkView::OnLButtonDown(UINT nFlags, CPoint point) { if( point.x <=theApp.margin || point.y<=theApp.margin ||\ point.x >= theApp.margin +lenx*width || point.y >= theApp.margin +leny*width ) return ; int x = ( point.x - theApp.margin ) / width ; int y = ( point.y - theApp.margin ) / width ; int Px = ( theApp.PreClick.x - theApp.margin) / width ; int Py = ( theApp.PreClick.y - theApp.margin ) / width ; //设置画笔的属性,并关联到dc CClientDC dc(this) ; int penWidth = 5; CPen pen(PS_SOLID, penWidth, RGB(255, 0, 0)); dc.SelectObject(&pen); if( x == Px && y == Py ) //前后两次点击的是同一张图片 return ; else if( Px <0 || Py <0 ) //这是第一次点击的情况 return ; else if( theApp.PicArray[ y ][ x ].visible == true && \ theApp.PicArray[ Py ][ Px ].visible == true &&\ theApp.PicArray[ y ][ x ].type == theApp.PicArray[ Py ][ Px ].type &&\ match( theApp.PicArray[ y ][ x ] , theApp.PicArray[ Py ][ Px ] , dc ) ) { theApp.PicArray[ y ][ x ].visible = false ; theApp.PicArray[ Py ][ Px ].visible = false ; CDC* pDC=GetDC(); paint_black( theApp.PicArray[ y ][ x ] , pDC ); paint_black( theApp.PicArray[ Py ][ Px ] ,pDC ) ; theApp.score += 10 ; CString str ; str.Format( "您的得分是 %u ,共%d关,现在是第 %d 关", theApp.score ,totalStage,theApp.stage) ; pDC->TextOut( 150 , 15 , str) ; theApp.remain_num -= 2 ; if( theApp.remain_num == 0 ) //剩余图片数为0,则通关 { theApp.score += theApp.stage * 100 ; CString str ; str.Format( "您的得分是 %u ,共%d关,现在是第 %d 关", theApp.score ,totalStage,theApp.stage) ; pDC->TextOut( 150 , 15 , str) ; if( theApp.stage == totalStage ) MessageBox( "你已经成功完成所有关卡!!","恭喜!!",MB_OK ) ; else { MessageBox("成功完成游戏!下面进行下一关!","恭喜!!",MB_OK ); theApp.remain_num = lenx * leny ; theApp.stage ++ ; NewStage( pDC ) ; } } ReleaseDC( pDC ) ; } theApp.PreClick = point ; } //重画黑色的背景 BOOL CLinkView::OnEraseBkgnd(CDC* pDC) { //设置brush为希望的背景颜色 CBrush backBrush( RGB(0, 0, 0) ); //保存旧的brush CBrush* pOldBrush = pDC->SelectObject(&backBrush); CRect rect; pDC->GetClipBox(&rect); //画需要的区域 pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); pDC->SelectObject(pOldBrush); return TRUE; } //最小化后再次恢复窗口时,需要重画窗口 void CLinkView::OnPaint() { CPaintDC dc(this); CDC* pDC = GetDC(); theApp.PaintPicture( pDC ); ReleaseDC( pDC ) ; } //鼠标移动时,经过的的图片要变色 void CLinkView::OnMouseMove(UINT nFlags, CPoint point ) { //在图片范围内 if( point.x > theApp.margin && point.y > theApp.margin &&\ point.x < theApp.margin + width * lenx && point.y <theApp.margin + width * leny ) { CDC* pDC = GetDC(); //重画所有图片,主要是为了将上次经过的变色的图片恢复正常状态 theApp.PaintPicture( pDC ); int i = ( point.x - theApp.margin )/width ; int j = ( point.y - theApp.margin )/width ; if( theApp.PicArray[j][i].visible == true ) { //鼠标经过的图片要变色 CBitmap bitmap3 ; bitmap3.LoadBitmap( 171 + theApp.stage ) ; //171是第一张变色图片的资源号 CDC dcCompatible3 ; dcCompatible3.CreateCompatibleDC( pDC) ; dcCompatible3.SelectObject( &bitmap3 ) ; pDC->BitBlt( theApp.margin + i*width, theApp.margin + j*width,width,width,&dcCompatible3,0,theApp.PicArray[j][i].type*width,SRCCOPY ) ; //将鼠标指向的图片画到右边的空白处,图片下面显示说明文字 CBitmap bitmap4 ; bitmap4.LoadBitmap( 191 + theApp.stage ) ; //191是第一张正常图片的资源号 CDC dcCompatible4 ; dcCompatible4.CreateCompatibleDC( pDC) ; dcCompatible4.SelectObject( &bitmap4 ) ; pDC->BitBlt( theApp.margin + width*lenx + width , theApp.margin + width ,width,width,&dcCompatible4,0,theApp.PicArray[j][i].type*width,SRCCOPY ) ; pDC->TextOut( theApp.margin + width*lenx + width , theApp.margin + width *2 , theApp.pic_info[theApp.stage -1 ][theApp.PicArray[j][i].type] ) ; } ReleaseDC( pDC ) ; } } void CLinkView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if( nChar == 1 ) { CDC * pDC = GetDC() ; CString str ; str.Format( "您的得分是 %u ,共%d关,现在是第 %d 关", theApp.score ,totalStage,theApp.stage) ; pDC->TextOut( 150 , 15 , str) ; if( theApp.stage > totalStage ) MessageBox( "你已经成功完成所有关卡!!","恭喜!!",MB_OK ) ; else { MessageBox("您使用了秘籍,直接进入下一关!","提示",MB_OK ) ; theApp.remain_num = lenx * leny ; theApp.stage ++ ; NewStage( pDC ) ; str.Format( "您的得分是 %u ,共%d关,现在是第 %d 关", theApp.score ,totalStage,theApp.stage) ; pDC->TextOut( 150 , 15 , str) ; } ReleaseDC( pDC ) ; } } void CLinkView::OnCancelMode() { CView::OnCancelMode(); }