www.pudn.com > renju_src.rar > RenjuView.cpp
// RenjuView.cpp : implementation of the CRenjuView class // #include "stdafx.h" #include "Renju.h" #include "RenjuDoc.h" #include "RenjuView.h" #include "LinkDialog.h" //#include#pragma comment(lib, "winmm.lib") #define ID_TIMER 1 #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CRenjuView IMPLEMENT_DYNCREATE(CRenjuView, CView) BEGIN_MESSAGE_MAP(CRenjuView, CView) //{{AFX_MSG_MAP(CRenjuView) ON_WM_PAINT() ON_COMMAND(ID_ACTION_LINK, OnActionLink) ON_UPDATE_COMMAND_UI(ID_ACTION_LINK, OnUpdateActionLink) ON_COMMAND(ID_ACTION_DISLINK, OnActionDislink) ON_UPDATE_COMMAND_UI(ID_ACTION_DISLINK, OnUpdateActionDislink) ON_COMMAND(ID_ACTION_SURRENDER, OnActionSurrender) ON_UPDATE_COMMAND_UI(ID_ACTION_SURRENDER, OnUpdateActionSurrender) ON_WM_SETCURSOR() ON_WM_LBUTTONDOWN() ON_COMMAND(ID_ACTION_NEW, OnActionNew) ON_UPDATE_COMMAND_UI(ID_ACTION_NEW, OnUpdateActionNew) ON_COMMAND(ID_MUSIC_MUSIC, OnMusicMusic) ON_UPDATE_COMMAND_UI(ID_MUSIC_MUSIC, OnUpdateMusicMusic) ON_WM_TIMER() //}}AFX_MSG_MAP ON_MESSAGE(WM_USER_NEWGAME, OnNewGame) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CRenjuView construction/destruction CRenjuView::CRenjuView() { // TODO: add construction code here m_bMusicOn = FALSE; m_pListenSocket = NULL; m_pClientSocket = NULL; m_pClientSocket2 = NULL; m_bMyTurn = FALSE; m_bLinked = FALSE; m_bOpponentWin = FALSE; m_bInGame = FALSE; ResetCoords(); CreateListenSocket(); } CRenjuView::~CRenjuView() { DestroyListenSocket(); DestroyClientSocket(); DestroyClientSocket2(); m_bLinked = FALSE; if(m_bMusicOn) KillTimer(ID_TIMER); } BOOL CRenjuView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CRenjuView drawing void CRenjuView::OnDraw(CDC* pDC) { CRenjuDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here } ///////////////////////////////////////////////////////////////////////////// // CRenjuView diagnostics #ifdef _DEBUG void CRenjuView::AssertValid() const { CView::AssertValid(); } void CRenjuView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CRenjuDoc* CRenjuView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CRenjuDoc))); return (CRenjuDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CRenjuView message handlers void CRenjuView::OnPaint() { //GetParent()->SetWindowText(_T("Renju")); CPaintDC dc(this); // device context for painting CBitmap bitmap; bitmap.LoadBitmap (IDB_BKWOOD); CDC dcMem; dcMem.CreateCompatibleDC(&dc); CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap); CRect rect(0, 0, 0, 0); GetClientRect(&rect); dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &dcMem, 0, 0, 640, 640, SRCCOPY); for(int i = 1; i <= DIVISIONS; i++) { dc.MoveTo(CELLSIZE, i * CELLSIZE); dc.LineTo(DIVISIONS * CELLSIZE, i * CELLSIZE); dc.MoveTo(i * CELLSIZE, CELLSIZE); dc.LineTo(i * CELLSIZE, DIVISIONS * CELLSIZE); } dc.SelectStockObject(BLACK_BRUSH); int nRadius = 4; dc.Ellipse(CELLSIZE + CELLSIZE * 3 - nRadius, CELLSIZE + CELLSIZE * 3 - nRadius, CELLSIZE + CELLSIZE * 3 + nRadius, CELLSIZE + CELLSIZE * 3 + nRadius); dc.Ellipse(CELLSIZE + CELLSIZE * (DIVISIONS - 3 - 1) - nRadius, CELLSIZE + CELLSIZE * 3 - nRadius, CELLSIZE + CELLSIZE * (DIVISIONS - 3 - 1) + nRadius, CELLSIZE + CELLSIZE * 3 + nRadius); dc.Ellipse(CELLSIZE + CELLSIZE * (DIVISIONS / 2) - nRadius, CELLSIZE + CELLSIZE * (DIVISIONS / 2) - nRadius, CELLSIZE + CELLSIZE * (DIVISIONS / 2) + nRadius, CELLSIZE + CELLSIZE * (DIVISIONS / 2) + nRadius); dc.Ellipse(CELLSIZE + CELLSIZE * 3 - nRadius, CELLSIZE + CELLSIZE * (DIVISIONS - 3 - 1) - nRadius, CELLSIZE + CELLSIZE * 3 + nRadius, CELLSIZE + CELLSIZE * (DIVISIONS - 3 - 1) + nRadius); dc.Ellipse(CELLSIZE + CELLSIZE * (DIVISIONS - 3 - 1) - nRadius, CELLSIZE + CELLSIZE * (DIVISIONS - 3 - 1) - nRadius, CELLSIZE + CELLSIZE * (DIVISIONS - 3 - 1) + nRadius, CELLSIZE + CELLSIZE * (DIVISIONS - 3 - 1) + nRadius); dc.SelectStockObject(NULL_BRUSH); CPen pen(PS_SOLID, 4, RGB(0, 0, 0)); CPen* pOldPen = dc.SelectObject(&pen); CRect rectFrame(CELLSIZE, CELLSIZE, DIVISIONS * CELLSIZE + 2, DIVISIONS * CELLSIZE + 2); rectFrame.InflateRect(5, 5); dc.Rectangle(&rectFrame); dc.SelectObject(pOldPen); dc.SelectObject(pOldBitmap); DrawPieces(); // Do not call CView::OnPaint() for painting messages } void CRenjuView::OnActionLink() { // TODO: Add your command handler code here CLinkDialog dlg; if(dlg.DoModal() == IDOK) { GetParent()->SetWindowText(_T("Renju - Waiting for reply")); CreateClientSocket(dlg.m_strAddress); } } void CRenjuView::OnUpdateActionLink(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->Enable(!m_bLinked); } void CRenjuView::OnActionDislink() { // TODO: Add your command handler code here int result = AfxMessageBox(_T("Are you sure you want to disconnect?"), MB_YESNO); if(result == IDYES) { int buf[3] = {DISCONNECT, 0, 0}; m_pClientSocket->Send(buf, 3 * sizeof(int)); m_bLinked = FALSE; m_bInGame = FALSE; DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); } } void CRenjuView::OnUpdateActionDislink(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->Enable(m_bLinked); } void CRenjuView::OnActionSurrender() { // TODO: Add your command handler code here int result = AfxMessageBox(_T("Are you sure you want to surrender?"), MB_YESNO); if(result == IDYES) { m_bMyTurn = FALSE; m_bInGame = FALSE; int buf[3] = {SURRENDER, 0, 0}; if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR) { AfxMessageBox(_T("Connection interrupted!\n" "Cannot connect to your partner.")); m_bLinked = FALSE; m_bInGame = FALSE; DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); return; } GetParent()->SetWindowText(_T("Renju - Game over")); } } void CRenjuView::OnUpdateActionSurrender(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->Enable(m_bLinked && m_bInGame); } void CRenjuView::OnActionNew() { // TODO: Add your command handler code here int buf[3] = {NEWGAME, 0, 0}; if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR) { AfxMessageBox(_T("Connection interrupted!\n" "Cannot connect to your partner.")); m_bLinked = FALSE; DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); return; } GetParent()->SetWindowText(_T("Renju - Waiting for reply")); } void CRenjuView::OnUpdateActionNew(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->Enable(m_bLinked && !m_bInGame); } void CRenjuView::OnMusicMusic() { // TODO: Add your command handler code here m_bMusicOn = !m_bMusicOn; if(m_bMusicOn) { PlayBGMusic(_T("bgmusic.mid")); SetTimer(ID_TIMER, m_midi.GetMidiLen() + 500, NULL); } else { KillTimer(ID_TIMER); PlayBGMusic(NULL); } } void CRenjuView::OnUpdateMusicMusic(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->SetCheck(m_bMusicOn); } void CRenjuView::PlayBGMusic(LPCSTR FileName) { m_midi.Open(FileName); m_midi.Play(); } void CRenjuView::CreateListenSocket() { if(m_pListenSocket) DestroyListenSocket(); m_pListenSocket = new CListenSocket(this); if(!m_pListenSocket->Create(PORT_NUM)) { DestroyListenSocket(); AfxMessageBox(_T("Port creation failed!\n" "Please try again later.")); return; } if(!m_pListenSocket->Listen()) { DestroyClientSocket(); AfxMessageBox(_T("Due to socket problems on your machine,\n" "you cannot respond to incoming request.\n" "You can only request a new game to others.")); } } void CRenjuView::DestroyListenSocket() { if(m_pListenSocket) { delete m_pListenSocket; m_pListenSocket = NULL; } } void CRenjuView::CreateClientSocket(CString& strAddress) { if(m_pClientSocket) DestroyClientSocket(); m_pClientSocket = new CClientSocket(this); if(!m_pClientSocket->Create()) { DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); AfxMessageBox(_T("Port creation failed!\n" "Please try again later.")); return; } while(!m_pClientSocket->Connect(strAddress, PORT_NUM)) { if(AfxMessageBox(_T("Cannot reach your partner right now.\n"), MB_RETRYCANCEL) == IDCANCEL) { DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); return; } } } void CRenjuView::DestroyClientSocket() { if(m_pClientSocket) { delete m_pClientSocket; m_pClientSocket = NULL; } } void CRenjuView::DestroyClientSocket2() { if(m_pClientSocket2) { delete m_pClientSocket2; m_pClientSocket2 = NULL; } } void CRenjuView::RequestAccepted(int accept) { if(!m_pClientSocket) { m_pClientSocket = new CClientSocket(this); if(!m_pListenSocket->Accept(*m_pClientSocket)) { DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); AfxMessageBox(_T("You cannot accept this request!")); } if(accept == IDYES) { int buf[3] = {ACCEPT, 0, 0}; if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR) { AfxMessageBox(_T("Connection interrupted!\n" "Cannot open the new game.")); m_bLinked = FALSE; m_bInGame = FALSE; DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); return; } m_bMyTurn = TRUE; m_bLinked = TRUE; m_bOpponentWin = FALSE; m_bInGame = TRUE; ResetCoords(); m_nColor = 1; GetParent()->SetWindowText(_T("Renju - Your turn")); } else { int buf[3] = {DECLINE, 0, 0}; m_pClientSocket->Send(buf, 3 * sizeof(int)); GetParent()->SetWindowText(_T("Renju - Ready")); DestroyClientSocket(); } return; } if(m_pClientSocket2) DestroyClientSocket2(); m_pClientSocket2 = new CClientSocket(this); if(!m_pListenSocket->Accept(*m_pClientSocket2)) { DestroyClientSocket2(); GetParent()->SetWindowText(_T("Renju - Ready")); AfxMessageBox(_T("You cannot accept this request!")); } int buf[3] = {DECLINE, 0, 0}; m_pClientSocket2->Send(buf, 3 * sizeof(int)); GetParent()->SetWindowText(_T("Renju - Ready")); DestroyClientSocket2(); } // process the new game request LRESULT CRenjuView::OnNewGame(WPARAM wParam, LPARAM lParam) { int result = AfxMessageBox(_T("Do you want to play a new game?"), MB_YESNO); if(result == IDYES) { int buf[3] = {ACCEPT, 0, 0}; if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR) { AfxMessageBox(_T("Connection interrupted!\n" "Cannot open the new game.")); m_bLinked = FALSE; m_bInGame = FALSE; DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); return 1; } m_bMyTurn = TRUE; m_bLinked = TRUE; m_bOpponentWin = FALSE; m_bInGame = TRUE; ResetCoords(); m_nColor = 1; GetParent()->SetWindowText(_T("Renju - Your turn")); } else { int buf[3] = {NONEWGAME, 0, 0}; if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR) { AfxMessageBox(_T("Connection interrupted!\n" "Cannot open the new game.")); m_bLinked = FALSE; m_bInGame = FALSE; DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); return 1; } GetParent()->SetWindowText(_T("Renju - Game over")); } return 0; } // zero set the array void CRenjuView::ResetCoords() { for(int i = 0; i < DIVISIONS; i++) { for(int j = 0; j < DIVISIONS; j++) m_nCoords[i][j] = 0; } Invalidate(FALSE); UpdateWindow(); } // change the cursor according to whose turn it is BOOL CRenjuView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if(nHitTest == HTCLIENT && m_bLinked && m_bInGame) { if((m_bMyTurn && (m_nColor == 1)) || (!m_bMyTurn && (m_nColor == -1))) ::SetCursor(AfxGetApp()->LoadCursor(IDC_BLACK)); else ::SetCursor(AfxGetApp()->LoadCursor(IDC_WHITE)); return TRUE; } return CView::OnSetCursor(pWnd, nHitTest, message); } void CRenjuView::OnLButtonDown(UINT nFlags, CPoint point) { if(m_bLinked && m_bMyTurn) { int x = (point.x - CELLSIZE / 2) / CELLSIZE; int y = (point.y - CELLSIZE / 2) / CELLSIZE; if(x >= 0 && x < DIVISIONS && y >= 0 && y < DIVISIONS) { if(m_nCoords[x][y] == 0) { CRect invalidOldRect((m_ptLastStep.x + 1) * CELLSIZE - CELLSIZE / 2, (m_ptLastStep.y + 1) * CELLSIZE - CELLSIZE / 2, (m_ptLastStep.x + 1) * CELLSIZE + CELLSIZE / 2, (m_ptLastStep.y + 1) * CELLSIZE + CELLSIZE / 2); InvalidateRect(&invalidOldRect, FALSE); PlaySound(_T("down.wav"), NULL, SND_FILENAME | SND_ASYNC); m_ptLastStep.x = x; m_ptLastStep.y = y; m_nCoords[x][y] = m_nColor; m_bMyTurn = FALSE; CRect invalidRect((x + 1) * CELLSIZE - CELLSIZE / 2, (y + 1) * CELLSIZE - CELLSIZE / 2, (x + 1) * CELLSIZE + CELLSIZE / 2, (y + 1) * CELLSIZE + CELLSIZE / 2); InvalidateRect(&invalidRect, FALSE); int buf[3] = {0, x, y}; if(IsWin(x, y)) { if(m_nColor == -1) { if(m_bOpponentWin) { buf[0] = EVEN; // even and game over m_bInGame = FALSE; GetParent()->SetWindowText(_T("Renju - Game over")); } else { buf[0] = ULOSE; // white win and game over m_bInGame = FALSE; GetParent()->SetWindowText(_T("Renju - Game over")); } } else { buf[0] = IWIN; // black temp win, waiting for white's last step GetParent()->SetWindowText(_T("Renju - Opponent's turn")); } } else { if(m_bOpponentWin) { buf[0] = UWIN; // I lose and game over m_bInGame = FALSE; GetParent()->SetWindowText(_T("Renju - Game over")); } else { GetParent()->SetWindowText(_T("Renju - Opponent's turn")); buf[0] = COORDS; // nobody wins, just an ordinary step } } if(m_pClientSocket->Send(buf, 3 * sizeof(int)) == SOCKET_ERROR) { AfxMessageBox(_T("Connection interrupted!\n" "Cannot continue with the game.")); m_bLinked = FALSE; m_bInGame = FALSE; DestroyClientSocket(); GetParent()->SetWindowText(_T("Renju - Ready")); return; } // show game result messagebox if gameover if(buf[0] == EVEN) { AfxMessageBox(_T("Even game!")); } else if(buf[0] == ULOSE) { AfxMessageBox(_T("Congratulations!\n" "You won this game.")); } else if(buf[0] == UWIN) { AfxMessageBox(_T("Sorry!\n" "You lost this game.")); } } } else { ::MessageBeep(MB_ICONEXCLAMATION); } } CView::OnLButtonDown(nFlags, point); } BOOL CRenjuView::IsWin(int x, int y) { int xMin=max(0, x - 4); int xMax=min(DIVISIONS - 1, x + 4); int yMin=max(0, y - 4); int yMax=min(DIVISIONS - 1, y + 4); int i, j, p, q, sum1, sum2, sum3, sum4; for(j=xMin; j<=xMax-4; j++) { for(i=j, sum1=0; i xMin && j>yMin; i--, j--); for(; i<=xMax-4 && j<=yMax-4; i++, j++) { for(sum3=0, p=i, q=j; pxMin && j =yMin+4; i++, j--) { for(sum4=0, p=i, q=j; p