오늘 학습 진행 내용
언리얼 강의
라이브 세션
DAY 3 블루프린트를 이용한 비주얼 스크립팅
블루 프린트가 무엇인지 배우고, 변수,이벤트 함수에 대해 배워본다.
Branch,Sequence, 함수에 대해 배워보고 이를 이용하여 간단한 과제 진행
While, For, Array, ForEach, 열거형 구조체, Switch에 대해 배워보고 간단한 과제 진행
언리얼 블루프린트
프로젝트 환경설정
프로젝트 생성 후 언리얼 에디터 최상단 Edit 클릭 -> Editor Preferencs에서 언어 설정 변경 가능
Winodws 메뉴에서 Load Layout 기능 활용해서 자기만의 레이아웃 설정 가능
블루프린트
언리얼 엔진에서 제공하는 비주얼 스크립팅 시스템
복잡한 코드 작성 없이, 노드 기반의 블럭 연결해서 프로그래밍 가능하게 하는 시스템
변수와 연산
이벤트 함수와 PrintString() 함수
이벤트 함수 : 어떤 Event 발생하면 호출되는 함수
블루 프린트 변수
블루 프린트 연산 노드
비교 연산 노드(==, !=, >, <, <=, >=)를 사용해서 두 값 비교하여 참 또는 거짓 반환
논리 연산 노드 (AND,OR,NOT,XOR)을 사용해서 여러 조건을 조합하거나 반전하여 복잡한 논리적 흐름 처리할 때 사용
흐름 제어
Brach와 Sequence 조건 만족 시 실행 혹은 순서에 따라서 실행하게 제어 가능
실습
텍스트 슈팅 게임
Bullets 변수로 총알 카운트 처리하고 각각 마우스 좌클릭에 Subtrect, R 버튼에 Set활용해서 발사 및 재장전 기능 구현
1) 30발 이상 격발 할 수 있는 버그**
현재 총알의 개수가 0보다 작은 경우에는 발사할 수 없게끔 로직을 수정해보세요.
”Out of ammo…”라는 문구가 출력되면 더 좋습니다.
2) 총알이 가득차 있는 경우에도 재장전 되는 버그**
현재 총알의 개수가 30발 만발인 경우에는 재정전 되지 않게끔 수정해보세요.
”Already full…”이라는 문구가 출력되면 더 좋습니다.
발사와 재장전 실행 되기 전에 Branch로 조건으로 각각 버그 발생 원인(현재 총알 갯수) 조건 검사하게 해서 버그 수정
텍스트 슈팅 게임 기능 추가하기
총알을 발사하고 장전만 할 수 있는 게임은 너무 지루함.
두 가지 추가 기능을 구현해보자.
1) 과열 상태 추가
여러 발을 격발할 경우, 총기가 과열될 수 있습니다.
CurrentTemperature라는 속성을 추가하고 한 발당 1씩 증가하게끔 로직을 짜봅시다.
그리고 CurrentHeatState라는 속성을 추가하고,
CurrentTemperature가 0~30까지는 CurrentHeatState가 ”Normal”
CurrentTemperature가 31~70까지는 CurrentHeatState가 ”High”
CurrentTemperature가 71이상은 CurrentHeatState가 ”Over”로 설정되게끔 합니다.
2) 쿨다운 기능
특정 키를 누를때마다 총기의 온도가 내려가게끔 구현해봅시다.
T키를 누르면 CurrentTemperature를 1씩 감소하게끔 로직을 작성해보세요.
CurrentTemperature가 변하면 CurrentHeatState도 그에따라 변해야합니다.
CurrentTemperature 속성 추가 후 발사 시 Add 처리해서 올라가게 하고 TempToHeatState 함수 제작해서 온도에 따른 State 정해지게 함수로 반영 마우스 좌클릭으로 발사 시 온도에 따른 State 결정
함수
코드 재사용이 빈번한 것들 함수로 처리해서 하나의 코드로 처리
흐름 제어
While Loop, For Loop
While은 조건 기반, For은 인덱스 기반
Array와 ForEach Loop
다양한 타입의 변수를 하나의 객체로 관리 가능
열거형과 구조체 그리고 Switch
실습
텍스트 슈팅 게임 무기 추가하기
라이플, 샷건, 피스톨 무기를 추가하고 무기교체를 구현해봅시다.
무기 별 Staete, 온도, 탄 수 관리를 위해 열거형으로 추가하고 무기 별 탄환 수 다르게 하기 위해 최대 탄환 변수 추가
기존 코드에 발사와 재장전, 온도 관련 부분에 Set Weapon Value 함수 만들어서 추가, 그리고 무기 교체 이벤트 시 해당 무기의 정보 가져오는 Get Weapon Value 함수 만들어서 추가
GetWeaponValue 함수는 무기 정보 들어있는 열거형 변수에서 가져와서 할당하는 함수
SetWeaponValue는 현재 정보값 열거형 변수에 할당하는 함수(Max Bullet은 불변값으로 계속 열거형 변수에 할당되어 있던 값 가져오는 형태)
실습 과제 추가 구현 해보기
실습 과제에 추가적으로 실제로 로직 상 발사 시 캐릭터가 애니메이션 동작 이어서 할 수 있게 2번 키 누르면 피스톨 장착하고 우클릭 시 조준, 좌클릭 시 발사 동작되게 구현 (애니메이션은 기본 템플릿 캐릭터에서 제공하는 애니메이션 활용)
캐릭터 애니메이션 블루프린트에 조준중(bIsAiming) 변수 캐릭터 블루프린트의 변수 받아와서 설정하게 구성
가져온 조준중 변수에 따라서 서있는 상태에서 변수 Boolean 값에 따라서 조준 액션 취하게 Staete Machine 구성
캐릭터 스켈레탈 메시의 HanGrip_L에 총 자연스럽게 할당되게 배치 및 조정 후 2번 키 누를 시 총 엑터가 캐릭터 HandGrip_L에 소환되게 Attached되게 구성, 총 안든 상태에서 발사 모션 취하는 것 방지하기 위해 총은 CurrentWeapon에 할당되게 추가
총구에 발사 이펙트 보이게 하기 위해 총기 Static Mesh에 소켓 추가 후 발사 동작 시 발사 모션 몽타주 실행하고 해당 소켓 자리에 이펙트 효과 생성되게 블루프린트 구성
구현 결과
C++ 프로그래머스 연습
수열과 구간 쿼리 4
문제 설명
정수 배열 arr와 2차원 정수 배열 queries이 주어집니다. queries의 원소는 각각 하나의 query를 나타내며, [s, e, k] 꼴입니다.
각 query마다 순서대로 s ≤ i ≤ e인 모든 i에 대해 i가 k의 배수이면 arr[i]에 1을 더합니다.
위 규칙에 따라 queries를 처리한 이후의 arr를 return 하는 solution 함수를 완성해 주세요.
제한사항
1 ≤ arr의 길이 ≤ 1,000
0 ≤ arr의 원소 ≤ 1,000,000
1 ≤ queries의 길이 ≤ 1,000
0 ≤ s ≤ e < arr의 길이
0 ≤ k ≤ 5
통과 답안
#include <string>
#include <vector>
using namespace std;
vector<int> solution(vector<int> arr, vector<vector<int>> queries) {
vector<int> answer;
for(int i=0; i<queries.size(); i++){
int s = queries[i][0];
int e = queries[i][1];
int k = queries[i][2];
for(s; s<=e; s++){
if(s%k==0){
arr[s] +=1;
}
}
}
answer = arr;
return answer;
}
다른 사람 풀이
#include <string>
#include <vector>
using namespace std;
vector<int> solution(vector<int> arr, vector<vector<int>> queries) {
vector<int> answer;
for(auto q:queries){
for(int i = q[0]; i<=q[1]; i++){
if(i%q[2] == 0){
arr[i]++;
}
}
}
return arr;
}
배열 만들기 2
문제 설명
정수 l과 r이 주어졌을 때, l 이상 r이하의 정수 중에서 숫자 "0"과 "5"로만 이루어진 모든 정수를 오름차순으로 저장한 배열을 return 하는 solution 함수를 완성해 주세요.
만약 그러한 정수가 없다면, -1이 담긴 배열을 return 합니다.
제한사항
1 ≤ l ≤ r ≤ 1,000,000
통과 답안(모르는 부분 존재해서 검색 이용)
🔎 find 계열 함수 요약
| 함수 | 설명 | 찾는 기준 | 반환값 | 찾지 못했을 때 |
|---|---|---|---|---|
find | 부분 문자열을 앞에서부터 검색 | 문자열 or 문자 | 첫 번째 발견 위치 | npos |
rfind | 부분 문자열을 뒤에서부터 검색 | 문자열 or 문자 | 마지막 발견 위치 | npos |
find_first_of | 문자 집합 중 하나라도 처음 등장하는 위치 | 문자들 집합 | 위치 | npos |
find_last_of | 문자 집합 중 하나를 뒤에서부터 찾기 | 문자들 집합 | 위치 | npos |
find_first_not_of | 특정 문자 집합에 없는 문자 첫 등장 위치 | 제외할 문자들 | 위치 | npos |
find_last_not_of | 특정 문자 집합에 없는 문자를 뒤에서부터 찾기 | 제외할 문자들 | 위치 | npos |
#include <string>
#include <vector>
#include <string>
using namespace std;
vector<int> solution(int l, int r) {
vector<int> answer;
int min_count = 0;
int max_count = 0;
min_count = l/5;
max_count = r/5;
if(l%5!=0){
min_count+=1;
}
for (int i=min_count; i<=max_count; i++){
if(to_string(i*5).find_first_not_of("05") == string::npos){
answer.push_back(i*5);
}
};
if(answer.size()==0){
answer.push_back(-1);
}
return answer;
}
다른 사람 풀이
#include <string>
#include <vector>
#include <queue>
using namespace std;
vector<int> solution(int l, int r) {
vector<int> answer; // 조건을 만족하는 숫자들을 담을 벡터
queue<int> q; // 숫자를 생성하기 위해 사용할 큐 (BFS 용도)
// 시작 숫자: 5만으로 이루어진 가장 작은 수
q.push(5);
// 큐가 빌 때까지 반복 (BFS 방식으로 숫자 생성)
while (!q.empty()) {
int n = q.front(); // 현재 숫자
q.pop();
// 현재 숫자가 r보다 크면, 이 숫자에서 더 큰 숫자를 만들어도
// 모두 r을 넘게 되므로, 더 이상 확장하지 않고 건너뜀
if (n > r) continue;
// 구간 [l, r] 안에 들어가면 정답 벡터에 추가
if (n >= l) {
answer.push_back(n);
}
// 현재 숫자 n 뒤에 0과 5를 붙여서
// "0과 5로만 이루어진 숫자"를 계속 만들어나감
// 예: n = 5 → 50, 55
q.push(n * 10); // 끝에 0을 붙인 숫자 (예: 5 → 50)
q.push(n * 10 + 5); // 끝에 5를 붙인 숫자 (예: 5 → 55)
}
// [l, r] 구간 안에 조건을 만족하는 숫자가 하나도 없으면 -1 추가
if (answer.empty()) {
answer.push_back(-1);
}
return answer;
}
카운트 업
문제 설명
정수 start_num와 end_num가 주어질 때, start_num부터 end_num까지의 숫자를 차례로 담은 리스트를 return하도록 solution 함수를 완성해주세요.
제한사항
0 ≤ start_num ≤ end_num ≤ 50
통과 답안
#include <string>
#include <vector>
using namespace std;
vector<int> solution(int start_num, int end_num) {
vector<int> answer;
for (start_num; start_num<=end_num; start_num++){
answer.push_back(start_num);
}
return answer;
}
콜라츠 수열 만들기
문제 설명
모든 자연수 x에 대해서 현재 값이 x이면 x가 짝수일 때는 2로 나누고, x가 홀수일 때는 3 * x + 1로 바꾸는 계산을 계속해서 반복하면 언젠가는 반드시 x가 1이 되는지 묻는 문제를 콜라츠 문제라고 부릅니다.
그리고 위 과정에서 거쳐간 모든 수를 기록한 수열을 콜라츠 수열이라고 부릅니다.
계산 결과 1,000 보다 작거나 같은 수에 대해서는 전부 언젠가 1에 도달한다는 것이 알려져 있습니다.
임의의 1,000 보다 작거나 같은 양의 정수 n이 주어질 때 초기값이 n인 콜라츠 수열을 return 하는 solution 함수를 완성해 주세요.
제한사항
1 ≤ n ≤ 1,000
통과 답안
#include <string>
#include <vector>
using namespace std;
vector<int> solution(int n) {
vector<int> answer;
while(n!=1){
answer.push_back(n);
if(n%2==0){
n/=2;
}
else if(n%2==1){
n = 3*n + 1;
}
}
answer.push_back(1);
return answer;
}
다른 사람 풀이
#include <vector>
using namespace std;
vector<int> solution(int n){
vector<int> a; // 콜라츠(?) 수열을 저장할 벡터
for(;;) { // 조건 없는 무한루프. 내부에서 return으로 빠져나옴.
a.push_back(n); // 현재 n 값을 수열에 추가
// n이 1이면 수열이 끝났다고 보고 지금까지의 벡터를 그대로 반환
if (n == 1) return a;
// n이 홀수인지 짝수인지에 따라 다음 n을 계산
// (n & 1) : n의 최하위 비트가 1이면 홀수, 0이면 짝수
// - 홀수면 true, 짝수면 false
//
// 홀수일 때 : n = 3 * n + 1
// n + (n << 1) + 1
// = n + (n * 2) + 1
// = 3n + 1
//
// 짝수일 때 : n = n / 2 (오른쪽 시프트 1비트 == 2로 나누기)
n = (n & 1) ? (n + (n << 1) + 1) : (n >> 1);
}
}
배열 만들기4
문제 설명
정수 배열 arr가 주어집니다. arr를 이용해 새로운 배열 stk를 만드려고 합니다.
변수 i를 만들어 초기값을 0으로 설정한 후 i가 arr의 길이보다 작으면 다음 작업을 반복합니다.
만약 stk가 빈 배열이라면 arr[i]를 stk에 추가하고 i에 1을 더합니다.
stk에 원소가 있고, stk의 마지막 원소가 arr[i]보다 작으면 arr[i]를 stk의 뒤에 추가하고 i에 1을 더합니다.
stk에 원소가 있는데 stk의 마지막 원소가 arr[i]보다 크거나 같으면 stk의 마지막 원소를 stk에서 제거합니다.
위 작업을 마친 후 만들어진 stk를 return 하는 solution 함수를 완성해 주세요.
제한사항
1 ≤ arr의 길이 ≤ 100,000
1 ≤ arr의 원소 ≤ 100,000
통과 답안
#include <string>
#include <vector>
using namespace std;
vector<int> solution(vector<int> arr) {
vector<int> stk;
int i=0;
while(i<arr.size()){
if(stk.size()!=0 && stk.back()<arr[i]){
stk.push_back(arr[i]);
i+=1;
}
else if(stk.size()!=0 && stk.back()>=arr[i]){
stk.pop_back();
}
else{
stk.push_back(arr[i]);
i+=1;
}
}
return stk;
}
다른 사람 풀이
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> solution(vector<int> arr) {
vector<int> stk; // 조건을 만족하는 원소들을 담아갈 "스택 역할"의 벡터
int i = 0; // arr를 순회하기 위한 인덱스
// i가 arr의 크기보다 작을 동안 계속 반복
while (i < arr.size()) {
// 1️⃣ stk가 비어있으면 무조건 현재 원소를 넣는다.
if (stk.empty()) {
stk.push_back(arr[i]); // 현재 arr[i]를 스택에 넣고
i++; // 다음 원소로 이동
}
// 2️⃣ stk가 비어있지 않고,
// 스택의 맨 뒤 값(stk.back)이 현재 arr[i]보다 작으면
// → "증가하는 흐름 유지" 가능하므로 현재 값을 추가.
else if (stk.back() < arr[i]) {
stk.push_back(arr[i]); // 현재 값을 스택에 추가
i++; // 다음 원소로 이동
}
// 3️⃣ 그 외의 경우 (stk.back() >= arr[i]):
// → 스택의 마지막 값이 현재 값보다 크거나 같으므로
// "마지막 값을 제거"해서 더 나은(작은 값으로 시작되는) 증가 수열을 만들려는 의도
else {
// stk의 마지막 원소를 제거 (pop_back과 같은 효과)
stk.erase(stk.end() - 1);
}
}
return stk; // 최종적으로 조건을 만족하며 남은 값들 반환
}