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

📄 bwchessdlg.cpp

📁 这是我用vc编写的一个黑白棋网络游戏的使用程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// BWChessDlg.cpp : implementation file
#include "stdafx.h"
#include <math.h>
#include <mmsystem.h>//播放声音的头文件
#include "BWChess.h"
#include "SetupDlg.h"
#include "AboutDlg.h"
#include "Globalvar0.h"
#include "HelperAPI.h" //定义了3个对话框函数
#include "BWChessDlg.h"
#include "RecorDdlg.h"
#include "BestDlg.h"
#include <time.h>
#include "SettingDlg.h"
#include "Demo.h"
#include "windows.h"
#include "Message1.h"
#include "ip1.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBWChessDlg dialog
BOOL PlaySounds(UINT IDSoundRes, WORD wFlag)//播放声音
{  //PlaySound 是标准函数<win.h>             
	if (g_bSoundOn)
		if (PlaySound(MAKEINTRESOURCE(IDSoundRes),//播放的声音资源
			AfxGetInstanceHandle(),//指明实例
			wFlag|SND_RESOURCE|SND_NODEFAULT))//标志位:不默认,使用实例包含的资源
			return TRUE;
	return FALSE;
}

CBWChessDlg::CBWChessDlg(CWnd* pParent ): CDialog(IDD_BWCHESS_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);//载入图标 to m_hIcon ,不载入则使用默认图标
	m_pMenu = new CMenu();//菜单
	m_PaintNum=0;
	hAccelerator=::LoadAccelerators(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_ACC));
    //载入加速键
	g_nCanHintTimeB= 3;
	g_nCanHintTimeW= 3;
	g_nStrollSpeed= 2;
	//获得时间和速度
	g_nStrollSpeed=abs(g_nStrollSpeed);
	g_nStrollSpeed%=3;//速度分为3种:低 中 高
	g_nCanHintTimeB=abs(g_nCanHintTimeB);
	g_nCanHintTimeB%=31;
	if(g_nCanHintTimeB<3)
		g_nCanHintTimeB=3;
	g_nCanHintTimeW=abs(g_nCanHintTimeW);
	g_nCanHintTimeW%=31;
	if(g_nCanHintTimeW<3)
	  g_nCanHintTimeW=3;
    //读注册表(关于英雄榜)
	g_nTime1		=AfxGetApp()->GetProfileInt(pSettings, _T("Time1"), 0);    
	g_nTime2		=AfxGetApp()->GetProfileInt(pSettings, _T("Time2"), 0);    
	g_nTime3		=AfxGetApp()->GetProfileInt(pSettings, _T("Time3"), 0);
	g_nMark1		=AfxGetApp()->GetProfileInt(pSettings, _T("Mark1"), 0);    
	g_nMark2		=AfxGetApp()->GetProfileInt(pSettings, _T("Mark2"), 0);    
	g_nMark3		=AfxGetApp()->GetProfileInt(pSettings, _T("Mark3"), 0);    
	g_strName1		=AfxGetApp()->GetProfileString(pSettings, _T("Name1"), _T("Anonymous"));    
	g_strName2		=AfxGetApp()->GetProfileString(pSettings, _T("Name2"), _T("Anonymous"));    
	g_strName3		=AfxGetApp()->GetProfileString(pSettings, _T("Name3"), _T("Anonymous"));
	//写入注册表(关于英雄榜)
	CString str;
	str.LoadString (IDS_AUTHOR);//载入字符串 “庞长才  制作”
	AfxGetApp()->WriteProfileString(_T("Author"), _T("Shuker"), str);  
	AfxGetApp()->WriteProfileInt(pSettings, _T("Time1"), g_nTime1);    
	AfxGetApp()->WriteProfileInt(pSettings, _T("Time2"), g_nTime2);    
	AfxGetApp()->WriteProfileInt(pSettings, _T("Time3"), g_nTime3);  
	AfxGetApp()->WriteProfileInt(pSettings, _T("Mark1"), g_nMark1);    
	AfxGetApp()->WriteProfileInt(pSettings, _T("Mark2"), g_nMark2);    
	AfxGetApp()->WriteProfileInt(pSettings, _T("Mark3"), g_nMark3);    
	AfxGetApp()->WriteProfileString(pSettings, _T("Name1"), g_strName1);    
	AfxGetApp()->WriteProfileString(pSettings, _T("Name2"), g_strName2);    
	AfxGetApp()->WriteProfileString(pSettings, _T("Name3"), g_strName3); 	
}

CBWChessDlg::~CBWChessDlg()//释放资源
{   //以下为new对应的资源
	delete m_pMenu;
}

void CBWChessDlg::InitParams()
{
	for (int i=0; i<NUM;i++)
	    for (int j=0; j<NUM; j++)
	    	kernel[i][j] = 0;	//0 for none,1 for white,2 for black,棋盘的初态

	kernel[3][3]=kernel[4][4]=2;//开局的
	kernel[3][4]=kernel[4][3]=1;//     4颗子

	m_CurPt.x = m_CurPt.y =-1;//放子的位置(初态)

	num_black=2;//黑白子
	num_white=2;//的颗数

	m_PassedTime=0;//黑棋流逝的时间
	m_PassedTime0=0;//白棋流逝的时间
	m_bGameOver = FALSE;//游戏是否已经结束
	
	//m_byColor是本程序的核心变量!!!!!!!!!!!!!!!
	m_byColor = 0; //代表棋手的颜色,在使用之前代表前一个棋手的颜色,
	                //使用完之后代表当前棋手的颜色,因此使用之前要将其取反 1:黑 0:白
	m_Skip=0;//对方是否无子可下,即对方是否跳过不下
	g_nStoneNum=0;//格子的个数
	m_TimerOn=0;//时间是否在计数
	m_HintOnce=0;//是否提示
	m_PeekOnce=0;//是否查看可下棋的位置
	m_IsGameStart=0;//游戏是否已经开始
	m_ListInfo.ResetContent();//清空列表
	m_HintTime0=0;//白棋点击的次数
	m_HintTime1=0;//黑棋点击的次数
	ListInfo.destroy();//stack 类,清空信息空栈
	m_UndoPoint.Destroy();//undo类,清空悔棋信息空栈
}

void CBWChessDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CBWChessDlg)
	//以下部分是将控件与变量联系起来
	DDX_Control(pDX, IDC_TIME_CHINESE0, m_Time0);//白棋用时
	DDX_Control(pDX, IDC_INFO, m_Info);//走棋信息
	DDX_Control(pDX, IDC_LISTINFO, m_ListInfo);//走棋信息列表
	DDX_Control(pDX, IDC_WNUM, m_Wnum);//白棋数目
	DDX_Control(pDX, IDC_TIME_CHINESE, m_Time);//黑棋用时
	DDX_Control(pDX, IDC_BNUM, m_Bnum);////黑棋数目
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CBWChessDlg, CDialog)//消息映射函数
	//{{AFX_MSG_MAP(CBWChessDlg)
	ON_WM_PAINT()//窗口内画图
	ON_WM_LBUTTONDOWN() //鼠标左击                          	
	ON_COMMAND(IDM_NEW, OnNew)	 //菜		
	ON_COMMAND(IDM_EXIT, OnExit)   //单			
	ON_COMMAND(IDM_ABOUT, OnAbout)    //命令			
	ON_WM_SETCURSOR()
	ON_WM_QUERYDRAGICON()
	ON_WM_SYSCOMMAND()
	ON_WM_CONTEXTMENU()//弹出菜单
	ON_WM_TIMER()
	ON_COMMAND(IDM_UNDO, OnUndo)//以下全为菜单命令
	ON_COMMAND(IDM_BEST, OnBest)
	ON_COMMAND(IDM_HINT, OnHint)
	ON_COMMAND(IDM_CANPLACE, OnCanplace)
	ON_COMMAND(IDM_SETTING, OnSetting)
	ON_COMMAND(IDM_OPEN, OnOpen)
	ON_COMMAND(IDM_SAVE, OnSave)
	ON_COMMAND(IDM_SAVEINFO, OnSaveinfo)
	ON_COMMAND(IDM_DEMO, OnDemo)
	ON_COMMAND(ID_Onhost, OnHost)
	ON_COMMAND(ID_Onconnect, OnConnect)
	ON_COMMAND(ID_Unlink, OnUnlink)
	ON_COMMAND(IDM_REPLAY, OnReplay)
	//}}AFX_MSG_MAP
	ON_LBN_DBLCLK(IDC_LISTINFO , OnListDoubleClicked)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBWChessDlg message handlers

BOOL CBWChessDlg::OnInitDialog()
{
	 CDialog::OnInitDialog();
	 SetIcon(m_hIcon, TRUE);			// Set big icon,m_hIcon是图标变量
	 SetIcon(m_hIcon, FALSE);		// Set small icon
     CBitmap bitmap;
	 bitmap.LoadBitmap(IDB_EMPTY);
	 BITMAP bm;
     bitmap.GetBitmap(&bm);
     m_wStoneWidth=(unsigned short) bm.bmWidth;         //bmWidth,bm.bmHeight
     m_wStoneHeight=(unsigned short)bm.bmHeight;
     CBitmap bitmap1;
	 bitmap1.LoadBitmap(IDB_F1_2);
     bitmap1.GetBitmap(&bm);
     m_wFrameWidth=(unsigned short)bm.bmWidth;         //bmWidth,bm.bmHeight
     m_wFrameHeight=(unsigned short)bm.bmHeight;
    //获取系统的相关信息
	int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);
	int cyScreen = ::GetSystemMetrics(SM_CYSCREEN);
	int cxDlgFrame = ::GetSystemMetrics(SM_CXDLGFRAME);
	int cyDlgFrame = ::GetSystemMetrics(SM_CYDLGFRAME);
	int cxCaption = ::GetSystemMetrics(SM_CYCAPTION); 
	int cyMenu = ::GetSystemMetrics(SM_CYMENU);//系统菜单的宽度
	int nWidth = m_wFrameHeight*2+ m_wFrameWidth*8 + 2*cxDlgFrame;//根据位图和系统参数
	int nHeight = m_wFrameHeight*2+ m_wFrameWidth*8 + cxCaption + 2*cyDlgFrame + cyMenu;//确定界面的大下
	MoveWindow((cxScreen-nWidth-230)/2, (cyScreen-nHeight)/2,nWidth+230, nHeight+2);
			     //确定窗口的位置和大小,默认状态是响应重画消息
	TimeCount.Create(this,nWidth+ 20, 40  ,0,4);//时间和棋子计数控件(自定义)的创建,4代表4位数,0无效
	TimeCount0.Create(this,nWidth+20, 120 ,0,4);
	BCount.Create	(this,nWidth+ 34, 230 ,0,2);
	WCount.Create	(this,nWidth+ 34 ,310 ,0,2);
//	ShowNumber(1);static文本控件的位置和大小,以像素为单位,this的左上角为(0,0)
	m_Time.MoveWindow(nWidth+18  ,20  ,60,20);
	m_Time0.MoveWindow(nWidth+18 ,100 ,60,20);
	m_Bnum.MoveWindow(nWidth+18  ,210 ,60,20);
	m_Wnum.MoveWindow(nWidth+18  ,290 ,60,20);
	m_ListInfo.MoveWindow(nWidth+95,22,110,410);//列表
	m_Info.MoveWindow(nWidth+95,2,110,20);//m_Infostatic文本
	m_IsGameStart=1;//游戏是否开始
	//设置系统菜单
	CMenu* sysmenu=GetSystemMenu(FALSE);
	sysmenu->DeleteMenu(2,MF_BYPOSITION);
   	sysmenu->DeleteMenu(0,MF_BYPOSITION);
	sysmenu->DeleteMenu(2,MF_BYPOSITION);
	CString str;
	str.LoadString(IDS_TITLE_CHINESE);//IDS_TITLE_CHINESE:“黑白棋”
	SetWindowText(str);//设置标题
	m_pMenu->DestroyMenu();
	m_pMenu->LoadMenu(IDR_MENU_CHINESE);//载入主界面菜单
	SetMenu(m_pMenu);
	m_pMenu->EnableMenuItem(IDM_HINT,MF_GRAYED);//提示无效
	m_pMenu->EnableMenuItem(IDM_UNDO,MF_GRAYED);//悔棋无效
	m_pMenu->EnableMenuItem(IDM_CANPLACE,MF_GRAYED);//查看可以下子的地方无效
	m_pMenu->EnableMenuItem(IDM_SAVE,MF_GRAYED);//保存棋局无效
	m_pMenu->EnableMenuItem(IDM_SAVEINFO,MF_GRAYED);//导出走棋信息无效
	m_pMenu->EnableMenuItem(IDM_REPLAY,MF_GRAYED);//重温棋局无效
	if(g_bTopMost)//最前面,不移动,不改变大小
		SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
	else//不是最前面
		SetWindowPos(&wndNoTopMost,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
	m_wXNull = m_wFrameHeight+1;//9 //包括白线
	m_wYNull = m_wFrameHeight+1;//10
	m_Client.top = m_wYNull;//m_Client代表8*8棋盘
	m_Client.left = m_wXNull;
	m_Client.bottom =m_wYNull + NUM * m_wStoneHeight;
	m_Client.right =m_wXNull + NUM * m_wStoneWidth;
	int i,j;
	for (i=0; i<NUM;++i)
	    for (j=0; j<NUM; j++)
	    	kernel[i][j] = 0;	//0代表无子
	num_black=0;
	num_white=0;
	m_PassedTime=0;
	m_PassedTime0=0;
	m_TimerOn=0;
	m_HintOnce=0;//0 for have not hinted yet,1 for have hinted
	m_PeekOnce=0;
	m_HintTime0=0;
	m_HintTime1=0;
	m_bGameOver=TRUE;
	return TRUE;  // return TRUE  unless you set the focus to a control
}//end OnInitDialog

void CBWChessDlg::OnPaint() //游戏启动时作的一些准备工作
{
	CPaintDC dc(this); // device context for painting
	CDC * pdc=GetDC();
	if (IsIconic())//如果窗口已最小化,画图标(意义不大)
	{
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		int cxIcon = GetSystemMetrics(SM_CXICON);//获取图标的大小,像素为单位
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);//获得画图区,并画图于窗口中间
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;
		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);//m_hIcon 代表图标
	}
	else//normal 大小
	{
		ShowNumber(1);//显示计数器控件
		DrawFrame(&dc);//显示棋盘边框
        BYTE t;
		if(!m_IsGameStart)//没开始                                                 
		{
			for (int i=0; i<NUM; ++i)
				for (int j=0; j<NUM; ++j)
				{
                    t=(unsigned char)(kernel[i][j]-1);
		    		if (kernel[i][j])//0 for none, 1 for white,2 for black,             
						PutStone(t, CPoint(j,i), &dc);//画棋盘 PutStone:画棋子
				}
			if(m_CurPt.x >=0)//m_CurPt.x/y 取0——7
			{
				int nX = m_CurPt.x*m_wStoneWidth + m_wXNull;//计算棋子的位置(nx,ny)
				int nY = m_CurPt.y*m_wStoneHeight + m_wYNull;
				int byColor= kernel[m_CurPt.y][m_CurPt.x]-1;//棋子的颜色 :白 黑
				if (byColor == 0)//白
					DrawBitmap(pdc,nX,nY,IDB_CURWHITE, SRCCOPY);
				else if (byColor == 1)//黑
					DrawBitmap(pdc,nX,nY,IDB_CURBLACK, SRCCOPY);
			}	//此处画棋子
		}//end if(!m_IsGameStart)

		if(m_HintOnce)//0 for have not hinted yet,1 for have hinted :m_HintOnce代表是否提示
		{
			COLORREF crColor = m_byColor ? RGB(255,255,255) : RGB(0,0,0);//确定颜色
			CPen pen(PS_SOLID, 2, crColor);
			CPen *pOldPen = dc.SelectObject(&pen);	//画 提示符 “X”
			dc.MoveTo(x1, y1);
			dc.LineTo(x2, y1);
			dc.LineTo(x2, y2);
			dc.LineTo(x1, y2);
			dc.LineTo(x1, y1);
			dc.LineTo(x2, y2);
			dc.MoveTo(x2, y1);
			dc.LineTo(x1, y2);//x1 y1 x2 y2 的初值?????
			dc.SelectObject(pOldPen);
		}
		if(m_PeekOnce)//代表是否查看可下的位置,画可下的位置
		{
			int px,py;
			int xx1,yy1;
			int length,hy;

			if(m_byColor)//黑
				length=wsp.isempty();
			else//白
				length=bsp.isempty();
			if(length)
				return;

			do
			{
				if(m_byColor)//从栈里取可放子的格子
					length=wsp.GetNextPos(&py,&px,&hy);//有效格子的个数
				else
					length=bsp.GetNextPos(&py,&px,&hy);
				xx1 = px*m_wStoneWidth + m_wXNull;//-4 + m_cxGrid / 2;
				yy1 = py*m_wStoneHeight + m_wYNull;//-4 + m_cyGrid / 2;
				if(m_byColor)//显示可放子的格子(显示一个标志性的位图)
					DrawBitmap(pdc,xx1,yy1,IDB_CANPLACE2, SRCCOPY);
				else
					DrawBitmap(pdc,xx1,yy1,IDB_CANPLACE1, SRCCOPY);
			}while(length);

			if(m_byColor)
				wsp.CopyBackIndex ();
			else
				bsp.CopyBackIndex ();
		}
		Mutex1.Lock();//互斥,在“Globalvar0.h”里定义的变量
		if(g_nIsDemo && g_nMutex)
		{
			g_nMutex=0;

			m_Mutex.Unlock();//互斥,在“Globalvar0.h”里定义的变量
		}
		Mutex1.Unlock();
	}
	ReleaseDC(pdc);
}//end paint


HCURSOR CBWChessDlg::OnQueryDragIcon()//返回图标
{
	return (HCURSOR) m_hIcon;//返回图标
}

void CBWChessDlg::OnLButtonDown(UINT nFlag, CPoint point)//左击
{       
	if(!ready)// P 操作!!!!!!!!
	   return;


	CPoint pt;
	if(!IsInPanel(point) || m_bGameOver || g_nIsDemo)
		return;//无效 返回

	
	
	//此处为非网络模式
	if (g_nRunMode != MODE_NETWORK&&PointToStonePos(point, pt))
	{
		int nX = pt.x;
		int nY = pt.y;
		if (kernel[nY][nX]==0) //此处无子     
		{
			if (g_nRunMode == MODE_WITH_COMPUTER)//模式是与计算机对弈
			{
		 		if ((g_bUserBlack && !m_byColor) || 
	 				(!g_bUserBlack && m_byColor)) //数据正确
				{                                    
					// User
					m_byColor = !m_byColor;	// 0-Black  1-White//设置当前棋手的颜色,因为初值为黑色棋手,
					                                  //但是m_byColor==0,代表白色,所以要先设成黑色
					//undo
					duplicate();//保存副本
					//end undo
					if(BtoW(nY,nX,m_byColor+1))//将棋盘上被夹住的子变色
					{
						m_HintOnce=0;
						m_PeekOnce=0;
						m_CurPt=pt;
						AddStringToList(nY,nX,m_byColor);//将信息加入列表框
						InvalidateRect(m_Client, FALSE);//刷新窗口
						UpdateWindow();//显示窗口
						PlaySounds(IDSOUND_PUTSTONE);   
						Ring(IsEnd(!m_byColor+1));//根据棋盘的状态处理善后工作
						// -1 for both
        //棋盘的状态: // 0 for the int have no position
                      //1 for the int have one position ,no use now
                     //return 2 for have more than one
		//函数原型:int CBWChessDlg::IsEnd(int whogo);
         //whogo :1代表黑色,2代表白色
						// Computer                       
						if (!m_bGameOver && !m_Skip)
						{
							do
							{
								m_byColor = !m_byColor;			// 1-Black  0-White
								int ptBest_x,ptBest_y;
								//undo
								duplicate();//保存副本
								//end undo
								Place(&ptBest_x,&ptBest_y,m_byColor+1);//计算机寻找最佳位置
								//函数原型:void Place(int *x, int *y,int color,int nSkill)
								//color: 1 白 2 黑 
								BtoW(ptBest_x,ptBest_y,m_byColor+1);//将棋盘上被夹住的子变色
								CPoint pt;
								pt.x = ptBest_y*m_wStoneWidth + m_wXNull+m_wStoneWidth/2;
								pt.y = ptBest_x*m_wStoneHeight + m_wYNull+m_wStoneWidth/2;
								m_CurPt.x=ptBest_y;
								m_CurPt.y=ptBest_x;
								ClientToScreen(&pt);
								MoveCursor(pt.x, pt.y);//移动光标,此时m_byColor代表的是当前棋手的颜色
								InvalidateRect(m_Client, FALSE);
								UpdateWindow();//更新棋盘
								AddStringToList(ptBest_x,ptBest_y,m_byColor);//将信息加入列表框
								PlaySounds(IDSOUND_PUTSTONE);
								Ring(IsEnd(!m_byColor+1));//作善后处理,包括“游戏结束或对手无子可走”
							}while(m_Skip);//m_Skip==1表示对手无子可走,由计算机继续走
						}

						if(!m_bGameOver && g_bPeepOften)
							OnCanplace();//继续搜索
					}
					else//没有夹住任何棋子,撤消已有的操作
					{
						int temp[NUM*NUM];
						m_UndoPoint.pop(temp);
						m_byColor=!m_byColor;
						PlaySounds(IDSOUND_ERROR);
					}	
					
				}    //  end if ((g_bUserBlack && !m_byColor) ||(!g_bUserBlack && m_byColor)) 

			}// end  模式是与计算机对弈  

			else if (g_nRunMode == MODE_2PLAYER)// 人对人!!			// Users
			{
				m_byColor = !m_byColor;		// 1-Black  0-White,由当前棋手的ID取得当前棋手的颜色,
                                             //颜色与ID正好相反,故取反
				duplicate();
				if(BtoW(nY,nX,m_byColor+1))//有棋子可变色
				{
					m_HintOnce=0;//不提示
					m_PeekOnce=0;//不查看
					m_CurPt=pt;
					AddStringToList(nY,nX,m_byColor);
					InvalidateRect(m_Client,FALSE);
					UpdateWindow();
					PlaySounds(IDSOUND_PUTSTONE);        
					Ring(IsEnd(!m_byColor+1));
					if(!m_bGameOver && g_bPeepOften)
						OnCanplace();
				}
				else//没有夹住任何棋子,撤消已有的操作
				{
					int temp[NUM*NUM];
					m_UndoPoint.pop(temp);
					m_byColor=!m_byColor;
					PlaySounds(IDSOUND_ERROR);
				}
			}//end  人对人!!
			else ;//此情况非法!!

⌨️ 快捷键说明

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