⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 doc.cpp

📁 讲mfc的书
💻 CPP
字号:
// Doc.cpp : implementation of the CBfieldDoc class
// Battlefield document -- most real work is here

#include "stdafx.h"
#include "bfield.h"
#include "insert.h"
#include "bsocket.h"
#include "Doc.h"
#include "ConnDlg.h"
#include "HostDlg.h"
#include "packet.h"
#include "mainfrm.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

///////////////////////
// CBfieldDoc

IMPLEMENT_DYNCREATE(CBfieldDoc, CDocument)

BEGIN_MESSAGE_MAP(CBfieldDoc, CDocument)
        //{{AFX_MSG_MAP(CBfieldDoc)
        ON_COMMAND(IDM_CONNECT, OnConnect)
        ON_COMMAND(IDM_HOST, OnHost)
        ON_UPDATE_COMMAND_UI(IDM_CONNECT, OnUpdateConnect)
        ON_UPDATE_COMMAND_UI(ID_TURN, OnUpdateTurn)
        ON_UPDATE_COMMAND_UI(IDM_HOST, OnUpdateHost)
        ON_COMMAND(IDM_RESIGN, OnResign)
        ON_UPDATE_COMMAND_UI(IDM_RESIGN, OnUpdateResign)
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

///////////////////////
// CBfieldDoc construction/destruction

CBfieldDoc::CBfieldDoc()
{
        sockfile=NULL;
        xmit=NULL;
        rcv=NULL;
        MyTurn=FALSE;
}

CBfieldDoc::~CBfieldDoc()
{
    NetClose();
}

BOOL CBfieldDoc::OnNewDocument()
{
        if (!CDocument::OnNewDocument())
                return FALSE;
        NetClose();
    // empty grids
        for (int i=0;i<2;i++)
                for (int x=0;x<10;x++)
                        for (int y=0;y<10;y++)
                                grid[i][x][y]='.';
        mode=0;
        placed=0;
        HitCt[0]=0;
        HitCt[1]=0;
        MyTurn=FALSE;
        return TRUE;
}

///////////////////////
// CBfieldDoc serialization -- not used

void CBfieldDoc::Serialize(CArchive& ar)
{
        if (ar.IsStoring())
        {
                // TODO: add storing code here
        }
        else
        {
                // TODO: add loading code here
        }
}

///////////////////////
// CBfieldDoc diagnostics

#ifdef _DEBUG
void CBfieldDoc::AssertValid() const
{
        CDocument::AssertValid();
}

void CBfieldDoc::Dump(CDumpContext& dc) const
{
        CDocument::Dump(dc);
}
#endif //_DEBUG

///////////////////////
// CBfieldDoc commands

// Get state based on current mode
char CBfieldDoc::GetState(int x,int y)
{
   return grid[mode][x][y];
}

// Handle mouse click from view
void CBfieldDoc::OnClick(int x,int y)
{
if (grid[mode][x][y]!='.'||x>9||y>9)
        {
        AfxMessageBox("Please click a blank square");
        return;
        }
if (mode==0)  // setup
        {
        int q,step=1;
        CInsert dlg;
        if (placed==0x1F)
            {
            AfxMessageBox("You have placed all your pieces");
            return;
            }
// set up placement dialog
        dlg.m_placed=placed;
        dlg.m_x=x;
        dlg.m_y=y;
// call dialog
        int res=dlg.DoModal();
        if (res==-1) return;
        if (res=='.') return; // shouldn't happen
// check for piece sticking over edge
        if ((dlg.m_Dir==DIR_WEST && x-dlg.m_Len<-1)||
            (dlg.m_Dir==DIR_EAST && x+dlg.m_Len>10)||
            (dlg.m_Dir==DIR_NORTH && y-dlg.m_Len<-1)||
            (dlg.m_Dir==DIR_SOUTH && y+dlg.m_Len>10))
                {
                AfxMessageBox(
                  "The piece must completely fit on the board");
                return;
                }
// Now check for overlapping pieces
        if (dlg.m_Dir==DIR_WEST||dlg.m_Dir==DIR_NORTH) step=-1;
        if (dlg.m_Dir==DIR_EAST||dlg.m_Dir==DIR_WEST)
                {
                for (q=0;q<dlg.m_Len;q++)
                        if (grid[0][x+step*q][y]!='.')
                          {
                          AfxMessageBox(
                            "The piece overlaps another piece!");
                          return;
                          }
// set it up
                for (q=0;q<dlg.m_Len;q++)
                   grid[0][x+step*q][y]=res;
                }
        else
                {
                for (q=0;q<dlg.m_Len;q++)
                        if (grid[0][x][y+step*q]!='.')
                          {
                          AfxMessageBox(
                            "The piece overlaps another piece!");
                          return;
                          }
                for (q=0;q<dlg.m_Len;q++)
                    grid[0][x][y+step*q]=res;
                }
// mark it as placed and redraw
        placed|=dlg.m_Piece;
        UpdateAllViews(NULL);
        }
else  // not in setup mode -- hostile click!
        {
        CPacket pkt;
        if (!MyTurn) return; // no cheating
// build outbound packet
        pkt.cmd=CMD_CLICK;
        pkt.x=x;
        pkt.y=y;
        pkt.Serialize(*xmit);
        xmit->Flush();  // make sure to send it
// get reply -- might block for a bit
// but assuming everything works, no big deal
        pkt.Serialize(*rcv);
        if (pkt.cmd!=CMD_REPLY)
                {
                AfxMessageBox("Bad reply");
                return;
                }
// update board
        grid[1][pkt.x][pkt.y]=pkt.data;
// count our hits
        if (pkt.data!='X') HitCt[0]++;
// check for win!
        if (HitCt[0]==17)
                {
                AfxMessageBox("You win!");
                NetClose();
                OnNewDocument();
                UpdateAllViews(NULL);
                }
        UpdateAllViews(NULL);
        MyTurn=FALSE;
        }
}

int CBfieldDoc::GetMode(void)
{
   return mode;
}


// Come here to connect to host
// Host must be ready
void CBfieldDoc::OnConnect()
{
    CConnDlg dlg;
        if (dlg.DoModal()==IDCANCEL) return;
        mode=-1;
        UpdateStatus();
        if (!socket.Create())
                {
                err(socket.GetLastError());
                return;
                }

        if (!socket.Connect(dlg.m_Host,dlg.m_Port))
                if (socket.GetLastError()!=WSAECONNREFUSED)
                  {
                  mode=0;
                  err(socket.GetLastError());
                  socket.Close();
                  return;
                  }
                else
                  {
                  // Host not ready yet
                  mode=0;
                  AfxMessageBox("Host not available");
                  socket.Close();
                  return;
              }
        sockfile=new CSocketFile(&socket);
        xmit=new CArchive(sockfile,CArchive::store);
        rcv=new CArchive(sockfile,CArchive::load);
        mode=1;
        UpdateStatus();
        UpdateAllViews(NULL);
}

//Here to set up as host
void CBfieldDoc::OnHost()
{
        CHostDlg dlg;
        if (dlg.DoModal()==IDCANCEL) return;
        mode=-1;
        UpdateStatus();
        if (!hostsocket.Create(dlg.m_Port))
                {
                err(GetLastError());
                return;
                }
        if (!hostsocket.Listen())
                {
                err(GetLastError());
                return;
                }
      // wait for connection or error -- blocks
      while (!hostsocket.Accept(socket) &&
             !hostsocket.GetLastError());
      if (hostsocket.GetLastError())
          {
          err(hostsocket.GetLastError());
          return;
          }
        hostsocket.Close(); // no more connections
        sockfile=new CSocketFile(&socket);
        xmit=new CArchive(sockfile,CArchive::store);
        rcv=new CArchive(sockfile,CArchive::load);
        mode=1;
        UpdateStatus();
        UpdateAllViews(NULL);
        MyTurn=TRUE;
        AfxMessageBox("Connected: It is your turn");
        }

// Enable connect menu
void CBfieldDoc::OnUpdateConnect(CCmdUI* pCmdUI)
  {
  pCmdUI->Enable(mode==0&&placed==0x1F);
  }

// Enable host menu
void CBfieldDoc::OnUpdateHost(CCmdUI* pCmdUI)
{
pCmdUI->Enable(mode==0&&placed==0x1F);
}

// Resign game
void CBfieldDoc::OnResign()
{
  CPacket pkt;
  if (AfxMessageBox(
     "Do you really want to quit?",MB_YESNO)==IDNO)
        return;
  pkt.cmd=CMD_RESIGN;
  pkt.Serialize(*xmit);
  NetClose();
  OnNewDocument();
  UpdateAllViews(NULL);
  }

// Enable Resign
void CBfieldDoc::OnUpdateResign(CCmdUI* pCmdUI)
{
  pCmdUI->Enable(mode==1&&MyTurn);
}

// Very bad general error routine
void CBfieldDoc::err(int ern)
{
  CString s;
  s.Format("%x-%x",ern,GetLastError());
  AfxMessageBox(s);
}

// Close network connection
void CBfieldDoc::NetClose()
{
  if (xmit) delete xmit;
  if (rcv) delete rcv;
  if (sockfile) delete sockfile;
  socket.Close();
  sockfile=NULL;
  xmit=NULL;
  rcv=NULL;
  mode=0;
  placed=0;
}

void CBfieldDoc::OnCloseDocument()
{
        NetClose();
        CDocument::OnCloseDocument();
}


// CBattleSocket calls this when data is available
void CBfieldDoc::GoAhead(void)
{
  CPacket pkt;
  CPacket outgoing;
  UpdateStatus();
  pkt.Serialize(*rcv);  // get packet
  if (pkt.cmd==CMD_RESIGN) // quitter?
        {
        AfxMessageBox("Your opponent resigned");
        NetClose();
        OnNewDocument();
        UpdateAllViews(NULL);
        return;
        }
  if (pkt.cmd!=CMD_CLICK)
        {
        AfxMessageBox("Unexpected error");
        return;
        }
// prepare reply
  outgoing.data=grid[0][pkt.x][pkt.y];
  outgoing.cmd=CMD_REPLY;
  outgoing.x=pkt.x;
  outgoing.y=pkt.y;
  if (outgoing.data=='.') // convert our . to outbound X
    outgoing.data='X';
  else
     HitCt[1]++;  // He hit us!
// send it
  outgoing.Serialize(*xmit);
  xmit->Flush();
// check for loss
  if (HitCt[1]==17)
        {
        AfxMessageBox("You lose!");
        NetClose();
        OnNewDocument();
        UpdateAllViews(NULL);
        }
  MyTurn=TRUE;
  CString msg;
  if (outgoing.data!='X')
    msg.Format("Opponent hit: %c. ",outgoing.data);
  msg=msg+"It is your turn";
  AfxMessageBox(msg);
}

BOOL CBfieldDoc::GetTurn()
{
  return MyTurn;
}

// Helper function to update status bar
void CBfieldDoc::UpdateStatus(void)
{
  CMainFrame *fw=(CMainFrame *)AfxGetMainWnd();
  fw->UpdateStatus();
}

// We are ready if all pieces are placed (0x1F)
BOOL CBfieldDoc::GetReady(void)
{
  return placed==0x1F;
}

// This updates the status bar pane
void CBfieldDoc::OnUpdateTurn(CCmdUI* pCmdUI)
{
  int mode=GetMode();
  BOOL turn=GetTurn();
  CString s;
  if (!mode)
        {
        if (placed==0x1F)
          s="Ready to connect";
        else
          s="Setting up...";
        }
  else
    {
    if (mode==-1) s="Connecting...";
    if (turn)
      s="Your turn";
    else
      s="Waiting...";
    }
  CString counts;
  counts.Format("(%d/%d)",HitCt[0],HitCt[1]);
  s+=counts;
  pCmdUI->SetText(s);
  pCmdUI->Enable(TRUE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -