해쉬 테이블(Hash Table)

  • 키(Key)와 값(Value)을 갖는 구조
  • 시간 복잡도
    • 평균 : O(1)
  • 해쉬 충돌(Hash Collision) : 해쉬가 충돌하는 현상
    • 해결법 : 분리 연결법(Sperate Chaining)
      > 동일한 해쉬의 데이터에 대해 자료구조를 활용해 추가 메모리를 사용해, 다음 데이터의 주소를 저장하는 것
      > 예 : 동일한 해쉬(152)에 새로운 해쉬 테이블을 작성,
      그 테이블을 토대로 여러개의 값이 저장되게 하는 것으로 이해 중
  • C# Dictionary 등
  • 예 : 호텔의 키와 안의 고객 등

'Programming > Data Structure' 카테고리의 다른 글

완전 이진 트리(Complete Binary Tree)  (0) 2021.04.22
리스트(List)  (0) 2021.04.21
이진 트리(Binary Tree)  (0) 2021.04.20
트리(Tree)  (0) 2021.04.20
큐(Queue)  (0) 2021.04.19
블로그 이미지

RIsN

,

큐(Queue)

  • FIFO : First In First Out / 먼저 들어온 게 먼저 나간다
  • 시간 복잡도
    • 삽입, 삭제 : O(1)
    • 검색 : O(n)
  • 용어
    • Enqueue : 삽입
    • Dequeue : 삭제
    • Front : 앞, 삭제되는 곳
    • Rear : 뒤, 삽입되는 곳
  • 배열의 경우 원형 배열로 구현을 추천
    • 선형일 경우, 삭제해도 데이터가 계속 밀려나는 현상이 일어난다.
  • 아니면 연결 리스트를 사용해 구현
  • 예 : 은행의 번호표(Queue)

'Programming > Data Structure' 카테고리의 다른 글

완전 이진 트리(Complete Binary Tree)  (0) 2021.04.22
리스트(List)  (0) 2021.04.21
이진 트리(Binary Tree)  (0) 2021.04.20
트리(Tree)  (0) 2021.04.20
해쉬 테이블(Hash Table)  (0) 2021.04.20
블로그 이미지

RIsN

,
블로그 이미지

RIsN

,

: 입력, 한 줄(엔터까지엔터까지)을 읽어 온다.

1줄 받아오기

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', (input) => {
  console.log(`Received: ${input}`);
});

2줄 받아오기

const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on('line', function (line) {
    input.push(line);
    if(input.length >= 2)
        rl.close();
}).on('close', function () {
    console.log(input);
    process.exit();
});
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];
let count = 0;

rl.on('line', function (line) {
    input.push(line);
    
    // :: 입력 제한 관리
    count++;
    if(count >= 2)
        rl.close();
}).on('close', function () {
    console.log(input);
    process.exit();
});

>> 좀 더 직관적으로 만들어 본 코드 

블로그 이미지

RIsN

,

싱글톤 패턴이란?

: 최대한 용어를 안 쓰고 정리해보자

정의한 설계도(클래스, 함수)를
오직 1개(인스턴스)만 구현하게 하고
작업 전체에서 접근 가능(전역 변수)하도록 만든 것

아파트를 짓는데, 내부 인테리어 설계도(클래스, 함수)가 있다.
> 이 설계도는 아파트 내부에서 단 한 번만 쓰여야 한다.
> 하지만 누구나 이 제작된 내부 인테리어를 보고, 안에 있는 것을 건드리고 옮길 수 있다.
> 모델 하우스? 

왜 쓰면 안되는가?

(이해중) 전역 변수는 코드를 어지럽힌다.

  • 코드를 이해하기 어렵게 한다.
  • 커플링(의존) 문제

대체품

  • 하위 클래스 샌드박스 패턴
  • 서비스 중개자 패턴

왜 썼는가?

현재 제작중인 게임(Summerfield / Tamago)에서
> Zombie의 Status를 수정할 때 여러곳에서 필요로 하는 경우가 있었다.
>> 대체 예정

참고 서적 : 더 빠르고 깔끔한 게임 코드를 구현하는 13가지 디자인 패턴 게임 프로그래밍 패턴

'Programming > Pattern' 카테고리의 다른 글

관찰자 패턴(Observer Pattern) with Unity  (0) 2021.03.13
블로그 이미지

RIsN

,

관찰자 패턴이란?

준비중...

왜 썼는가?

현재 제작중인 게임(Summerfield / Tamago)에서
> 매 분마다 처리를 하는 것은 최종 관리자 스크립트(Dictator)의 역할로
> 다른 스크립트들은 그 때마다 보여주는 것만 업데이트하는 설계로 되어 있음

따라서 매분 처리가 발생할 때마다 다른 스크립트가 관찰을 해서,
자신의 UI나 게임오브젝트를 업데이트 하도록 사용

인터페이스 구성

public interface ISubject
{
    void RegisterObserver(IObserver observer);
    void RemoveObserver(IObserver observer);
    void NotifyObservers_Minute();
}

public interface IObserver
{
    void UpdateMinute();
}

'Programming > Pattern' 카테고리의 다른 글

싱글톤 패턴(Singleton Pattern) with Unity  (0) 2021.03.15
블로그 이미지

RIsN

,

간단 해결

  • 해당 Shader에서 CustomEditor 항목을 제거한다

복잡 해결

  • 이해중
블로그 이미지

RIsN

,

<데이터베이스 테이블 작성>

  • 스키마 이름 : user_db
  • 테이블 이름 : users
  • utf-8 설정
  • 데이터
    • userID : varchar(45) / pk, nn
    • userName : varchar(45) / nn
    • userEmail : varchar(45) / nn, uq
    • userPassword : varchar(255) / nn
    • userConnectedTime : datetime / Default : CURRENT_TIMESTAMP

<프로토콜 문서 작성>

<환경 설정>

  1. 테스트 폴더를 작성한다
    • 이름 : test-express
  2. 터미널을 열어서 해당 폴더에서 필요한 것들을 설치 및 설정한다
    1. npm init -y : npm을 사용하기 전의 초기화
    2. npm i express : express 설치
    3. npm i mysql2 : my-sql를 편하게 사용할 수 있게 해주는 거인듯?
    4. npm i crypto-js : 암호화
    5. npm i uuid : 유니크 ID
    6. npm i nodemon : 딱히 필요 없지만, 스크립트가 갱신될 때마다 서버를 알아서 다시 돌려주는 녀석

<테스트 케이스>

  1. 폴더에 메인이 될 app.js를 만든다
    • const { response } = require('express');
      const express = require('express'); // :: Express 사용
      const app = express();
      
      app.use(express.json());
      
      app.get('/', (require, response) => {
          response.sendStatus(200); // :: OK 돌려보내준다.
      });
      const portNumber = 3000;
      app.listen(portNumber, () => {
          console.log(`server is running at ${portNumber} port`);
      });
  2. nodemon app으로 서버를 켠다
    • postman 설치 생략
    • postman으로 get으로 해놓고 <localhost:3000/>에 전송해보면 문제 없으면 OK가 돌아온다
  3. My SQL 데이터베이스와 연결을 담당할 connectPool.js를 만든다
    • const mysql = require('mysql2');
      
      const connectPool = mysql.createPool({
          host: 'localhost',
          user: 'root', // :: 데이터베이스 유저 id
          database: 'user_db',
          password: '<패스워드 넣어주세요>', // :: 데이터베이스 유저 패스워드
          waitForConnections: true,
          connectionLimit: 10,
          queueLimit: 0
      });
      
      module.exports = connectPool;
  4. 작성한 프로토콜을 기준으로 유저 라우터 router/uesrs.js를 만든다
    • // : Express 사용
      const express = require('express');
      const router = express.Router();
      
      // : 암호화
      const CrpytoJS = require('crypto-js');
      const encodeKey = 'saint place'; // :: 암호화 키
      
      // : 유니크 아이디
      const {v4: uuid4} = require('uuid');
      
      // : 데이터베이스 커넥트
      const connectPool = require('../connectPool');
      
      router.post('/', async (require, response) => {
      
          // :: 받아옴
          const { userName, userEmail, userPassword } = require.body;
      
          // :: 유니크 아이디 생성
          const userID = uuid4();
      
          // :: 패스워드 암호화
          const password = CrpytoJS.AES.encrypt(userPassword, encodeKey).toString();
          
          // :: 암호화 확인
          const encodePass = password;
          console.log("encode Password : " + encodePass);
      
          // :: 복호화 확인
          const decodePass = CrpytoJS.AES.decrypt(encodePass, encodeKey).toString(CrpytoJS.enc.Utf8);
          console.log("decode Password : " + decodePass);
      
          // :: 쿼리 생성
          const query = "insert into users(userID, userName, userEmail, userPassword) values (?, ?, ?, ?);";
      
          // :: 쿼리 적용
          try {
              let[rows, fields] = await connectPool.promise()
              .query(query, [userID, userName, userEmail, password]); // :: 적용
      
              response.sendStatus(200);
          } catch(error) {
              
              response.sendStatus(500);
          }
      });
      
      
      router.delete('/', async (require, response) => {
          console.log('회원목록 가져오기 테스트');
      
          try {
              const query = "select * from users";
              let[rows, fields] = await connectPool.promise().query(query);
      
              rows.forEach(row => {
                  const name = row.userName;
                  const email = row.userEmail;
                  const password = CrpytoJS.AES.decrypt(row.userPassword, encodeKey).toString(CrpytoJS.enc.Utf8);
                  const time = row.userConnectedTime;
                  console.log(`이름 : ${name}, 이메일 : ${email}, 패스워드 : ${password}, 시간 : ${time}`);
              });
          } catch (error) {
              response.sendStatus(500);
          }
      
          response.sendStatus(200);
      });
      
      module.exports = router;
  5. 회원가입 전송 테스트
    • {
          "userName" : "아이유",
          "userEmail" : "mylifefor@IU",
          "userPassword" : "IU4EVER"
      }
  6. 성공
  7. 추가 테스트(회원 목록 받아오기)
블로그 이미지

RIsN

,

진행과정

  1. 알파 채널이 있는 불 이미지들(fireTest : 불 모양 / noise2 : 노이즈)을 준비해 프로젝트에 넣는다.
    fireTest.tga
    4.00MB
    noise2.png
    0.07MB
  2. 3D > Quad 제작
  3. 새 Standard Surface Shader 제작 및 수정
    1. Shader "Custom/Fire"
      {
          Properties
          {
              _MainTex("Albedo (RGB)", 2D) = "white" {} // :: 불 모양
              _MainTex2("Albedo (RGB)", 2D) = "white" {} // :: 흘러가는 불 기둥
          }
          SubShader
          {
              Tags { "RenderType"="Transparent" "Queue"="Transparent" } // :: 투명도 적용
              LOD 200
      
              CGPROGRAM
              #pragma surface surf Standard alpha:fade // :: 투명도 적용
      
              sampler2D _MainTex;
              sampler2D _MainTex2;
      
              struct Input
              {
                  float2 uv_MainTex;
                  float2 uv_MainTex2;
              };
      
              void surf (Input IN, inout SurfaceOutputStandard o)
              {
                  // :: 2번째의 노이즈를 우선 연산(-y 위로 올라가도록)
                  fixed4 c = tex2D (_MainTex2, float2(IN.uv_MainTex2.x, IN.uv_MainTex2.y - _Time.y));
                  
                  // :: cr <= c 텍스쳐(노이즈)의 의존도(투명도?)를 0.5(50%)로 낮춤
                  // :: 노이즈보다 불 모양을 우선시하라는 것으로 이해
                  float cr = c * 0.5; 
                  
                  // :: Saturate : 0 이하의 값을 0으로 1 이상의 값을 1로 즉, 이미지 한계 조정
                  fixed4 d = tex2D(_MainTex, saturate(IN.uv_MainTex + cr));
                  
                  // :: Emission : Light 영향을 적게
                  o.Emission = d.rgb; 
                  o.Alpha = d.a; // :: 투명도
              }
              ENDCG
          }
          FallBack "Diffuse"
      }
  4. 새 Material 제작 후 Custom / Fire 쉐이더 적용
  5. 각 불 모양의 이미지를 해당 Material에 넣는다.
    1. 첫번째 Albedo : 불 모양
    2. 두번째 Albedo : 노이즈
  6. 완성

 
 

 

 

블로그 이미지

RIsN

,

진행과정

  1. 알파 채널이 있는 불 이미지들(fireTest : 불 모양 / 4_2 : 불 기둥 모양)을 준비해 프로젝트에 넣는다.
    fireTest.tga
    4.00MB
    4_2.tga
    0.25MB
  2. 3D > Quad 제작
  3. 새 Standard Surface Shader 제작 및 수정
    1. //
      // >> 흘러가는 형태의 불
      //
      Shader "Custom/Fire"
      {
          Properties
          {
              _MainTex("Albedo (RGB)", 2D) = "white" {} // :: 불 모양
              _MainTex2("Albedo (RGB)", 2D) = "white" {} // :: 흘러가는 불 기둥
          }
          SubShader
          {
              Tags { "RenderType"="Transparent" "Queue"="Transparent" } // :: 투명도 적용
              LOD 200
      
              CGPROGRAM
              #pragma surface surf Standard alpha:fade // :: 투명도 적용
      
              sampler2D _MainTex;
              sampler2D _MainTex2;
      
              struct Input
              {
                  float2 uv_MainTex;
                  float2 uv_MainTex2;
              };
      
              void surf (Input IN, inout SurfaceOutputStandard o)
              {
                  fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
                  fixed4 d = tex2D (_MainTex2, float2(IN.uv_MainTex2.x, IN.uv_MainTex2.y - _Time.y)); // :: -y 위로 흘러가도록
                  // :: Emission : Light 영향을 적게
                  // :: c 텍스쳐와 d 텍스쳐를 곱해서 둘이 겹쳐져 흘러가는 것
                  o.Emission = c.rgb * d.rgb; 
                  o.Alpha = c.a * d.a; // :: 투명도
              }
              ENDCG
          }
          FallBack "Diffuse"
      }
  4. 새 Material 제작 후 Custom / Fire 쉐이더 적용
  5. 각 불 모양의 이미지를 해당 Material에 넣는다.
    1. 첫번째 Albedo : 불 모양
    2. 두번째 Albedo : 불 기둥
  6. 완성

블로그 이미지

RIsN

,