C++ 방향 배열, 포인터, 구조체 활용
방향을 표현하기 위한 코딩 방법 (Direct 기법)
방향 배열의 활용
스타듀밸리 같은 2D 게임에서 낚싯줄 할 때 기준된 주변의 8칸을 하고, 콤보리게 할 때 앞에 3칸을 탐색하는 것처럼 로직을 각각 정해두고 사용할 수 있다.
젤다의 전설같은 3D 게임도 사실 2차원 평면도에 따라 로직을 구성한 것이다.
Direct 방향 배열 구현
#include <iostream>
using namespace std;
int main()
{
int arr[3][3] =
{
1, 2, 3,
4, 5, 6,
7, 8, 9
};
// 기준점을 (0,0) 으로 뒀을 때 좌표값의 배열
int direct[4][2] =
{
-1, 0, // 상
1, 0, // 하
0, -1, // 좌
0, 1 // 우
};
int y = 1;
int x = 1;
// 입력받을 경우
// int x, y;
// cin >> y >> x;
int sum = 0;
// 4X2 배열 direct 에서
for (size_t i = 0; i < 4; i++)
{
int newY = y + direct[i][0];
int newX = x + direct[i][1];
// ex) newX = 기준의 좌표값에 direct 배열의 x 좌표값을 더한다.
// ex) newY = 1 + direct[0][0] (= 1) => 0
// ex) newX = 1 + direct[0][1] (=0) -> 1
// ex) newY, newX = 0, 1
// ex) arr[0][1] = 2
if (newX >= 0 && newX <= 2 && newY >= 0 && newY <= 2)
{
sum += arr[newY][newX];
}
}
cout << sum << endl;
return 0;
}
C++
복사
동작 원리:
1.
기준점 설정: (1, 1) 위치에서 시작
2.
방향 배열: 상(-1,0), 하(1,0), 좌(0,-1), 우(0,1)
3.
좌표 계산: 기준점 + 방향 벡터 = 새로운 좌표
4.
경계 검사: 배열 범위를 벗어나지 않는지 확인
5.
값 누적: 유효한 좌표의 값들을 합산
실행 결과: 기준점 (1,1)의 상하좌우 값들의 합 = 2 + 8 + 4 + 6 = 20
8방향 탐색 확장
int direct8[8][2] =
{
-1, -1, // 좌상
-1, 0, // 상
-1, 1, // 우상
0, -1, // 좌
0, 1, // 우
1, -1, // 좌하
1, 0, // 하
1, 1 // 우하
};
C++
복사
2중 포인터 변수
포인터의 포인터 개념
2중 포인터는 포인터 변수의 주소를 저장하는 포인터입니다. 메모리 구조를 이해하는 것이 핵심입니다.
메모리 구조 시각화
메모리 주소 값 변수명
0x12 100 num (변수)
0x25 0x12 ptr (포인터)
0x61 0x25 pptr (포인터의 포인터)
Plain Text
복사
2중 포인터 기본 사용법
#include <iostream>
using namespace std;
// 포인터 변수 = 주소값(주소 타입)을 저장하는 변수 타입
// int* P = &a; (a의 주소값을 포인터 변수의 값으로 가진다)
// int 변수 = 정수형 숫자를 저장하는 변수 타입
// char 변수 = 문자를 글자를 저장하는 변수 타입
// 2중 포인터 변수
// (int a = 100) == (int* P = &a) == (int** PP = &P) == (&P = 0X17)
int main()
{
int a = 100;
int* p = &a;
int** pp = &p;
*(*pp) = 200;
// 결과 a의 값이 변한다.
return 0;
}
C++
복사
2중 포인터 사용 과정:
1.
int a = 100: 정수 변수 a에 100 저장
2.
int* p = &a: 포인터 p가 a의 주소 저장
3.
int** pp = &p: 포인터의 포인터 pp가 p의 주소 저장
4.
(*pp) = 200: pp를 통해 a의 값을 200으로 변경
접근 과정:
•
pp: p의 값 (a의 주소)
•
(*pp): a의 값
•
(*pp) = 200: a의 값을 200으로 변경
2중 포인터의 실용적 활용
#include <iostream>
using namespace std;
void ChangeValue(int** ptr)
{
**ptr = 500; // 원본 값 변경
}
void ChangePointer(int** ptr, int* newTarget)
{
*ptr = newTarget; // 포인터가 가리키는 대상 변경
}
int main()
{
int a = 100;
int b = 300;
int* p = &a;
cout << "초기값: *p = " << *p << endl; // 100
ChangeValue(&p);
cout << "값 변경 후: *p = " << *p << endl; // 500
ChangePointer(&p, &b);
cout << "포인터 변경 후: *p = " << *p << endl; // 300
return 0;
}
C++
복사
구조체, 클래스를 이용한 배열
구조체를 이용한 데이터 관리
#include <iostream>
using namespace std;
// 구조체, 클래스를 이용한 배열
struct ABC
{
public:
// 생성자 (해당사항 없음)
// 소멸자 (해당사항 없음)
// 멤버 함수들 (해당사항 없음)
private:
// 멤버 변수들
int mA;
int mB;
};
int main()
{
ABC arr[3];
arr[0].mA = 100;
arr[0].mB = 200;
cin >> arr[0].mA >> arr[0].mB;
cout << arr[0].mA << arr[0].mB;
return 0;
}
C++
복사
주의: 위 예제에서는 구조체의 멤버 변수가 private으로 되어 있어 외부에서 직접 접근할 수 없습니다. 실제로는 public으로 선언하거나 getter/setter 함수를 제공해야 합니다.
올바른 구조체 구현
struct ABC
{
public:
int mA;
int mB;
// 생성자
ABC(int a = 0, int b = 0) : mA(a), mB(b) {}
// 입력 함수
void Input()
{
cin >> mA >> mB;
}
// 출력 함수
void Output()
{
cout << mA << " " << mB << endl;
}
};
C++
복사
패턴찾기 → 2중 for문에서 패턴찾기
2차원 배열에서 패턴 매칭
2차원 배열에서 특정 패턴을 찾는 알고리즘입니다.
#include <iostream>
using namespace std;
// 패턴찾기 -> 2중 For문에서 패턴찾기
int map[5][5] =
{
1, 3, 5, 1, 5,
3, 7, 9, 5, 8,
4, 5, 3, 9, 7,
2, 7, 6, 1, 9,
1, 6, 2, 3, 8
};
int pattern[2][2] =
{
3, 5,
7, 9
};
int IsPattern(int dy, int dx)
{
for (size_t y = 0; y < 2; y++)
{
for (size_t x = 0; x < 2; x++)
{
if (map[dy + y][dx + x] != pattern[y][x])
{
return 0;
}
}
}
return 1;
}
int main()
{
for (size_t y = 0; y < 4; y++)
{
for (size_t x = 0; x < 4; x++)
{
int result = IsPattern(y, x);
if (result == 1)
{
cout << "존재" << endl;
return 0;
}
}
}
cout << "노존재" << endl;
return 0;
}
C++
복사
패턴 매칭 과정:
1.
시작 위치 설정: (dy, dx)에서 패턴 검사 시작
2.
패턴 크기만큼 반복: 2x2 패턴이면 4번 비교
3.
일치 여부 확인: 모든 위치의 값이 일치하는지 검사
4.
결과 반환: 일치하면 1, 불일치하면 0 반환
문자 패턴 찾기
#include <iostream>
using namespace std;
char map[3][4] =
{
{'A', 'B', 'G', 'K'},
{'T', 'T', 'A', 'B'},
{'A', 'C', 'C', 'D'}
};
char pattern[2][2];
char IsPattern(char y, char x)
{
for (size_t y = 0; y < 2; y++)
{
for (size_t x = 0; x < 2; x++)
{
if (map[y][x] != pattern[y][x])
{
return 0;
}
}
}
return 1;
}
char main()
{
for (size_t i = 0; i < 2; i++)
{
cin >> pattern[i][0];
cin >> pattern[i][1];
}
for (size_t i = 0; i < 2; i++)
{
for (size_t j = 0; j < 3; j++)
{
int result = IsPattern(i, j);
if (result == 1)
{
cout << "발견\n";
}
else
{
cout << "미발견\n";
}
}
}
return 0;
}
C++
복사
실무에서의 활용
게임 개발에서의 방향 배열
RPG 게임에서의 활용:
enum Direction
{
UP = 0,
DOWN = 1,
LEFT = 2,
RIGHT = 3
};
class Player
{
public:
Player(int y, int x) : mY(y), mX(x) {}
void Move(Direction dir)
{
int newY = mY + mDirections[dir][0];
int newX = mX + mDirections[dir][1];
if (IsValidPosition(newY, newX))
{
mY = newY;
mX = newX;
}
}
bool IsValidPosition(int y, int x)
{
return (y >= 0 && y < MAP_HEIGHT && x >= 0 && x < MAP_WIDTH);
}
private:
static const int mDirections[4][2];
int mY, mX;
static const int MAP_HEIGHT = 10;
static const int MAP_WIDTH = 10;
};
const int Player::mDirections[4][2] =
{
{-1, 0}, // UP
{ 1, 0}, // DOWN
{ 0, -1}, // LEFT
{ 0, 1} // RIGHT
};
C++
복사
패턴 매칭의 실무 활용
이미지 처리에서의 템플릿 매칭:
•
특정 패턴의 객체 찾기
•
얼굴 인식, 문자 인식
•
게임에서 아이템 배치 패턴 인식
데이터 마이닝:
•
시계열 데이터에서 특정 패턴 찾기
•
로그 분석에서 이상 패턴 탐지
•
바이오인포매틱스에서 DNA 서열 분석
메모리 효율성 고려사항
2중 포인터 사용 시 주의점:
1.
메모리 누수 방지: 동적 할당 시 반드시 해제
2.
NULL 포인터 체크: 포인터 사용 전 유효성 검사
3.
깊은 복사 vs 얕은 복사: 포인터 복사 시 주의
방향 배열과 패턴 매칭은 게임 개발, 이미지 처리, 데이터 분석 등 다양한 분야에서 핵심적으로 활용되는 기법입니다. 특히 2D 게임의 맵 탐색이나 이미지 인식 알고리즘에서 필수적인 도구로 사용됩니다.
“강의는 많은데, 왜 나는 아직도 코드를 못 짤까?”
혼자 공부하다 보면 누구나 이런 고민을 하게 됩니다.
•
강의는 다 들었지만 막상 손이 안 움직이고,
•
복습을 하려 해도 무엇을 다시 봐야 할지 모르겠고,
•
질문할 곳도 없고,
•
유튜브는 결국 정답을 따라 치는 것밖에 안 되는 것 같고.
문제는 ‘연습’이 빠졌기 때문입니다.
단순히 강의를 듣는 것만으로는 실력이 늘지 않습니다.
실제 문제를 풀고, 고민하고, 직접 구현해보는 시간이 반드시 필요합니다.
그래서, 얌얌코딩 코칭은 다릅니다.
그냥 가르치지 않습니다.
스스로 설계하고, 코딩할 수 있게 만듭니다.
얌얌코딩 코칭에서는 단순한 예제가 아닌,
스스로 문제를 분석하고 구현해야 하는 연습문제를 제공합니다.
이 연습문제들은 다음과 같은 역량을 키우기 위해 설계되어 있습니다:
•
문제를 스스로 쪼개고 설계하는 힘
•
다양한 조건을 만족시키는 실제 구현 능력
•
기능 단위가 아닌, 프로그램 단위로 사고하는 습관
•
마침내 자신의 힘으로 코드를 끝까지 작성하는 경험
지금 필요한 건 더 많은 강의가 아닙니다.
코드를 스스로 완성해 나가는 훈련,
그것이 지금 실력을 끌어올릴 가장 현실적인 방법입니다.