📄 boxmanclass.cpp
字号:
// 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 + -