📄 hanoiview.cpp
字号:
// HanoiView.cpp : implementation of the CHanoiView class
//
#include "stdafx.h"
#include "Hanoi.h"
#include "HanoiDoc.h"
#include "HanoiView.h"
#include "DlgOption.h"
#include "mmsystem.h" //I added
#pragma comment(lib,"winmm.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/*
enum DrawType
{
DT_NORMAL;
DT_MOUSEMOVE;
DT_MOUSEDOWN;
}
*/
/////////////////////////////////////////////////////////////////////////////
// CHanoiView
IMPLEMENT_DYNCREATE(CHanoiView, CView)
BEGIN_MESSAGE_MAP(CHanoiView, CView)
//{{AFX_MSG_MAP(CHanoiView)
ON_WM_ERASEBKGND()
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_HELP, OnHelp)
ON_COMMAND(ID_OPTION_SET, OnOptionSet)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_COMMAND(ID_OPTION_RESTART, OnOptionRestart)
ON_COMMAND(ID_DEMO, OnDemo)
ON_WM_LBUTTONUP()
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHanoiView construction/destruction
CHanoiView::CHanoiView()
{
// TODO: add construction code here
}
CHanoiView::~CHanoiView()
{
}
BOOL CHanoiView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CHanoiView drawing
int FirstTime=0;
void CHanoiView::OnDraw(CDC* pDC)
{
/* CBitmap bgBmp;
bgBmp.LoadBitmap(IDB_BG);
pDC->BitBlt(0,0,520,425,
*/
// Sleep (2000);
// pDC->Rectangle (100,100,200,200);
/*
int* p_temp=new int[5];
CString temp;
for(int i=0;i<5;i++)
{*(p_temp+i)=2;
// temp.Format(" %d,%d",*(p_temp+i),FirstTime);
// MessageBox( temp);
}
*/
if (FirstTime==0)//作一些初始化工作!!
{
NUM=3;
state= new int[NUM];
// for(int i=0;i<NUM;i++) *(state+i)=1;//放到第一列!
DrawType=new int[3];
// for( i=1;i<=3;i++) *(DrawType+i-1)=0;//初始化为正常显示!!
NewGame();
DrawColumn(state,DrawType,pDC);//
}
FirstTime++;
DrawColumn(state,DrawType,pDC);
CHanoiDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CHanoiView diagnostics
#ifdef _DEBUG
void CHanoiView::AssertValid() const
{
CView::AssertValid();
}
void CHanoiView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CHanoiDoc* CHanoiView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CHanoiDoc)));
return (CHanoiDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CHanoiView message handlers
BOOL CHanoiView::OnEraseBkgnd(CDC* pDC)
{
SetBG(pDC);
return 1;
//return CView::OnEraseBkgnd(pDC);//这句话是将客户区涂白色!!
}
void CHanoiView::DrawColumn(int* state, int* DrawType,CDC * dc)
{
SetBG(dc);
int temp;
for(int i=1;i<=3;i++) //三列!!
{
CBrush Brush;
//出现那个复杂错误,因为不能一次性创建两个刷子!!
if(i==1)
{
if(*(DrawType+0)==0) Brush.CreateSolidBrush (RGB(150,50,0));//当心,原来写成“=”导致程序失去响应!
if(*(DrawType+0)==1) Brush.CreateSolidBrush (RGB(255,0,0));//当心,原来写成“=”导致程序失去响应!
if(*(DrawType+0)==2) Brush.CreateSolidBrush (RGB(33,33,33));//当心,原来写成“=”导致程序失去响应!
}
else if(i==2)
{
if(*(DrawType+1)==0) Brush.CreateSolidBrush (RGB(0,150,50));//当心,原来写成“=”导致程序失去响应!
if(*(DrawType+1)==1) Brush.CreateSolidBrush (RGB(0,255,0));//当心,原来写成“=”导致程序失去响应!
if(*(DrawType+1)==2) Brush.CreateSolidBrush (RGB(33,33,33));//当心,原来写成“=”导致程序失去响应!
}
else if(i==3)
{
if(*(DrawType+2)==0) Brush.CreateSolidBrush (RGB(50,0,150));//当心,原来写成“=”导致程序失去响应!
if(*(DrawType+2)==1) Brush.CreateSolidBrush (RGB(0,0,255));//当心,原来写成“=”导致程序失去响应!
if(*(DrawType+2)==2) Brush.CreateSolidBrush (RGB(33,33,33));//当心,原来写成“=”导致程序失去响应!
}
dc->SelectObject (&Brush);
temp=0;
for (int j=0;j<NUM;j++)
{
if( *(state+j)==i)
{
temp++; // temp表征高度 ;j表征宽度!
dc->Rectangle (100+(i-1)*160-(50-j*3),400-20*temp,100+(i-1)*160+(50-j*3),400-20*(temp-1));
}
}
}
/*
//============================================================================
temp=0;
for (j=0;j<=NUM;j++)
{
if( *(state+j)==2)
{
temp++;
dc->Rectangle (260-(50-j*3),400-20*temp,260+(50-j*3),400-20*(temp-1));
//dc->Rectangle (100+(i-1)*160-(50-j*3),400-20*temp,100+(i-1)*100+(50-j*3),400-20*(temp-1));
//dc->Rectangle (100,100,200*j,200*j);
}
}
//============================================================================
temp=0;
for (j=0;j<=NUM;j++)
{
if( *(state+j)==3)
{
temp++;
dc->Rectangle (420-(50-j*3),400-20*temp,420+(50-j*3),400-20*(temp-1));
//dc->Rectangle (100+(i-1)*160-(50-j*3),400-20*temp,100+(i-1)*100+(50-j*3),400-20*(temp-1));
//dc->Rectangle (100,100,200*j,200*j);
}
}
//============================================================================
*/
}
void CHanoiView::SetBG(CDC *dc)
{
// 设置所要求背景色的刷子
CBrush brush;
CBitmap bmp;
bmp.LoadBitmap(IDB_BG);
brush.CreatePatternBrush(&bmp);//用位图建立刷子
CBrush* pOldBrush = dc->SelectObject(&brush); // 同时保存旧刷子
CRect rect;
dc->GetClipBox(&rect); // 获取擦除所需的区域
dc->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
dc->SelectObject(pOldBrush);
}
void CHanoiView::OnEditCut()
{
//下面仅仅是用于测试获取dc
CClientDC CCDC(this);
CClientDC* dc=&CCDC; //能够获取当前指针!!
// CDC* dc=GetDC( );//也能够获取当前指针!!
SetBG(dc);
}
int lastRegion=0;//记录了上一次所在区域
void CHanoiView::OnMouseMove(UINT nFlags, CPoint point)
{
int x,y;
x=point.x;
y=point.y;
int temp=0;//记录经过的是哪个区域;
if (x>20&&x<=180) {temp=1;SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR6));}
else if (x>180&&x<=340) {temp=2;SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR7));}
else if (x>340&&x<=500) {temp=3;SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR8));}
if( temp!=0) //仅对有效区域中的事件作出相应
{
// if(temp!=Source)*(DrawType+temp-1)=1;//置为1(Mouse_move)
for(int i=1;i<=3;i++)
{
if(i==temp && i!=Source) *(DrawType+i-1)=1;//置为1(Mouse_move)
if(i!=temp && i!=Source) *(DrawType+i-1)=0;//置为0(Normal)
}
CClientDC * dc = (CClientDC *) GetDC();
if(temp!=lastRegion)
{
DrawColumn(state,DrawType,dc);//防止同一区域内移动时频繁刷新,导致闪烁!
CString temp("snd\\1.wav");
// playSnd(temp); // 鼠标切换时候就不发声了,否则太乱!!
}
lastRegion=temp;
}
CView::OnMouseMove(nFlags, point);
}
void CHanoiView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
int x,y;
x=point.x;
y=point.y;
// if (x>20&&x<180)MessageBox("sfd");
int temp=0;//记录经过的是哪个区域;
if (x>20&&x<=180)temp=1;
else if (x>180&&x<=340)temp=2;
else if (x>340&&x<=500)temp=3;
int Last=-1; //记录Source最后一次出现,也即Source列的最上面!
bool Success=true; //判断是否可以移动!!
if (temp!=0) //仅对有效区域中的事件作出相应
{
if (Source==0)
{
Source=temp;
*(DrawType+temp-1)=2;
CString temp("snd\\2.wav");
playSnd(temp); // TODO: Add your command handler code here
}//Source==0必是奇数次按键,
else
{
Dest=temp;
for(int i=0;i<NUM;i++)
{
if(*(state+i)==Source)Last=i; //通过不断刷新,记录了最后一次出现的位置
}
// CString aa;
// aa.Format ("%d",Last);
// MessageBox (aa);
if(Last==-1)Success=false; //虽然没有此句,到最后也不过把一个State前面的置值,但毕竟不爽,还是这样完美!
for(i=Last;i<NUM;i++)
{
if(*(state+i)==Dest)Success=false; //若后面有同号者,则不成功!(具体缘由请见我的程序设计报告)
}
if (Success==false)
{
*(DrawType+Source-1)=0;
Source=0;
Dest=0;// 对失败时多余,但为整洁而保留
}
else if (Success==true)
{
*(DrawType+Source-1)=0;
*(state+Last)=Dest;
Source=0;
Dest=0;// 保留
steps++;
//===============================SetPanel=========================================
CString tem;
CStatusBar *pStatus;
pStatus=(CStatusBar *)AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
tem.Format ("本局已执行 %d 步",steps);
pStatus->SetPaneText (0,tem);
//===============================SetPanel=========================================
CString temp("snd\\3.wav");
playSnd(temp); // TODO: Add your command handler code here
}
for(i=1;i<=3;i++)*(DrawType+i-1)=0;//全部变成正常!!
}
CClientDC * dc = (CClientDC *) GetDC();
DrawColumn(state,DrawType,dc);//
//======================判断是否已经成功================
int EndOfGame=0;
for(int i=0;i<NUM;i++)
{
if(*(state+i)!=3) EndOfGame++;
}
if (EndOfGame==0)
{
CString temp;
CString tem("snd\\end.wav");
playSnd(tem); // TODO: Add your command handler code here
Sleep(100);
temp.Format ("恭喜,您成功了!您共走了 %d 步!",steps);
MessageBox(temp);
NewGame();
}
//======================判断是否已经成功================
}
/*========================Test=========================
CClientDC * dc = (CClientDC *) GetDC();
CString test;
test.Format ("%d -> %d",Source,Dest);
dc->TextOut (0,0,test);
for (int i=0;i<NUM;i++){
test.Format ("%d",*(state+i));
dc->TextOut (12*i,30,test);
}
//========================Test=========================*/
SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR2));
CView::OnLButtonDown(nFlags, point);
}
void CHanoiView::OnEditCopy()
{
// 这里仅仅是测试播放声音!!
CString temp("siren.wav");
playSnd(temp);
// playSnd(temp);
}
bool CHanoiView::playSnd(CString Filename)
{
/*
WORD m_wDeviceID;
Load:
MCI_OPEN_PARMS OpenParms;
OpenParms.lpstrDeviceType="waveaudio";
OpenParms.lpstrElementName=Filename; //这样是可以的!!
if(mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_ELEMENT|MCI_OPEN_TYPE,(DWORD)(LPVOID)&OpenParms))
return FALSE;
m_wDeviceID=OpenParms.wDeviceID;
Play:
MCI_PLAY_PARMS PlayParms;
mciSendCommand(m_wDeviceID,MCI_SEEK,MCI_SEEK_TO_START,NULL);
if(mciSendCommand(m_wDeviceID,MCI_PLAY,NULL,(DWORD)(LPVOID)&PlayParms))
return FALSE;
Sleep(1500);
Stop:
mciSendCommand(m_wDeviceID,MCI_STOP,NULL,NULL);
*/
::PlaySound(Filename, NULL, SND_ASYNC | SND_FILENAME);//发现不用MCI,直接有函数!!
return true;
}
void CHanoiView::OnHelp()
{
// WinExec("\"G:\\game\\***.exe\" 参数",SW_SHOWDEFAULT);
// WinExec("c:\\windows\\hh.exe hanoi.chm",SW_SHOWDEFAULT); 也可以的!
WinExec("hh.exe hanoi.chm",SW_SHOWDEFAULT);
}
void CHanoiView::OnOptionSet()
{
CDlgOption dlg;
dlg.m_num =NUM;
if(dlg.DoModal ()==IDOK)
{
NUM=dlg.m_num ;
NewGame();
}
}
void CHanoiView::OnEditPaste()
{
CString temp("siren.wav");
playSnd(temp); // TODO: Add your command handler code here
}
void CHanoiView::DELAY(int mSeconds)//实际未用,采用的是sleep!
{
DWORD dwStart = GetTickCount();
while( GetTickCount() - dwStart >= mSeconds );
}
void CHanoiView::OnOptionRestart()
{
// TODO: Add your command handler code here
NewGame();
CClientDC * dc = (CClientDC *) GetDC();
DrawColumn(state,DrawType,dc);
}
void CHanoiView::OnDemo()
{
NewGame();
CClientDC * dc = (CClientDC *) GetDC();
DrawColumn(state,DrawType,dc);
hanoi(NUM,1,2,3);
CString temp("snd\\end.wav");
playSnd(temp); // TODO: Add your command handler code here
Sleep(1600);
NewGame();
}
void CHanoiView::NewGame()
{
for(int i=0;i<NUM;i++)
{
*(state+i)=1; //全部复位!!
}
for( i=1;i<=3;i++) *(DrawType+i-1)=0;//初始化为正常显示!!
Source=0;
Dest=0;
steps=0;//未走子
SetTimer(1,1000,NULL);
startTime=CTime::GetCurrentTime ();
}
void CHanoiView::hanoi(int n, int Column1, int Column2, int Column3)
{
if(n==1)move(Column1,Column3);
else
{
hanoi(n-1,Column1,Column3,Column2);
move(Column1,Column3);
hanoi(n-1,Column2,Column1,Column3);
}
}
void CHanoiView::move(int a, int b)
{
Sleep(800);
int Last=-1;
for(int i=0;i<NUM;i++)
{
if(*(state+i)==a)Last=i; //通过不断刷新,记录了最后一次出现的位置
}
if (Last==-1)MessageBox("sfd");
*(state+Last)=b;
CClientDC * dc = (CClientDC *) GetDC();
DrawColumn(state,DrawType,dc);
}
void CHanoiView::OnLButtonUp(UINT nFlags, CPoint point)
{
SetCursor(AfxGetApp()->LoadCursor(IDC_CURSOR2));
CView::OnLButtonUp(nFlags, point);
}
void CHanoiView::OnTimer(UINT nIDEvent)
{
CString temp;
CStatusBar *pStatus;
pStatus=(CStatusBar *)AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
CTime time=CTime::GetCurrentTime ();
if (time.GetSecond() -startTime.GetSecond ()>=0)
{
temp.Format ("这一局您已经走了:%d分%d秒 ",time.GetMinute() -startTime.GetMinute() ,time.GetSecond() -startTime.GetSecond ());
}
else if (time.GetSecond() -startTime.GetSecond ()<0)
{
temp.Format("这一局您已经走了:%d分%d秒 ",time.GetMinute() -startTime.GetMinute()-1 ,time.GetSecond() -startTime.GetSecond ()+60);
}
pStatus->SetPaneText (2,temp);
CView::OnTimer(nIDEvent);
}
void CHanoiView::OnDestroy()
{
CView::OnDestroy();
KillTimer(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -