初心者文系主婦がブロックチェーンを学ぶブログ

IT革命のビッグウェーブに乗り遅れた主婦が、ブロックチェーン革命の波にのるべく、ブロックチェーン技術を学ぶブログです。

【CryptZombies】レッスン3チャプター12:Forループ

getZombiesByOwner関数を素直に実装しようとするなら、オーナーからゾンビ軍団へのmappingをZombieFactoryコントラクトに持たせればOKのはずです。

mapping (address => uint[]) public ownerToZombies

新しいゾンビを作る度に、ownerToZombies[owner].push(zombieId)を使ってオーナーのゾンビ配列に追加していくだけです。するとgetZombiesByOwnerは非常にシンプルな関数になります。

function getZombiesByOwner(address _owner) external view returns (uint[]) {
  return ownerToZombies[_owner];
}

 

この方法の問題点

ゾンビを誰かに譲る関数をあとで作成した時に問題が起きます。

その関数には次の動作が必要になります。

1.ゾンビを新しいオーナーのownerToZombies配列に追加する。

2.元のオーナーのownerToZombies配列からゾンビを削除する。

3.穴を埋めるために、元のオーナーの各ゾンビの配列の番号を変更する。

4.配列のlengthを1減らす。

ステップ3は、ゾンビの位置を全てずらすことになるので、ガスコストは非常に高額です。もしオーナーがゾンビを20体持っていて、最初のゾンビを誰かにあげたとします。すると残りの19体の配列番号を書き直さなくてはいけません。

この場合、view関数は外部から呼び出したときにガスコストがかからないので、getZombiesByOwner内でforループを使ってそのオーナーのゾンビ軍団の配列を作ってしまえばOKです。そうすればtransfer関数はstorage内の配列を並び替える必要がないため安く抑えられ。全体のコストも抑えられます。

 

forループを使う

SolidityのforループはJavaScriptと同じようなものです。

forループとは、「これだけの回数、同じ処理を繰り返す」という繰り返し処理を書くときに使う構文です。

<定型>

for (i = 0; i <【繰り返す回数】; i++) {

   繰り返してやりたい処理

}

 

 <説明>

for (【1】,【2】,【3】) {

    【4】

}

 

①変数「i」の中身は、最初は「0」【1】

②変数「i」の中身が5より小さい間、繰り返す【2】

③画面に変数「i」の中身を表示する【4】

④繰り返す度に変数「i」の中身に1足す【3】

 

偶数の数字を格納する配列の例:

function getEvens() pure external returns(uint[]) {
  uint[] memory evens = new uint[](5);
  // 新しい配列のインデックスをトラックする:
  uint counter = 0;
  // 1から10までループさせる:
  for (uint i = 1; i <= 10; i++) {
    // もし `i` が偶数なら...
    if (i % 2 == 0) {
      // 配列に格納する
      evens[counter] = i;
      // カウンタを増やして `evens`の空のインデックスにする:
      counter++;
    }
  }
  return evens;
}

この関数は[2, 4, 6, 8, 10]の配列を返します。

 

テストの実行

getZombiesByOwnerを完成させよ。forループでDApp内の全てのゾンビをループさせ、オーナーが一致するかどうかを判定し、result配列に格納して返却せよ。

①counterというuintを宣言し、0に設定せよ。この変数はresult配列のインデックスとして使用する。

f:id:nomadomama:20181211163730p:plain

 

②uint i = 0から始めて、i < zombies.length(※)までループするforループを宣言せよ。このループは配列内の全てのゾンビをイテレートする。

f:id:nomadomama:20181211164450p:plain

lengthは、主に文字列の長さや配列の要素数を取得することができるプロパティのこと。zombies.lengthでzombies配列の要素数にアクセスできます。

 

③forループ内にifステートメントを作成し、zombieToOwner[i]が_ownerと一致するか判定せよ。2つのアドレスを比較することでチェックしているのだ。

zombieToOwnerマッピングのキーであるiで読み出せるaddress(バリュー)が_ownerと一致するか判定します。

f:id:nomadomama:20181211164526p:plain

 

④ifステートメント内部には以下を設定せよ。

 1.result配列内にゾンビのIDを追加せよ。result[conter]をiと同等になるよう設定するだけでよい。

f:id:nomadomama:20181211164627p:plain

    2.conterを1増やせ。(forループの例を参考にするのだ)

f:id:nomadomama:20181211164703p:plain


お疲れさまでした!

 

 

<参考>

CryptoZombies - イーサリアム上でゲームを開発する方法を学習。Powered by Loom Network

https://wa3.i-3-i.info/word15412.html

【JavaScript入門】lengthで文字列や配列の長さを取得する方法 | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト