247-cryptozombies全攻略二







cryptozombies全攻略二







第二章.映射mapping和地址address
我们现在要存储僵尸的所有权
就是说
每个僵尸都属于一个用户
一个用户有多个僵尸
所以我们要用映射来反应这个关系
    mapping (uint => address) public zombieToOwner;
    mapping (address => uint) ownerZombieCount;
第一个mapping的key是uint,也就是僵尸的id
value是address,也就是用户的地址

第二个mapping的key是address,用户地址
value是uint,是用户拥有的僵尸的数量










第三章.msg.sender
solidity中,有一些全局变量,可以被所有函数调用
msg.sender获取的是当前调用者的address

我们现在修改_createZombie方法,
把僵尸分配给调用这个函数的用户
    function _createZombie(string _name, uint _dna) private {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        zombieToOwner[id]=msg.sender;
        ownerZombieCount[msg.sender]++;
        NewZombie(id, _name, _dna);
    }

zombieToOwner的key为id,value是地址
ownerZombieCount取出key为msg.sender的int,然后加1,
也就是数量count+1










第四章.require
require的功能是
当require中的条件不满足的时候
就抛出错误,并且停止执行

现在我们修改一下createRandomZombie方法
如果ownerZombieCount[msg.sender]的值为0,才执行
否则就停止执行
也就是说,执行这个方法的时候
看一下这个地址的count,
也就是这个用户拥有的僵尸数量
如果不为0,就停止,
没有僵尸的情况下,才可以创建僵尸
require(ownerZombieCount[msg.sender]==0)

看下完整代码
    function createRandomZombie(string _name) public {
        require(ownerZombieCount[msg.sender]==0);
        uint randDna = _generateRandomDna(_name);
        _createZombie(_name, randDna);
    }











第五章.继承
一个合约Son,继承另一个合约Father
那么子合约就可以调用父合约中的方法
contract ZombieFeeding is ZombieFactory{
    
}








第六章.引入
我们刚刚是把ZombieFeeding这个子合约和父合约写在同一个文件中
如果代码很多,会比较冗长
那么我们可以把这个子合约单独拿出来放在另一文件中
比如
刚刚那个父合约ZombieFactory,我们就放在一个叫
zombiefactory.sol的文件中

然后我们再新建一个文件
叫做zombiefeeding.sol
这个文件就只放ZombieFeeding这个合约

然后我们需要导入一下zombiefactory.sol这个文件
pragma solidity ^0.4.19;

import "./zombiefactory.sol";

contract ZombieFeeding is ZombieFactory {

}










第七章.storage和memory
Storage变量是指永久存储在区块链中的变量
Memory变量则是临时的
当外部函数对某合约调用完成时,内存型变量即被移除

  function feedAndMultiply(uint _zombieId, uint _targetDna) public {
    require(msg.sender == zombieToOwner[_zombieId]);
    Zombie storage myZombie = zombies[_zombieId];
  }

首先用require方法判断msg.sender
根据_zombieId,从zombieToOwner这个mapping中取出address
然后比较msg.sender与address
如果相同,
那么说明当前调用这个方法的用户,是这个僵尸的主人
否则就停止执行











第八章.结合
刚刚我们判断了地址,
然后根据id把从zombies里取出zombie对象
然后现在
我们要根据参数_targetDna和zombie对象的dna
生成一个新的dna
这个新的dna就是新的僵尸的dna
  function feedAndMultiply(uint _zombieId, uint _targetDna) public {
    require(msg.sender == zombieToOwner[_zombieId]);
    Zombie storage myZombie = zombies[_zombieId];
    _targetDna = _targetDna % dnaModulus;
    uint newDna = (_targetDna + myZombie.dna) /2;
    _createZombie("NoName", newDna);
  }

这里我们先将_targetDna取余dnaModulus得到一个标准的16位的dna
然后将_targetDna与原僵尸的dna进行取平均值
然后得到一个新的dna
然后我们根据这个新的dna
生成一个新的僵尸










第九章.函数可见性
我们刚刚写了feedAndMultiply函数
在这个函数中调用了_createZombie方法
但是我们发现,
function _createZombie(string _name, uint _dna) private 
这个函数是private函数
所以实际上我们不能成功调用这个函数
但是我们不能修改成public,因为那样所有人都可以调用createZombie
那么我们应该怎么做

那么除了private和public
还有2个描述函数可见性的修饰词,
就是internal和external

internal和private类似,
但是,子合约可以调用父合约的internal方法

external和public类似,
但是external函数只能在合约之外调用
也就是不能被合约内的其他函数调用

所以这边我们把private改成internal
    function _createZombie(string _name, uint _dna) internal {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        zombieToOwner[id] = msg.sender;
        ownerZombieCount[msg.sender]++;
        NewZombie(id, _name, _dna);
    }











第十章.合约交互
如果我们的合约需要和区块链上的其他合约进行交互
我们需要interface接口

举个例子,假设区块链上有这样一个合约
contract LuckyNumber {
  mapping(address => uint) numbers;

  function setNum(uint _num) public {
    numbers[msg.sender] = _num;
  }

  function getNum(address _myAddress) public view returns (uint) {
    return numbers[_myAddress];
  }
}

然后如果我们的合约需要调用这个LuckyNumber合约里的方法
我们需要定义这个合约的interface接口
contract NumberInterface{
	function getNum(address _myAddress) public view returns(uint);
}


现在,我们尝试一下与区块链上的CryptoKitties这个应用进行交互
CryptoKitties应用里有这样的一个函数getKitty
就是获取一只加密猫CryptoKitty的数据
function getKitty(uint256 _id) external view returns(...){}
我们可以看到,
就是传入一只kitty的id,
然后获取这只kitty的数据

现在我们来试一下
先来写接口
contract KittyInterface{
    function getKitty(uint256 _id) external view returns (
    bool isGestating,
    bool isReady,
    uint256 cooldownIndex,
    uint256 nextActionAt,
    uint256 siringWithId,
    uint256 birthTime,
    uint256 matronId,
    uint256 sireId,
    uint256 generation,
    uint256 genes
);
}










第十一章.使用接口
刚刚我们定义好了接口KittyInterface
现在我们来用一下
  address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
  KittyInterface kittyContract = KittyInterface(ckAddress);

ckAddress就是CryptoKitties的合约的地址
然后我们传入到KittyInterface中就可以了










第十二章.处理多返回值
getKitty方法是多返回值,一共返回了10个值
那么我们要进行接收
  function feedOnKitty(uint _zombieId, uint _kittyId) public {
    uint kittyDna;
    (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
    feedAndMultiply(_zombieId, kittyDna);
  }
我们定义一个uint,kittyDna,来接收kitty的uint256 genes
也就是kitty这个应用也有一个genes属性,来表示kitty的基因
前面的返回值我们都不要,直接用,逗号忽略
然后只接收最后一个返回值,然后指向kittyDna
然后我们用zombieId和kittyDna来调用feedAndMultiply










第十三章.种族
我们修改一下dna,
如果是kitty类型的僵尸
那么dna最后两位就是99
    if (keccak256(_species) == keccak256("kitty")) {
      newDna = newDna - newDna % 100 + 99;
    }










第二大章完成了
看下完整代码

pragma solidity ^0.4.19;

import "./zombiefactory.sol";

contract KittyInterface {
  function getKitty(uint256 _id) external view returns (
    bool isGestating,
    bool isReady,
    uint256 cooldownIndex,
    uint256 nextActionAt,
    uint256 siringWithId,
    uint256 birthTime,
    uint256 matronId,
    uint256 sireId,
    uint256 generation,
    uint256 genes
  );
}

contract ZombieFeeding is ZombieFactory {

  address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
  KittyInterface kittyContract = KittyInterface(ckAddress);

  function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) public {
    require(msg.sender == zombieToOwner[_zombieId]);
    Zombie storage myZombie = zombies[_zombieId];
    _targetDna = _targetDna % dnaModulus;
    uint newDna = (myZombie.dna + _targetDna) / 2;
    
    if (keccak256(_species) == keccak256("kitty")) {
      newDna = newDna - newDna % 100 + 99;
    }
    _createZombie("NoName", newDna);
  }

  function feedOnKitty(uint _zombieId, uint _kittyId) public {
    uint kittyDna;
    (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
    
    feedAndMultiply(_zombieId, kittyDna, "kitty");
  }

}









 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值