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

📄 pengpenggamedlg.cpp

📁 我写的搞怪碰碰球!里面游戏性还是蛮好玩的!对于学习游戏编程来说也是一个好代码!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// pengpengGameDlg.cpp : implementation file
//

#include "stdafx.h"
#include "pengpengGame.h"
#include "pengpengGameDlg.h"
#include "GetNameDlg.h"
#include <mmsystem.h>
//#include <vfw.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
extern CPengpengGameApp theApp;
class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPengpengGameDlg dialog

CPengpengGameDlg::CPengpengGameDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPengpengGameDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPengpengGameDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CPengpengGameDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPengpengGameDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPengpengGameDlg, CDialog)
	//{{AFX_MSG_MAP(CPengpengGameDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_WM_TIMER()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPengpengGameDlg message handlers

BOOL CPengpengGameDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

//	PlayMidi("F:\\梦里水乡.mid");
	//装入图片资源
	CBitmap bmBack,bmBallan,bmBallhei,bmScore,bmButtonsys;
	bmBack.LoadBitmap(IDB_BACK);
	bmBallan.LoadBitmap(IDB_BALLAN);
	bmBallhei.LoadBitmap(IDB_BALLHEI);
	bmScore.LoadBitmap(IDB_SCORE);
	bmButtonsys.LoadBitmap(IDB_BUTTONSYS);

	//初始化DC
	CClientDC dc(this);
	m_dcBack.CreateCompatibleDC(&dc);
	m_dcBallAn.CreateCompatibleDC(&dc);
	m_dcBallHei.CreateCompatibleDC(&dc);
	m_dcScore.CreateCompatibleDC(&dc);
	m_dcButtonSys.CreateCompatibleDC(&dc);

	//把图片放到对应的DC
	m_dcBack.SelectObject(&bmBack);
	m_dcBallAn.SelectObject(&bmBallan);
	m_dcBallHei.SelectObject(&bmBallhei);
	m_dcScore.SelectObject(&bmScore);
	m_dcButtonSys.SelectObject(&bmButtonsys);

	//释放
	bmBack.DeleteObject();
	bmBallan.DeleteObject();
	bmBallhei.DeleteObject();
	bmScore.DeleteObject();
	bmButtonsys.DeleteObject();

	//调整窗口大小及位置改窗口标题
	CRect rt1,rt2;
	GetWindowRect(&rt1);
	GetClientRect(&rt2);
	int cx=rt1.right-rt1.left-(rt2.right-rt2.left);
	int cy=rt1.bottom-rt1.top-(rt2.bottom-rt2.top);
	MoveWindow(0,0,539+cx,485+cy);
	CenterWindow();
	SetWindowText("搞怪PKLANG");

	srand(time(NULL));//初始化随机发生器

	//打开用于记录前五名的信息文件
	  CFile fHero;
	  int i;
	  PK_Hero da;
	  if(fHero.Open("Hero.dat",CFile::modeRead)==0)//找不到文件就新建一个
	  {
		  //随便几个名字和分数
		  char *name[]={"鏒ぢ箆麖ぜ蔆","PKLANG's GF[Nancy]","PKLANG's GF[XiaoQian]","PKLANG's GF[Wenwen]","PKLANG's GF[Dandan]"};
		  int score[5]={885,750,640,620,520};
		  fHero.Open("Hero.dat",CFile::modeCreate|CFile::modeWrite);
		  for(i=0;i<5;i++)
		  {
			  strcpy(da.Name,name[i]);
			  da.Score=score[i];
			  fHero.Write(&da,sizeof(PK_Hero));
			  m_arrHero.Add(da);

		  }
		  fHero.Close();
	  }
	  else//找到就读出来放进m_arrHero链表里
	  {
		  
		  for(i=0;i<5;i++)
		  {
			  fHero.Read(&da,sizeof(PK_Hero));
			  m_arrHero.Add(da);

		  }
		  fHero.Close();
	  }
	
	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	// TODO: Add extra initialization here

	//设置6个按钮的矩形位置
	m_rtSelect[0].SetRect(476,0,504,32);
	m_rtSelect[1].SetRect(508,0,540,32);
	m_rtSelect[2].SetRect(409,246,495,246+33);
	m_rtSelect[3].SetRect(409,286,495,286+33);
	m_rtSelect[4].SetRect(409,326,495,326+33);
	m_rtSelect[5].SetRect(395,374,530,420);

	m_nButtonSelect=-1;//鼠标不在任何一个按钮
	m_nSelected=-1;		//还没有选中球子
	ReStart();//初始化游戏

	return TRUE;  // return TRUE  unless you set the focus to a control
}


// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

//////////////////////////////////////////////////////////////////////
//         在OnPaint()里重画各个小球以及分数
//
//
/////////////////////////////////////////////////////////////////////


void CPengpengGameDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		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+100, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();


		CClientDC ddc(this);
		//重画各个球子
		for(int i=0;i<81;i++)
			if(m_Ball[i]!=-1)
			{
					if(i%2)
						ddc.BitBlt(20+(i%9)*40+2,60+i/9*40+2,36,38,&m_dcBallHei,2,m_Ball[i]*40,SRCCOPY);
					else
						ddc.BitBlt(20+(i%9)*40+2,60+i/9*40+2,36,38,&m_dcBallAn,2,m_Ball[i]*40,SRCCOPY);

			}


		//重画下一要出现的球子
		for( i=0;i<3;i++)
				ddc.BitBlt(400+i*40+2,94,36,38,&m_dcBallHei,2,m_NextBall[i]*40,SRCCOPY);
		//重画玩家当前分数
		DisplayScore(&ddc,410,188,m_nScore);

		//重画最高分数的姓名和分数
		int oldMode=ddc.SetBkMode(TRANSPARENT);//设置透明背景   
		int oldColor=ddc.SetTextColor(RGB(255,10,10));//文字颜色
		ddc.DrawText(m_arrHero.GetAt(0).Name,CRect(280,458,420,475),DT_CENTER|DT_VCENTER);
		DisplayScore(&ddc,430,458,m_arrHero.GetAt(0).Score);
		ddc.SetBkMode(oldMode);
		ddc.SetTextColor(oldColor);

	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPengpengGameDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}
//////////////////////////////////////////////////////////////////////
//        重载OnEraseBkgnd设置窗口的背景图片
//		
//
/////////////////////////////////////////////////////////////////////

BOOL CPengpengGameDlg::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	pDC->BitBlt(0,0,539,485,&m_dcBack,0,0,SRCCOPY);
	pDC->SetBkMode(TRANSPARENT);
	CFont *ft=GetFont();
	pDC->SelectObject(ft);
	pDC->TextOut(10,3,"送给 鏒ぢ箆麖ぜ蔆 ");
	return TRUE;//CDialog::OnEraseBkgnd(pDC);
}

//////////////////////////////////////////////////////////////////////
//        重载OnLButtonDown处理鼠标单击时
//		
//
/////////////////////////////////////////////////////////////////////
void CPengpengGameDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{

	//如果鼠标在6个按钮其中一个时
	if(m_nButtonSelect!=-1)
		ClickVirtualButton();
	else
		if(point.y<20)//如果横坐标<20时就给它认为是单击在标题栏上,用于移动窗口
			PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));

	//重要部分:单击在棋盘上时
	if( point.x>20 && point.x<380 && point.y>60 && point.y<420)
	{
		CUIntArray ar,arrgood;
		int i,j,ret[3],old,pos;
		CRect rt;
		CClientDC dc(this);
	    pos=(point.x-20)/40+(point.y-60)/40*9;	//换算成一维数组的坐标
		if( m_nSelected!=-1)//如果已经选定了一个球子
		{
			if(pos==m_nSelected)return;	//不处理重复原来的
			if( m_Ball[pos]==-1 )//如果点的位置是空的   
			{
				if(BFSPathBest(m_nSelected,pos,&ar))//如果两个点是可以连通
				{
					old=m_Ball[m_nSelected];//保存原来选中的位置
					m_Ball[m_nSelected]=-1;//把原来选中的设置为空  
					KillTimer(1313);//关闭闪烁效果
					PlayMySound(IDR_F4);//播放移动效果声音
				
					//这个循环是两个点前移动过去的视觉效果
					for( i=ar.GetSize()-1;i>0;i-- )
					{
						rt.SetRect(20+ar.GetAt(i)%9*40,60+ar.GetAt(i)/9*40,20+ar.GetAt(i)%9*40+40,60+ar.GetAt(i)/9*40+40);

						RedrawWindow(rt);
						if(ar.GetAt(i-1)%2)
							dc.BitBlt(20+(ar.GetAt(i-1)%9)*40+2,60+ar.GetAt(i-1)/9*40+2,36,38,&m_dcBallHei,2,old*40,SRCCOPY);
						else
							dc.BitBlt(20+(ar.GetAt(i-1)%9)*40+2,60+ar.GetAt(i-1)/9*40+2,36,38,&m_dcBallAn,2,old*40,SRCCOPY);
						Sleep(100);//延时时间,想快就改为更小的时间

					}

					m_Ball[pos]=old;//交换位置信息
					m_nSelected=-1;//设置没有球子选中状态
					
					//判断刚才移过去的位置是否满足削球子的条件
					//for循环是要判断上下,左右,左斜,右斜等四个方向的
					for(j=0;j<4;j++)
						if(FindSuccLine(pos,j,&arrgood))
						{
							FlashTheCheak(&dc,&arrgood);//如果满足就执行闪烁效果
							return;		//记得要返回了
						}

					//没有满足削球时就生成三个球子
					for( i=0;i<3;i++)
					{
						ret[i]=RandFindAt();//ret数组保存随机来的位置
						m_Ball[ret[i]]=m_NextBall[i];//设置新三个位置的球子信息
						m_NextBall[i]=rand()%8;//随机下次要出现的球子信息
						if(ret[i]==-1)//如果已经没有足够位置了
						{
							//如果得分已经超第五名了
							if(m_nScore>m_arrHero.GetAt(4).Score)
							{
								//输入大名对话框
								CGetNameDlg nameDlg;
								if(nameDlg.DoModal()==IDOK)//确认保存
									SaveHero(nameDlg.m_strName);
							}
							else//不然呵呵!
								AfxMessageBox("HAHA!玩完了!");
							ReStart();//重新游戏
							RedrawWindow();//重画窗口
						   	return;
						}
					}
					PlayMySound(IDR_C0);//播放新生球子的欢乐声音

					//判断刚才移过去的位置是否满足削球子的条件
					//I循环是要判断上下,左右,左斜,右斜等四个方向的
					for( i=1;i<4;i++ )
					{
						for( j=0;j<3;j++)
						{

							if(ret[j]%2)
								dc.BitBlt(20+(ret[j]%9)*40+2,60+ret[j]/9*40+2,36,38,&m_dcBallHei,2+(rand()%5+1)*40,m_Ball[ret[j]]*40,SRCCOPY);
							else
								dc.BitBlt(20+(ret[j]%9)*40+2,60+ret[j]/9*40+2,36,38,&m_dcBallAn,2+(rand()%5+1)*40,m_Ball[ret[j]]*40,SRCCOPY);

						}
						Sleep(200);
					}
					rt.SetRect(400,94,400+120,94+40);
					RedrawWindow(rt);

					//判断刚才移过去的位置是否满足削球子的条件
					//j循环是要判断上下,左右,左斜,右斜等四个方向的
					
					for(i=0;i<3;i++)//I循环是有三个球子
					{
						
						for(j=0;j<4;j++)
							if(FindSuccLine(ret[i],j,&arrgood))
							{
								FlashTheCheak(&dc,&arrgood);//跟上面效果一样
								break;
									//MessageBox("good Line");
							}
					}
				}//BFSPathBest(m_nSelected,pos,&ar)
				else//两点没有连通时播放警告声音
				{
					PlayMySound(IDR_J0);
				}
			}//m_Ball[pos]==-1 )
			else//这是当前单击位置是有球子时且已经有选中球子时
			{
				rt.SetRect(20+m_nSelected%9*40,60+m_nSelected/9*40,20+m_nSelected%9*40+38,60+m_nSelected/9*40+38);
				RedrawWindow(rt);
				PlayMySound(IDR_D2);//播放点中的声音
				m_nSelected=pos;//交换选中位置
			}

		}//m_nSelected!=-1)
		else if(m_Ball[pos]!=-1)//是开始有选中时
		{
			PlayMySound(IDR_D2);//播放点中的声音
			m_nSelected=pos;//交换选中位置
			SetTimer(1313,300,NULL);//用定时器来动画左看看右看看下看看上看看的效果
			SendMessage(WM_TIMER,1313);//给我马上动作
		}
	
	}//if inRect(...	

	CDialog::OnLButtonDown(nFlags, point);
}
//////////////////////////////////////////////////////////////////////
//        重要:判断两点是否连通
//	 这里采用广度优先搜索法(BFS)来查找两个点是否连通
//    以及经过的最短路径
//	 其中from来开始点,to为到达点,arrSave保存经过的位置				
//  如果能通就返回TRUE,不然返回FALSE
/////////////////////////////////////////////////////////////////////
BOOL CPengpengGameDlg::BFSPathBest(int from, int to, CUIntArray *arrSave)
{

	int i,head;					//队列头
	int tail;					//队列尾
	int data[81];				//队列数组
	int pnt[81];				//保存父结点位置
	int bcheck[81];				//记录是否已经走过 0没有 1已经走过
	for( i=0;i<81;i++)
		bcheck[i]=0;			//初始都没有走过

	//初始队列
	head=0;						
	tail=1;
	data[0]=from;
	pnt[0]=0;
	while(1)
	{

		//判断上下左右是否有路通

		//从上搜索
		if( (data[head]-9)>=0 && //没有越界
			m_Ball[data[head]-9]==-1 && //且位置是空的
			bcheck[data[head]-9]==0)    //且还没有走过
		{
			data[tail]=data[head]-9;    //满足了保存进队列尾去
			pnt[data[tail]]=data[head]; //保存父结点位置
			if(data[tail]==to)break;    //如果已经到达目标了就退出循环
			bcheck[data[tail]]=1;		//设置已经走过标志
			tail++;						//队列尾加一个
		}
		//以下方法基本一样,只是方向不同

		//从下搜索
		if( (data[head]+9)<81 && m_Ball[data[head]+9]==-1 && bcheck[data[head]+9]==0)
		{
			data[tail]=data[head]+9;
			pnt[data[tail]]=data[head];
			if(data[tail]==to)break;
			bcheck[data[head]+9]=1;
			tail++;
		}
		//从左搜索
		if( ((data[head])%9)>0 && m_Ball[data[head]-1]==-1 && bcheck[data[head]-1]==0)
		{
			data[tail]=data[head]-1;
			pnt[data[tail]]=data[head];
			if(data[tail]==to)break;
			bcheck[data[head]-1]=1;
			tail++;
		}
		//从右搜索
		if( ((data[head])%9)<8 && m_Ball[data[head]+1]==-1 && bcheck[data[head]+1]==0)
		{
			data[tail]=data[head]+1;

⌨️ 快捷键说明

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