#include <iostream>
#include <WS2tcpip.h>
#include <WinSock2.h>
#include <set>
using namespace std;
#pragma comment (lib, "Ws2_32.lib") // cpp
/*
* 기본 자료형
int, float, bool,
*/
/*
사용자정의 자료형
struct 구조체명
{
자료형 멤버변수명;
자료형 멤버변수명2;
};
int num;
구조체명 변수명;
변수명.멤버변수명 = 값;
*/
struct ClientInfo
{
WSAOVERLAPPED overlapped;
SOCKET socket;
char buffer[512];
WSABUF dataBuf;
DWORD recvByte;
DWORD flags;
BOOL isSend;
};
/*
자료구조
구현이 쉽다.
임의접근에 유리하다.
삽입삭제에 유리하다.
다 준수하면서 검색(탐색)에 능하다.
map, set
탐색, 검색
*/
set<ClientInfo*> g_clientList;
void CALLBACK RecvCallBackFunc(DWORD _error, DWORD _recvLen, LPWSAOVERLAPPED _overlapped, DWORD _inflags)
{
ClientInfo* info = (ClientInfo*)_overlapped;
if (_recvLen == 0)
{
cout << "클라 연결 종료" << endl;
closesocket(info->socket);
g_clientList.erase(info);
delete info;
return;
}
if (_error == 0)
{
if (info->isSend == false)
{
cout << "받았다" << endl;
cout << "수신 메시지 : " << info->buffer << endl;
for (auto iter = g_clientList.begin(); iter != g_clientList.end(); iter++)
{
ClientInfo* data = *iter;
strcpy_s(data->dataBuf.buf, 512, info->dataBuf.buf);
data->dataBuf.len = _recvLen;
WSASend(
data->socket,
&data->dataBuf,
1,
nullptr,
0,
&data->overlapped,
RecvCallBackFunc);
data->isSend = true;
}
}
else
{
info->dataBuf.len = 512;
WSARecv(
info->socket,
&info->dataBuf,
1,
&info->recvByte,
&info->flags,
&info->overlapped,
RecvCallBackFunc);
cout << "수신대기 시작" << endl;
info->isSend = false;
}
}
}
int main()
{
// WSAStartup
WSADATA wsa;
int result;
result = WSAStartup(MAKEWORD(2, 2), &wsa);
if (result != 0)
{
cout << "WSAStartup 에러" << endl;
return -1;
}
// 소켓 생성
SOCKET mySocket = WSASocket(
AF_INET,
SOCK_STREAM,
0,
nullptr,
0,
WSA_FLAG_OVERLAPPED);
if (mySocket == INVALID_SOCKET)
{
cout << "소켓 생성 에러" << endl;
WSACleanup();
return -1;
}
// 바인딩
sockaddr_in recviverAddr = {};
recviverAddr.sin_family = AF_INET;
recviverAddr.sin_port = htons(12345);
recviverAddr.sin_addr.s_addr = INADDR_ANY;
result = bind(
mySocket,
(sockaddr*)&recviverAddr,
sizeof(recviverAddr));
if (result != 0)
{
cout << "바인딩 에러" << endl;
closesocket(mySocket);
WSACleanup();
return -1;
}
// 리슨
if (listen(mySocket, SOMAXCONN) == SOCKET_ERROR)
{
cout << "리슨 에러" << endl;
closesocket(mySocket);
WSACleanup();
}
SOCKET clientSocket;
while (true)
{
cout << "연결 대기 시작" << endl;
// 어셉
clientSocket = accept(mySocket, nullptr, nullptr);
if (clientSocket == INVALID_SOCKET)
{
cout << "어셉 에러" << endl;
closesocket(mySocket);
WSACleanup();
return -1;
}
cout << "클라 연결 성공" << endl;
ClientInfo* info = new ClientInfo;
info->socket = clientSocket;
info->dataBuf.buf = info->buffer;
info->dataBuf.len = 512;
info->flags = 0;
info->recvByte = 0;
info->isSend = false;
// 리스트에 클라 정보 저장
g_clientList.insert(info);
// 웰컴 멘트 제작
strcpy_s(info->dataBuf.buf, info->dataBuf.len, "system : welcome");
info->dataBuf.len = strlen("system : welcome");
// 송신
WSASend(
info->socket,
&info->dataBuf,
1,
nullptr,
0,
&info->overlapped,
RecvCallBackFunc);
info->isSend = true;
}
// 해제들
closesocket(clientSocket);
closesocket(mySocket);
WSACleanup();
return 0;
}
상속
<aside> 🚛 class Child : public Parent {
}
</aside>
생성자 호출 타이밍
<aside> 📋 클래스이름() {
}
</aside>
소멸자 호출 타이밍
<aside> 📋 ~클래스이름() {
}
</aside>
다형성
클래스 포인터
함수 오버라이딩
상관관계에서 부모의 함수를 자식이 재정의하는 문법
→ 아니 다른 함수 만들면 되지 왜 굳이 같은 이름으로?
같은 이름의 함수가 포함되어있는데 그냥 부르면 본인의 함수를 호출함
<aside> 📋 부모의 함수를 불러서 쓰려면? 자식객체이름.부모클래스이름::쓰려는부모의함수명();
</aside>
<aside> 🌩️ 부모 포인터에 담은 자식 클래스는? → 같은 이름의 함수가 있으면 부모의 함수가 불림!! 더 앞에 있는게 불리는 느낌
</aside>
Child a{};
Child2 b{};
Child3 c{};
Parent* list[3]{};
list[0] = &a;
list[1] = &b;
list[2] = &c;
c.Test();
list[2]->Test(); 는 존재하지 않음!!!
list[] 안에는 부모포인터로 지정해서 넣었기때문에 c에만 있는 특별함수인 Test를 호출할 수 없음 → 가상함수 필요
가상함수
순수 가상함수
가상함수는 부모에 있는 함순데 자식에서도 재구현해서 쓸수있음~
순수가상함수는 아 나 부몬데 모르겠고 이 함수 있음~ 애들이 만들거임~
추상클래스 / abstract
인터페이스 / interface
생성자 오버로딩
멤버이니셜라이저
부모의 접근제어지정자
#include <iostream>
#include <random>
using namespace std;
/*
상태패턴
*/
class Monster
{
public:
int m_nHP{};
int m_nAtk{};
string m_strName{};
Monster()
{
m_nHP = 20;
m_nAtk = 5;
m_strName = "이름";
}
virtual void Attack(int* _hp, int* _atk, int nInput = 0) // 디폴트 매개변수
{
*_hp -= m_nAtk;
}
virtual void Heal(int nInput = 0)
{
m_nHP += m_nAtk;
}
};
class Monster1 : public Monster
{
public:
Monster1()
{
m_nAtk = 20;
m_nHP = 50;
m_strName = "Monster1";
}
void Attack(int* _hp, int* _atk, int nInput = 0) // 디폴트 매개변수
{
cout << m_nAtk << "의 피해를 주었다." << '\\n';
*_hp -= m_nAtk;
}
void Heal(int nInput = 0)
{
cout << m_nAtk << "만큼 회복했다." << '\\n';
m_nHP += m_nAtk;
}
};
class Monster2 : public Monster
{
public:
Monster2()
{
m_nAtk = 100;
m_nHP = 20;
m_strName = "Monster2";
}
void Attack(int* _hp, int* _atk, int nInput = 0) // 디폴트 매개변수
{
cout << m_nAtk << "의 피해를 주었다." << '\\n';
*_hp -= m_nAtk;
}
void Heal(int nInput = 0)
{
cout << m_nAtk << "만큼 회복했다." << '\\n';
m_nHP += m_nAtk;
}
};
class Monster3 : public Monster
{
public:
Monster3()
{
m_nAtk = 10;
m_nHP = 200;
m_strName = "Monster3";
}
void Attack(int* _hp, int* _atk, int nInput = 0) // 디폴트 매개변수
{
cout << m_nAtk << "의 피해를 주었다." << '\\n';
*_hp -= m_nAtk;
}
void Heal(int nInput = 0)
{
cout << m_nAtk << "만큼 회복했다." << '\\n';
m_nHP += m_nAtk;
}
};
int main()
{
srand(time(nullptr));
int nHP = 1000;
int nAtk = 50;
int nInput{};
int nMonsterInput{};
while (true)
{
Monster* monster = nullptr;
int nType = rand() % 3;
switch (nType)
{
case 0:
monster = new Monster1{};
break;
case 1:
monster = new Monster2{};
break;
case 2:
monster = new Monster3{};
break;
default:
monster = new Monster;
}
while (true)
{
cout << "HP : " << nHP << '\\n';
cout << monster->m_strName << "가 나타났다!" << '\\n';
cout << "Monster HP : " << monster->m_nHP << '\\n';
if (nHP <= 0)
{
cout << "패배" << '\\n';
break;
}
else if (monster->m_nHP <= 0)
{
cout << "승리" << '\\n';
break;
}
cout << "1. 공격 2. 회복" << '\\n';
cout << "입력 : ";
int nInput{};
cin >> nInput;
switch (nInput)
{
case 1:
cout << "플레이어가 공격합니다." << '\\n';
monster->m_nHP -= nAtk;
break;
case 2:
cout << "플레이어가 회복합니다." << '\\n';
nHP += nAtk;
break;
}
nMonsterInput = rand() % 2 + 1;
switch (nMonsterInput)
{
case 1:
monster->Attack(&nHP, &nAtk, nInput);
break;
case 2:
monster->Heal(nInput);
break;
}
system("pause");
system("cls");
}
delete monster;
cout << "Continue? / 0.끝 1.계속" << '\\n';
cout << "입력 : ";
cin >> nInput;
if (nInput == 0)
{
break;
}
else
{
nHP = 1000;
system("cls");
}
}
}