Table.cpp
上传用户:fjjkzlh
上传日期:2010-04-06
资源大小:469k
文件大小:24k
源码类别:

棋牌游戏

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "Five.h"
  3. #include "Table.h"
  4. #include "Messages.h"
  5. #include "Resource.h"
  6. //////////////////////////////////////////////////////////////////////////
  7. // 构造函数,初始化棋盘数据以及图像数据
  8. //////////////////////////////////////////////////////////////////////////
  9. CTable::CTable()
  10. {
  11.     // 初始化玩家姓名
  12.     TCHAR str[10];
  13.     CFiveApp *pApp = (CFiveApp *)AfxGetApp();
  14.     ::GetPrivateProfileString( _T("Options"), _T("Name"), _T("Renjiu"), str, 15, pApp->m_szIni );
  15.     m_strMe = str;
  16.     // 初始化图像列表
  17.     m_iml.Create( 24, 24, ILC_COLOR24 | ILC_MASK, 0, 2 );
  18.     // 载入黑、白棋子掩码位图
  19.     CBitmap bmpBlack, bmpWhite;
  20.     bmpBlack.LoadBitmap( IDB_BMP_BLACK );
  21.     m_iml.Add( &bmpBlack, 0xff00ff );
  22.     bmpWhite.LoadBitmap( IDB_BMP_WHITE );
  23.     m_iml.Add( &bmpWhite, 0xff00ff );
  24.     // 初始化游戏模式
  25.     m_pGame = NULL;
  26. }
  27. //////////////////////////////////////////////////////////////////////////
  28. // 析构函数,释放m_pGame指针
  29. //////////////////////////////////////////////////////////////////////////
  30. CTable::~CTable()
  31. {
  32.     // 写入玩家姓名
  33.     CFiveApp *pApp = (CFiveApp *)AfxGetApp();
  34.     ::WritePrivateProfileString( _T("Options"), _T("Name"), m_strMe, pApp->m_szIni );
  35.     // 写入战绩统计
  36.     TCHAR str[10];
  37.     wsprintf( str, _T("%d"), pApp->m_nWin );
  38.     ::WritePrivateProfileString( _T("Stats"), _T("Win"), str, pApp->m_szIni );
  39.     wsprintf( str, _T("%d"), pApp->m_nDraw );
  40.     ::WritePrivateProfileString( _T("Stats"), _T("Draw"), str, pApp->m_szIni );
  41.     wsprintf( str, _T("%d"), pApp->m_nLost );
  42.     ::WritePrivateProfileString( _T("Stats"), _T("Lost"), str, pApp->m_szIni );
  43.     if ( NULL != m_pGame )
  44.         delete m_pGame;
  45. }
  46. //////////////////////////////////////////////////////////////////////////
  47. // 在指定棋盘坐标处绘制指定颜色的棋子
  48. //////////////////////////////////////////////////////////////////////////
  49. void CTable::Draw( int x, int y, int color )
  50. {
  51.     POINT pt;
  52.     pt.x = 12 + 25 * x;
  53.     pt.y = 84 + 25 * y;
  54.     CDC *pDC = GetDC();
  55.     CPen pen;
  56.     pen.CreatePen( PS_SOLID, 1, 0xff );
  57.     pDC->SelectObject( &pen );
  58.     pDC->SetROP2( R2_NOTXORPEN );
  59.     m_iml.Draw( pDC, color, pt, ILD_TRANSPARENT );
  60.     STEP step;
  61.     // 利用R2_NOTXORPEN擦除先前画出的矩形
  62.     if ( !m_pGame->m_StepList.empty() )
  63.     {
  64.         // 获取最后一个点
  65.         step = *( m_pGame->m_StepList.begin() );
  66.         pDC->MoveTo( 11 + 25 * step.x, 83 + 25 * step.y );
  67.         pDC->LineTo( 36 + 25 * step.x, 83 + 25 * step.y );
  68.         pDC->LineTo( 36 + 25 * step.x, 108 + 25 * step.y );
  69.         pDC->LineTo( 11 + 25 * step.x, 108 + 25 * step.y );
  70.         pDC->LineTo( 11 + 25 * step.x, 83 + 25 * step.y );
  71.     }
  72.     // 更新最后落子坐标数据,画新的矩形
  73.     step.color = color;
  74.     step.x = x;
  75.     step.y = y;
  76.     m_pGame->m_StepList.push_front( step );
  77.     pDC->MoveTo( 11 + 25 * step.x, 83 + 25 * step.y );
  78.     pDC->LineTo( 36 + 25 * step.x, 83 + 25 * step.y );
  79.     pDC->LineTo( 36 + 25 * step.x, 108 + 25 * step.y );
  80.     pDC->LineTo( 11 + 25 * step.x, 108 + 25 * step.y );
  81.     pDC->LineTo( 11 + 25 * step.x, 83 + 25 * step.y );
  82.     ReleaseDC( pDC );
  83. }
  84. //////////////////////////////////////////////////////////////////////////
  85. // 清空棋盘
  86. //////////////////////////////////////////////////////////////////////////
  87. void CTable::Clear( BOOL bWait )
  88. {
  89.     int x, y;
  90.     for ( y = 0; y < 15; y++ )
  91.     {
  92.         for ( x = 0; x < 15; x++ )
  93.         {
  94.             m_data[x][y] = -1;
  95.         }
  96.     }
  97.     // 设置等待标志
  98.     m_bWait = bWait;
  99.     Invalidate();
  100.     // 删除游戏
  101.     if ( m_pGame != NULL )
  102.     {
  103.         delete m_pGame;
  104.         m_pGame = NULL;
  105.     }
  106. }
  107. //////////////////////////////////////////////////////////////////////////
  108. // 设置玩家颜色
  109. //////////////////////////////////////////////////////////////////////////
  110. void CTable::SetColor( int color )
  111. {
  112.     m_color = color;
  113. }
  114. //////////////////////////////////////////////////////////////////////////
  115. // 获取玩家颜色
  116. //////////////////////////////////////////////////////////////////////////
  117. int CTable::GetColor() const
  118. {
  119.     return m_color;
  120. }
  121. //////////////////////////////////////////////////////////////////////////
  122. // 设置等待标志,返回先前的等待标志
  123. //////////////////////////////////////////////////////////////////////////
  124. BOOL CTable::SetWait( BOOL bWait )
  125. {
  126.     m_bOldWait = m_bWait;
  127.     m_bWait = bWait;
  128.     return m_bOldWait;
  129. }
  130. //////////////////////////////////////////////////////////////////////////
  131. // 设置棋盘数据,并绘制棋子
  132. //////////////////////////////////////////////////////////////////////////
  133. void CTable::SetData( int x, int y, int color )
  134. {
  135.     m_data[x][y] = color;
  136.     Draw( x, y, color );
  137. }
  138. //////////////////////////////////////////////////////////////////////////
  139. // 判断指定颜色是否胜利
  140. //////////////////////////////////////////////////////////////////////////
  141. BOOL CTable::Win( int color ) const
  142. {
  143.     int x, y;
  144.     // 判断横向
  145.     for ( y = 0; y < 15; y++ )
  146.     {
  147.         for ( x = 0; x < 11; x++ )
  148.         {
  149.             if ( color == m_data[x][y] && color == m_data[x + 1][y] &&
  150.                 color == m_data[x + 2][y] && color == m_data[x + 3][y] &&
  151.                 color == m_data[x + 4][y] )
  152.             {
  153.                 return TRUE;
  154.             }
  155.         }
  156.     }
  157.     // 判断纵向
  158.     for ( y = 0; y < 11; y++ )
  159.     {
  160.         for ( x = 0; x < 15; x++ )
  161.         {
  162.             if ( color == m_data[x][y] && color == m_data[x][y + 1] &&
  163.                 color == m_data[x][y + 2] && color == m_data[x][y + 3] &&
  164.                 color == m_data[x][y + 4] )
  165.             {
  166.                 return TRUE;
  167.             }
  168.         }
  169.     }
  170.     // 判断“”方向
  171.     for ( y = 0; y < 11; y++ )
  172.     {
  173.         for ( x = 0; x < 11; x++ )
  174.         {
  175.             if ( color == m_data[x][y] && color == m_data[x + 1][y + 1] &&
  176.                 color == m_data[x + 2][y + 2] && color == m_data[x + 3][y + 3] &&
  177.                 color == m_data[x + 4][y + 4] )
  178.             {
  179.                 return TRUE;
  180.             }
  181.         }
  182.     }
  183.     // 判断“/”方向
  184.     for ( y = 0; y < 11; y++ )
  185.     {
  186.         for ( x = 4; x < 15; x++ )
  187.         {
  188.             if ( color == m_data[x][y] && color == m_data[x - 1][y + 1] &&
  189.                 color == m_data[x - 2][y + 2] && color == m_data[x - 3][y + 3] &&
  190.                 color == m_data[x - 4][y + 4] )
  191.             {
  192.                 return TRUE;
  193.             }
  194.         }
  195.     }
  196.     // 不满足胜利条件
  197.     return FALSE;
  198. }
  199. //////////////////////////////////////////////////////////////////////////
  200. // 发送再玩一次请求
  201. //////////////////////////////////////////////////////////////////////////
  202. void CTable::PlayAgain()
  203. {
  204.     MSGSTRUCT msg;
  205.     msg.uMsg = MSG_PLAYAGAIN;
  206.     m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  207. }
  208. //////////////////////////////////////////////////////////////////////////
  209. // 发送和棋请求
  210. //////////////////////////////////////////////////////////////////////////
  211. void CTable::DrawGame()
  212. {
  213.     CDialog *pDlg = (CDialog *)AfxGetMainWnd();
  214.     // 使按钮失效
  215.     pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  216.     pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow( FALSE );
  217.     pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow( FALSE );
  218.     // 设置等待标志
  219.     SetWait( TRUE );
  220.     MSGSTRUCT msg;
  221.     msg.uMsg = MSG_DRAW;
  222.     m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  223. }
  224. //////////////////////////////////////////////////////////////////////////
  225. // 设置游戏模式
  226. //////////////////////////////////////////////////////////////////////////
  227. void CTable::SetGameMode( int nGameMode )
  228. {
  229.     if ( 1 == nGameMode )
  230.         m_pGame = new COneGame( this );
  231.     else
  232.         m_pGame = new CTwoGame( this );
  233.     m_pGame->Init();
  234. }
  235. //////////////////////////////////////////////////////////////////////////
  236. // 悔棋
  237. //////////////////////////////////////////////////////////////////////////
  238. void CTable::Back()
  239. {
  240.     m_pGame->Back();
  241. }
  242. //////////////////////////////////////////////////////////////////////////
  243. // 处理对方落子后的工作
  244. //////////////////////////////////////////////////////////////////////////
  245. void CTable::Over()
  246. {
  247.     // 判断对方是否胜利
  248.     if ( Win( 1 - m_color ) )
  249.     {
  250.         CFiveApp *pApp = (CFiveApp *)AfxGetApp();
  251.         pApp->m_nLost++;
  252.         CDialog *pDlg = (CDialog *)GetParent();
  253.         PlaySound( MAKEINTRESOURCE( IDR_WAVE_LOST ), NULL, SND_RESOURCE | SND_SYNC );
  254.         pDlg->MessageBox( _T("您输了,不过不要灰心,失败乃成功之母哦!"), _T("失败"), MB_ICONINFORMATION );
  255.         pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow( FALSE );
  256.         pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  257.         pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow( FALSE );
  258.         // 如果是网络对战,则生效“重玩”
  259.         if ( m_bConnected )
  260.         {
  261.             pDlg->GetMenu()->EnableMenuItem( ID_MENU_PLAYAGAIN, MF_ENABLED | MF_BYCOMMAND );
  262.         }
  263.         return;
  264.     }
  265.     m_bWait = FALSE;
  266. }
  267. //////////////////////////////////////////////////////////////////////////
  268. // 设置菜单状态(主要为网络对战准备)
  269. //////////////////////////////////////////////////////////////////////////
  270. void CTable::SetMenuState( BOOL bEnable )
  271. {
  272.     UINT uEnable, uDisable;
  273.     if ( bEnable )
  274.     {
  275.         uEnable = MF_ENABLED;
  276.         uDisable = MF_GRAYED | MF_DISABLED;
  277.     }
  278.     else
  279.     {
  280.         uEnable = MF_GRAYED | MF_DISABLED;
  281.         uDisable = MF_ENABLED;
  282.     }
  283.     CMenu *pMenu = GetParent()->GetMenu();
  284.     pMenu->GetSubMenu( 0 )->EnableMenuItem( 0, uEnable | MF_BYPOSITION );
  285.     pMenu->EnableMenuItem( ID_MENU_SERVER, uEnable );
  286.     pMenu->EnableMenuItem( ID_MENU_CLIENT, uEnable );
  287.     pMenu->EnableMenuItem( ID_MENU_LEAVE, uDisable );
  288.     pMenu->EnableMenuItem( ID_MENU_PLAYAGAIN, uEnable );
  289. }
  290. //////////////////////////////////////////////////////////////////////////
  291. // 接受连接
  292. //////////////////////////////////////////////////////////////////////////
  293. void CTable::Accept( int nGameMode )
  294. {
  295.     if ( 2 == nGameMode )
  296.     {
  297.         m_sock.Accept( m_conn );
  298.     }
  299.     m_bConnected = TRUE;
  300. SetColor( 0 );
  301.     Clear( FALSE );
  302.     SetGameMode( nGameMode );
  303. }
  304. //////////////////////////////////////////////////////////////////////////
  305. // 主动连接
  306. //////////////////////////////////////////////////////////////////////////
  307. void CTable::Connect( int nGameMode )
  308. {
  309.     SetColor( 1 );
  310.     Clear( TRUE );
  311.     SetGameMode( nGameMode );
  312. }
  313. //////////////////////////////////////////////////////////////////////////
  314. // 发送聊天消息
  315. //////////////////////////////////////////////////////////////////////////
  316. void CTable::Chat( LPCTSTR lpszMsg )
  317. {
  318.     MSGSTRUCT msg;
  319.     msg.uMsg = MSG_CHAT;
  320.     lstrcpy( msg.szMsg, lpszMsg );
  321.     m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  322. }
  323. //////////////////////////////////////////////////////////////////////////
  324. // 发送认输消息
  325. //////////////////////////////////////////////////////////////////////////
  326. void CTable::GiveUp()
  327. {
  328.     CFiveApp *pApp = (CFiveApp *)AfxGetApp();
  329.     pApp->m_nLost++;
  330.     CDialog *pDlg = (CDialog *)AfxGetMainWnd();
  331.     // 使按钮失效
  332.     pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  333.     pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow( FALSE );
  334.     pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow( FALSE );
  335.     // 修改等待状态
  336.     SetWait( TRUE );
  337.     // 生效菜单项
  338.     CMenu *pMenu = pDlg->GetMenu();
  339.     pMenu->EnableMenuItem( ID_MENU_PLAYAGAIN, MF_ENABLED | MF_BYCOMMAND );
  340.     // 发送认输消息
  341.     MSGSTRUCT msg;
  342.     msg.uMsg = MSG_GIVEUP;
  343.     m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  344. }
  345. //////////////////////////////////////////////////////////////////////////
  346. // 接收来自对方的数据
  347. //////////////////////////////////////////////////////////////////////////
  348. void CTable::Receive()
  349. {
  350.     MSGSTRUCT msgRecv;
  351.     m_pGame->ReceiveMsg( &msgRecv );
  352.     // 对各种消息分别进行处理
  353.     switch ( msgRecv.uMsg )
  354.     {
  355.     case MSG_PUTSTEP:
  356.         {
  357.             PlaySound( MAKEINTRESOURCE( IDR_WAVE_PUT ), NULL, SND_RESOURCE | SND_SYNC );
  358.             SetData( msgRecv.x, msgRecv.y, msgRecv.color );
  359.             // 大于1步才能悔棋
  360.             GetParent()->GetDlgItem( IDC_BTN_BACK )->EnableWindow( m_pGame->m_StepList.size() > 1 );
  361.             Over();
  362.         }
  363.         break;
  364.     case MSG_BACK:
  365.         {
  366.             if ( IDYES == GetParent()->MessageBox( _T("对方请求悔棋,接受这个请求吗?"),
  367.                 _T("悔棋"), MB_ICONQUESTION | MB_YESNO ) )
  368.             {
  369.                 // 发送允许悔棋消息
  370.                 MSGSTRUCT msg;
  371.                 msg.uMsg = MSG_AGREEBACK;
  372.                 m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  373.                 // 给自己悔棋
  374.                 STEP step;
  375.                 step = *( m_pGame->m_StepList.begin() );
  376.                 m_pGame->m_StepList.pop_front();
  377.                 m_data[step.x][step.y] = -1;
  378.                 step = *( m_pGame->m_StepList.begin() );
  379.                 m_pGame->m_StepList.pop_front();
  380.                 m_data[step.x][step.y] = -1;
  381.                 // 大于1步才能悔棋
  382.                 GetParent()->GetDlgItem( IDC_BTN_BACK )->EnableWindow( m_pGame->m_StepList.size() > 1 );
  383.                 Invalidate();
  384.             }
  385.             else
  386.             {
  387.                 // 发送不允许悔棋消息
  388.                 MSGSTRUCT msg;
  389.                 msg.uMsg = MSG_REFUSEBACK;
  390.                 m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  391.             }
  392.         }
  393.         break;
  394.     case MSG_REFUSEBACK:
  395.         {
  396.             CDialog *pDlg = (CDialog *)AfxGetMainWnd();
  397.             pDlg->MessageBox( _T("很抱歉,对方拒绝了您的悔棋请求。"), _T("悔棋"), MB_ICONINFORMATION );
  398.             pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow();
  399.             pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow();
  400.             pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow();
  401.             RestoreWait();
  402.         }
  403.         break;
  404.     case MSG_AGREEBACK:
  405.         {
  406.             STEP step;
  407.             step = *( m_pGame->m_StepList.begin() );
  408.             m_pGame->m_StepList.pop_front();
  409.             m_data[step.x][step.y] = -1;
  410.             step = *( m_pGame->m_StepList.begin() );
  411.             m_pGame->m_StepList.pop_front();
  412.             m_data[step.x][step.y] = -1;
  413.             CDialog *pDlg = (CDialog *)AfxGetMainWnd();
  414.             pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow();
  415.             pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow();
  416.             // 大于1步才能悔棋
  417.             pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( m_pGame->m_StepList.size() > 1 );
  418.             RestoreWait();
  419.             Invalidate();
  420.         }
  421.         break;
  422.     case MSG_DRAW:
  423.         {
  424.             if ( IDYES == GetParent()->MessageBox( _T("对方请求和棋,接受这个请求吗?"),
  425.                 _T("和棋"), MB_ICONQUESTION | MB_YESNO ) )
  426.             {
  427.                 CFiveApp *pApp = (CFiveApp *)AfxGetApp();
  428.                 pApp->m_nDraw++;
  429.                 // 发送允许和棋消息
  430.                 MSGSTRUCT msg;
  431.                 msg.uMsg = MSG_AGREEDRAW;
  432.                 m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  433.                 // 和棋后,禁用按钮和棋盘
  434.                 CDialog *pDlg = (CDialog *)GetParent();
  435.                 pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow( FALSE );
  436.                 pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow( FALSE );
  437.                 pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  438.                 SetWait( TRUE );
  439.                 // 使“重玩”菜单生效
  440.                 pDlg->GetMenu()->EnableMenuItem( ID_MENU_PLAYAGAIN, MF_ENABLED | MF_BYCOMMAND );
  441.             }
  442.             else
  443.             {
  444.                 // 发送拒绝和棋消息
  445.                 MSGSTRUCT msg;
  446.                 msg.uMsg = MSG_REFUSEDRAW;
  447.                 m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  448.             }
  449.         }
  450.         break;
  451.     case MSG_AGREEDRAW:
  452.         {
  453.             CFiveApp *pApp = (CFiveApp *)AfxGetApp();
  454.             pApp->m_nDraw++;
  455.             CDialog *pDlg = (CDialog *)GetParent();
  456.             pDlg->MessageBox( _T("看来真是棋逢对手,对方接受了您的和棋请求。"), _T("和棋"), MB_ICONINFORMATION );
  457.             // 和棋后,使“重玩”菜单生效
  458.             pDlg->GetMenu()->EnableMenuItem( ID_MENU_PLAYAGAIN, MF_ENABLED | MF_BYCOMMAND );
  459.         }
  460.         break;
  461.     case MSG_REFUSEDRAW:
  462.         {
  463.             CDialog *pDlg = (CDialog *)GetParent();
  464.             pDlg->MessageBox( _T("看来对方很有信心取得胜利,所以拒绝了您的和棋请求。"),
  465.                 _T("和棋"), MB_ICONINFORMATION );
  466.             // 重新设置按钮状态,并恢复棋盘状态
  467.             pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow();
  468.             pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow();
  469.             pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow();
  470.             RestoreWait();
  471.         }
  472.         break;
  473.     case MSG_CHAT:
  474.         {
  475.             CString strAdd;
  476.             strAdd.Format( _T("%s 说:%srn"), m_strAgainst, msgRecv.szMsg );
  477.             CEdit *pEdit = (CEdit *)GetParent()->GetDlgItem( IDC_EDT_CHAT );
  478.             pEdit->SetSel( -1, -1, TRUE );
  479.             pEdit->ReplaceSel( strAdd );
  480.         }
  481.         break;
  482.     case MSG_INFORMATION:
  483.         {
  484.             m_strAgainst = msgRecv.szMsg;
  485.             GetParent()->GetDlgItem( IDC_ST_ENEMY )->SetWindowText( m_strAgainst );
  486.             // 在先手接到姓名信息后,回返自己的姓名信息
  487.             if ( 0 == m_color )
  488.             {
  489.                 MSGSTRUCT msg;
  490.                 msg.uMsg = MSG_INFORMATION;
  491.                 lstrcpy( msg.szMsg, m_strMe );
  492.                 m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  493.             }
  494.         }
  495.         break;
  496.     case MSG_GIVEUP:
  497.         {
  498.             CFiveApp *pApp = (CFiveApp *)AfxGetApp();
  499.             pApp->m_nWin++;
  500.             CDialog *pDlg = (CDialog *)GetParent();
  501.             pDlg->MessageBox( _T("对方已经投子认输,恭喜您不战而屈人之兵!"), _T("胜利"), MB_ICONINFORMATION );
  502.             // 禁用各按钮及棋盘
  503.             pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  504.             pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow( FALSE );
  505.             pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow( FALSE );
  506.             SetWait( TRUE );
  507.             // 设置“重玩”为真
  508.             pDlg->GetMenu()->EnableMenuItem( ID_MENU_PLAYAGAIN, MF_ENABLED | MF_BYCOMMAND );
  509.         }
  510.         break;
  511.     case MSG_PLAYAGAIN:
  512.         {
  513.             CDialog *pDlg = (CDialog *)GetParent();
  514.             if ( IDYES == pDlg->MessageBox( _T("对方看来意犹未尽,请求与您再战一局,接受这个请求吗?nn选“否”将断开与他的连接。"),
  515.                 _T("再战"), MB_YESNO | MB_ICONQUESTION ) )
  516.             {
  517.                 pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  518.                 pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow();
  519.                 pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow();
  520.                 MSGSTRUCT msg;
  521.                 msg.uMsg = MSG_AGREEAGAIN;
  522.                 m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  523.                 Clear( (BOOL)m_color );
  524.                 SetGameMode( 2 );
  525.             }
  526.             else
  527.             {
  528.                 m_conn.Close();
  529.                 m_sock.Close();
  530.                 pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  531.                 pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow( FALSE );
  532.                 pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow( FALSE );
  533.                 pDlg->GetDlgItem( IDC_CMB_CHAT )->EnableWindow( FALSE );
  534.                 // 设置菜单状态
  535.                 SetMenuState( TRUE );
  536.                 // 设置棋盘等待状态
  537.                 SetWait( TRUE );
  538.                 // 设置网络连接状态
  539.                 m_bConnected = FALSE;
  540.                 // 重新设置玩家名称
  541.                 pDlg->SetDlgItemText( IDC_ST_ENEMY, _T("无玩家加入") );
  542.             }
  543.         }
  544.         break;
  545.     case MSG_AGREEAGAIN:
  546.         {
  547.             CDialog *pDlg = (CDialog *)GetParent();
  548.             pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  549.             pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow();
  550.             pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow();
  551.             Clear( (BOOL)m_color );
  552.             SetGameMode( 2 );
  553.         }
  554.         break;
  555.     }
  556. }
  557. // 消息映射表
  558. BEGIN_MESSAGE_MAP( CTable, CWnd )
  559. //{{AFX_MSG_MAP(CTable)
  560.     ON_WM_PAINT()
  561.     ON_WM_LBUTTONUP()
  562. //}}AFX_MSG_MAP
  563. END_MESSAGE_MAP()
  564. //////////////////////////////////////////////////////////////////////////
  565. // 处理WM_PAINT消息
  566. //////////////////////////////////////////////////////////////////////////
  567. void CTable::OnPaint()
  568. {
  569.     CPaintDC dc( this );
  570.     CDC MemDC;
  571.     MemDC.CreateCompatibleDC( &dc );
  572.     // 装载棋盘
  573.     CBitmap bmp;
  574.     CPen pen;
  575.     bmp.LoadBitmap( IDB_BMP_QP );
  576.     pen.CreatePen( PS_SOLID, 1, 0xff );
  577.     MemDC.SelectObject( &bmp );
  578.     MemDC.SelectObject( &pen );
  579.     MemDC.SetROP2( R2_NOTXORPEN );
  580.     // 根据棋盘数据绘制棋子
  581.     int x, y;
  582.     POINT pt;
  583.     for ( y = 0; y < 15; y++ )
  584.     {
  585.         for ( x = 0; x < 15; x++ )
  586.         {
  587.             if ( -1 != m_data[x][y] )
  588.             {
  589.                 pt.x = 12 + 25 * x;
  590.                 pt.y = 84 + 25 * y;
  591.                 m_iml.Draw( &MemDC, m_data[x][y], pt, ILD_TRANSPARENT );
  592.             }
  593.         }
  594.     }
  595.     // 绘制最后落子的指示矩形
  596.     if ( NULL != m_pGame && !m_pGame->m_StepList.empty() )
  597.     {
  598.         STEP step = *( m_pGame->m_StepList.begin() );
  599.         MemDC.MoveTo( 11 + 25 * step.x, 83 + 25 * step.y );
  600.         MemDC.LineTo( 36 + 25 * step.x, 83 + 25 * step.y );
  601.         MemDC.LineTo( 36 + 25 * step.x, 108 + 25 * step.y );
  602.         MemDC.LineTo( 11 + 25 * step.x, 108 + 25 * step.y );
  603.         MemDC.LineTo( 11 + 25 * step.x, 83 + 25 * step.y );
  604.     }
  605.     // 完成绘制
  606.     dc.BitBlt( 0, 0, 395, 472, &MemDC,0, 0, SRCCOPY );
  607. }
  608. //////////////////////////////////////////////////////////////////////////
  609. // 处理左键弹起消息,为玩家落子之用
  610. //////////////////////////////////////////////////////////////////////////
  611. void CTable::OnLButtonUp( UINT nFlags, CPoint point )
  612. {
  613.     STEP stepPut;
  614.     if ( m_bWait )
  615.     {
  616.         MessageBeep( MB_OK );
  617.         return;
  618.     }
  619.     int x, y;
  620.     x = ( point.x - 12 ) / 25;
  621.     y = ( point.y - 84 ) / 25;
  622.     // 如果在(0, 0)~(14, 14)范围内,且该坐标没有落子,则落子于此,否则发声警告并退出过程
  623.     if ( x < 0 || x > 14 || y < 0 || y > 14 || m_data[x][y] != -1 )
  624.     {
  625.         MessageBeep( MB_OK );
  626.         return;
  627.     }
  628.     else
  629.     {
  630.         // 如果位置合法,则落子
  631.         SetData( x, y, m_color );
  632.         stepPut.color = m_color;
  633.         stepPut.x = x;
  634.         stepPut.y = y;
  635.         // 大于1步才能悔棋
  636.         GetParent()->GetDlgItem( IDC_BTN_BACK )->EnableWindow( m_pGame->m_StepList.size() > 1 );
  637.     }
  638.     // 判断胜利的情况
  639.     if ( Win( m_color ) )
  640.     {
  641.         CFiveApp *pApp = (CFiveApp *)AfxGetApp();
  642.         pApp->m_nWin++;
  643.         m_pGame->Win( stepPut );
  644.         CDialog *pDlg = (CDialog *)GetParent();
  645.         PlaySound( MAKEINTRESOURCE( IDR_WAVE_WIN ), NULL, SND_SYNC | SND_RESOURCE );
  646.         pDlg->MessageBox( _T("恭喜,您获得了胜利!"), _T("胜利"), MB_ICONINFORMATION );
  647.         pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow( FALSE );
  648.         pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  649.         pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow( FALSE );
  650.         m_bWait = TRUE;
  651.         return;
  652.     }
  653.     else
  654.     {
  655.         // 开始等待
  656.         m_bWait = TRUE;
  657.         // 发送落子信息
  658.         PlaySound( MAKEINTRESOURCE( IDR_WAVE_PUT ), NULL, SND_SYNC | SND_RESOURCE );
  659.         m_pGame->SendStep( stepPut );
  660.     }
  661. }
  662. //////////////////////////////////////////////////////////////////////////
  663. // 重新设置先前的等待标志
  664. //////////////////////////////////////////////////////////////////////////
  665. void CTable::RestoreWait()
  666. {
  667.     SetWait( m_bOldWait );
  668. }