달팽이 배열?
-----------------------------------------------------------------------------------------------
위 링크의 코드는 1년 10개월전 쯤 작성 했던 코드.
그때 뭐 대충 작성하긴 했지만.
오늘 할게없어서..(휴가중)
이전 코드를 찾아 리팩토링 해봤다.
하면서 기능 추가도 했고.
이제 객체로서의 볼품을 갖춘 모습.
(대학 과제로 자주 나오나보다 --)
-----------------------------------------------------------------------------------------------
#include <stdio.h>
#include <map>
#include <assert.h>
class IDrawableObject
{
public:
virtual void Draw() = 0;
}
// 이 클래스 자체는 자료구조 목적의 기능만을 가져야 한다.
// 하지만 예제 이해의 접근성을 위해 따로 데이터를 가지고 랜더링하는 오브젝트를 만들지는 않았다.
class CSnailArray : public IDrawableObject
{
private:
typedef int Direction;
typedef int Increase;
typedef std::map<Direction, Increase> IncreaseByDirection;
private :
static int const FirstDirection = 0;
static int const DirCount = 4;
Direction m_dirRight;
Direction m_dirDown;
Direction m_dirLeft;
Direction m_dirUp;
int m_nSize;
int * m_pArr;
IncreaseByDirection m_mIncreaseByDirection;
public :
CSnailArray();
CSnailArray( int nSize );
virtual ~CSnailArray( );
void SetReverse(bool bReverse);
bool IsReverse(); // default false
bool GenerateSnailArray(int nSize);
void Release();
bool GetValue(int& outBuffer, int _1DimensionIndex, int _2DimensionIndex);
int const * GetArray();
// 이 클래스는 기본으로 콘솔에 출력 한다.
virtual void Draw();
private:
void SetSize(int nSize);
int GetSize();
bool IsFirstDirection(Direction dir);
Direction GetFirstDir();
Direction GetNextDirection(Direction curDir);
// 달팽이 배열이 진행될 순서를 정한다
void SetDirectionFlow(int nRight, int nDown, int nLeft, int nUp);
void InitializeList();
void GenIncreasement();
void GenArray();
void CreateArray();
void ReleaseArray();
Increase GetIncreaseOffsetCount(Direction dir);
void DrawToArray(Direction startDir);
void DrawToArray(int& nCurOffset, int&nCurValue, Direction dir, int nDrawCount);
void PrintToConsole( );
};
CSnailArray::CSnailArray()
{
InitializeList();
}
CSnailArray::CSnailArray( int nSize )
{
InitializeList();
SetSize(nSize);
GenerateSnailArray(nSize);
}
CSnailArray::~CSnailArray( )
{
ReleaseArray();
}
void CSnailArray::InitializeList()
{
m_nSize = 0;
m_pArr = NULL;
// 정방향 셋팅
SetReverse(false);
}
void CSnailArray::SetDirectionFlow(int nRight, int nDown, int nLeft, int nUp)
{
m_dirRight = nRight;
m_dirDown = nDown;
m_dirLeft = nLeft;
m_dirUp = nUp;
}
CSnailArray::Direction CSnailArray::GetFirstDir()
{
if( IsFirstDirection(m_dirRight) ) return m_dirRight;
if( IsFirstDirection(m_dirDown) ) return m_dirDown;
if( IsFirstDirection(m_dirLeft) ) return m_dirLeft;
if( IsFirstDirection(m_dirUp) ) return m_dirUp;
assert( 0 && "First Dir이 존재하지 않음" );
return (Direction)-1;
}
bool CSnailArray::IsFirstDirection(Direction dir)
{
return dir == FirstDirection;
}
void CSnailArray::SetReverse(bool bReverse)
{
int nRightIndex = bReverse ? 1 : 0;
int nDownIndex = bReverse ? 0 : 1;
int nLeftIndex = bReverse ? 3 : 2;
int nUpIndex = bReverse ? 2 : 3;
SetDirectionFlow(nRightIndex, nDownIndex, nLeftIndex, nUpIndex);
}
bool CSnailArray::IsReverse()
{
// Down방향이 첫번째 방향이면 리버스
return IsFirstDirection(m_dirDown);
}
void CSnailArray::CreateArray( )
{
ReleaseArray( );
m_pArr = new int[m_nSize*m_nSize];
int i = 0;
while( i < m_nSize*m_nSize ) m_pArr[i++] = 0;
}
void CSnailArray::ReleaseArray( )
{
// SAFE_DELETE_ARR(m_pArr);
if( m_pArr )
{
delete [] m_pArr;
m_pArr = NULL;
}
}
void CSnailArray::GenArray( )
{
CreateArray( );
}
void CSnailArray::GenIncreasement()
{
m_mIncreaseByDirection.clear();
m_mIncreaseByDirection[m_dirRight] = 1; // Right방향은 오른쪽으로 한칸 이동
m_mIncreaseByDirection[m_dirDown] = m_nSize; // Down방향은 사이즈만큼 앞으로 이동
m_mIncreaseByDirection[m_dirLeft] = -1; // Left방향은 왼쪽으로 한칸 이동
m_mIncreaseByDirection[m_dirUp] = -m_nSize; // Up방향은 사이즈만큼 뒤로 이동
}
void CSnailArray::SetSize(int nSize)
{
m_nSize = nSize;
GenIncreasement();
}
int CSnailArray::GetSize()
{
return m_nSize;
}
bool CSnailArray::GenerateSnailArray(int nSize)
{
SetSize(nSize);
GenArray( );
Direction direction = GetFirstDir();
if( direction == -1 ) return false;
DrawToArray(direction);
return true;
}
void CSnailArray::DrawToArray(Direction startDir)
{
int nDrawCount = m_nSize;// 최대사이즈
int nDrawCountLifeCycle = 1;// 최대사이즈는 한번만 긋는다
// 처음 오프셋 증가값을 대입하기전에 대입시 0이 되게 -값 대입 == Offset 0부터 시작되게 하는 처리
int nOffset = -m_mIncreaseByDirection[startDir];
Direction curDirection = startDir;
int nValue = 1;
while( nValue <= (m_nSize * m_nSize) )
{
if( nDrawCountLifeCycle == 0 )
{
--nDrawCount;
nDrawCountLifeCycle = 2;
}
DrawToArray(nOffset, nValue, curDirection, nDrawCount);
--nDrawCountLifeCycle;
curDirection = GetNextDirection(curDirection);
}
}
// nCurOffset부터 nCurValue를 dir방향으로 nDrawCount만큼 씀
void CSnailArray::DrawToArray(int& nCurOffset, int&nCurValue, Direction dir, int nDrawCount)
{
for( int iCount = 0; iCount < nDrawCount; ++nCurValue, ++iCount )
{
nCurOffset += GetIncreaseOffsetCount(dir);
m_pArr[nCurOffset] = nCurValue;
}
}
CSnailArray::Increase CSnailArray::GetIncreaseOffsetCount(Direction dir)
{
return m_mIncreaseByDirection[dir];
}
CSnailArray::Direction CSnailArray::GetNextDirection(Direction curDir)
{
Direction dirNextValue = curDir + 1;
Direction dirDispatchedNextValue = dirNextValue % DirCount;
return dirDispatchedNextValue;
}
void CSnailArray::Release()
{
m_nSize = 0;
ReleaseArray();
}
bool CSnailArray::GetValue(int& outBuffer, int _1DimensionIndex, int _2DimensionIndex)
{
if( _1DimensionIndex < 0 || _1DimensionIndex >= m_nSize ) return false;
if( _2DimensionIndex < 0 || _2DimensionIndex >= m_nSize ) return false;
int nIndex = (_2DimensionIndex*m_nSize + _1DimensionIndex);
outBuffer = *(m_pArr + nIndex);
return true;
}
int const * CSnailArray::GetArray()
{
return m_pArr;
}
void CSnailArray::Draw()
{
PrintToConsole();
}
void CSnailArray::PrintToConsole( )
{
printf( "\n" );
int i = 0;
while( i < m_nSize * m_nSize )
{
printf( "%3d ", m_pArr[i] );
if( (( i+1 ) % m_nSize) == 0 )
printf( "\n" );
++i;
}
}
void main()
{
CSnailArray kSnArr(10);
kSnArr.Draw();
kSnArr.Release();
// reverse snail
kSnArr.SetReverse(true);
kSnArr.GenerateSnailArray(5);
kSnArr.Draw();
// kSnArr.Release();
int nPickVal = -1;
if( kSnArr.GetValue(nPickVal, 4, 3) )
printf("\narray[4,3] == %d\n", nPickVal);
else
printf("\n[CSnailArray::GetValue] 유효하지 않은 범위의 인덱스로 참조 시도\n");
kSnArr.Release();
}
-----------------------------------------------------------------------------------------------
결과
__1 __2 __3 __4 __5 __6 __7 __8 __9 _10
_36 _37 _38 _39 _40 _41 _42 _43 _44 _11
_35 _64 _65 _66 _67 _68 _69 _70 _45 _12
_34 _63 _84 _85 _86 _87 _88 _71 _46 _13
_33 _62 _83 _96 _97 _98 _89 _72 _47 _14
_32 _61 _82 _95 100 _99 _90 _73 _48 _15
_31 _60 _81 _94 _93 _92 _91 _74 _49 _16
_30 _59 _80 _79 _78 _77 _76 _75 _50 _17
_29 _58 _57 _56 _55 _54 _53 _52 _51 _18
_28 _27 _26 _25 _24 _23 _22 _21 _20 _19
__1 _16 _15 _14 _13
__2 _17 _24 _23 _12
__3 _18 _25 _22 _11
__4 _19 _20 _21 _10
__5 __6 __7 __8 __9
array[4,3] == 10
-----------------------------------------------------------------------------------------------
놀자!

덧글