본문 바로가기

블록체인_9기/⛓ BlockChain

66강_231005_Blockchain(컨트랙트 배포, 숫자 야구 게임)

728x90

 

 

 


Contract Truffle 배포

counter.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract Counter{
    uint256 value;

    constructor(){}

    function increment() public {
        value += 1;
    }

    function decrement() public {
        // 조건식. value가 0이 아니면 실행
        // 조건문 통과가 안되면 가스비 지불하지 않고 에러구문이 뜬다.
        require(value != 0, "vlaue 0 error");
        value -= 1;
    }

    function getValue() public view returns(uint256){
        return value;
    }
}

 

1_deploy_Counter.js

// build 폴더 안에 컴파일된 Counter.json을 가져온다.
const Counter = artifacts.require("Counter");

module.exports = (deployer)=>{
    // deployer.deploy 메서드를 통해, 가져온 json파일 내용으로 배포를 진행한다.
    deployer.deploy(Counter);
}

 

 


숫자 야구 게임

Baseball.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract Baseball{
    // 컨트랙트를 배포한 사람
    // 컨트랙트 소유자를 지정. CA에 있는 balance를 가져오거나 게임을 리셋시킬 수 있는 사람.

    // 게임 규칙
    //// 1. 컴퓨터가 숫자 3개를 랜덤하게 뽑는다.
    //// 2. 이 숫자 3개를 플레이어들이 맞추는 게임
    //// 3. 숫자를 입력해서 값을 비교하고 틀리면 그 사람은 이더를 CA에 보낸다.
    //// 4. CA 플레이어들이 게임을 하면서 모인 이더를 최종적으로 맞춘 사람에게 보상으로 준다.
    //// 5. 게임 플레이 횟수가 있는데 라운드가 모두 종료되었을 때까지 아무도 맞추지 못하면 보상은 플레이어가 아닌 컨트랙트 소유자가 보상으로 받는다.

    // 컨트랙트 배포자
    address private owner;

    // 게임의 횟수
    // constant : 상태를 변경하지 않는 상태 변수이다. (JS의 const 같은)
    uint256 private constant GAME_COUNT = 5;

    // 게임에 참가하기 위해 지불해야 하는 이더
    uint256 private ticket = 5 ether;

    // 정답의 값(랜덤 값)을 담아놓을 변수
    // 컴퓨터가 정할 랜덤 값. 3자리 수의 숫자
    uint256 private random;

    // 게임의 진행도
    uint256 private progress;

    // 플레이어가 지불한 총 상금
    uint256 private reward;

    // 게임의 현재 상태
    enum GameStatus {
        Playing,    // 0
        GameOver   // 1
    }

    GameStatus gameStatus;  // 최초의 상태 값은 0이다. 따라서 게임 플레이(playing) 중이다.

    // 컨트랙트 생성자
    // 컨트랙트가 배포되면 딱 한 번 실행된다.
    // 따라서, 컨트랙트 생성자를 실행시킨 사람이 배포자일 것이다.
    constructor(){
        // 최초에 딱 한 번 배포자가 상태변수에 담긴다.
        owner = msg.sender;

        // keccak256 : 솔리디티에서 랜덤 값을 뽑을 때 사용한다. 매개변수를 해시 값으로 변경해준다.
        // SHA-3을 사용한다.
        // block
        // abi.encodePacked : 매개변수로 전달 된 내용들을 가지고 바이트 배열로 만들어준다.
        random = uint256(keccak256(abi.encodePacked(block.timestamp, block.coinbase, block.number)));
        // 큰 숫자가 나오는데, 이 숫자를 가지고 나머지 연산을 통해 원하는 자릿수의 숫자를 구하자
        
        // 100 ~ 999 까지의 범위를 지정할 예정이다.
        random = (random % 900) + 100;
        // 100 ~ 999 까지의 랜덤 값
    }

    // 유저의 값을 받아서 비교를 통해 값이 맞는지 게임의 정답을 맞췄는지 구할 함수
    function gameStart(uint256 _value) public payable {
        require(progress < GAME_COUNT, "GameOver");     // 게임의 진행도가 정해진 라운드를 지났는지
        require(msg.value == ticket, "ticket amount error (5 ether)" );     // 지불한 금액이 티켓 금액과 동일한지 확인
        require((_value >= 100) && (_value < 1000), "_value error (99 < _value < 1000)");      // 입력한 값이 100~999의 값인지 확인

        progress += 1;

        if(_value == random){       // 정답을 맞췄으면
            // 게임 끝
            // this.balance : 게임 CA에 잔액을 가리킨다.
            require(reward <= address(this).balance);       // CA의 잔액이 보상만큼 있는지 검사
            payable(msg.sender).transfer(address(this).balance);
            reward = 0;

            // gameStatus 상태가 상수값 1로 들어감
            // 1은 게임이 끝났다는 얘기이다.
            gameStatus = GameStatus.GameOver;
        }
        else if(progress == GAME_COUNT){
            // 게임 끝
            // this.balance : 게임 CA에 잔액을 가리킨다.
            require(reward <= address(this).balance);       // CA의 잔액이 보상만큼 있는지 검사
            payable(owner).transfer(address(this).balance);
            reward = 0;

            // gameStatus 상태가 상수값 1로 들어감
            // 1은 게임이 끝났다는 얘기이다.
            gameStatus = GameStatus.GameOver;
        }
        else{
            reward += msg.value;
        }
    }

    // 지금 현재 쌓인 보상을 보여줄 함수
    function getReward()public view returns(uint256){
        return reward;
    }

    // 게임이 얼마나 진행됐는지 보여줄 함수
    function getProgress() public view returns(uint256){
        return progress;
    }

    // 티켓의 금액을 보여줄 함수
    function getTicketPrice() public view returns(uint256){
        return ticket;
    }

    // 어드민 모드로 정답을 확인하는 함수
    function getRandom() public view returns(uint256){
        require(msg.sender == owner, "only admin");
        return random;
        // return msg.sender;
    }

    // 게임 중인지 확인할 함수
    function getPlaying() public view returns(uint256){
        // 메모리 영역 변수. 지역변수로 생각하면 된다.
        // 게임이 진행되고 있는 상수값이 0
        uint256 Playing = 0;
        if((gameStatus != GameStatus.Playing) || (progress == GAME_COUNT)){
            // 게임이 끝났다.
            Playing = 1;
        }
        return Playing;
    }

    // 게임을 재시작하는 함수
    function setRestart() public {
        gameStatus = GameStatus.Playing;
        reward = 0;
        progress = 0;
    }
}

 

 

 

728x90