目录
一、前言
二、实战
1、实战1-输与赢
1.要求
2.代码
2、实战2-僵尸胜利了
1.要求
2.代码
3、实战3-僵尸失败了
1.要求
2.代码
看了一些区块链的教程,论文,在网上刚刚找到了一个项目实战,CryptoZombies。
我们来继续完善我们的代码,这节课的内容就是实战。
如果你想了解更多有关于机器学习、深度学习、区块链、计算机视觉等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!
对我们的僵尸游戏来说,我们将要追踪我们的僵尸输赢了多少场。有了这个我们可以在游戏里维护一个 "僵尸排行榜"。
所以我们需要在Zombie结构体中添加两个新的属性winCount
和 lossCount。并做相关操作:
1.修改
Zombie
结构体,添加两个属性:winCount
(uint16
),lossCount(uint16)
2.
修改僵尸生成_createZombie()
中的函数定义,让每个新僵尸都有0
赢和0
输。
pragma solidity >=0.5.0 <0.6.0;
import "./ownable.sol";
contract ZombieFactory is Ownable {
event NewZombie(uint zombieId, string name, uint dna);
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
uint cooldownTime = 1 days;
struct Zombie {
string name;
uint dna;
uint32 level;
uint32 readyTime;
// 1. Add new properties here
uint16 winCount;
uint16 lossCount;
}
Zombie[] public zombies;
mapping (uint => address) public zombieToOwner;
mapping (address => uint) ownerZombieCount;
function _createZombie(string memory _name, uint _dna) internal {
// 2. Modify new zombie creation here:
uint id = zombies.push(Zombie(_name, _dna, 1, uint32(now + cooldownTime), 0, 0)) - 1;
zombieToOwner[id] = msg.sender;
ownerZombieCount[msg.sender]++;
emit NewZombie(id, _name, _dna);
}
function _generateRandomDna(string memory _str) private view returns (uint) {
uint rand = uint(keccak256(abi.encodePacked(_str)));
return rand % dnaModulus;
}
function createRandomZombie(string memory _name) public {
require(ownerZombieCount[msg.sender] == 0);
uint randDna = _generateRandomDna(_name);
randDna = randDna - randDna % 100;
_createZombie(_name, randDna);
}
}
假定在我们的游戏中,玩家可以通过支付ETH来升级他们的僵尸。ETH将存储在你拥有的合约中 —— 一个简单明了的例子,向你展示你可以通过自己的游戏赚钱。
1.创建一个
if
语句来检查rand
是不是 小于或者等于attackVictoryProbability
。
2.
如果以上条件为true
, 我们的僵尸就赢了,做如下操作:(1)增加
myZombie
的winCount
。(2)增加
myZombie
的level
。(3)增加
enemyZombie
的lossCount
。(4)运行
feedAndMultiply
函数。 在zombiefeeding.sol
里查看调用它的语句。 对于第三个参数 (_species
),传入字符串 "zombie". (现在它实际上什么都不做,不过在稍后, 如果我们愿意,可以添加额外的方法,用来制造僵尸变的僵尸)。
pragma solidity >=0.5.0 <0.6.0;
import "./zombiehelper.sol";
contract ZombieAttack is ZombieHelper {
uint randNonce = 0;
uint attackVictoryProbability = 70;
function randMod(uint _modulus) internal returns(uint) {
randNonce++;
return uint(keccak256(abi.encodePacked(now, msg.sender, randNonce))) % _modulus;
}
function attack(uint _zombieId, uint _targetId) external ownerOf(_zombieId) {
Zombie storage myZombie = zombies[_zombieId];
Zombie storage enemyZombie = zombies[_targetId];
uint rand = randMod(100);
// Start here
if (rand <=attackVictoryProbability) {
myZombie.winCount++;
myZombie.level++;
enemyZombie.lossCount++;
feedAndMultiply(_zombieId, enemyZombie.dna, "zombie");
}
}
}
在我们的游戏中,僵尸输了后并不会降级 —— 只是简单地给 lossCount
加一,并触发冷却,等待一天后才能再次参战。
1.添加一个
else
语句。 若我们的僵尸输了:(1) 增加
myZombie
的lossCount
。(2)增加
enemyZombie
的winCount
。
2.
在else
最后, 对myZombie
运行_triggerCooldown
方法。这让每个僵尸每天只能参战一次。
注,在这里,我们用到else语句,学过其他编程语言的如C++,应该对else不陌生,在solidity中,和在C++中是一样的。
pragma solidity >=0.5.0 <0.6.0;
import "./zombiehelper.sol";
contract ZombieAttack is ZombieHelper {
uint randNonce = 0;
uint attackVictoryProbability = 70;
function randMod(uint _modulus) internal returns(uint) {
randNonce++;
return uint(keccak256(abi.encodePacked(now, msg.sender, randNonce))) % _modulus;
}
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");
} // start here
else {
myZombie.lossCount++;
enemyZombie.winCount++;
_triggerCooldown(myZombie);
}
}
}