[크립토좀비게임]-좀비공장만들기

오미희·2021년 10월 10일
0

blockchain

목록 보기
7/13

크립토 좀비게임 : https://cryptozombies.io/ko/

1. 좀비공장만들기

전체코드

pragma solidity ^0.4.19;

contract ZombieFactory {

    event NewZombie(uint zombieId, string name, uint dna);

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;

    function _createZombie(string _name, uint _dna) private {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        NewZombie(id, _name, _dna);
    }

    function _generateRandomDna(string _str) private view returns (uint) {
        uint rand = uint(keccak256(_str));
        return rand % dnaModulus;
    }

    function createRandomZombie(string _name) public {
        uint randDna = _generateRandomDna(_name);
        _createZombie(_name, randDna);
    }

}

코드해석

1. 1 컨트랙트

pragma solidity ^0.4.19;
// 모든 솔리디리 코드는 pragma solidity '버전' 으로 시작함.
// solidity는 버전업이 빨라 버전을 함께 명시해 줌으로써 추후에 
					// 버전업이 맞지 않아 발생하는 오류를 줄여줌.
// 즉 쓰여진 솔리디티 언어를 어떤 버전으로 컴파일 할 것인지에 대한 명시.

contract ZombieFactory{
// ZombieFactory 컨트랙트를 생성한다는 의미
// 솔리디티 코드는 컨트랙트 안에 담김.
// 클래스와 비슷한 개념.

}

컴파일이란?
   사람이 해석할 수 있는 프로그래밍 언어로 쓰여진 코드를 컴퓨터가 이해할 수 있는    언어로 바꾸어 주는 것

1. 2 상태변수 & 정수

pragma solidity ^0.4.19;

contract ZombieFactory{
  uint dnaDigits = 16;
  // 부호없는정수의 자료형인 uint로 dnaDigits를 선언하고 16이라는 값을 저장.
  // uint -> 부호없는 정수의 자료형 즉 값이 음수가 아니어야 함
  // int -> 부호있는 정수의 자료형
}

상태변수?        --- state variable ---
  컨트랙트 저장소에 영구히 저장될 것.
  즉 이더리움 블록체인에 영원히 저장되는 내용을 의미.

1. 3 수학연산

pragma solidity ^0.4.19;

contract ZombieFactory{
	uint dnaDigits = 16;
  	uint dnaModulus = 10 ** dnaDigits;
  // uint형으로 dnaModules 변수를 생성하고 10의 danDigits 승을 값으로 담음.
}

solidity 수학연산자

-- 덧셈 : +

-- 뺄셈 : -

-- 곱셈 : *

-- 나누기 : /

-- 나머지 : %

-- 제곱 : **

1. 4 구조체

pragma solidity ^0.4.19;

contract ZombieFactory{
	uint dnaDigits = 16;
  	uint dnaModulus = 10 ** dnaDigits;
  
  	struct Zombie{
      // Zombie라는 구조체 생성
      // 구조체 생성시에는 struct '변수명'
    	      string name;
      	      uint dna;
      	     // Zombie구조체는 string형의 name과 uint형의 dna 두가지 특성을 가짐.
    }
}

구조체?         --- struct type ---
  각각 다른 유형의 변수를 묶는 사용자 정의 유형.

1. 5 배열 ( 정적 / 동적 )

pragma solidity ^0.4.19;

contract ZombieFactory{
    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;
    
    struct Zombie{
    	string name;
        uint dna;
    }
}

1. 5 -1 정적배열

: 배열의 크기가 고정되어 있음, 고정된 크기만큼만 메모리 공간을 할당하여 메모리 절약.
-- 배열 선언시 크기 고정

uint[2] fixedArray
// 정적배열에서는 배열안에 준 원소값 만큼의 원소만 가짐.

1. 5 -2 동적배열

: 배열의 크기를 정하지 않고,
-- 실행시 배열의 크기 결정됨.

uint dynamicArray
// 배열내 원소 수의 제약 없이 원소를 자유롭게 가짐. 

*** 구조체의 배열을 생성하는 것도 가능

Zombie[] zombies;
pragma solidity ^0.4.19;

contract ZombieFactory{
   uint dnaDigits = 16;
   uint dnaModulus = 10 ** dnaDigits;
  
   struct Zomble {
      string name;
      uint dna;
   }
  
   Zombie[] public zombies;
  // Zombie 구조체의 배열을 public으로 선언후 이름을 zombies로 함. 
}

*** public으로 선언한 경우 getter 함수를 자동 생성

  • getter   :
let MyMeMine = {
	name:'mihee',
    age:26,
    get I(){
    	return `이름 : ${this.name} 나이 : ${this.age}`
    }
}
// console.log(MyMeMine.I)   // 이름 : mihee 나이 : 26
  • setter

1. 6 함수선언

pragma solidity ^0.4.19;

contract ZombieFactory {
	uint dnaDigits = 16;
  	uint dnaModulus = 10 ** dnaDigits;
  
  	struct Zombie {
    	    string name;
      	    uint dna;
    }
  	Zombie[] public zombies;
  
  	function createZombie(string _name, uint _dna) {
    // string형의 _name과 uint형의 _dna 두 인자를 받는 createZombie함수
    }
} 

1. 7 구조체와 배열 활용

pragma solidity  ^0.4.19;

contract ZombieFactory{
	uint dnaDigits = 16;
  	uint dnaModulus = 10 ** dnaDigits;
  
  	struct Zombie {
    	    string name;
      	    uint dna;
    }
  	Zombie[] public zombies;
  
  	function createZombie(string _name,uint _dna) {
    	zombies.push(Zombie(_name,_dna));
        // createZombie 함수를 만들고, 
        // 함수내용으로 동적배열인 zombies에 인자값인 
        			//_name과 _dna을 통해 구조체 Zombie를 새롭게 생성
    }
}

1. 8 private / public 함수

** 솔리디티에서 함수는 기본적으로 public으로 선언된다.

pragma solidity ^0.4.19;

contract ZombieFactory{
	uint dnaDigits = 16;
    uint dnamodulus = 10 ** dnaDigits;
    
    struct Zombie{
    	string name;
        uint dna;
    }
    Zombie[] public zombies;
    
    function _createZombie(string _name, uint _dna) private {
     	zombies.push(Zombie(_name,_dna));
        // private으로 선언하는 함수명은 _로 시작하는 것이 관례.
    }
}

접근제어자

  • private
    : 해당 컨트랙트 내에서만 사용이 가능한 것.
  • public
    : 해당 컨트랙트 뿐만 아니라 다른 컨트랙트에서도 호출 가능하도록 되어있는 것.

1. 9 함수의 반환값 / 함수제어자

pragma solidity ^0.4.19;

contract ZombieFactory{
	uint dnaDigits = 16;
  	uint dnaModulus = 10 ** dnaDigits;
  
  	struct Zombie {
    	    uint name;
      	    uint dna;
    	}
  	Zombie[] public zombies;
  
  	function _createZombie(string _name, uint _dna) private{
      		zombies.push(Zombie(_name,_dna);
    	}
  	function _generateRandomDna(string _str) private view returns(uint){
    	// _generateRandomDna함수는 uint형 값을 반환함.
      	// view로 선언
        }
}

함수의 반환값
: 반환값을 가지는 함수의 경우 returns를 명시하고 그 뒤에(자료형), 반환되는 값을 자료형을 넣어준다.

function sayHello() public returns (string){
	return "Hello"
  	// 주의!! 함수 선언에서 선언하는 것은 return이 아닌 returns이다.
  	// sayHello함수는 string형태의 값을 반환하여줌
}

함수의 제어자

  • view
    : 다른 데이터에 접근하지만, 그 상태는 변화시키지 않고, 기존의 데이터 그대로 읽기만 하는 것. ==> 즉 읽기전용
string greeting = "what's up dog";
function sayHello() public view returns (string) {
	return greeting;
  // sayHello함수에서 string형태의 greeting데이터에 접근,
  // 해당 데이터의 상태 변화없이 그대로 읽고 데이터를 반환함.
}
  • pure
    : 어떠한 데이터에도 읽지도 변경시키지도 않음, 즉 다른 컨트랙트의 어떠한 data에도 접근하지 않음. ==> 순수하게 인자값만을 이용.
    // 인자값을 받아 해당 인자값을 활용하여 값 반환
function _multply(uint a, uint b) private pure returns (uint) {
	return a * b;
  // 다른 데이터를 받는 것 없이 인자값만을 받아 이용하여 반환.
}

** view와 pure의 구분은 경고메세지를 통해 구분 가능.

1. 10 Keccak256과 형변환

pragma solidity ^0.4.19;

contract ZombieFactory {
  uint dnaDigits = 16;
  uint dnaModulus = 10 ** dnaModulus;
  
  struct Zombie {
  	string name;
        uint dna;
  }
  
  Zombie[] public zombies;
  
  function _createZombie(string _name, uint _dna) private {
    zombies.push(Zombie(_name, _dna));
  }
  function _generateRandomDna(string _str) private view returns (uint) {
  	uint rand = uint(keccak256(_str));
    	return rand % dnamodulus;
    // _str을 솔리디티의 내장해시함수인 keccak256함수를 이용하여 난수를 생성하고
    // 생성된 난수를 uint형으로 변환하고 이를 다시 uint형 rand에 담음
    // rand에 담아진 결과값에 % dnamodulus 하여 return함
  }
}

keccak256()
: 이더리움의 내장해시함수, 난수생성함수
형변환
: 변환하려는 자료형을 명시후 변환하려는 값을 ()안에 넣어줌.

uint8 a = 5;
uint b = 6;
// 위의 a와 b는 현재 자료형이 같지 않아서 연산에 함께 이용할 경우 오류 유발
// 그러므로 형 변환 필요
uint c = a * uint8(b);
// uint형인 b를 uint8로 감싸서 형변환시킴.

1. 11 이벤트

pragma solidity ^0.4.19;

contract ZombieFactory {
  event NewZombie(uint zombieId, string name, uint dna);
  //이벤트 선언
  // 이벤트 => 내가 생성한 컨트랙트가 블록체인 상에서 앱의 사용자 단에서 액션이
  //          발생하면 의사소통하는 방법.
  
  uint dnaDigits = 16;
  uint dnaModulus = 10 ** dnaDigits;
  
  struct Zombie {
  	string name;
    	uint dna;
  }
  
  zombie[] public zombies;
  
  function _createZombie(string _name, uint _dna) private {
   	uint id = zombies.push(Zombie(_name, _dna)) - 1;
    	NewZombie(id, _name, _dna);
    //이벤트가 실행되는 부분
  }
  function -generateRandomDna(string _str) private view returns (uint) {
  	uint rand = uint(keccak256(_str));
    	return rand % dnaModulus; 
  }
  function createRandomZombie(string _name) public {
  	uint randDna = _generateRandomDna(_name);
    	_createZombie(_name, rnaDna)
  }

}

이벤트
: 특정한 조건이 충족될 때 사전에 프로그래밍된 특정한 기능이 수행되도록 한 것.
// 이벤트는 프론트와 연결되어 특정 조건이 충족되는 경우 프론트에서도 충족된 해당 내용과 일치하는 결과 출력.

// 프론트단 코드 예시)
myContract.NewZombie(function(error,result)=>{
   // 사전에 명시된 조건이 충족된 경우 발생할 이벤트내용
})

1. 12 web3

: 완성된 컨트랙트와 상호작용하는 사용자 단의 자바스크립트코드의 작성을 쉽게 할 수 있도록 도와주는 라이브러리.
// web3에 대해 더욱 알아볼 것...!!!

// 아래의 코드는 해당 cryptozombies사이트에서 완전히 복사 붙여넣기 한 내용
// 아직 온전히 이해는 하지 못했음
// 나중에 이해를 돕기 위한 참고용
var ZombieFactoryContract = web3.eth.contract(abi)
var contractAddress = /* 배포된 이후 컨트랙트 주소 */
var ZombieFactory = ZombieFactoryContract.at(contractAddress)
// `ZombieFactory`는 우리 컨트랙트의 public 함수와 이벤트에 접근할 수 있다.

// 일종의 이벤트 리스너가 텍스트 입력값을 취한다:
$("#ourButton").click(function(e) {
  var name = $("#nameInput").val()
  // 우리 컨트랙트의 `createRandomZombie`함수를 호출한다:
  ZombieFactory.createRandomZombie(name)
  // createRandomZombie함수 안에는 _createZombie() 함수가 존재
})

// `NewZombie` 이벤트가 발생하면 사용자 인터페이스를 업데이트한다
var event = ZombieFactory.NewZombie(function(error, result) {
  if (error) return
  generateZombie(result.zombieId, result.name, result.dna)
})

// 좀비 DNA 값을 받아서 이미지를 업데이트한다
function generateZombie(id, name, dna) {
  let dnaStr = String(dna)
  // DNA 값이 16자리 수보다 작은 경우 앞 자리를 0으로 채운다
  while (dnaStr.length < 16)
    dnaStr = "0" + dnaStr

  let zombieDetails = {
    // 첫 2자리는 머리의 타입을 결정한다. 머리 타입에는 7가지가 있다. 
    // 그래서 모듈로(%) 7 연산을 하여
    // 0에서 6 중 하나의 값을 얻고 여기에 1을 더해서 1에서 7까지의 숫자를 만든다. 
    // 이를 기초로 "head1.png"에서 "head7.png" 중 하나의 이미지를 불러온다:
    headChoice: dnaStr.substring(0, 2) % 7 + 1,
    // 두번째 2자리는 눈 모양을 결정한다. 눈 모양에는 11가지가 있다:
    eyeChoice: dnaStr.substring(2, 4) % 11 + 1,
    // 셔츠 타입에는 6가지가 있다:
    shirtChoice: dnaStr.substring(4, 6) % 6 + 1,
    // 마지막 6자리는 색깔을 결정하며, 360도(degree)까지 지원하는 
    //CSS의 "filter: hue-rotate"를 이용하여 아래와 같이 업데이트된다:
    skinColorChoice: parseInt(dnaStr.substring(6, 8) / 100 * 360),
    eyeColorChoice: parseInt(dnaStr.substring(8, 10) / 100 * 360),
    clothesColorChoice: parseInt(dnaStr.substring(10, 12) / 100 * 360),
    zombieName: name,
    zombieDescription: "A Level 1 CryptoZombie",
  }
  return zombieDetails
}
profile
안녕하세요

0개의 댓글