?? skyblue_llkdlg.cpp
字號:
/*++
Copyright (c) AFE(Active-Free-Elegance)
Module Name:
skyblue_LLKDlg.cpp
Abstract:
LLK-Game's kernal-solving Dialog
Author:
Weijian Luo (Arthur Luo) 15-Jun-2005
E-mail: skybluehacker@yahoo.com.cn
Revision History: 1.0
--*/
#include "stdafx.h"
#include "skyblue_LLK.h"
#include "skyblue_LLKDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// C_LLK_Dlg dialog
#define BKCOLOR RGB(128,128,128) //背景顏色
#define FRONTWIDTH (39+2) //前面方塊的寬度
#define FRONTHEIGHT (39+12) //前面方塊的高度
#define BKWIDTH 46 //背景方塊的寬度
#define BKHEIGHT 56 //背景方塊的高度
#define ROWCOUNT 7 //行數(shù)
#define COLCOUNT 12 //列數(shù)
#define BLANK_STATE -1 //空方塊(沒有任何動物)
/////////////////////////////////////////////////////////////////////////////
// C_LLK_Dlg dialog
C_LLK_Dlg::C_LLK_Dlg(CWnd* pParent /*=NULL*/)
: CDialog(C_LLK_Dlg::IDD, pParent)
{
//{{AFX_DATA_INIT(C_LLK_Dlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
//記錄方塊置為無效狀態(tài)
m_nY1= BLANK_STATE;
m_nX1= BLANK_STATE;
//初始化行列數(shù)
m_nRow=ROWCOUNT;
m_nCol=COLCOUNT;
//根據(jù)行列數(shù)動態(tài)分配內(nèi)核數(shù)據(jù)數(shù)組空間
m_map=new int[m_nRow*m_nCol];
}
C_LLK_Dlg::~C_LLK_Dlg()
{
//釋放動態(tài)數(shù)組空間
delete[] m_map;
}
void C_LLK_Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(C_LLK_Dlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(C_LLK_Dlg, CDialog)
//{{AFX_MSG_MAP(C_LLK_Dlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// C_LLK_Dlg message handlers
BOOL C_LLK_Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//獲取程序框架的設(shè)備環(huán)境
CDC *pWinDC = GetDC();
//內(nèi)存設(shè)備環(huán)境以及內(nèi)存位圖的創(chuàng)建,初始化,關(guān)聯(lián)
//3D方塊邊框圖樣內(nèi)存位圖
m_mem3DBkDC.CreateCompatibleDC(pWinDC);
m_mem3DBkBmp.LoadBitmap(IDB_BITMAP_3D_FRAMES);
m_mem3DBkDC.SelectObject(&m_mem3DBkBmp);
//動物圖樣內(nèi)存位圖
m_memAnimalDC.CreateCompatibleDC(pWinDC);
m_memAnimalBmp.LoadBitmap(IDB_BMP_ANIMAL);
m_memAnimalDC.SelectObject(&m_memAnimalBmp);
//整個游戲區(qū)域內(nèi)存位圖
m_MemDC.CreateCompatibleDC(pWinDC);
m_memBitmap.CreateCompatibleBitmap(pWinDC,
m_nCol*FRONTWIDTH+5,
m_nRow*FRONTHEIGHT+5);
m_MemDC.SelectObject(&m_memBitmap);
//開始一個新的游戲
StartNewGame();
//放在最桌面的前面顯示
HWND hWnd = ::AfxGetMainWnd()->m_hWnd;
::SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
return TRUE; // return TRUE unless you set the focus to a control
}
void C_LLK_Dlg::StartNewGame()
{
//初始化地圖,將地圖中所有方塊區(qū)域位置置為空方塊狀態(tài)
for(int iNum=0;iNum<(m_nCol*m_nRow);iNum++)
{
m_map[iNum] = BLANK_STATE;
}
//部下隨機(jī)種子
srand(time(NULL));
//生成隨機(jī)地圖
//將所有匹配成對的動物物種放進(jìn)一個臨時的地圖中
CDWordArray tmpMap;
for(int i=0;i<(m_nCol*m_nRow)/4;i++)
for(int j=0;j<4;j++)
tmpMap.Add(i);
//每次從上面的臨時地圖中取走(獲取后并在臨時地圖刪除)
//一個動物放到地圖的空方塊上
for(i=0;i<m_nRow*m_nCol;i++)
{
//隨機(jī)挑選一個位置
int nIndex=(int(rand()*0.1+rand()*0.01+rand()))%tmpMap.GetSize();
//獲取該選定物件放到地圖的空方塊
m_map[i]=tmpMap.GetAt(nIndex);
//在臨時地圖除去該動物
tmpMap.RemoveAt(nIndex);
}
//更新顯示
Invalidate(TRUE);
}
//
// 游戲區(qū)域的繪制
//
void C_LLK_Dlg::GameDraw(CDC * pDC)
{
//繪制背景顏色
pDC->FillSolidRect(0,0,m_nCol*FRONTWIDTH+5,m_nRow*FRONTHEIGHT+5,BKCOLOR);
for(int i=0;i<m_nRow;i++)
{
for(int j=0;j<m_nCol;j++)
{
if(m_map[i*m_nCol+j]==BLANK_STATE)
{
continue;
}
//繪制方塊邊框
pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT,
BKWIDTH,BKHEIGHT,
&m_mem3DBkDC,
0,BKHEIGHT,
SRCCOPY);
//繪制方塊
//因?yàn)橐沟眯Ч该鳎杂蓤D樣的底色以及表面兩部分構(gòu)成
pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT,
FRONTWIDTH-2,FRONTHEIGHT-12,
&m_memAnimalDC,
FRONTWIDTH-2,m_map[i*m_nCol+j]*(FRONTHEIGHT-12),
SRCAND);
pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT,
FRONTWIDTH-2,FRONTHEIGHT-12,
&m_memAnimalDC,
0,m_map[i*m_nCol+j]*(FRONTHEIGHT-12),
SRCPAINT);
}
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR C_LLK_Dlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void C_LLK_Dlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
//先將整個游戲區(qū)域的圖像繪制到內(nèi)存位圖
GameDraw(&m_MemDC);
//將內(nèi)存位圖中繪制好的圖像一次性拷貝到屏幕
dc.BitBlt(0,0,m_nCol*FRONTWIDTH,m_nCol*FRONTHEIGHT,&m_MemDC,0,0,SRCCOPY);
}
//
// 鼠標(biāo)左鍵消息處理
//
void C_LLK_Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
//1.計算鼠標(biāo)點(diǎn)擊方塊的的位置
int x=point.x/FRONTWIDTH+(point.x%FRONTWIDTH?1:0)-1;
int y=point.y/FRONTHEIGHT+(point.y%FRONTHEIGHT?1:0)-1;
//2.在游戲區(qū)域內(nèi)并且該區(qū)域還有該區(qū)域不是空的區(qū)域
if(x<m_nCol&&y<m_nRow&&m_map[y*m_nCol+x]!= BLANK_STATE)
{
//3.假設(shè)尚未記錄第一個方塊
if(m_nX1==BLANK_STATE)
{
//4.記錄第一個方塊的位置
m_nX1=x;
m_nY1=y;
//獲取程序框架的設(shè)備環(huán)境
CDC *pWinDC = GetDC();
//臨時繪制點(diǎn)中的方塊外框
//只繪屏幕不載入內(nèi)存位圖
CPen myPen;
CPen *pOldPen;
myPen.CreatePen(PS_SOLID, 4, RGB(255,0,0));
pOldPen = pWinDC->SelectObject(&myPen);
//方塊外框繪制,線條環(huán)繞繪制框架
pWinDC->MoveTo(x*FRONTWIDTH,y*FRONTHEIGHT);
pWinDC->LineTo(x*FRONTWIDTH,(y+1)*FRONTHEIGHT);
pWinDC->LineTo((x+1)*FRONTWIDTH,(y+1)*FRONTHEIGHT);
pWinDC->LineTo((x+1)*FRONTWIDTH,y*FRONTHEIGHT);
pWinDC->LineTo(x*FRONTWIDTH,y*FRONTHEIGHT);
//現(xiàn)場恢復(fù)
pWinDC->SelectObject(pOldPen);
}
else
{
//5.判斷是否點(diǎn)擊的方塊非本身, 是否點(diǎn)擊同一種動物
if((m_nX1!=x||m_nY1!=y)&&
m_map[m_nY1*m_nCol+m_nX1]==m_map[y*m_nCol+x]
)
{
//6.檢測是否可以消除
if(IsLink(m_nX1,m_nY1,x,y))
{
//7.數(shù)據(jù)清理
m_map[m_nY1*m_nCol+m_nX1]=BLANK_STATE;
m_map[y*m_nCol+x]=BLANK_STATE;
}
}
//8.清空記錄方塊的值
m_nX1=BLANK_STATE;
m_nY1=BLANK_STATE;
//通知重繪
Invalidate(FALSE);
}
}
//察看是否已經(jīng)勝利
if(IsWin())
{
MessageBox("恭喜您勝利闖關(guān),即將開始新局");
StartNewGame();
}
}
//
//X直接連通
//
BOOL C_LLK_Dlg::X1_Link_X2(int x, int y1,int y2)
{
//保證y1的值小于y2
if(y1>y2)
{
//數(shù)據(jù)交換
int n=y1;
y1=y2;
y2=n;
}
//直通
for(int i=y1+1;i<=y2;i++)
{
if(i==y2)
return TRUE;
if(m_map[i*m_nCol+x]!=BLANK_STATE)
break;
}
//左通
if(XThrough(x-1,y1,FALSE)&&XThrough(x-1,y2,FALSE))
return TRUE;
//右通
if(XThrough(x+1,y1,TRUE)&&XThrough(x+1,y2,TRUE))
return TRUE;
return FALSE;
}
//
//Y直接連通
//
BOOL C_LLK_Dlg::Y1_Link_Y2(int x1,int x2,int y)
{
if(x1>x2)
{
int x=x1;
x1=x2;
x2=x;
}
//直通
for(int i=x1+1;i<=x2;i++)
{
if(i==x2)
return TRUE;
if(m_map[y*m_nCol+i]!=BLANK_STATE)
break;
}
//上通
if(YThrough(x1,y-1,FALSE)&&YThrough(x2,y-1,FALSE))
return TRUE;
//下通
if(YThrough(x1,y+1,TRUE)&&YThrough(x2,y+1,TRUE))
return TRUE;
return FALSE;
}
//
// 是否同一直線通
//
BOOL C_LLK_Dlg::LineX(int x,int y1,int y2)
{
if(y1>y2)
{
int y=y1;
y1=y2;
y2=y;
}
for(int y=y1;y<=y2;y++)
{
if(m_map[y*m_nCol+x]!=BLANK_STATE)
return FALSE;
if(y==y2)
return TRUE;
}
return FALSE;
}
//
// 是否同一直線通
//
BOOL C_LLK_Dlg::LineY(int x1,int x2,int y)
{
if(x1>x2)
{
int x=x1;
x1=x2;
x2=x;
}
for(int x=x1;x<=x2;x++)
{
if(m_map[y*m_nCol+x]!=BLANK_STATE)
return FALSE;
if(x==x2)
return TRUE;
}
return FALSE;
}
//
// 1直角接口連通
//
BOOL C_LLK_Dlg::OneCornerLink(int x1, int y1,int x2, int y2)
{
if(x1>x2)
{
int n=x1;
x1=x2;
x2=n;
n=y1;
y1=y2;
y2=n;
}
if(y2<y1)
{
if(LineY(x1+1,x2,y1)&&LineX(x2,y1,y2+1))
return TRUE;
if(LineY(x2-1,x1,y2)&&LineX(x1,y2,y1-1))
return TRUE;
return FALSE;
}
else
{
if(LineY(x1+1,x2,y1)&&LineX(x2,y1,y2-1))
return TRUE;
if(LineY(x2-1,x1,y2)&&LineX(x1,y2,y1+1))
return TRUE;
return FALSE;
}
return FALSE;
}
//
// 2直角接口連通
//
BOOL C_LLK_Dlg::TwoCornerLink(int x1, int y1, int x2, int y2)
{
if(x1>x2)
{
int n=x1;
x1=x2;
x2=n;
n=y1;
y1=y2;
y2=n;
}
//右通
if(XThrough(x1+1,y1,TRUE)&&XThrough(x2+1,y2,TRUE))
return TRUE;
//左通
if(XThrough(x1-1,y1,FALSE)&&XThrough(x2-1,y2,FALSE))
return TRUE;
//上通
if(YThrough(x1,y1-1,FALSE)&&YThrough(x2,y2-1,FALSE))
return TRUE;
//下通
if(YThrough(x1,y1+1,TRUE)&&YThrough(x2,y2+1,TRUE))
return TRUE;
//右
for(int x=x1+1;x<m_nCol;x++)
{
if(m_map[y1*m_nCol+x]>-1)
break;
if(OneCornerLink(x,y1,x2,y2))
return TRUE;
}
//左
for(x=x1-1;x>-1;x--)
{
if(m_map[y1*m_nCol+x]!=BLANK_STATE)
break;
if(OneCornerLink(x,y1,x2,y2))
return TRUE;
}
//上
for(int y=y1-1;y>-1;y--)
{
if(m_map[y*m_nCol+x1]!=BLANK_STATE)
break;
if(OneCornerLink(x1,y,x2,y2))
return TRUE;
}
//下
for(y=y1+1;y<m_nRow;y++)
{
if(m_map[y*m_nCol+x1]!=BLANK_STATE)
break;
if(OneCornerLink(x1,y,x2,y2))
return TRUE;
}
return FALSE;
}
BOOL C_LLK_Dlg::XThrough(int x, int y, BOOL bAdd)
{
if(bAdd)
{
for(int i=x;i<m_nCol;i++)
if(m_map[y*m_nCol+i]!=BLANK_STATE)
return FALSE;
}
else
{
for(int i=0;i<=x;i++)
if(m_map[y*m_nCol+i]!=BLANK_STATE)
return FALSE;
}
return TRUE;
}
BOOL C_LLK_Dlg::YThrough(int x, int y,BOOL bAdd)
{
if(bAdd)
{
for(int i=y;i<m_nRow;i++)
if(m_map[i*m_nCol+x]!=BLANK_STATE)
return FALSE;
}
else
{
for(int i=0;i<=y;i++)
if(m_map[i*m_nCol+x]!=BLANK_STATE)
return FALSE;
}
return TRUE;
}
//
// 判斷選中的兩個方塊是否可以消除
//
BOOL C_LLK_Dlg::IsLink(int x1, int y1, int x2, int y2)
{
//X直連方式
if(x1==x2)
{
if(X1_Link_X2(x1,y1,y2))
return TRUE;
}
//Y直連方式
else if(y1==y2)
{
if(Y1_Link_Y2(x1,x2,y1))
return TRUE;
}
//一個轉(zhuǎn)彎直角的聯(lián)通方式
if(OneCornerLink(x1,y1,x2,y2))
{
return TRUE;
}
//兩個轉(zhuǎn)彎直角的聯(lián)通方式
else if(TwoCornerLink(x1,y1,x2,y2))
{
return TRUE;
}
return FALSE;
}
//
// 截獲鍵盤消息 F2 (用于新游戲開始)
//
BOOL C_LLK_Dlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message==WM_KEYDOWN)
{
if(pMsg->wParam==VK_F2)
{
StartNewGame();
}
}
return CDialog::PreTranslateMessage(pMsg);
}
//
// 檢測是否已經(jīng)贏得了游戲
//
BOOL C_LLK_Dlg::IsWin(void)
{
//檢測所有是否尚有非未被消除的方塊
// (非BLANK_STATE狀態(tài))
for(int i=0;i<m_nRow*m_nCol;i++)
{
if(m_map[i] != BLANK_STATE)
{
return FALSE;
}
}
return TRUE;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -