本文共 5076 字,大约阅读时间需要 16 分钟。
看了一些区块链的教程,论文,在网上刚刚找到了一个项目实战,CryptoZombies。
如果你想了解更多有关于机器学习、深度学习、区块链、计算机视觉等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!
之前我们看到,我们使用了一个返回多个值的函数。
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) { Kitty storage kit = kitties[_id]; // if this variable is 0 then it's not gestating isGestating = (kit.siringWithId != 0); isReady = (kit.cooldownEndBlock <= block.number); cooldownIndex = uint256(kit.cooldownIndex); nextActionAt = uint256(kit.cooldownEndBlock); siringWithId = uint256(kit.siringWithId); birthTime = uint256(kit.birthTime); matronId = uint256(kit.matronId); sireId = uint256(kit.sireId); generation = uint256(kit.generation); genes = kit.genes;}
很多用户python的同学对这种方式是比较习惯的,比如,我们写一个函数,我们有一个函数,并给出其参数和自变量的值:
a = 2b = 4c = 6x1 = 1x2 = 1y = a * x1 + b * x2 + c
我们定义一个函数,用于修改参数:
def changePara(new_a,new_b,new_c): return new_a,new_b,new_ca,b,c = changePara(1,2,3)
这种方式就是多返回值。
接下来我们通过一个简单的例子来讲解一下在以太坊中的多返回值。
首先,我们可以定义一个具有多返回值的函数:
function multipleReturns() internal returns(uint a, uint b, uint c) { return (1, 2, 3);}
当我们定义完这样一个函数,我们就可以在下面调用,进行多个参数同时赋值:
function processMultipleReturns() external { uint a; uint b; uint c; // 这样来做批量赋值: (a, b, c) = multipleReturns();}
如果我们只想对一个参数进行赋值,我们对其他的参数留空即可:
// 如果我们只想返回其中一个变量:function getLastReturnValue() external { uint c; // 可以对其他字段留空: (,,c) = multipleReturns();}
我们来定义一个函数,从 kitty 合约中获取它的基因:
1.创建一个名为
feedOnKitty
的函数。它需要2个uint
类型的参数,_zombieId
和_kittyId
,这是一个public
类型的函数。2.函数首先要声明一个名为
kittyDna
的uint
。3.这个函数接下来调用
kittyContract.getKitty
函数, 传入_kittyId
,将返回的genes
存储在kittyDna
中。记住 ——getKitty
会返回一大堆变量。 (确切地说10个 - 我已经为你数过了,不错吧!)。但是我们只关心最后一个--genes
。数逗号的时候小心点哦!4.最后,函数调用了
feedAndMultiply
,并传入了_zombieId
和kittyDna
两个参数。
pragma solidity >=0.5.0 <0.6.0;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) public { require(msg.sender == zombieToOwner[_zombieId]); Zombie storage myZombie = zombies[_zombieId]; _targetDna = _targetDna % dnaModulus; uint newDna = (myZombie.dna + _targetDna) / 2; _createZombie("NoName", newDna); } // define function here function feedOnKitty(uint _zombieId,uint _kittyId) public { uint kittyDna; (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId); feedAndMultiply(_zombieId,kittyDna); }}
我们完成了函数多返回值的学习,也就完成了基本的功能逻辑主体了,接下来我们为其添加一个奖励功能。
首先我们需要给kitty制造的僵尸添加一些特征,用以说明他们是小猫僵尸。我们在第一节课讲到DNA中的前12位用于指定僵尸外观,我们使用后两位来处理特殊特征。
我们常说猫有9条命,所以将最后两位设为99,在这里我们要使用判断语句,这与在JavaScript中差不多。示例如下:
function eatBLT(string sandwich) public { // 看清楚了,当我们比较字符串的时候,需要比较他们的 keccak256 哈希码 if (keccak256(sandwich) == keccak256("BLT")) { eat(); }}
在僵尸代码中实现小猫的基因。:
1.首先,修改下
feedAndMultiply
函数的定义,给它传入第三个参数:一条名为_species
的字符串(存储为memory)。2.接下来,在我们计算出新的僵尸的DNA之后,添加一个
if
语句来比较_species
和字符串"kitty"
的keccak256
哈希值。注意:我们不能直接把字符串传递给keccak256。相反,我们将在左侧传递abi.encodePacked(_species)作为参数,在右侧传递abi.encodePacked(“kitty”)作为参数。
3.在
if
语句中,我们用99
替换了新僵尸DNA的最后两位数字。可以这么做:newDna = newDna - newDna % 100 + 99;4.最后,我们修改了
feedOnKitty
中的函数调用。当它调用feedAndMultiply
时,增加“kitty”
作为最后一个参数。
pragma solidity >=0.5.0 <0.6.0;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); // Modify function definition here: function feedAndMultiply(uint _zombieId, uint _targetDna, string memory _species) public { require(msg.sender == zombieToOwner[_zombieId]); Zombie storage myZombie = zombies[_zombieId]; _targetDna = _targetDna % dnaModulus; uint newDna = (myZombie.dna + _targetDna) / 2; // Add an if statement here if(keccak256(abi.encodePacked(_species)) == keccak256(abi.encodePacked("kitty"))) { newDna = newDna - newDna % 100 + 99; } _createZombie("NoName", newDna); } function feedOnKitty(uint _zombieId, uint _kittyId) public { uint kittyDna; (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId); // And modify function call here: feedAndMultiply(_zombieId, kittyDna, "kitty"); }}
转载地址:http://qzyni.baihongyu.com/