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

棋牌游戏

开发平台:

Visual C++

  1. #include "StdAfx.h"
  2. #include "Table.h"
  3. #include "Game.h"
  4. #include "Messages.h"
  5. #include "Resource.h"
  6. //////////////////////////////////////////////////////////////////////////
  7. // CGame类的实现部分
  8. //////////////////////////////////////////////////////////////////////////
  9. CGame::~CGame()
  10. {
  11. }
  12. void CGame::Win( const STEP& stepSend )
  13. {
  14. }
  15. //////////////////////////////////////////////////////////////////////////
  16. // COneGame类的实现部分
  17. //////////////////////////////////////////////////////////////////////////
  18. COneGame::~COneGame()
  19. {
  20. }
  21. void COneGame::Init()
  22. {
  23.     // 设置网络连接状态
  24.     m_pTable->m_bConnected = FALSE;
  25.     // 设置敌人姓名
  26.     m_pTable->GetParent()->SetDlgItemText( IDC_ST_ENEMY, _T("计算机") );
  27.     // 计算获胜组合情况
  28.     int i, j, k, nCount = 0;
  29.     for ( i = 0; i < 15; i++ )
  30.     {
  31.         for ( j = 0; j < 15; j++ )
  32.         {
  33.             for ( k = 0; k < 572; k++ )
  34.             {
  35.                 m_Player[i][j][k] = false;
  36.                 m_Computer[i][j][k] = false;
  37.             }
  38.         }
  39.     }
  40.     for ( i = 0; i < 2; i++ )
  41.     {
  42.         for ( j = 0; j < 572; j++ )
  43.         {
  44.             m_Win[i][j] = 0;
  45.         }
  46.     }
  47.     for ( i = 0; i < 15; i++ )
  48.     {
  49.         for ( j = 0; j < 11; j++ )
  50.         {
  51.             for ( k = 0; k < 5; k++ )
  52.             {
  53.                 m_Player[j + k][i][nCount] = true;
  54.                 m_Computer[j + k][i][nCount] = true;
  55.             }
  56.             nCount++;
  57.         }
  58.     }
  59.     for ( i = 0; i < 15; i++ )
  60.     {
  61.         for ( j = 0; j < 11; j++ )
  62.         {
  63.             for ( k = 0; k < 5; k++ )
  64.             {
  65.                 m_Player[i][j + k][nCount] = true;
  66.                 m_Computer[i][j + k][nCount] = true;
  67.             }
  68.             nCount++;
  69.         }
  70.     }
  71.     for ( i = 0; i < 11; i++ )
  72.     {
  73.         for ( j = 0; j < 11; j++ )
  74.         {
  75.             for ( k = 0; k < 5; k++ )
  76.             {
  77.                 m_Player[j + k][i + k][nCount] = true;
  78.                 m_Computer[j + k][i + k][nCount] = true;
  79.             }
  80.             nCount++;
  81.         }
  82.     }
  83.     for ( i = 0; i < 11; i++ )
  84.     {
  85.         for ( j = 14; j >= 4; j-- )
  86.         {
  87.             for ( k = 0; k < 5; k++ )
  88.             {
  89.                 m_Player[j - k][i + k][nCount] = true;
  90.                 m_Computer[j - k][i + k][nCount] = true;
  91.             }
  92.             nCount++;
  93.         }
  94.     }
  95.     if ( 1 == m_pTable->GetColor() )
  96.     {
  97.         // 如果玩家后走,则手动控制电脑占据天元
  98.         m_pTable->SetData( 7, 7, 0 );
  99.         PlaySound( MAKEINTRESOURCE( IDR_WAVE_PUT ), NULL, SND_RESOURCE | SND_SYNC );
  100.         m_bStart = false;
  101.         for ( i = 0; i < 572; i++ )
  102.         {
  103.             // 保存先前数据,做悔棋之用
  104.             m_nOldWin[0][i] = m_Win[0][i];
  105.             m_nOldWin[1][i] = m_Win[1][i];
  106.             m_bOldPlayer[i] = m_Player[7][7][i];
  107.         }
  108.         for ( i = 0; i < 572; i++ )
  109.         {
  110.             // 修改计算机下子后,棋盘的变化状况
  111.             if ( m_Computer[7][7][i] && m_Win[1][i] != -1 )
  112.             {
  113.                 m_Win[1][i]++;
  114.             }
  115.             if ( m_Player[7][7][i] )
  116.             {
  117.                 m_Player[7][7][i] = false;
  118.                 m_Win[0][i] = -1;
  119.             }
  120.         }
  121.     }
  122.     else
  123.     {
  124.         m_bStart = true;
  125.     }
  126. }
  127. void COneGame::SendStep( const STEP& stepPut )
  128. {
  129.     int bestx, besty, i, j, pi, pj, ptemp, ctemp, pscore = 10, cscore = -10000;
  130.     int ctempTable[15][15], ptempTable[15][15];
  131.     int m, n, temp1[20], temp2[20]; // 暂存第一步搜索的信息
  132.     m_pTable->GetParent()->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  133.     // 保存先前数据,做悔棋之用
  134.     for ( i = 0; i < 572; i++)
  135.     {
  136.         m_nOldWin[0][i] = m_Win[0][i];
  137.         m_nOldWin[1][i] = m_Win[1][i];
  138.         m_bOldPlayer[i] = m_Player[stepPut.x][stepPut.y][i];
  139.         m_bOldComputer[i] = m_Computer[stepPut.x][stepPut.y][i];
  140.     }
  141.     // 修改玩家下子后棋盘状态的变化
  142.     for ( i = 0; i < 572; i++ )
  143.     {
  144.         // 修改状态变化
  145.         if ( m_Player[stepPut.x][stepPut.y][i] && m_Win[0][i] != -1 )
  146.             m_Win[0][i]++;
  147.         if ( m_Computer[stepPut.x][stepPut.y][i] )
  148.         {
  149.             m_Computer[stepPut.x][stepPut.y][i] = false;
  150.             m_Win[1][i] = -1;
  151.         }
  152.     }
  153.     if ( m_bStart )
  154.     {
  155.         // 手动确定第一步:天元或(8, 8)
  156.         if ( -1 == m_pTable->m_data[7][7] )
  157.         {
  158.             bestx = 7;
  159.             besty = 7;
  160.         }
  161.         else
  162.         {
  163.             bestx = 8;
  164.             besty = 8;
  165.         }
  166.         m_bStart = false;
  167.     }
  168.     else
  169.     {
  170.         STEP step;
  171.         // 寻找最佳位置
  172.         GetTable( ctempTable, m_pTable->m_data );
  173.         while ( SearchBlank( i, j, ctempTable ) )
  174.         {
  175.             n = 0;
  176.             pscore = 10;
  177.             GetTable( ptempTable, m_pTable->m_data );
  178.             ctempTable[i][j] = 2; // 标记已被查找
  179.             step.color = 1 - m_pTable->GetColor();
  180.             step.x = i;
  181.             step.y = j;
  182.             // 给这个空位打分
  183.             ctemp = GiveScore( step );
  184.             for ( m = 0; m < 572; m++ )
  185.             {
  186.                 // 暂时更改玩家信息
  187.                 if ( m_Player[i][j][m] )
  188.                 {
  189.                     temp1[n] = m;
  190.                     m_Player[i][j][m] = false;
  191.                     temp2[n] = m_Win[0][m];
  192.                     m_Win[0][m] = -1;
  193.                     n++;
  194.                 }
  195.             }
  196.             ptempTable[i][j] = 0;
  197.             
  198.             pi = i;
  199.             pj = j;
  200.             while ( SearchBlank( i, j, ptempTable ) )
  201.             {
  202.                 
  203.                 ptempTable[i][j] = 2; // 标记已被查找
  204.                 step.color = m_pTable->GetColor();
  205.                 step.x = i;
  206.                 step.y = j;
  207.                 ptemp = GiveScore( step );
  208.                 if ( pscore > ptemp ) // 此时为玩家下子,运用极小极大法时应选取最小值
  209.                     pscore = ptemp;
  210.             }
  211.             for ( m = 0; m < n; m++ )
  212.             {
  213.                 // 恢复玩家信息
  214.                 m_Player[pi][pj][temp1[m]] = true;
  215.                 m_Win[0][temp1[m]] = temp2[m];
  216.             }
  217.             if ( ctemp + pscore > cscore ) // 此时为计算机下子,运用极小极大法时应选取最最大值
  218.             {
  219.                 cscore = ctemp + pscore;
  220.                 bestx = pi;
  221.                 besty = pj;
  222.             }
  223.         }
  224.     }
  225.     m_step.color = 1 - m_pTable->GetColor();
  226.     m_step.x = bestx;
  227.     m_step.y = besty;
  228.     for ( i = 0; i < 572; i++ )
  229.     {
  230.         // 修改计算机下子后,棋盘的变化状况
  231.         if ( m_Computer[bestx][besty][i] && m_Win[1][i] != -1 )
  232.             m_Win[1][i]++;
  233.         if ( m_Player[bestx][besty][i] )
  234.         {
  235.             m_Player[bestx][besty][i] = false;
  236.             m_Win[0][i] = -1;
  237.         }
  238.     }
  239.     m_pTable->GetParent()->GetDlgItem( IDC_BTN_BACK )->EnableWindow();
  240.     // 由于是单人游戏,所以直接接收数据
  241.     m_pTable->Receive();
  242. }
  243. void COneGame::ReceiveMsg( MSGSTRUCT *pMsg )
  244. {
  245.     pMsg->color = m_step.color;
  246.     pMsg->x = m_step.x;
  247.     pMsg->y = m_step.y;
  248.     pMsg->uMsg = MSG_PUTSTEP;
  249. }
  250. void COneGame::Back()
  251. {
  252.     int i;
  253.     // 单人游戏直接允许悔棋
  254.     STEP step;
  255.     // 悔第一步(电脑落子)
  256.     step = *( m_StepList.begin() );
  257.     m_StepList.pop_front();
  258.     m_pTable->m_data[step.x][step.y] = -1;
  259.     // 恢复原有胜负布局
  260.     for ( i = 0; i < 572; i++ )
  261.     {
  262.         m_Win[0][i] = m_nOldWin[0][i];
  263.         m_Win[1][i] = m_nOldWin[1][i];
  264.         m_Player[step.x][step.y][i] = m_bOldPlayer[i];
  265.     }
  266.     // 悔第二步(玩家落子)
  267.     step = *( m_StepList.begin() );
  268.     m_StepList.pop_front();
  269.     m_pTable->m_data[step.x][step.y] = -1;
  270.     // 恢复原有胜负布局
  271.     for ( i = 0; i < 572; i++ )
  272.     {
  273.         m_Computer[step.x][step.y][i] = m_bOldComputer[i];
  274.     }
  275.     m_pTable->Invalidate();
  276.     // 考虑到程序的负荷,这时候就不允许悔棋了
  277.     AfxGetMainWnd()->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  278. }
  279. int COneGame::GiveScore( const STEP& stepPut )
  280. {
  281.     int i, nScore = 0;
  282.     for ( i = 0; i < 572; i++ )
  283.     {
  284.         if ( m_pTable->GetColor() == stepPut.color )
  285.         {
  286.             // 玩家下
  287.             if ( m_Player[stepPut.x][stepPut.y][i] )
  288.             {
  289.                 switch ( m_Win[0][i] )
  290.                 {
  291.                 case 1:
  292.                     nScore -= 5;
  293.                     break;
  294.                 case 2:
  295.                     nScore -= 50;
  296.                     break;
  297.                 case 3:
  298.                     nScore -= 500;
  299.                     break;
  300.                 case 4:
  301.                     nScore -= 5000;
  302.                     break;
  303.                 default:
  304.                     break;
  305.                 }
  306.             }
  307.         }
  308.         else
  309.         {
  310.             // 计算机下
  311.             if ( m_Computer[stepPut.x][stepPut.y][i] )
  312.             {
  313.                 switch ( m_Win[1][i] )
  314.                 {
  315.                 case 1:
  316.                     nScore += 5;
  317.                     break;
  318.                 case 2:
  319.                     nScore += 50;
  320.                     break;
  321.                 case 3:
  322.                     nScore += 100;
  323.                     break;
  324.                 case 4:
  325.                     nScore += 10000;
  326.                     break;
  327.                 default:
  328.                     break;
  329.                 }
  330.             }
  331.         }
  332.     }
  333.     return nScore;
  334. }
  335. void COneGame::GetTable( int tempTable[][15], int nowTable[][15] )
  336. {
  337.     int i, j;
  338.     for ( i = 0; i < 15; i++ )
  339.     {
  340.         for ( j = 0; j < 15; j++ )
  341.         {
  342.             tempTable[i][j] = nowTable[i][j];
  343.         }
  344.     }
  345. }
  346. bool COneGame::SearchBlank( int &i, int &j, int nowTable[][15] )
  347. {
  348.     int x, y;
  349.     for ( x = 0; x < 15; x++ )
  350.     {
  351.         for ( y = 0; y < 15; y++ )
  352.         {
  353.             if ( nowTable[x][y] == -1 && nowTable[x][y] != 2 )
  354.             {
  355.                 i = x;
  356.                 j = y;
  357.                 return true;
  358.             }
  359.         }
  360.     }
  361.     return false;
  362. }
  363. //////////////////////////////////////////////////////////////////////////
  364. // CTwoGame类的实现部分
  365. //////////////////////////////////////////////////////////////////////////
  366. CTwoGame::~CTwoGame()
  367. {
  368. }
  369. //////////////////////////////////////////////////////////////////////////
  370. void CTwoGame::Init()
  371. {
  372. }
  373. void CTwoGame::Win( const STEP& stepSend )
  374. {
  375.     SendStep( stepSend );
  376. }
  377. void CTwoGame::SendStep( const STEP& stepPut )
  378. {
  379.     MSGSTRUCT msg;
  380.     msg.uMsg = MSG_PUTSTEP;
  381.     msg.color = stepPut.color;
  382.     msg.x = stepPut.x;
  383.     msg.y = stepPut.y;
  384.     m_pTable->m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  385. }
  386. void CTwoGame::ReceiveMsg( MSGSTRUCT *pMsg )
  387. {
  388.     int nRet = m_pTable->m_conn.Receive( pMsg, sizeof( MSGSTRUCT ) );
  389.     if ( SOCKET_ERROR == nRet )
  390.     {
  391.         AfxGetMainWnd()->MessageBox( _T("接收数据时发生错误,请检查您的网络连接。"), _T("错误"), MB_ICONSTOP );
  392.     }
  393. }
  394. void CTwoGame::Back()
  395. {
  396.     CDialog *pDlg = (CDialog *)AfxGetMainWnd();
  397.     // 使按钮失效
  398.     pDlg->GetDlgItem( IDC_BTN_BACK )->EnableWindow( FALSE );
  399.     pDlg->GetDlgItem( IDC_BTN_HQ )->EnableWindow( FALSE );
  400.     pDlg->GetDlgItem( IDC_BTN_LOST )->EnableWindow( FALSE );
  401.     // 设置等待标志
  402.     m_pTable->SetWait( TRUE );
  403.     MSGSTRUCT msg;
  404.     msg.uMsg = MSG_BACK;
  405.     m_pTable->m_conn.Send( (LPCVOID)&msg, sizeof( MSGSTRUCT ) );
  406. }