249-cryptozombies全攻略四










cryptozombies全攻略四








第一章.可支付
先总结一下之前的函数修饰符
1.private  合约内部调用
2.public   任何地方调用
3.internal 能被继承的合约调用
4.external 只能从合约外部调用

5.view	   不会更改和保存任何数据
6.pure	   不写数据,也不读数据

7.自定义modifier

然后我们来学一个新的函数修饰符payable
payable方法是一种可以接收以太的特殊函数
在以太坊中,因为钱(以太),数据(事务负载)以及合约代码
本身都存在于以太坊,
所以可以同时调用函数并付钱给另一个合约

举个例子
contract OnlineStore {
  function buySomething() external payable {
    // 检查以确定0.001以太发送出去来运行函数:
    require(msg.value == 0.001 ether);
    // 如果为真,一些用来向函数调用者发送数字内容的逻辑
    transferThing(msg.sender);
  }
}

我们来写一个payable函数
  uint levelUpFee = 0.001 ether;

  function levelUp(uint _zombieId) external payable {
    require(msg.value == levelUpFee);
    zombies[_zombieId].level++;
  }
这里我们定义一个uint,为0.001以太
然后写一个payable方法
如果数额满足0.001以太
那么就根据zombieId找到zombie
然后让它的level+1











第二章.提现
我们需要写一个函数从合约中提现以太
举个例子
contract GetPaid is Ownable {
  function withdraw() external onlyOwner {
    owner.transfer(this.balance);
  }
}
这里的this.balance将返回这个合约里存储了多少以太
然后通过transfer

我们可以通过transfer向任何以太坊地址付钱
比如
msg.sender.transfer(msg.value);

我们创建一个withdraw函数用来提现
再创建一个函数,来设置levelUpFee来修改这个费用
  function withdraw() external onlyOwner {
    owner.transfer(this.balance);
  }

  function setLevelUpFee(uint _fee) external onlyOwner {
    levelUpFee = _fee;
  }










第三章.新合约
pragma solidity ^0.4.19;

import "./zombiehelper.sol";

contract ZombieBattle is ZombieHelper {

}










第四章.随机数
我们还是通过keccak256来制造一些随机数
uint randNonce = 0;
uint random = uint(keccak256(now, msg.sender, randNonce)) % 100;
randNonce++;
uint random2 = uint(keccak256(now, msg.sender, randNonce)) % 100;
通过时间,地址和randNonce来生成随机数

contract ZombieBattle is ZombieHelper {

  uint randNonce = 0;

  function randMod(uint _modulus) internal returns(uint) {
    randNonce++;
    return uint(keccak256(now, msg.sender, randNonce)) % _modulus;
  }

}

我们定义一个randNonce
然后创建一个randMod函数
传入一个uint _modulus,返回一个uint
每次执行函数的时候
randNonce++
然后我们根据now,msg.sender,randNonce计算出一个keccak256值
再用这个值% _modulus
得到一个伪随机数.












第五章.对战
定义一个  uint attackVictoryProbability = 70;
再创建一个函数
  function attack(uint _zombieId, uint _targetId) external {
  }
传入一个zombieId,再传入一个targetId,也就是要攻击的僵尸的id












第六章.重构通用逻辑
在我们执行attack方法的时候
需要去检查一下传入的zombieId的拥有者是否是当前用户
所以我们需要执行
require(msg.sender == zombieToOwner[_zombieId]);

我们发现再很多方法里面我们都需要执行这个方法
那么我们可以把这行代码
放到modifier里面,变成一个函数修饰符

  modifier ownerOf(uint _zombieId) {
    require(msg.sender == zombieToOwner[_zombieId]);
    _;
  }










第七章.重构
然后我们把其他的一些方法加上ownerOf修饰符
  function changeName(uint _zombieId, string _newName) external aboveLevel(2, _zombieId) ownerOf(_zombieId) {
    zombies[_zombieId].name = _newName;
  }

  function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) ownerOf(_zombieId) {
    zombies[_zombieId].dna = _newDna;
  }












第八章.攻击
  function attack(uint _zombieId, uint _targetId) external ownerOf(_zombieId) {
    Zombie storage myZombie = zombies[_zombieId];
    Zombie storage enemyZombie = zombies[_targetId];
    uint rand = randMod(100);
  }
我们根据_zombieId从zombies里面拿到myZombie对象
再根据_targetId从zombies里面拿到enemyZombie对象
然后给randMod方法传入一个modulus,100
拿到一个rand随机数












第九章.输赢
我们需要给Zombie结构体增加两个属性
    struct Zombie {
      string name;
      uint dna;
      uint32 level;
      uint32 readyTime;
      uint16 winCount;
      uint16 lossCount;
    }












第十章.胜利
  function attack(uint _zombieId, uint _targetId) external ownerOf(_zombieId) {
    Zombie storage myZombie = zombies[_zombieId];
    Zombie storage enemyZombie = zombies[_targetId];
    uint rand = randMod(100);
    if (rand <= attackVictoryProbability) {
      myZombie.winCount++;
      myZombie.level++;
      enemyZombie.lossCount++;
      feedAndMultiply(_zombieId, enemyZombie.dna, "zombie");
    }

如果rand随机数小于等于attackVictoryProbability
也就是小于等于70的时候,就是胜利了
那么winCount++
level++
然后输家lossCount++
然后调用feedAndMultiply













第十一章.失败
  function attack(uint _zombieId, uint _targetId) external ownerOf(_zombieId) {
    Zombie storage myZombie = zombies[_zombieId];
    Zombie storage enemyZombie = zombies[_targetId];
    uint rand = randMod(100);
    if (rand <= attackVictoryProbability) {
      myZombie.winCount++;
      myZombie.level++;
      enemyZombie.lossCount++;
      feedAndMultiply(_zombieId, enemyZombie.dna, "zombie");
    } else {
      myZombie.lossCount++;
      enemyZombie.winCount++;
      _triggerCooldown(myZombie);
    }
  }
失败后
自身lossCount++;
赢家winCount++;
然后执行triggerCooldown方法











 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值