(转)连连看API版本的源代码

简介:

head.h

#define M 14
//M为连连看牌的高+2
#define N 10
//N为连连看牌的宽+2

struct point
{
 int x;
 int y;
};

/*********************************************************/

template < typename T, int m, int n > class Matrix
{
protected: 
 T matrix[M][N];
public:
 Matrix();
 Matrix( char* filename );//通过文件里的数据初始化
 void show_matrix();//输出矩阵
 void set_element( int x, int y, T num );//num为元素值
 T get_element( int x, int y );
};

/*********************************************************/

class Linker_Matrix:public Matrix < int, M, N >  //连连看的牌矩阵类
{
 /* matrix[M][N]为牌矩阵;
  从[1][1]开始,到[M-2][N-2]有效;
  外围一圈为预留的配对路径;
  值=0为无牌,即牌配对之后被消掉的的状态;
  其他值即为牌的类别,相同值的牌方可配对;  
 */
private:
 //time_t curtime;
 point p1,p2,way[ 4 ];
  //p1为起点,p2为终点,way[M+N]用于记录搜索到的路径
 int index;//路径的长度;
 int turn_count;//路径的转弯次数,>2就搜索失败;
 Matrix < int, M, N > visited;
  //是否访问过矩阵类,1:访问过 0:未访问 
public:

 Linker_Matrix();
 Linker_Matrix( int low, int high, int num );
  //随机选择元素初始化,元素值的范围在low-high,
  //每个值有num个;
 Linker_Matrix( int num );
  //随机选择元素初始化,从1开始,每个值有num个;
  
 void show_matrix();
 void count( int low, int high );//统计各个值的个数,测试用;
 bool auto_search();//自动搜索出一对配对的牌
 bool find_way( point p1, point p2 );
  //搜索路径 true-有路径 false-无;  
 void auto_play();//自动完成所有的配对;
 void init_search();//进行搜索前的初始化 
 bool man_search( point p1,  point p2);
 bool is_matched( point p1, point p2 );
  //是否配对 true-配对 false-否;
 int  get_element( int x, int y );
 void get_point(point &p1,point &p2);
  //通过p1,p2提取自动搜索出的匹配两点
 void reShuffle();//重新洗牌;
};

/*********************************************************/

head.cpp

#include "head.h"
#include<iostream.h>
#include<fstream.h>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<time.h>
#include<conio.h>

template < typename T, int m, int n > 
Matrix < T, m, n >::Matrix()
{
 for( int i=0; i<m; i++ )
  for( int j=0; j<n; j++ )
   matrix[i][j] = 0;
 
}

template < typename T, int m, int n > 
Matrix< T, m, n >::Matrix( char* filename )
{
 ifstream infile(filename);
 
 for( int i=0; i<M; i++ )
  for( int j=0; j<N; j++ )
   infile >> matrix[i][j];
}

template < typename T, int m, int n > 
void Matrix< T, m, n >::show_matrix()

 for( int i=0; i<m; i++ )
 {
  for( int j=0; j<n; j++ )
   cout<< matrix[i][j]<<'\t';
  cout<<endl;
 }
 cout<<endl;
}

template < typename T, int m, int n > 
inline void Matrix< T, m, n >::set_element( int x, int y, T element )
{
 matrix[x][y] = element;
}

template < typename T, int m, int n > 
T Matrix< T, m, n >::get_element( int x, int y )
{
 return matrix[x][y];
}

/*********************************************************/

Linker_Matrix::Linker_Matrix():Matrix< int, M, N >()
{
 p1.x = p1.y = 0;
 p2.x = p2.y = 0;
 index = 0;
 turn_count = 0;
 //max=0;

 for( int k=0; k<4; k++ )
  way[k].x = way[k].y = 0;
}

Linker_Matrix::Linker_Matrix( int low, int high, int num )
 :Matrix< int, M, N >()

 
 int m,n;
 time_t curtime; //记录当前时间

 p1.x = p1.y = 0;
 p2.x = p2.y = 0;
 index = 0;

 time(&curtime);//取得当前时间
 //srand(curtime);//用当前时间作种子,产生随机数

 for( int k=0; k<4; k++ )
  way[k].x = way[k].y = 0;

 for( int i=low; i<=high; i++ )
  for( int j=0; j<num; j++ )
  {
   do
   {
    m = rand()%(M-2) + 1;
    n = rand()%(N-2) + 1;
   }
   while( 0==m || 0==n || 0!=matrix[m][n] );
   matrix[m][n]=i;
  }
}

Linker_Matrix::Linker_Matrix(int num ):Matrix< int, M, N >()

 
 int m,n;
 time_t curtime; //记录当前时间

 p1.x = p1.y = 0;
 p2.x = p2.y = 0;
 index = 0;

 time(&curtime);//取得当前时间
 srand(curtime);//用当前时间作种子,产生随机数

 for( int k=0; k<4; k++ )
  way[k].x = way[k].y = 0;

 for( int i=1; i<=(M-2)*(N-2)/num; i++ )
  for( int j=0; j<num; j++ )
  {
   do
   {
    m = rand()%(M-2) + 1;
    n = rand()%(N-2) + 1;
   }
   while( 0==m || 0==n || 0!=matrix[m][n] );
   matrix[m][n]=i;
  }
}

void Linker_Matrix::show_matrix()
{
 
 for( int i=1; i<M-1; i++ )
 {
  for( int j=1; j<N-1; j++ )
   cout<<matrix[i][j]<<'\t';
  cout<<endl;
 }
 cout<<endl;
}

void Linker_Matrix::count( int low, int high )
{
 int *num,k;

 //动态分配 
 num = new int[ high-low+2 ];
 //初始化
 for( k=0; k<high-low+2; k++ )
  num[k]=0;
 
 //计数
 for( int i=1; i<M-1; i++ )
  for( int j=1; j<N-1; j++ )
   num[ matrix[i][j] ]++; 
  
 //输出
 for( k=0; k<high-low+2; k++ )
  cout<<k<<":"<<num[k]<<'\t';
 cout<<endl;

 //销毁
 delete[] num;
}

inline bool Linker_Matrix::is_matched( const point p1, const point p2 )
{
 return matrix[ p1.x ][ p1.y ] == matrix[ p2.x ][ p2.y ];
}

bool Linker_Matrix::auto_search()
{
 int i,j,m,n;
 //static k = 0;
 bool all_is_zero = true;//是否所有元素都为0 true:yes false:no

 for( i=1; i<M-1; i++ )
 for( j=1; j<N-1; j++ )
 {
  if( matrix[i][j]!=0 )//元素不为0时方进行配对
  {
   all_is_zero=false;
   p1.x = i; p1.y = j;

   for( m=1; m<M-1; m++ )
   for( n=1; n<N-1; n++ )
   { 
    if( i!=m || j!=n )//元素不为本身时,方进行搜索路径
    { 
     //k++;
     p2.x=m; p2.y=n;

     init_search();
     /*if(k==29)
     {
      init_search();
      show_matrix();
     }*/
     
     if ( is_matched( p1, p2 ) && find_way( p1, p2 ) )
     /*逻辑式这样写的原因是只要is_matched(p1,p2)为false,
     逻辑式必为false,find_way(p1,p2)就不会执行;
     当两元素数值相同且有路径时,执行下面
     */
     { 
       //show_matrix();
       //cout<<turn_count<<endl;
       //matrix[ p1.x ][ p1.y ] = 0;
       //matrix[ p2.x ][ p2.y ] = 0;
       //k++;
       //cout<<p1.x<<' '<<p1.y<<' '<<p2.x<<' '<<p2.y<<':'<<k<<endl;
       //show_matrix();
       //count(1,21);
       //goto jump;
       //找到一个就退出
      
       return true;
      //}
     }
     
    }/*
    if( k>MAX)//搜索次数过大,强制跳出
        return false;*/
   }
  }
  //jump:  ;
 }

 if( true==all_is_zero )//元素全部为0,返回false
  return false;
 return false;//没有匹配时,返回false
}

bool Linker_Matrix::find_way(  point p1, point p2 )
{
 /*
 本方法是本程序的核心算法,
 作用是以p1为起点,p2为终点进行路径的搜索;*/
 /*采用水平垂直扫描法,先确定两个转折点之间是否相通,再判断
 转折点与相应端点间是否相通
 */

 int i,j;
 int px1,px2,py1,py2;
 int temp;
 bool x_across,y_across;

 //如果相邻
 if( ( p1.x+1==p2.x && p1.y==p2.y )
  || ( p1.x==p2.x && p1.y+1==p2.y )
  || ( p1.x-1==p2.x && p1.y==p2.y )
  || ( p1.x==p2.x && p1.y-1==p2.y ) )
 {
  //把路径记录下来
  //起点
  way[0].x=p1.x;
  way[0].y=p1.y;
  //直线转折点为0
  way[1].x=0;
  way[1].y=0;
  way[2].x=0;
  way[2].y=0;
  //终点
  way[3].x=p2.x;
  way[3].y=p2.y;

  return true;
 }

 //直线连通
 //如果在水平方向上
 if( p1.x==p2.x )
 {
  if(p1.y>p2.y)
  {
   temp=p1.y;
   p1.y=p2.y;
   p2.y=temp;
  }

  for(j=p1.y+1; j<p2.y; j++ )
  {
   if( matrix[p1.x][j]!=0)
   {
    break;
   }
  }

  //如果两点之间相通
  if(j==p2.y &&  matrix[p1.x][j-1]==0 )
  {
   
   //把路径记录下来
   //起点
   way[0].x=p1.x;
   way[0].y=p1.y;
   //直线转折点为0
   way[1].x=0;
   way[1].y=0;
   way[2].x=0;
   way[2].y=0;
   //终点
   way[3].x=p2.x;
   way[3].y=p2.y;

   return true;
  }
 }

 //如果在垂直方向上
 if( p1.y==p2.y )
 {
  if(p1.x>p2.x)
  {
   temp=p1.x;
   p1.x=p2.x;
   p2.x=temp;
  }

  for(i=p1.x+1; i<p2.x; i++ )
  {
   if( matrix[i][p1.y]!=0)
   {
    break;
   }
  }
  //如果两点之间相通
  if(i==p2.x &&  matrix[i-1][p1.y]==0 )
  {


   //把路径记录下来
   //起点
   way[0].x=p1.x;
   way[0].y=p1.y;
   //直线转折点为0
   way[1].x=0;
   way[1].y=0;
   way[2].x=0;
   way[2].y=0;
   //终点
   way[3].x=p2.x;
   way[3].y=p2.y;

   return true;
  }
 }


 
 //折线连通
 /*if( p1.x!=p2.x && p1.y!=p2.y)
 {*/
  if(p1.y>p2.y)
  {
   //两点交换
   temp=p1.x;
   p1.x=p2.x;
   p2.x=temp;

   temp=p1.y;
   p1.y=p2.y;
   p2.y=temp;


  }


 //横向扫描
 for(i=0;i<=M-1;i++)
 {  
  x_across=true;

  //是否水平连通
  for(j=p1.y+1; j<=p2.y-1; j++ )
  {
   if(matrix[i][j]!=0 )
   {
    x_across=false;
    break;
   }
  }

  if(matrix[i][p1.y]!=0  )
  {
   if( i!=p1.x )
    x_across=false;
  }
  if(matrix[i][p2.y]!=0  )
  {
   if( i!=p2.x )
    x_across=false;
  } 
   
  if(x_across)
  {//水平连通才执行下面
  /* for(j=1; j<N-2; j++ )
   {*/
    //检验在垂直上是否连通

   px1=px2=i;
   py1=p1.y;
   py2=p2.y;
   while( px1!=p1.x || px2!=p2.x )
   {
    //如果当前点不空且不为p1点,就跳出循环,从下一行开始检测
    if( matrix[px1][py1]!=0 && (px1!=p1.x || py1!=p1.y) )
     break;

    //如果当前点不空且不为p2点,就跳出循环,从下一行开始检测
    if( matrix[px2][py2]!=0 && (px2!=p2.x || py2!=p2.y) )
     break;

    //如果两点都为空
    //垂直向p1点靠近一格
    if(px1<p1.x)
     px1++;
    else if(px1>p1.x)
     px1--;
    //垂直向p2点靠近一格
    if(px2<p2.x)
     px2++;
    else if(px2>p2.x)
     px2--;
   }
     
   //如果能到达两个端点
   if(px1==p1.x && py1==p1.y && px2==p2.x && py2==p2.y )
   {
    //起点
    way[0].x=p1.x;
    way[0].y=p1.y;
    //两个转折点
    way[1].x=i;
    way[1].y=p1.y;
    way[2].x=i;
    way[2].y=p2.y;
    //终点
    way[3].x=p2.x;
    way[3].y=p2.y; 
    return true;
   }

  }
 }

 if(p1.x>p2.x)
  {
   //两点交换
   temp=p1.x;
   p1.x=p2.x;
   p2.x=temp;

   temp=p1.y;
   p1.y=p2.y;
   p2.y=temp;


  }
 //纵向扫描
 for(j=0;j<=N-1;j++)
 {  
  y_across=true;
  //是否垂直连通
  for(i=p1.x+1; i<=p2.x-1; i++ )
  {
   if(matrix[i][j]!=0)
   {
    y_across=false;
    break;
   }
  }

  if(matrix[p1.x][j]!=0  )
  {
   if( j!=p1.y )
    y_across=false;
  }
  if(matrix[p2.x][j]!=0  )
  {
   if( j!=p2.y )
    y_across=false;
  }
    
  if(y_across)
  {//垂直连通才执行下面
  /* for(j=1; j<N-2; j++ )
   {*/
    //检验在水平上是否连通

   py1=py2=j;
   px1=p1.x;
   px2=p2.x;
   while( py1!=p1.y || py2!=p2.y)
   {
    //如果当前点不空且不为p1点,就跳出循环,从下一行开始检测
    if( matrix[px1][py1]!=0 && (px1!=p1.x || py1!=p1.y) )
     break;

    //如果当前点不空且不为p2点,就跳出循环,从下一行开始检测
    if( matrix[px2][py2]!=0 && (px2!=p2.x || py2!=p2.y) )
     break;

    //如果两点都为空
    //水平向p1点靠近一格
    if(py1<p1.y)
     py1++;
    else if(py1>p1.y)
     py1--;
    //水平向p2点靠近一格
    if(py2<p2.y)
     py2++;
    else if(py2>p2.y)
     py2--;
   }
     
   //如果能到达两个端点
   if(px1==p1.x && py1==p1.y && px2==p2.x && py2==p2.y )
   {
    //起点
    way[0].x=p1.x;
    way[0].y=p1.y;
    //两个转折点
    way[1].x=p1.x;
    way[1].y=j;
    way[2].x=p2.x;
    way[2].y=j;
    //终点
    way[3].x=p2.x;
    way[3].y=p2.y; 
    return true;
   }

  }
 }
 //} 
 return false;

}

void Linker_Matrix::init_search()
{
 visited = Matrix< int, M, N >();
 index = 0;
 turn_count = 0;
}

void Linker_Matrix::auto_play()
{
  while( auto_search() );
}

bool Linker_Matrix::man_search(const point p1, const point p2)
{
 init_search();
 if( find_way( p1, p2 ) )
 {
  matrix[p1.x][p1.y]=0;
  matrix[p2.x][p2.y]=0;
  return true;
 }
 return false;
}

 int Linker_Matrix::get_element( int x, int y )
 {
  return matrix[x][y];
 }

void Linker_Matrix::get_point(point &p1,point &p2)
{
 //if( auto_search() )
 //{
  p1=this->p1;
  p2=this->p2;
  //return true;
 //}
 
 //return false;
}

void Linker_Matrix::reShuffle()
{
 int m,n,k;
 time_t curtime; //记录当前时间

 //p1.x = p1.y = 0;
 //p2.x = p2.y = 0;
 //index = 0;

 time(&curtime);//取得当前时间
 srand(curtime);//用当前时间作种子,产生随机数

 //for( int k=0; k<4; k++ )
 // way[k].x = way[k].y = 0;

 for( int i=1; i<=(M-2); i++ )
 for( int j=1; j<=(N-2); j++ )
 {
  if(matrix[i][j]!=0)
  {
   do
   {
    m = rand()%(M-2) + 1;
    n = rand()%(N-2) + 1;
   }
   while( 0==matrix[m][n] );

   k=matrix[i][j];
   matrix[i][j]=matrix[m][n];
   matrix[m][n]=k;
  }
 }
}

linker.cpp

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include <windows.h>

#include "head.h"
#include "resource.h"

TCHAR szAppName[] = TEXT ("Linker") ;//程序名称
const int xsize=610,ysize=520;
const int TimerID=1;


LRESULT CALLBACK WndProc ( HWND, UINT, WPARAM, LPARAM ) ;

int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow )

 HWND         hwnd ;
 MSG          msg ;
 WNDCLASS     wndclass ;
 HACCEL hAccel ;//快捷键表


 wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
 wndclass.lpfnWndProc   = WndProc ;
 wndclass.cbClsExtra    = 0 ;
 wndclass.cbWndExtra    = 0 ;
 wndclass.hInstance     = hInstance ;
 wndclass.hIcon         = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON)) ;
 wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
 wndclass.lpszMenuName  = szAppName ;
 wndclass.lpszClassName = szAppName ;

 if (!RegisterClass (&wndclass))
 {
  MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
    szAppName, MB_ICONERROR) ;
  return 0 ;
 }
     
 hwnd = CreateWindow ( szAppName,  // window class name
                          TEXT ("连连看 V1.08.18.01"), // window caption
                          WS_OVERLAPPEDWINDOW & 
     ~WS_MAXIMIZEBOX & ~WS_SIZEBOX,// window style
     //没有最大化按钮和无法改变窗口大小
                          CW_USEDEFAULT,  // initial x position
                          CW_USEDEFAULT,  // initial y position
                          xsize,  // initial x size
                          ysize,  // initial y size
                          NULL,    // parent window handle
                          NULL,    // window menu handle
                          hInstance,   // program instance handle
                          NULL ) ;   // creation parameters
     
 ShowWindow (hwnd, iCmdShow) ;
 UpdateWindow (hwnd) ;
     
 hAccel = LoadAccelerators (hInstance, TEXT ("MY_ACCELERATOR")) ;

 while(GetMessage (&msg, NULL, 0, 0))
 {
  if(!TranslateAccelerator (hwnd, hAccel, &msg))
  {
                  TranslateMessage (&msg) ;
                  DispatchMessage (&msg) ;
  }
 }

 return msg.wParam ;
}

BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message, 
                            WPARAM wParam, LPARAM lParam)
{
     switch (message)
     {
     case WM_INITDIALOG :
          return TRUE ;
          
     case WM_COMMAND :
          switch (LOWORD (wParam))
          {
          case IDOK :
          case IDCANCEL :
               EndDialog (hDlg, 0) ;
               return TRUE ;
          }
          break ;
     }
     return FALSE ;
}

LRESULT CALLBACK WndProc ( HWND hwnd, UINT message, 
    WPARAM wParam, LPARAM lParam )
{
 HDC  hdc,hdcMem;
 //HBRUSH hBrush ;
 PAINTSTRUCT ps ;//绘图结构
 static RECT  rect,rect2 ;//矩形
 static HBITMAP hBitmap1,hBitmap2;//两个位图文件句柄
 HBITMAP hBitmap3;
 BITMAP  bitmap ;//位图文件
 static int cxBack,cyBack,cxPre,cyPre,cxStart,cyStart;
    //cxBack,cyBack:背景图片大小
    //cxPre,cyPre:牌面图片大小  
 int x,y,i,j,num;

 bool find;//是否有路径标志
 static bool first_started=false;//是否是刚打开程序
 static bool bPrompt=false;//是否提示
 TCHAR    szBuffer[14];
 static HINSTANCE hInstance ;
 static HMENU  hMenu ;//菜单句柄
 static int  iCurrentLevel = IDM_APP_LOW ;//记录游戏难度
 static int  iTime = 100 ;//记录游戏的剩余时间
 static  int  iShuffle=0,iPrompt=0;
  //iShuffle:重新洗牌的剩余次数,iPrompt:提示的剩余次数
 static int iCount=0;//统计消去的对数,用于判断是否胜利
 static Linker_Matrix linker ;//连连看的运算矩阵
 static point  pSelected[2] ;//用于记录选择的两个点
     
 switch (message)
 {
 case WM_CREATE://进行初始化;
  //PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
  //GetClientRect(hwnd,&rect);

  MoveWindow(hwnd,(GetSystemMetrics(SM_CXSCREEN)-xsize)/2,(GetSystemMetrics(SM_CYSCREEN)-ysize)/2,xsize,ysize,false);
  //将窗口移置屏幕中间

  hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
  hMenu = GetMenu (hwnd) ;
  pSelected[0].x=pSelected[0].y=0;
  pSelected[1].x=pSelected[1].y=0;

  hBitmap1 = LoadBitmap (hInstance, TEXT ("IDB_BITMAP_BACK"));
  hBitmap2 = LoadBitmap (hInstance, TEXT ("IDB_BITMAP_PRE"));
  

  GetObject (hBitmap1, sizeof (BITMAP), &bitmap) ;

  cxBack = bitmap.bmWidth ;
  cyBack = bitmap.bmHeight/7 ;
  GetObject (hBitmap2, sizeof (BITMAP), &bitmap) ;

  cxPre = bitmap.bmWidth/2 ;
  cyPre = bitmap.bmHeight/42 ;

  //SendMessage(hwnd,WM_COMMAND,IDM_APP_START,0);
  first_started=true;
  
  return 0 ;

 case WM_TIMER:
  if(iTime>0)
   iTime--;

  //使字体所在区域无效化,重绘
  rect.left = 0;
  rect.right = xsize;
  rect.top  = 0;
  rect.bottom = 20;
  InvalidateRect (hwnd, &rect, true) ;
  rect.left = 0;
  rect.right = 0;
  rect.top  = 0;
  rect.bottom = 0;

  if( iTime<=0 )
  {
   iCount=0;
   KillTimer (hwnd, TimerID) ;
   MessageBox (hwnd, TEXT ("时间到,你输了!!"),szAppName, MB_OK | MB_ICONQUESTION) ;
   

   SendMessage(hwnd,WM_COMMAND,IDM_APP_START,0);

   linker=Linker_Matrix();
   InvalidateRect (hwnd, NULL, true) ;
  }
  


  return 0;

  

 case WM_PAINT:
  hdc = BeginPaint (hwnd, &ps) ;
  
  //GetClientRect (hwnd, &rect) ;
  hdcMem = CreateCompatibleDC (hdc) ;
   
  

  //绘制牌面
  for(i=1; i<=M-2; i++ )
   for(j=1; j<=N-2; j++ )
   {
    num=linker.get_element(i,j);
    if( num!=0 )
    {
    x=i*(cxBack-3);
    y=j*(cyBack-4)-30;
    SelectObject (hdcMem, hBitmap1) ;
    BitBlt (hdc, x, y, cxBack, cyBack, hdcMem, 0, cyBack*(num%6+1), SRCCOPY) ;
    SelectObject (hdcMem, hBitmap2) ;
    BitBlt (hdc, x+1, y+6, cxPre, cyPre, hdcMem,  cxPre, cyPre*num, SRCAND) ;
    BitBlt (hdc, x+1, y+6, cxPre, cyPre, hdcMem,  0, cyPre*num, SRCPAINT) ;
   
    }
   }
  
  //当选中第一张牌时,在上面画个圈
  if(rect.left!=0 && rect.right!=0 && rect.top!=0 && rect.bottom!=0 && bPrompt==false)
  {
   SelectObject (hdc, GetStockObject (GRAY_BRUSH)) ;
   Ellipse(hdc,rect.left ,rect.top ,rect.left+10 ,rect.top+10 );
   rect.left=0;
   rect.right=0 ;
   rect.top=0; 
   rect.bottom=0;

  }
  if( first_started==false)
  {
   sprintf(szBuffer,"剩余时间: %d 秒",iTime);
   TextOut (hdc, 0, 0, szBuffer, strlen (szBuffer)) ;
   TextOut (hdc, xsize/5, 0, TEXT("每消去一对剩余时间+2秒"), strlen (TEXT("每消去一对剩余时间+3秒"))) ;
   sprintf(szBuffer,"剩余洗牌次数: %d 次",iShuffle);
   TextOut (hdc, xsize/2+10, 0, szBuffer, strlen (szBuffer)) ;
   sprintf(szBuffer,"剩余提示次数: %d 次",iPrompt);
   TextOut (hdc, xsize/4*3, 0, szBuffer, strlen (szBuffer)) ;
  }

  if(first_started)
  {//第一次打开程序

   /*SendMessage(hwnd,WM_COMMAND,IDM_APP_ABOUT,0);
   //发送 单击关于菜单 消息
   SendMessage(hwnd,WM_COMMAND,IDM_APP_START,0);
   //发送 单击开始游戏菜单 消息,询问是否开始;*/
   hBitmap3 = LoadBitmap (hInstance, TEXT ("IDB_BITMAP_START"));
   GetObject (hBitmap3, sizeof (BITMAP), &bitmap) ;
   cxStart = bitmap.bmWidth;
   cyStart = bitmap.bmHeight;

   SelectObject (hdcMem, hBitmap3) ;
   StretchBlt  (hdc, 0, 0, xsize, ysize, hdcMem, 0,0, cxStart, cyStart,MERGECOPY) ;
   PlaySound (TEXT ("start.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
   //first_started=false;
  }
 
  if(bPrompt)
  {
   SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ;
   Ellipse(hdc,rect.left ,rect.top ,rect.left+10 ,rect.top+10 );
   Ellipse(hdc,rect2.left ,rect2.top ,rect2.left+10 ,rect2.top+10 );
   rect.left=0;
   rect.right=0 ;
   rect.top=0; 
   rect.bottom=0;
   rect2.left=0;
   rect2.right=0 ;
   rect2.top=0; 
   rect2.bottom=0;

   bPrompt=false;
  }

  DeleteDC (hdcMem) ;
  EndPaint (hwnd, &ps) ;

  return 0 ;
 case WM_INITMENUPOPUP:

  if( first_started==false )
  {
   EnableMenuItem ((HMENU) wParam, IDM_APP_RESHUFFLE,   MF_ENABLED) ;
   EnableMenuItem ((HMENU) wParam, IDM_APP_PROMPT,   MF_ENABLED) ;
  }

  if(iShuffle==0)
   EnableMenuItem ((HMENU) wParam, IDM_APP_RESHUFFLE,  MF_GRAYED) ;
  if(iPrompt==0)
   EnableMenuItem ((HMENU) wParam, IDM_APP_PROMPT,  MF_GRAYED) ;

  
  break;

 case WM_COMMAND :
  switch (LOWORD (wParam))
  {

  case IDM_APP_START://单击开始游戏菜单
   if ( IDYES == MessageBox (hwnd, TEXT ("开始游戏吗?"),
    szAppName, MB_YESNO | MB_ICONQUESTION) )
   //弹出确认窗口,按YES开始游戏
   {
    if ( iCurrentLevel==IDM_APP_LOW )
    {//难度为低
     iTime=90;
     iPrompt=3;
     iShuffle=2;
     linker=Linker_Matrix(6);
    
    }

    if ( iCurrentLevel==IDM_APP_MIDDLE )
    {//难度为中
     iTime=90;
     iPrompt=3;
     iShuffle=2;
     linker=Linker_Matrix(4);
     
    }
    
    if ( iCurrentLevel==IDM_APP_HIGH )
    {//难度为高
     iTime=60;
     iPrompt=3;
     iShuffle=1;
     linker=Linker_Matrix(4);
    
    }
   
    SetTimer (hwnd, TimerID, 1000, NULL) ;
    InvalidateRect (hwnd, NULL, TRUE) ;
    first_started=false;
    iCount=0;

   }
   else
    SendMessage(hwnd,WM_CLOSE,0,0);
   break;

  case IDM_APP_EXIT ://单击退出游戏菜单
   SendMessage(hwnd,WM_CLOSE,0,0);
   break;

  case IDM_APP_ABOUT ://单击关于菜单
   DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ;
   break ;

  case IDM_APP_LOW:
  case IDM_APP_MIDDLE:
  case IDM_APP_HIGH:
   //单击难度菜单
   CheckMenuItem (hMenu, iCurrentLevel, MF_UNCHECKED) ;
   iCurrentLevel = LOWORD (wParam) ;
   CheckMenuItem (hMenu, iCurrentLevel, MF_CHECKED) ;
   break;

  case IDM_APP_RESHUFFLE://单击重新洗牌按钮
   if(iShuffle>0 )
   { 
    iShuffle--;
    linker.reShuffle();
   }
   //if(iShuffle==0)
    //EnableMenuItem ((HMENU) wParam, IDM_APP_RESHUFFLE,  MF_GRAYED) ;
   
   //使文字所在区域无效化,重绘
   /*rect.left = 0;
   rect.right = xsize;
   rect.top  = 0;
   rect.bottom = 20;*/
   InvalidateRect (hwnd, NULL , true) ;
   rect.left = 0;
   rect.right = 0;
   rect.top  = 0;
   rect.bottom = 0;
   break;

  case IDM_APP_PROMPT:
   if(iPrompt>0 && linker.auto_search() )//提示次数>0,且找到匹配
   {
    //pSelected[0].x=pSelected[0].y=0;
    linker.get_point(pSelected[0],pSelected[1]);
    iPrompt--;

    //使文字所在区域无效化,重绘
    rect.left = 0;
    rect.right = xsize;
    rect.top  = 0;
    rect.bottom = 20;
    InvalidateRect (hwnd, &rect, true) ;
    rect.left = 0;
    rect.right = 0;
    rect.top  = 0;
    rect.bottom = 0;
     
    //sprintf(szBuffer," %d %d %d %d",pSelected[0].x,pSelected[0].y,pSelected[1].x,pSelected[1].y);
    //MessageBox (hwnd, szBuffer,szAppName, MB_OK | MB_ICONQUESTION) ;
    
    rect.left = pSelected[0].x*(cxBack-3);
    rect.right = rect.left+(cxBack-3)+3;
    rect.top  = pSelected[0].y *(cyBack-4)-30;
    rect.bottom = rect.top + (cyBack-4)+4;
    //Ellipse(hdc,rect.left ,rect.top ,rect.right ,rect.bottom );
    InvalidateRect (hwnd, &rect, true) ;
    
    rect2.left = pSelected[1].x *(cxBack-3);
    rect2.right = rect2.left+(cxBack-3)+3;
    rect2.top  = pSelected[1].y *(cyBack-4)-30;
    rect2.bottom = rect2.top + (cyBack-4)+4;
    //Ellipse(hdc,rect.left ,rect.top ,rect.right ,rect.bottom );
    InvalidateRect (hwnd, &rect2, true) ;
 
    pSelected[0].x=0;
    pSelected[0].y=0;
    pSelected[1].x=0;
    pSelected[1].y=0;

   }

   bPrompt=true;
   //if(iPrompt==0)
    //EnableMenuItem ((HMENU) wParam, IDM_APP_PROMPT,  MF_GRAYED) ;
   break;
  }
  return 0 ;
 case WM_LBUTTONUP:
  //取得鼠标坐标
  x= LOWORD (lParam)/(cxBack-3);
  y= ( HIWORD (lParam)+30)/(cyBack-4);
  if (x>=1 && x<=M-2 && y>=1 && y<=N-2 && linker.get_element(x,y)!=0 )
  {
  /*
  sprintf(szBuffer,"%d",y);
  MessageBox (hwnd, TEXT (szBuffer),
    szAppName, MB_YESNO | MB_ICONQUESTION) ;*/
  //如果是在第一张牌按下鼠标
  if(pSelected[0].x==0 && pSelected[0].y==0 )
  {
   //hBrush = GetStockObject (GRAY_BRUSH) ;
   //SelectObject (hdc, hBrush) ;
   
   //hdc = BeginPaint (hwnd, &ps) ;
   //SelectObject (hdc, GetStockObject (BLACK_PEN)) ;

   //在该牌上画圆
    rect.left = x *(cxBack-3);
    rect.right = rect.left+(cxBack-3)+3;
    rect.top  = y *(cyBack-4)-30;
    rect.bottom = rect.top + (cyBack-4)+4;
    //Ellipse(hdc,rect.left ,rect.top ,rect.right ,rect.bottom );
    InvalidateRect (hwnd, &rect, true) ;
    //EndPaint (hwnd, &ps) ;
   //把牌的位置记录下来
   pSelected[0].x=x;
   pSelected[0].y=y;
  }
  else 
  { //如果是第二张牌上按鼠标

   //把牌的位置记录下来
   pSelected[1].x=x;
   pSelected[1].y=y;

  
   if( (pSelected[0].x!=pSelected[1].x ||
    pSelected[0].y!=pSelected[1].y) &&
    linker.is_matched(pSelected[0],pSelected[1]) )
   {//如果不是同一张牌并且花色一致
    
    //寻找路径
    find=linker.man_search(pSelected[0],pSelected[1])
     || linker.man_search(pSelected[1],pSelected[0]);;

    if(find)
    {//找到

     //GetClientRect (hwnd, &rect) ;
     rect.left = pSelected[0].x *(cxBack-3);
     rect.right = rect.left+(cxBack-3)+3;
     rect.top  = pSelected[0].y *(cyBack-4)-30;
     rect.bottom = rect.top + (cyBack-4)+4;
     InvalidateRect (hwnd, &rect, true) ;

     rect.left = pSelected[1].x *(cxBack-3);
     rect.right = rect.left+(cxBack-3)+3;
     rect.top  = pSelected[1].y *(cyBack-4)-30;
     rect.bottom = rect.top + (cyBack-4)+4;
     InvalidateRect (hwnd, &rect, true) ;

     rect.left=0;
     rect.right=0 ;
     rect.top=0; 
     rect.bottom=0;

     iCount++;
     iTime+=2;

     PlaySound (TEXT ("yes.wav"), NULL, SND_FILENAME | SND_ASYNC) ;

     //InvalidateRect (hwnd, NULL, true) ;

    }
    else
    {//没找到
    /*
     sprintf(szBuffer,"%d",find);
     MessageBox (hwnd, TEXT (szBuffer),
     szAppName, MB_YESNO | MB_ICONQUESTION) ;*/

     rect.left = pSelected[0].x *(cxBack-3);
     rect.right = rect.left+(cxBack-3)+3;
     rect.top  = pSelected[0].y *(cyBack-4)-30;
     rect.bottom = rect.top + (cyBack-4)+4;
     InvalidateRect (hwnd, &rect, true) ;

     rect.left=0;
     rect.right=0 ;
     rect.top=0; 
     rect.bottom=0;
     PlaySound (TEXT ("no.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
    
    }
    pSelected[0].x=0;
    pSelected[0].y=0;
    pSelected[1].x=0;
    pSelected[1].y=0;

    
   }
   else
   {//同一张牌或花色不一致

    rect.left = pSelected[0].x *(cxBack-3);
    rect.right = rect.left+(cxBack-3)+3;
    rect.top  = pSelected[0].y *(cyBack-4)-30;
    rect.bottom = rect.top + (cyBack-4)+4;
    InvalidateRect (hwnd, &rect, true) ;

    pSelected[0].x=x;
    pSelected[0].y=y;
    pSelected[1].x=0;
    pSelected[1].y=0;

    rect.left = pSelected[0].x *(cxBack-3);
    rect.right = rect.left+(cxBack-3)+3;
    rect.top  = pSelected[0].y *(cyBack-4)-30;
    rect.bottom = rect.top + (cyBack-4)+4;
    InvalidateRect (hwnd, &rect, true) ;
    /*
    rect.left=0;
    rect.right=0 ;
    rect.top=0; 
    rect.bottom=0;*/
   }
  

  }
  }

  if( iCount==(M-2)*(N-2)/2 )
  { 
   iCount=0;
   KillTimer (hwnd, TimerID) ;
   MessageBox (hwnd, TEXT ("恭喜你,你赢了!!"),szAppName, MB_OK | MB_ICONQUESTION) ;


   SendMessage(hwnd,WM_COMMAND,IDM_APP_START,0);
  }
  return 0;
  

 case WM_CLOSE://用户关闭程序
  if ( IDYES == MessageBox (hwnd, TEXT ("确认关闭程序"),
    szAppName, MB_YESNO | MB_ICONQUESTION) )
  //弹出确认窗口,按YES退出程序
  {
   PlaySound (TEXT ("close.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
   KillTimer (hwnd, TimerID) ;
   DestroyWindow (hwnd) ;
   Sleep(2000);
  }
  return 0 ;
 case WM_DESTROY:
  
  PostQuitMessage (0) ;
  return 0 ;
 }

 return DefWindowProc (hwnd, message, wParam, lParam) ;
}

目录
相关文章
|
6月前
|
存储 开发框架 小程序
社区每周丨小程序 CLI 1.8.10 版本上线及基础API新增接口(7.3-7.7)
社区每周丨小程序 CLI 1.8.10 版本上线及基础API新增接口(7.3-7.7)
87 11
|
6月前
|
敏捷开发 JavaScript 前端开发
❤❤❤【Vue.js最新版】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本❤❤❤
❤❤❤【Vue.js最新版】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本❤❤❤
|
Java API
Java调用淘宝API demo源代码
Java调用淘宝API demo源代码
114 0
|
2月前
|
API
本地hook API MessageBoxA的masm32源代码[07-10更新]
本地hook API MessageBoxA的masm32源代码[07-10更新]
|
3月前
|
文字识别 算法 API
视觉智能开放平台产品使用合集之海外是否可以访问人物动漫化的api版本
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
51 0
|
3月前
|
Oracle Java 关系型数据库
JDK版本特性问题之在 JDK 11 中,HTTP Client API 的特点有哪些
JDK版本特性问题之在 JDK 11 中,HTTP Client API 的特点有哪些
|
3月前
|
缓存 JavaScript 前端开发
微信 JS-SDK Demo “分享信息设置” API 及数字签名生成方法(NodeJS版本)
微信 JS-SDK Demo “分享信息设置” API 及数字签名生成方法(NodeJS版本)更新时间(2020-10-29)
|
4月前
|
人工智能 自然语言处理 数据挖掘
详解:Google AI Gemini中文版本(基于API 开发实现对话)
谷歌旗下的人工智能应用Gemini,自问世以来凭借其强大的计算能力和高效的处理性能,迅速成为全球用户的宠儿。作为一款由世界顶尖科技公司开发的产品,Gemini不仅在语言处理、图像识别、数据分析等领域表现出色,还在多种复杂任务中展现了其卓越的智能决策能力。然而,由于网络限制等问题,国内用户往往无法直接访问和使用Gemini的网站,这也导致了许多技术爱好者和专业人士未能亲身体验这一先进技术所带来的便利和强大功能。
|
4月前
|
Java API PHP
【亲测有效,官方提供】php版本企查查api接口请求示例代码,php请求企查查api接口,thinkphp请求企查查api接口
【亲测有效,官方提供】php版本企查查api接口请求示例代码,php请求企查查api接口,thinkphp请求企查查api接口
142 1
|
5月前
|
API
个人微信api接口源代码
个人微信api接口源代码

热门文章

最新文章