[TIL] 23-12-22

Lev·2023년 12월 22일
0

📓TIL Archive

목록 보기
10/33

배열

2차원 배열

실제로 램은 1차원 메모리이기 때문에 램 상에 2차원으로 존재하는 것은 아니고, 문법일 뿐이다.

#include <iostream>

int main()
{
	char Arr[3][4] = { {'0', '1', '2'}, {'3', '4', '5'}, {'6', '7', '8'} };
	// char Arr[3][4] = { "123", "345", "678" };
	
	// [[0][0]] [[0][1]] [[0][2]] [[0][3]]
	// [[1][0]] [[1][1]] [[1][2]] [[1][3]]
	// [[2][0]] [[2][1]] [[2][2]] [[2][3]]
	
	// '0' '1' '2' 0
	// '3' '4' '5' 0
	// '6' '7' '8' 0

	__int64 Address = reinterpret_cast<__int64>(&Arr);	// 100번지(라고 한다면)
	__int64 Address0 = reinterpret_cast<__int64>(&Arr[0][0]);	// 100번지
	__int64 Address1 = reinterpret_cast<__int64>(&Arr[0][1]);	// 101번지
	__int64 Address2 = reinterpret_cast<__int64>(&Arr[0][2]);	// 102번지
	__int64 Address3 = reinterpret_cast<__int64>(&Arr[0][3]);	// 103번지
	__int64 Address4 = reinterpret_cast<__int64>(&Arr[1][0]);	// 104번지
	__int64 Address5 = reinterpret_cast<__int64>(&Arr[1][1]);	// 105번지
	__int64 Address6 = reinterpret_cast<__int64>(&Arr[1][2]);	// 106번지
	__int64 Address7 = reinterpret_cast<__int64>(&Arr[1][3]);	// 107번지
	__int64 Address8 = reinterpret_cast<__int64>(&Arr[2][0]);	// 108번지
	// .....

	
	// Arr			char[3][4]형
	// [00] [01] [02] [03]
	// [10] [11] [12] [13]
	// [20] [21] [22] [23]
	
	// Arr[0]		char[4]형
	// ['0'] ['1'] ['2'] [0] = "012" => Arr[0]
	// ['3'] ['4'] ['5'] [0] = "345" => Arr[1]
	// ['6'] ['7'] ['8'] [0] = "678" => Arr[2]
	
	// Arr[0][0]	char형

	int IntArr[10];
	int* Ptr = IntArr;

	char* Ptr0 = Arr[0];
	char* Ptr1 = Arr[1];
	char* Ptr2 = Arr[2];

	printf_s(Ptr0);
	printf_s(Ptr1);
	printf_s(Ptr2);
}
#include <iostream>

int main()
{
	{
		int Var = 10;
		Arr[10][Var];	// 불가능!
		// 한번 컴파일이 되고 나면, 함수의 실행 메모리는 고정되어 있어야 한다
		// exe에 함수가 사용할 메모리의 크기가 적혀 있으므로 절대로 바뀔 수 없다
		// 그래서 변수는 배열의 크기를 지정하는 데에 사용할 수 없다
	}
	{
		const int ScreenX = 6;
		const int ScreenY = 5;

		char Arr[ScreenY][ScreenX] = {0, };	// 가능
		// char Arr[5][6];
		// 변할 가능성이 없다고 판단해 컴파일러가 상수로 대체해버린다

		for (int y = 0; y < ScreenY; y++)
		{
			for (int x = 0; x < ScreenX - 1; x++)
			{
				Arr[y][x] = '*';
			}
		}
		// ['*'] ['*'] ['*'] ['*'] ['*'] [0]
		// ['*'] ['*'] ['*'] ['*'] ['*'] [0]
		// ['*'] ['*'] ['*'] ['*'] ['*'] [0]
		// ['*'] ['*'] ['*'] ['*'] ['*'] [0]
		// ['*'] ['*'] ['*'] ['*'] ['*'] [0]

		for (int y = 0; y < ScreenY; y++)
		{
			char* Ptr = Arr[y];
			printf_s(Ptr);
			printf_s("\n");
		}
		// *****
		// *****
		// *****
		// *****
		// *****
	}
}

Console Game

/*
<과제1 : 상하좌우 조작 만들기>
<과제2 : 화면 외곽을 벽으로 만들기>
<과제3 : 플레이어가 특정 키를 누르면 화면에 총알이 나타나도록 만들기>
*/

#include <iostream>
#include <conio.h>

class int2
{
	// 보통 수학 관련 클래스는 멤버변수를 public으로 둔다
	// 일반적인 수학 함수처럼 접근을 용이하게 하기 위해
public:
	int X = 0;
	int Y = 0;
};

typedef int2 Pos;	// 권장하진... 않음...

// 전역변수는 영역과 관련없이, 위에 있다면 사용 가능하다
const int ScreenX = 21;
const int ScreenY = 10;
const int ScreenXHalf = ScreenX / 2;
const int ScreenYHalf = ScreenY / 2;

class ConsoleScreen
{
public:
	ConsoleScreen(char _BaseChar)
	{
		BaseCh = _BaseChar;
	}
	// 이미 특정 형태로 생성자를 만들었기 때문에
	// ConsoleScreen() 이 디폴트 생성자가 자동으로 생기지 않는다

	void PrintScreen()
	{
		for (int y = 0; y < ScreenY; y++)
		{
			char* Ptr = Arr[y];
			printf_s(Ptr);
			printf_s("\n");
		}
	}

	void ClearScreen()
	{
		system("cls");

		for (int y = 0; y < ScreenY; y++)	// (2)
		{
			Arr[y][0] = '#';
			Arr[y][ScreenX - 2] = '#';
		}

		for (int x = 0; x < ScreenX - 1; x++)	// (2)
		{
			Arr[0][x] = '#';
			Arr[ScreenY - 1][x] = '#';
		}

		for (int y = 1; y < ScreenY - 1; y++)
		{
			for (int x = 1; x < ScreenX - 2; x++)
			{
				Arr[y][x] = BaseCh;
			}
		}
	}

	void SetPixel(const int2& _Position, char _Char)
	{
		SetPixel(_Position.X, _Position.Y, _Char);
	}

	void SetPixel(int _X, int _Y, char _Char)
	{
		Arr[_Y][_X] = _Char;
	}

protected:

private:
	char Arr[ScreenY][ScreenX] = { 0, };
	char BaseCh = ' ';
};

class Player
{
public:
	Player()
	{

	}

	Player(const int2& _StartPos, char _RenderChar)
		: Pos(_StartPos), RenderChar(_RenderChar)
	{

	}
	
	inline int2 GetPos()	// inline(치환)에 성공하면 조금 더 빨라질 것
	{
		return Pos;
	}

	inline char GetRenderChar()	// inline(치환)에 성공하면 조금 더 빨라질 것
	{
		return RenderChar;
	}

	inline bool GetIsFire()	// (3)
	{
		return IsFire;
	}

	void CheckPos()	// (2)
	{
		if (Pos.X < 1)
		{
			Pos.X = 1;
		}
		else if (Pos.X > ScreenX - 3)
		{
			Pos.X = ScreenX - 3;
		}
		else if (Pos.Y < 1)
		{
			Pos.Y = 1;
		}
		else if (Pos.Y > ScreenY - 2)
		{
			Pos.Y = ScreenY - 2;
		}
	}

	void Update()
	{
		int dir = _getch();	// 리턴값은 꼭 받아서 확인해보자!


		switch (dir)	// (1)
		{
			// case를 두개씩 겹처서 만들 수 있다!
		case'a':
		case'A':
		{
			Pos.X -= 1;
			break;
		}
		case'd':
		case'D':
		{
			Pos.X += 1;
			break;
		}
		case'w':
		case'W':
		{
			Pos.Y -= 1;
			break;
		}
		case's':
		case'S':
		{
			Pos.Y += 1;
			break;
		}
		case'q':	// (3)
		case'Q':
		{
			IsFire = true;
		}
		default:
			break;
		}

		CheckPos();	// (2)
	}

private:
	int2 Pos = { 0, 0 };
	char RenderChar = '@';
	bool IsFire = false;
};

class Bullet	// (3)
{
public:
	Bullet()
	{

	}

	inline int2 GetPos()
	{
		return Pos;
	}

	inline char GetRenderChar()
	{
		return RenderChar;
	}

	bool IsVisible(bool _IsFire)
	{
		Visible = _IsFire;

		return Visible;
	}

protected:

private:
	int2 Pos = { 0, 0 };
	char RenderChar = '^';
	bool Visible = false;
};

int main()
{
	ConsoleScreen NewScreen = ConsoleScreen('*');
	Player NewPlayer = Player({ ScreenXHalf, ScreenYHalf }, '@');
	Bullet NewBullet = Bullet();

	while (true)
	{
		NewScreen.ClearScreen();
		NewScreen.SetPixel(NewPlayer.GetPos(), NewPlayer.GetRenderChar());
		if (NewBullet.IsVisible(NewPlayer.GetIsFire()))	// (3)
		{
			NewScreen.SetPixel(NewBullet.GetPos(), NewBullet.GetRenderChar());
		}
		NewScreen.PrintScreen();
		NewPlayer.Update();
	}
}

과제 풀이


📢 기억해두면 좋은 VS단축키 & 정보

  • Shift + Del ⇒ 한 줄 삭제
  • Shift + 위/아래 ⇒ 한 줄 드래그
  • Shift + Home ⇒ 한 줄 안에서 커서 앞쪽으로 드래그
  • Shift + End ⇒ 한 줄 안에서 커서 뒤쪽으로 드래그
  • Shift + Ctrl + 좌/우 ⇒ 단어 단위로 드래그
  • Shift + Alt + 위/아래 ⇒ 커서 n층으로 만들기
  • Shift + Alt + 위/아래 → Ctrl + 좌/우 ⇒ n층 단어 단위로 드래그
  • Alt + 드래그 ⇒ 지정 사각형만큼 드래그
  • 범위지정 + Alt + 위/아래 ⇒ 윗줄 또는 아랫줄로 이동
  • Ctrl + 좌/우 ⇒ 단어 단위로 이동
  • Ctrl + A ⇒ 문서 코드 전체 선택
  • 변수명 위에 커서 + Ctrl + R + R ⇒ 동일한 개념을 가진 변수명을 동시에 변경
    • 항상 제대로 작동하는 것은 아니다
    • 변수가 많을수록 엄청 오래 걸린다
  • 범위지정 + Ctrl + K+ C ⇒ 주석
  • Ctrl + K + F ⇒ 자동 줄맞춤
  • 파일명 위에 커서 + Ctrl + Shift + G ⇒ 파일 열기
  • 이름 위에 커서 + F12 ⇒ 정의로 이동
profile
⋆꙳⊹⋰ 𓇼⋆ 𝑻𝑰𝑳 𝑨𝑹𝑪𝑯𝑰𝑽𝑬 ⸝·⸝⋆꙳⊹⋰

0개의 댓글