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

📄 hanio.h

📁 这是一个小游戏
💻 H
字号:
#include	"windows.h"
#include	"string.h"
#include	"stdlib.h"
#include	"stdio.h"
#include	"time.h"
#include	"resource.h"

#define		X		600
#define		Y		400
#define		ESC		27
#define		Dx		20
#define		Dx2		10
#define		MAXLEVEL	8
#define		MAXSTEP	1000

int NUM=3;
const char szTitle[]="Hanio 1.0";
const char szWndClass[]="WndClass";
const char szAuthor[]="作者:武冬生";
const char szMail[]="E-mail:cangzhu@163.com";
const char szMsg1[]="F2 撤销    F3 自动";
const char szMsg2[]="F4 上一关  F5 下一关  ESC 退出";
char szCurMsg[256];
const int Center[3]={X/6,X/2,5*X/6};
HWND hWnd;

void Draw();
BOOL MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

//矩形的宽度函数
int Width(RECT rect)
{
	return abs(rect.right-rect.left);
}

//判断一点是不是在一个矩形内
BOOL PointInRect(POINT point,RECT Rect)
{
	int x=point.x;
	int y=point.y;
	if(x>Rect.left&&
		x<Rect.right&&
		y>Rect.top&&
		y<Rect.bottom)
		
		return TRUE;
	else
		return FALSE;
}

//又由点判断该点在第几个盘子的位置
int PointToNum(POINT pt)
{
	if(pt.x>=0&&pt.x<=X/3)
		return 0;
	if(pt.x>X/3&&pt.x<=2*X/3)
		return 1;
	if(pt.x>2*X/3&&pt.x<=X)
		return 2;

	else 
		return -1;

}
//记录每一步的盘子的情况
class CMap
{
public:
	//每组盘子的个数
	int iCount[3];
	//3组盘子里面,每个盘子的位置,用矩形表示
	RECT *Rect[3];
	//构造函数
	CMap()
	{
		//三组盘子,每组盘子的矩形
		for(int i=0;i<3;i++)
			Rect[i]=new RECT[NUM];
		//初始化每组盘子的个数
		iCount[0]=NUM;
		iCount[1]=0;
		iCount[2]=0;
		//第一组盘子的矩形的位置
		for(i=0;i<NUM;i++)
		{
			Rect[0][i].left=Center[0]-(NUM-i)*Dx2;
			Rect[0][i].right=Center[0]+(NUM-i)*Dx2;
			Rect[0][i].bottom=(NUM+1-i)*Dx;
			Rect[0][i].top=(NUM-i)*Dx;
		}
		//第二组盘子的矩形初始化为空
		for(i=0;i<NUM;i++)
		{
			Rect[1][i].left=0;
			Rect[1][i].right=0;
			Rect[1][i].bottom=0;
			Rect[1][i].top=0;
		}
		//第三组盘子的矩形初始化为空
		for(i=0;i<NUM;i++)
		{
			Rect[2][i].left=0;
			Rect[2][i].right=0;
			Rect[2][i].bottom=0;
			Rect[2][i].top=0;
		}
	}
	//运算符重载
	CMap operator=(CMap Other)
	{
		//对新的CMap对象,应该重新分配内存
		for(int i=0;i<3;i++)
			Rect[i]=new RECT[NUM];
		//依次赋值
		for(i=0;i<3;i++)
		{
			iCount[i]=Other.iCount[i];
			for(int j=0;j<NUM;j++)
				Rect[i][j]=Other.Rect[i][j];
		}
		//返回
		return *(this);
	}
	//画图,显示盘子的情况
	void OnDraw(HDC hdc)
	{
		//画出每个盘子
		for(int i=0;i<3;i++)
			for(int j=0;j<iCount[i];j++)
				Rectangle(hdc,
					Rect[i][j].left,
					Rect[i][j].top,
					Rect[i][j].right,
					Rect[i][j].bottom);
	}
	//析构函数
	~CMap()
	{
		//内存的释放
		for(int i=0;i<3;i++)
		{
			if(Rect[i]!=NULL)
			{
				Rect[i]=NULL;
				delete Rect[i];
			}
		}
	}
};

class Hanio
{
public:
	//当前的步数
	int iStep;
	//记录每一步的盘子的情况
	CMap Record[MAXSTEP];
public:
	//构造函数
	Hanio()
	{
		//初始化,步数为0
		iStep=0;
		//初始化记录
		for(int i=0;i<MAXSTEP;i++)
		{
			Record[i]=CMap();
		}
	}
	//画图,显示汉诺塔的情况
	void OnDraw(HDC hdc)
	{
		Record[iStep].OnDraw(hdc);
	}
	//撤销
	void Undo()
	{
		if(iStep>0)
			iStep--;
		//重绘
		Draw();
	}
	//移动盘子
	void Move(int iStart,int iEnd)
	{
		//得到当前盘子的记录
		CMap Map=Record[iStep];
		//移动的情况判断,去除非法的移动
		if(iStart<0||iStart>=3)
			return;
		if(iEnd<0||iEnd>=3)
			return;
		if(iStart==iEnd)
			return;
		if(Map.iCount[iStart]<1)
			return;
		//得到移动前的开始组,结束组的盘子的个数
		int iStartRectNum=Map.iCount[iStart];
		int iEndRectNum=Map.iCount[iEnd];
		//从小盘子移动到大盘子上面的情况是不可以的。
		if(iEndRectNum>0)
			if(Width(Map.Rect[iStart][iStartRectNum-1])>=Width(Map.Rect[iEnd][iEndRectNum-1]))
				return;
		//步数累加
		iStep++;
		//记录新的盘子的情况
		Record[iStep]=Record[iStep-1];
		//移走的那一组盘子的个数减少
		Record[iStep].iCount[iStart]--;
		//被移到的那一组的盘子个数增加
		Record[iStep].iCount[iEnd]++;
		//重新计算移动后的盘子的矩形
		//主要是被移到的那一组的最上面那个盘子的矩形的计算
		RECT rect;
		rect.left=Center[iEnd]-Width(Map.Rect[iStart][iStartRectNum-1])/2;
		rect.right=Center[iEnd]+Width(Map.Rect[iStart][iStartRectNum-1])/2;
		rect.bottom=(NUM+1-Map.iCount[iEnd])*Dx;
		rect.top=(NUM-Map.iCount[iEnd])*Dx;
		Record[iStep].Rect[iEnd][iEndRectNum]=rect;
		//刷新
		SendMessage(hWnd,WM_PAINT,0,0);
	}
	//自动移盘子
	void AutoMove(int iA,int iB,int iC,int iNum)
	{
		//递归实现自动移盘子
		//递归的出口,如果个数为3,按如下进行移动。
		if(iNum==3)
		{
			Move(iA,iC);
			::Sleep(500);

			Move(iA,iB);
			::Sleep(500);

			Move(iC,iB);
			::Sleep(500);

			Move(iA,iC);
			::Sleep(500);

			Move(iB,iA);
			::Sleep(500);

			Move(iB,iC);
			::Sleep(500);

			Move(iA,iC);
			::Sleep(500);
		}
		//个数大于3,递归实现移动。
		else
		{
			//递归自动移动。
			AutoMove(iA,iC,iB,iNum-1);
			Move(iA,iC);
			::Sleep(500);
			AutoMove(iB,iA,iC,iNum-1);
		}
	}
};

⌨️ 快捷键说明

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