과거에 Dos(Disk operating system)라는 시스템이 있었다. 아무런 운영체제도 없던 시절에 있었다. 명령 줄 기반의 시스템이었다.
우리가 VS에서 F5를 누르면 내 프로그램이 콘솔창을 포함하는 것이 아니고
예를 들어 123을 출력하는 프로그램을 실행시키면 내 프로그램이 콘솔창에 "123 출력해줘"라고 명령하는 것이다.
콘솔창을 사용하다보면 다양한 프로그램들(cls, dir 등의 명령어들이 exe파일임)을 사용할 수 있는데, 이것들은 윈도우에 환경변수로 등록되어 있어서 폴더와 상관없이 사용할 수 있다.
// 실제 데미지를 데이터적으로 주는 함수
void DamageLogic(const int& _Att, int& _DefHp)
{
// 축약연산자라고 부르기도 한다.
// - 뿐만 아니라 더하기 나누기 곱하기 비트단위등등 거의 모든 연산의
// 축약 연산자가 존재한다.
_DefHp -= _Att;
// _DefHp = _DefHp - _Att;
}
// 공격의 행동을 화면에 랜더링하는 함수
void DamageRender(const char* _Name, const int& _Att)
{
printf_s("%s 가 %d의 공격력으로 공격했습니다.\n", _Name, _Att);
}
사용할 때 두 개의 함수를 묶어도 된다.
void Damage(const char* _Name, const int& _Att, int& _DefHp)
{
DamageRender(_Name, _Att);
DamageLogic(_Att, _DefHp);
}
#include <conio.h>
을 활용한다.
_getch()
: 아무키나 눌릴 때까지 기다려준다.system()
: 콘솔창에 명령을 요청한다. #include <iostream>
#include <conio.h>
int StringCount(const char* const _Ptr)
{
int Count = 0;
while (_Ptr[Count])
{
++Count;
}
return Count;
}
// const를 붙인 이유
// 보여주기만 하는 함수, 수정할 목적이 없는 함수
void StatusRender(const char* _Name, int _Att, int _Hp) {
//int NameSize = StringCount(_Name);
//int NameSize = strlen(_Name);
int NameSize = printf_s("%s ", _Name); // 출력하면서 이름 글자수도 알아낼 수 있음.
// 콘솔창은 특수문자를 통해서 특수한 출력기호를 사용할 수 있는데, 전부다 \(역슬래시)를 사용해서 표현한다.
// \n <= 콘솔창에서 1글자로 본다.
// \r
for (int i = 0; i < 50 - NameSize; i++) {
printf_s("-");
}
printf_s("\n"); // 라인을 바꾸라는 의미.
printf_s("공격력 %d\n", _Att);
printf_s("체력 %d\n", _Hp);
for (int i = 0; i < 50; i++) {
printf_s("-");
}
printf_s("\n");
}
// 실제 데미지를 데이터적으로 주는 함수
void DamageLogic(const int& _Att, int& _DefHp)
{
// 축약연산자라고 부르기도 한다.
// - 뿐만 아니라 더하기 나누기 곱하기 비트단위등등 거의 모든 연산의
// 축약 연산자가 존재합니다.
_DefHp -= _Att;
// _DefHp = _DefHp - _Att;
}
// 공격의 행동을 화면에 랜더링하는 함수
void DamageRender(const char* _Name, const int& _Att)
{
printf_s("%s 가 %d의 공격력으로 공격했습니다.\n", _Name, _Att);
}
void Damage(const char* _Name, const int& _Att, int& _DefHp)
{
DamageRender(_Name, _Att);
DamageLogic(_Att, _DefHp);
}
int main()
{
// 존재하게 하기 위해 상태를 만들었다.
char PlayerName[100] = "Fighter";
int PlayerHp = 100;
int PlayerAtt = 10;
char MonsterName[100] = "Orc";
int MonsterHp = 50;
int MonsterAtt = 5;
// 몬스터나 플레이어를 눈에 보이게 만들기
StatusRender(PlayerName, PlayerHp, PlayerAtt);
StatusRender(MonsterName, MonsterHp, MonsterAtt);
while (true) {
{
int Input = _getch();
system("cls");
DamageLogic(PlayerAtt, MonsterHp);
StatusRender(PlayerName, PlayerAtt, PlayerHp);
StatusRender(MonsterName, MonsterAtt, MonsterHp);
DamageRender(PlayerName, PlayerAtt);
}
{
int Input = _getch();
system("cls");
DamageLogic(MonsterAtt, PlayerHp);
StatusRender(PlayerName, PlayerAtt, PlayerHp);
StatusRender(MonsterName, MonsterAtt, MonsterHp);
DamageRender(PlayerName, PlayerAtt);
DamageRender(MonsterName, MonsterAtt);
}
}
return 0;
}
아무 키나 클릭하면 공격이 순서대로 진행된다..
난수 : 정의되지 않은 수가 나오는 것.
특정 공식에 따라서 어떠한 수를 변형시킨 수가 나오는 것.
매번 다른 수가 나오려면 시드밸류가 바뀌어야 한다.
한 번 바뀐 시드밸류가 또 바뀔 필요는 없다.
C스타일의 난수는 rand()함수로 뽑을 수 있다.
rand() 함수는 난수를 뽑아준다.
srand()로 난수 계산식의 Seed값을 바꿔줄 수 있다.
int Value = 0;
__int64 Address = reinterpret_cast<__int64>(&Value);
// 시드값 바꾸기
srand(Address);
for (int i = 0; i < 5; i++)
{
int Number = rand();
printf_s("%d\n", Number);
}
부호비트를 사용하면
signed
부호비트를 사용하지 않으면unsigned
를 붙여줘야 한다. (부호비트 사용하지 않고 양수로 표현)
(반대로 음수도 음수로 표현해야 한다고 붙이는 키워드가 있다.)
평소에 쓰는 int
는 사실 signed int
가 생략된 것이었다.
unsigned int에 -1을 넣어주면 부호가 없을 때의 양수 최댓값이 된다.
typedef는 자료형에 별명을 붙이는 것이다.
// typedef는 자료형에 별명 붙이기 이다.
typedef unsigned int uint;
int main() {
uint UValue = 20;
return 0;
}
uint랑 size_t랑 색이 같다. size_t도 사실 자료형 별명임.
F12
눌러서 정의로 가서 보면 size_t는 unsigned __int64임을 알 수 있다.
F12
: size_t나 함수같은 프로그래머가 만든 선언이 따로 존재하는 경우, 커서를 두고 F12를 누르면 그 선언으로 이동. (프로젝트를 만약 처음 켰다면 느릴 수 있다)
typedef를 또 typedef할 수 있다.
typedef unsigned int uint;
typedef uint pint;
typedef pint dint;
uint, pint, dint 중 뭘 써도 똑같다.
프로그래밍 패러다임의 1가지 종류이다. 각 프로그래밍 언어는 추구하는 이상이 있다. C++ 객체지향 언어라는 표현은 잘못됐다. 객체지향"도" 할 수 있는 언어다. C++은 멀티패러다임 언어이다.
객체(Object)라는 개념만을 사용해서 코딩하는 것을 객체지향이라고 한다.
객체지향에는 전역이라는 개념이 존재하면 안된다. 모든 것이 개념 안에 묶여있어야 한다.
개념이 메모리화된 것을 객체라고 부른다.
예시(비유)
int ← 정수라는 개념
int Value = 0; ← 객체
........................................................................................
몬스터 ← 개념
Monster111 이라고 한 마리 만듦 ← 객체
자료형을 개념이라고 본다.
정수라는 개념만으로는 아무것도 할 수 없다. 정수로 계산을 하려면 객체화를 해야한다. int도 클래스이다. C++만든 사람들이 먼저 만들어준 "개념"으로, 기본 자료형이라고 부른다.
개념을 사용하려면 객체화 해야한다. 그때 Class라는 것을 만든다.
몬스터를 만들고 싶어 → 몬스터의 개념을 먼저 만들어야 한다.
class
→ 개념을 만들겠다.
Monster를 객체화하는 것은 int A;
로 변수를 선언하는 것과 똑같다.
#include <iostream>
// 몬스터를 만들고 싶다.
// 그 개념을 문법화 시켰다.
// 이걸 사용자 정의 자료형이라고 한다.
// user definition type
class Monster { // 몬스터의 개념
};
int main() {
int A;
Monster NewMonster;
}
만들기만 해도 초기화하는 방법이 있다. (나중에 자세히 다시 배움) 그리고 int에도 사실 있다.
// 몬스터 객체
Monster NewMonster = Monster(); // 만들기만 해도 초기화하는 방법
int NewInt = int(); // 사실 int도 갖고 있음.
Class 내부에는 개념이 가져야 하는 상태와 행동을 구체화할 수 있다.
클래스 내부에 있는 변수는 클래스 내부 함수 등에서 바로 사용할 수 있다. 그러므로 StatusRender함수에 인자가 필요없다.
#include <iostream>
class Player {
// 클래스 내부
// 상태
char Name[100];
int Hp;
int Att;
int Speed;
// 행동
// 구체화를 해야 한다.
void Damage(int& _Att);
void StatusRender();
};
class Monster {
};
int main() {
Player NewPlayer = Player();
}