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) ;
}