ブロックチェーンシミュレータ（２）


[ブロックチェーンシミュレータ（１）](https://qiita.com/MichihiroTsukano/items/8639416e128a3fcc1274)の続きになります。

ブロックチェーン技術に関してより詳しい記事 → [ブロックチェーン技術及び関連技術](https://qiita.com/MichihiroTsukano/items/1485f05a45a37d7ffe08)

今回は実際に**Unity(2D)**を使って**ブロックチェーンシミュレータ**の制作の内容を記していきます。**手順を一つずつ書いてはいない**ので、中級者以上向けになると思います。もし分からないことがあれば、コメントをください。
![スクリーンショット 2018-10-19 21.34.51.png](https://qiita-image-store.s3.amazonaws.com/0/309633/a1489b58-adac-311f-d293-0f4728c6ced2.png)

上記の画像が完成した**Game Scene**になります。これを作っていきましょう。
シーンは全部で**main、Game Scene、Win Scene、Lose Scene**の4つのシーンがあります。制作の際に使っている素材に関しては[Piskel](https://www.piskelapp.com/)で自作しています。



# mainのシーンの作成

![スクリーンショット 2018-11-02 17.38.35.png](https://qiita-image-store.s3.amazonaws.com/0/309633/8b010fa7-7928-5749-801d-68f3f2c7b1f9.png)
こちらがmainのシーンになります。
**難易度選択**に関して、**UI**の**Dropdown**を使っていますが、上から順に**EASY,NOMAL,HARD,DEMO**としています。
このシーンのスクリプトとして、**main.csをMain Cameraにアタッチ**しましょう。



```main.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class main : MonoBehaviour {

    public Dropdown _dLevelValue;
    public static int _iLevelValue;
    public Image[] _iBlockRedMain;
    public Image[] _iBlockBlueMain;

    private float _fTimeLimit = 0.5f;
    private int _iCounter = 0;

    // Use this for initialization
    void Start () {
        ResetBlock();
    }
	
	// Update is called once per frame
	void Update () {
        _iLevelValue = _dLevelValue.value;
        _fTimeLimit -= Time.deltaTime;

        if (_fTimeLimit <= 0.0){
            _iBlockRedMain[_iCounter].gameObject.SetActive(true);
            _iBlockBlueMain[_iCounter].gameObject.SetActive(true);
            _iCounter++;
            _fTimeLimit = 0.5f;
        }

        if (_iCounter == 5){
            ResetBlock();
            _iCounter = 0;
        }
    }
    public void StartButton(){
        SceneManager.LoadScene("Game Scene");
    }

    private void ResetBlock(){
        for (int i = 0; i < 4; i++){
            _iBlockRedMain[i].gameObject.SetActive(false);
            _iBlockBlueMain[i].gameObject.SetActive(false);
        }
    }
}

```

public static int _ iLevelValueのようにstaticをつけることで、他のクラスでも、_iLevelValueに格納されている値を使うことができます。
また、**publicとして定義した変数にそれぞれ、対応するGameObjectを入れましょう。**





# Game Sceneのシーンの作成

![スクリーンショット 2018-11-02 18.52.30.png](https://qiita-image-store.s3.amazonaws.com/0/309633/fd7173ac-fb0a-9a93-bcc1-e630682ee2ee.png)

こちらがGame Sceneのシーンになります。
BaseValue,AnswerValue,MakeTimeValue,ModValueの各値をTextで表示するので、**UIのTextを24個配置してあります。**
このシーンのスクリプトとして、**GameScene.csをMain Cameraにアタッチ**しましょう。


```GameScene.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameScene : MonoBehaviour {

    public Image[] _iBlockRed;
    public Image[] _iBlockBlue;
    public InputField _iQuestionField;
    public InputField _iAnswerField;
    public Text _tAnswerCounterText,_tMakeCountTimerText;
    public Text[] _tSaveValues;

    private int _iCheckNumberBlockRed = 1, _iCheckNumberBlockBlue = 1;
    private float _fWorldTime, _fTimeLimit = 0;
    private float _fResultNumber, _fModValue, _fBaseNumber, _fMakeTimeValue;
    private int _iSaveCount;
    private float _fMakeCountTimer = 0;

    // Use this for initialization
    void Start () {
        _fBaseNumber = Mathf.Round(Random.Range(0f, 10f));
        _iSaveCount = 0;

        if (main._iLevelValue == 0) { _fWorldTime = 15;}
        else if (main._iLevelValue == 1) { _fWorldTime = 7;}
        else if (main._iLevelValue == 2) { _fWorldTime = 1;}
        else { _fWorldTime = 100;}

        _fTimeLimit = _fWorldTime;

        for (int i = 1;i < 6; i++){
            _iBlockRed[i].gameObject.SetActive(false);
            _iBlockBlue[i].gameObject.SetActive(false);
        }

        ResetAnswerField();
        MakeQuestion();
    }
	
	// Update is called once per frame
	void Update () {
        _fMakeCountTimer += Time.deltaTime;

        if (_fWorldTime != 100) {
            _fTimeLimit -= Time.deltaTime;

            if (_fTimeLimit <= 0.0) {
                _iBlockRed[_iCheckNumberBlockRed].gameObject.SetActive(true);
                _iCheckNumberBlockRed++;
                _fTimeLimit = _fWorldTime;
            }
        }

        if (_fModValue == _fResultNumber){
            MakeQuestion();
        }

        _tAnswerCounterText.text = "求める値:" + _fResultNumber;
        _tMakeCountTimerText.text = "生成時間:" + Mathf.Round(_fMakeCountTimer);

        if (_iCheckNumberBlockRed == 6){SceneManager.LoadScene("Lose Scene");}
        else if (_iCheckNumberBlockBlue == 6){SceneManager.LoadScene("Win Scene");}
    }

    private void MakeQuestion()
    {
        _fModValue = Mathf.Round(Random.Range(1f, 10f));
        _fResultNumber = Mathf.Round(Random.Range(1f, 10f));

        while (_fModValue  < _fResultNumber){
            _fResultNumber = Mathf.Round(Random.Range(1f, 10f));
        }

        _iQuestionField.text = "("+ _fBaseNumber + "+?" + "," + _fModValue + ")";
    }

    private void ResetAnswerField()
    {
        _iAnswerField.text = "";
    }

    public void AnswerButton()
    {
        if (_fResultNumber == Hash1(_fBaseNumber + float.Parse(_iAnswerField.text), _fModValue)){
            _fMakeTimeValue = Mathf.Round(_fMakeCountTimer);
            _fMakeCountTimer = 0;

            _iBlockBlue[_iCheckNumberBlockBlue].gameObject.SetActive(true);
            _iCheckNumberBlockBlue++;

            _tSaveValues[_iSaveCount++].text = _fBaseNumber.ToString();
            _tSaveValues[_iSaveCount++].text = _iAnswerField.text;
            _tSaveValues[_iSaveCount++].text = _fMakeTimeValue.ToString();
            _tSaveValues[_iSaveCount++].text = _fModValue.ToString();

            _fBaseNumber = Hash2(_fBaseNumber, _fMakeTimeValue, float.Parse(_iAnswerField.text), _fModValue);

            ResetAnswerField();
            MakeQuestion();
        }

        ResetAnswerField();
    }

    private float Hash1(float BANumber, float ModValue){
        return BANumber % ModValue;
    }

    private float Hash2(float BaseNumber, float MakeTimeValue, float AnswerNumber, float ModValue)
    {
        return (BaseNumber + AnswerNumber + MakeTimeValue) % ModValue;
    }
}
```
こちらも同じように**publicとして定義した変数にそれぞれ、対応するGameObjectを入れましょう。**



# Win SceneとLose Sceneのシーンの作成


![スクリーンショット 2018-11-02 19.22.42.png](https://qiita-image-store.s3.amazonaws.com/0/309633/0f0e8e80-a30c-9e16-7b92-f4f402687e5e.png)


こちらがWin Sceneのシーンになります。


![スクリーンショット 2018-11-02 19.22.51.png](https://qiita-image-store.s3.amazonaws.com/0/309633/bb4b61e2-1468-9a2f-8fd0-7044441f4910.png)

こちらがLose Sceneのシーンになります。
それぞれのシーンのMain Cameraに**WinScene.cs**と**LoseScene.csをアタッチ**しましょう。

```WinScene.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class WinScene : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    public void MainBackButton(){
        SceneManager.LoadScene("main");
    }
}

```

```LoseScene.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class LoseScene : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    public void MainBackButton(){
        SceneManager.LoadScene("main");
    }
}

```

# 終わりに
以上でブロックチェーンシミュレータの全てとなります。表現の方法はいろいろあると思います。ぜひみなさんなりの表現でアレンジしてください。
ブロックチェーン技術に関しての理解が少しは増したでしょうか。もしそうであれば私は嬉しい限りです。

一つ目→[ブロックチェーンシミュレータ（１）](https://qiita.com/MichihiroTsukano/items/8639416e128a3fcc1274)

ブロックチェーン技術に関してより詳しい記事 → [ブロックチェーン技術及び関連技術](https://qiita.com/MichihiroTsukano/items/1485f05a45a37d7ffe08)