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

📄 boxmanclass.cpp

📁 推箱子游戏的源码。有很多关
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// BoxManClass.cpp: implementation of the BoxManClass class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "BoxMan.h"
#include "BoxManClass.h"

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

#define BM_THREAD_BUFFER_SIZE 0x40000

struct PathStruct{
	char manx;
	char many;
	char boxx;
	char boxy;
};
const char WALLB = 0;
const char NULLWALLB = 1;
const char NULLB = 2;
const char BOXB = 3;
const char BOXATPOINTB = 4;
const char POINTB = 5;
const char MANB = 6;
const char MANATPOINTB = 7;
const char dx[4] = { 1, 0, -1, 0 };
const char dy[4] = { 0, -1, 0, 1 };
const char pausetimer = 50;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

BoxManClass::BoxManClass()
{
	_ThreadCommand = BM_COMMAND_STOP_THREAD;
	_ThreadMessage = BM_MESSAGE_THINK_STOPED;
	m_size = 30;
	m_CanUndo = false;
	m_pmanmoveway = NULL;
	m_pDrawWnd = NULL;
	m_CanMoveToBadPoint = false;
	_ThinkingMap = 0;
	try{
		CFile fmap( "Map.dat", CFile::modeRead );
		m_MapFileLength = fmap.GetLength();
		m_hmap = ::GlobalAlloc( GHND, m_MapFileLength );
		void* p = (void*)::GlobalLock( m_hmap );
		fmap.Read( p, m_MapFileLength );
		::GlobalUnlock( m_hmap);
		fmap.Close();
	}catch( CFileException* fe ){
		switch( fe->m_cause ){
		case CFileException::fileNotFound:
			::MessageBox( NULL, "没有找到文件\"Map.dat\",程序不能继续.", fe->m_strFileName,
				MB_OK | MB_ICONERROR );
			::ExitProcess( 1 );
		default:
			::MessageBox( NULL, "文件错误,程序不能继续.", fe->m_strFileName,
				MB_OK | MB_ICONERROR );
			::ExitProcess( 2 );
		}
	}
	try{
		CFile fway( "MoveWay.dat", CFile::modeRead );
		m_wayfilelength = fway.GetLength();
		m_hway = ::GlobalAlloc( GHND, m_wayfilelength );
		void* p = (void*)::GlobalLock( m_hway );
		fway.Read( p, m_wayfilelength );
		::GlobalUnlock( m_hway);
		fway.Close();
	}catch( CFileException* fe ){
		::MessageBeep(MB_ICONEXCLAMATION);
		switch( fe->m_cause ){
		case CFileException::fileNotFound:
			::MessageBox( NULL, "没有找到文件\"MvoeWay.dat\",程序不能继续.", fe->m_strFileName ,
				MB_OK | MB_ICONERROR );
			::ExitProcess( 1 );
		default:
			::MessageBox( NULL, "文件错误,程序不能继续.", fe->m_strFileName ,
				MB_OK | MB_ICONERROR );
			::ExitProcess( 2 );
		}
	}
	m_wayfilechanged = false;
	m_nowmap = 1;
//	ReadMap( m_nowmap );
}

BoxManClass::~BoxManClass()
{
	_ThreadCommand = BM_COMMAND_STOP_THREAD;
	if( m_wayfilechanged ){
		try{
			CFile fway( "MoveWay.dat", CFile::modeWrite );
			fway.SetLength( m_wayfilelength );
			fway.SeekToBegin();
			void* p = (void*)::GlobalLock( m_hway );
			fway.Write( p, m_wayfilelength );
			::GlobalUnlock( m_hway);
			fway.Close();
		}catch( CFileException* fe ){
			switch( fe->m_cause ){
			case CFileException::fileNotFound:
				::MessageBox( NULL, "没有找到文件\"MvoeWay.dat\",走法不能纪录.", fe->m_strFileName ,
					MB_OK | MB_ICONERROR );
				::ExitProcess( 1 );
			default:
				::MessageBox( NULL, "文件错误,走法不能纪录.", fe->m_strFileName ,
					MB_OK | MB_ICONERROR );
				::ExitProcess( 2 );
			}
		}
	}
	::GlobalFree( m_hmap );
	::GlobalFree( m_hway );
	DeleteAllPath();
	m_mapB.DeleteObject();
}

void BoxManClass::SetDrawWnd(CWnd *pWnd)
{
	m_pDrawWnd = pWnd;
	CClientDC dc(m_pDrawWnd);
	m_mapB.CreateCompatibleBitmap( &dc, MAXMAPSIZEX*m_size, MAXMAPSIZEY*m_size );
}

bool BoxManClass::ReadMap(unsigned int index)
{
//	if (index != m_nowmap ) m_BoxMoveOk = false;
	char* p = (char*)::GlobalLock( m_hmap );
	char str[256];
	bool ism = false;
	int i = 0;
	for( DWORD n = 0; n < m_MapFileLength; n++, p++ ){
		if ( ism ){
			if (*p != '\r') {
				str[i++] = *p;
			}else{
				str[i] = 0;
				unsigned int value = atoi(str);
				if (value == index ) {
					//find the map
					if ( index != m_nowmap ){
						_ThreadCommand = BM_COMMAND_STOP_THREAD;
						//never delete the {::Sleep(1);}
						for ( int tt=0; tt<100 && _ThreadMessage == BM_MESSAGE_THINKING ; tt++ ) ::Sleep(1);
						//while ( _ThreadMessage == BM_MESSAGE_THINKING ) ::Sleep(2);
					}
					m_nowmap = index;
					p+=2;
					char* tp = p;
					m_x = 0;
					while ( *tp != '\r' ){
						m_x++;
						tp++;
					}
					m_y = 1;
					tp+=2;
					while ( (*tp == '+')||(*tp == '-') ){
						m_y++;
						tp += ( 2 + m_x );
					}
					if ( m_x > MAXMAPSIZEX || m_y > MAXMAPSIZEY ) return false;
					m_NumberOfBox = 0;
					for( int y=0; y<m_y; y++ ){
						for ( int x =0; x<m_x; x++ ){
							m_map[x][y] = *p++;
							switch( m_map[x][y] ){
							case '@':
								m_map[x][y] = '.';
								m_bnm[x][y] = '#';
								m_NumberOfBox++;
								break;
							case '$':
								m_map[x][y] = '.';
								m_bnm[x][y] = '^';
								break;
							case '^':
								m_map[x][y] = ' ';
								m_bnm[x][y] = '^';
								break;
							case '#':
								m_map[x][y] = ' ';
								m_bnm[x][y] = '#';
								m_NumberOfBox++;
								break;
							default:
								m_bnm[x][y] = 0;
							}
						}
						p+=2;
					}
					::GlobalUnlock( m_hmap );

					if ( m_x < 10 ) m_mapsizex = 10;
					else m_mapsizex = m_x;
					if ( m_y < 8 ) m_mapsizey = 8;
					else m_mapsizey = m_y;

					DeleteAllPath();
					m_HaveOneWay = PrepareThinking(index);
					m_CanUndo = false;
					m_TheShowStep=0;
					//可以开始线程
					if( !m_computerthinkout )
						_ThreadCommand = BM_COMMAND_RUN_THREAD;
					//else
					//	_ThreadMessage = BM_MESSAGE_THINK_OUT;
					//////////
					return true;
				}
				i = 0;
				ism = false;
			}
		}else if ( *p == 'M' ) ism = true;
	}
	::GlobalUnlock( m_hmap );
	return false;
}

void BoxManClass::Paint()
{
	CClientDC dc(m_pDrawWnd);

	CDC mapDC;
	mapDC.CreateCompatibleDC( &dc );
	CBitmap* pOB = mapDC.SelectObject( &m_mapB );

//	dc.Ellipse(10,10,100,100);

	dc.BitBlt( 0, 0, m_size * m_mapsizex, m_size * m_mapsizey, &mapDC, 0, 0, SRCCOPY );

	mapDC.SelectObject( pOB );
}

void BoxManClass::DrawIt(char x, char y)
{
	if ( (x<0) || (x>=m_x) || (y<0) || (y>=m_y) ) return;

	char index;
	switch( m_map[x][y] ){
	case '+':
		index = WALLB;
		break;
	case '-':
		index = NULLB;
		break;
	case ' ':
		{
			switch( m_bnm[x][y] ){
			case 0:
				index = NULLWALLB;
				break;
			case '^':
				index = MANB;
				m_mx = x;
				m_my = y;
				break;
			case '#':
				index = BOXB;
			}
		}
		break;
	case '*':
		{
			switch( m_bnm[x][y] ){
			case 0:
				index = NULLWALLB;
				break;
			case '^':
				index = MANB;
				m_mx = x;
				m_my = y;
				break;
			case '#':
				index = BOXB;
			}
		}
		break;
	case '.':
		{
			switch( m_bnm[x][y] ){
			case 0:
				index = POINTB;
				break;
			case '^':
				index = MANATPOINTB;
				m_mx = x;
				m_my = y;
				break;
			case '#':
				index = BOXATPOINTB;
			}
		}
		break;
	}
	
	x += (m_mapsizex - m_x)/2;
	y += (m_mapsizey - m_y)/2;
	
	CClientDC dc(m_pDrawWnd);
	//there must use CClientDC, can't use CPaintDC.
	//but I don't know why?
	CBitmap tB;
	tB.LoadBitmap( IDB_MAP );
	CDC	tDC;
	tDC.CreateCompatibleDC( &dc );
	tDC.SelectObject( &tB );
	dc.BitBlt( x*m_size, y*m_size, m_size, m_size, &tDC, index*m_size, 0, SRCCOPY );

	CDC mapDC;
	mapDC.CreateCompatibleDC( &dc );
	CBitmap* pOB = mapDC.SelectObject( &m_mapB );
	mapDC.BitBlt( x*m_size, y*m_size, m_size, m_size, &tDC, index*m_size, 0, SRCCOPY );
	mapDC.SelectObject( pOB );
}

void BoxManClass::DrawAllMap()
{
	//TRACE("ASDFGHJKL;\n");
	if (m_mapsizex>m_x || m_mapsizey>m_y){
		CClientDC dc(m_pDrawWnd);

		CBitmap tB;
		tB.LoadBitmap( IDB_MAP );
		
		CDC	tDC;
		tDC.CreateCompatibleDC( &dc );
		tDC.SelectObject( &tB );
		
		CDC mapDC;
		mapDC.CreateCompatibleDC( &dc );
		CBitmap* pOB = mapDC.SelectObject( &m_mapB );
		for( char y = 0; y<m_mapsizey; y++ ) for( char x = 0; x<m_mapsizex; x++ ){
			dc.BitBlt( x*m_size, y*m_size, m_size, m_size, &tDC, NULLB*m_size, 0, SRCCOPY );
			mapDC.BitBlt( x*m_size, y*m_size, m_size, m_size, &tDC, NULLB*m_size, 0, SRCCOPY );
		}
		mapDC.SelectObject( pOB );
	}
	for(char yy = 0; yy<m_y; yy++ ) for(char x = 0; x<m_x; x++ ) DrawIt( x, yy );
}

unsigned char BoxManClass::MoveTowards(char x, char y)
{
	unsigned char result=BM_ERROR_CANNOT_MOVE_THERE;
	if ( x==0 && y==0) return result;
	char tx = m_mx + x;
	char ty = m_my + y;
	char ttx = tx + x;
	char tty = ty + y;

	if ( m_map[tx][ty] != '+' ){
		switch ( m_bnm[tx][ty] ){
		case 0:
			result=BM_MAN_MOVED;
			break;
		case '#':
			if ( (m_map[ttx][tty] !='+') && (m_bnm[ttx][tty] != '#') ){
				if (m_CanMoveToBadPoint)
					result=BM_BOX_MOVED;
				else if (m_map[ttx][tty] !='*')
					result=BM_BOX_MOVED;
				else result=BM_MOVED_TO_BAD_POINT;
			}
		}
	}
	if ( (result==BM_MAN_MOVED) || (result==BM_BOX_MOVED) ){
		m_bnm[m_mx][m_my] = 0;
		DrawIt( m_mx , m_my );
		m_bnm[tx][ty] = '^';
		DrawIt( tx , ty );
		m_mx = tx;
		m_my = ty;
		if (result==BM_BOX_MOVED){
			m_bnm[ttx][tty] = '#';
			DrawIt( ttx , tty );
			AddMapToPath( tx-x, ty-y, tx, ty );
		}
	}
	
	for(int j=0; j<m_y; j++ )for( int i=0; i<m_x; i++ )
		if( (m_map[i][j] == '.') && (m_bnm[i][j] != '#') ) return result;
	BoxMoveOk(m_path);
	return BM_MOVED_OK;
}

void BoxManClass::BoxMoveOk(CPtrArray &record)
{
	// the map moved ok
	unsigned int boxmn = record.GetSize();
	char tc1='[';
	char tc2=']';
	if( &record == &m_path ){ tc1='{'; tc2='}'; }
	
	//可以停止线程
	//_ThreadCommand = BM_COMMAND_STOP_THREAD;
	//////////
	char c[80];
	wsprintf( c, "%d", m_nowmap );
	CString str( c );
	if ( m_noanswerrecoded ) {
		//在MoveWay.dat的最后纪录走法
		m_wayfilechanged = true;
		::GlobalReAlloc( m_hway, m_wayfilelength + 7 + str.GetLength() + boxmn*4 , GHND );
		char* p = (char*)::GlobalLock( m_hway );
		p+=m_wayfilelength;
		m_wayfilelength += 7 + str.GetLength() + boxmn*4;
		*p++ = 'M';
		for ( char stri=0; stri<str.GetLength() ; stri++ )
			*p++ = str.GetAt( stri );
		*p++ = '\r';
		*p++ = '\n';
		*p++ = tc1;
		for ( unsigned int t=0; t<boxmn; t++){
			PathStruct *ps = (PathStruct*)record.GetAt(t);
			*p++ = ps->manx;
			*p++ = ps->many;
			*p++ = ps->boxx;
			*p++ = ps->boxy;
		}
		*p++ = tc2;
		*p++ = '\r';
		*p = '\n';
		::GlobalUnlock( m_hway );
		m_boxmovestepnumber=boxmn;
	}else if ( !m_computerthinkout && ( boxmn<m_boxmovestepnumber || tc1=='[' ) ){
		//改变已有的纪录,将其放在最后
		m_wayfilechanged = true;
		char* p = (char*)::GlobalLock( m_hway );
		char* MoveBufferEnd = p+m_wayfilelength;
		p+=m_TheMapsMoveWaySavePoint;
		int delta = 7 + str.GetLength() + m_boxmovestepnumber*4;
		for ( char* tp=p+delta; tp < MoveBufferEnd; tp++, p++ ) *p=*tp;
		*p++ = 'M';
		for ( char stri=0; stri<str.GetLength() ; stri++ )
			*p++ = str.GetAt( stri );
		*p++ = '\r';
		*p++ = '\n';
		*p++ = tc1;
		for ( unsigned int t=0; t<boxmn; t++){
			PathStruct *ps = (PathStruct*)record.GetAt(t);
			*p++ = ps->manx;
			*p++ = ps->many;
			*p++ = ps->boxx;
			*p++ = ps->boxy;
		}
		*p++ = tc2;
		*p++ = '\r';
		*p = '\n';
		::GlobalUnlock( m_hway );
		//一定是减小内存
		::GlobalReAlloc( m_hway, m_wayfilelength - (m_boxmovestepnumber-boxmn)*4, GHND );
		m_wayfilelength-=(m_boxmovestepnumber-boxmn)*4;//::GlobalSize( m_hway );
		m_boxmovestepnumber=boxmn;
	}
}

void BoxManClass::AddMapToPath(char manx, char many, char boxx, char boxy)
{
	PathStruct *p = new PathStruct;
	p->manx = manx;
	p->many = many;
	p->boxx = boxx;
	p->boxy = boxy;
	m_path.Add( p );
	m_CanUndo = true;
}

void BoxManClass::DeleteAllPath()
{
	int n = m_path.GetSize();
	for( int i=0; i<n; i++ ){
		PathStruct *p = (PathStruct*)m_path.GetAt( i );
		delete p;
	}
	m_path.RemoveAll();
}

bool BoxManClass::Undo()
{
	if ( !m_CanUndo ) return false;
	int n = m_path.GetSize();
	PathStruct *p = (PathStruct*)m_path.GetAt( n-1 );
	m_path.RemoveAt( n-1 );
	if (n==1) m_CanUndo = false;

	m_bnm[m_mx][m_my] = 0;
	m_bnm[p->boxx][p->boxy] = '#';
	m_bnm[p->manx][p->many] = '^';
	char tx = 2 * p->boxx - p->manx;
	char ty = 2 * p->boxy - p->many;
	m_bnm[tx][ty] = 0;

	DrawIt( m_mx, m_my );
	DrawIt( p->boxx, p->boxy );
	DrawIt( p->manx, p->many );
	DrawIt( tx, ty );
	
	m_mx = p->manx;
	m_my = p->many;
	return true;
}

char BoxManClass::PointAt(CPoint point)
{
	int tx = ( m_mapsizex - m_x )/ 2;
	int ty = ( m_mapsizey - m_y )/ 2;
	if ( ( point.x > (tx + m_x)*m_size ) || ( point.x < tx*m_size ) || ( point.y > (ty + m_y)*m_size ) || ( point.y < ty*m_size ) )
		return BM_ERROR_PIONT_OUT;
	int tox =( point.x - tx * m_size )/ m_size;
	int toy =( point.y - ty * m_size )/ m_size;
	if ( m_bnm[tox][toy] == '^' )
		return BM_ERROR_POINT_MAN;
	if ( m_map[tox][toy] == '+' )
		return BM_ERROR_POINT_WALL;
	if ( m_map[tox][toy] == '-' )
		return BM_ERROR_PIONT_OUT;
	m_pmanmoveway = MoveManTo( tox, toy );
	if ( m_pmanmoveway != NULL )
		return DoManMove();
	return BM_ERROR_CANNOT_MOVE_THERE;
}

CPtrArray* BoxManClass::MoveManTo(char x, char y)

⌨️ 快捷键说明

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