이더리움 EVM과 Solidity - 3

Yona·2022년 1월 18일
1

블록체인

목록 보기
14/22
post-thumbnail
post-custom-banner

가위바위보 게임 만들기

사용자와 게임 구조체 생성

가위바위보, 게임 진행 상황

enum Hand {
  rock, paper, scissors
    }

enum PlayerStatus {
  STATUS_WIN, STATUS_LOSE, STATUS_TIE, STATUS_PENDING
    }

enum GameStatus {
  STATUS_NOT_STARTED, STATUS_STARTED, STATUS_COMPLETE, STATUS_ERROR
    }	

ds

struct Player {
  address payable addr;
  uint256 playerBetAmount;
  Hand hand;
  PlayerStatus playerStatus;
    }

struct Game {
  Player originator; // 만든사람
  Player taker; // 들어오는사람
  uint256 betAmount;
  GameStatus gameStatus;
    }

dd

mapping(uint => Game) rooms;
uint roomLen = 0;

modifier isValidHand (Hand _hand) {
  require((_hand == Hand.rock) || (_hand == Hand.paper) || (_hand == Hand.scissors));
  _;
 }

modifier isPlayer (uint roomNum, address sender) {
  require(sender == rooms[roomNum].originator.addr || sender == rooms[roomNum].taker.addr);
  _;
}

CreateRoom - 게임 생성

function createRoom (Hand _hand) public payable isValidHand(_hand) returns (uint roomNum) {
  rooms[roomLen] = Game({
    betAmount: msg.value,
    gameStatus: GameStatus.STATUS_NOT_STARTED,
    originator: Player({
      hand: _hand,
      addr: payable(msg.sender),
      playerStatus: PlayerStatus.STATUS_PENDING,
      playerBetAmount: msg.value
      }),
    taker: Player({
      hand: Hand.rock,
      addr: payable(msg.sender),
      playerStatus: PlayerStatus.STATUS_PENDING,
      playerBetAmount: 0
      })
    });
  roomNum = roomLen;
  roomLen = roomLen+1;
  }

JoinRoom - 방 참가

function joinRoom(uint roomNum, Hand _hand) public payable isValidHand( _hand) {
  rooms[roomNum].taker = Player({
    hand: _hand,
    addr: payable(msg.sender),
    playerStatus: PlayerStatus.STATUS_PENDING,
    playerBetAmount: msg.value
    });
  rooms[roomNum].betAmount = rooms[roomNum].betAmount + msg.value;
  compareHands(roomNum);
  }

CompareHands - 게임 진행

function compareHands(uint roomNum) private {
  uint8 originator = uint8(rooms[roomNum].originator.hand);
  uint8 taker = uint8(rooms[roomNum].taker.hand);

  rooms[roomNum].gameStatus = GameStatus.STATUS_STARTED;
  
  if(taker == originator) { // 비긴 경우
    rooms[roomNum].originator.playerStatus = PlayerStatus.STATUS_TIE;
    rooms[roomNum].taker.playerStatus = PlayerStatus.STATUS_TIE;
    }
  else if ((taker +1) % 3 == originator) { // 방장이 이긴 경우
    rooms[roomNum].originator.playerStatus = PlayerStatus.STATUS_WIN;
    rooms[roomNum].taker.playerStatus = PlayerStatus.STATUS_LOSE;
    }
  else if ((originator + 1)%3 == taker){  // 참가자가 이긴 경우
    rooms[roomNum].originator.playerStatus = PlayerStatus.STATUS_LOSE;
    rooms[roomNum].taker.playerStatus = PlayerStatus.STATUS_WIN;
    }
  else {  // 그 외의 상황에는 게임 상태를 에러로 업데이트한다
    rooms[roomNum].gameStatus = GameStatus.STATUS_ERROR;
    }
  }

Payout - 베팅 금액 송금

function payout(uint roomNum) public payable isPlayer(roomNum, msg.sender) {
  if (rooms[roomNum].originator.playerStatus == PlayerStatus.STATUS_TIE 
      && rooms[roomNum].taker.playerStatus == PlayerStatus.STATUS_TIE) {
    rooms[roomNum].originator.addr.transfer(rooms[roomNum].originator.playerBetAmount);
    rooms[roomNum].taker.addr.transfer(rooms[roomNum].taker.playerBetAmount);
    }
  else {
    if (rooms[roomNum].originator.playerStatus == PlayerStatus.STATUS_WIN) {
      rooms[roomNum].originator.addr.transfer(rooms[roomNum].betAmount);
      } 
    else if (rooms[roomNum].taker.playerStatus == PlayerStatus.STATUS_WIN) {
      rooms[roomNum].taker.addr.transfer(rooms[roomNum].betAmount);
      } 
    else {
      rooms[roomNum].originator.addr.transfer(rooms[roomNum].originator.playerBetAmount);
      rooms[roomNum].taker.addr.transfer(rooms[roomNum].taker.playerBetAmount);
      }
    }
  rooms[roomNum].gameStatus = GameStatus.STATUS_COMPLETE; // 게임이 종료되었으므로 게임 상태 변경
  }

어렵다...😭😭😭😭😭


가위바위보에서 내가 무엇을 냈는지 보여지면 안된다... public 말고 private 로 하면 되지않을까 싶다..?

post-custom-banner

0개의 댓글