2

the code

pragma solidity ^0.4.13;

contract TicTacToe {


    uint[3][]   arr ;

    function isSolved(int[3][] board) returns (int) {
        arr = board;
        //检查每个数组是不是横向的存在

        int check  = 0;
        int h1 =  checkH(arr[1]);

        if(h1 == -1){
            int h2 =  checkH(arr[2]);
            if(h2 == -1){
                int h3 =  checkH(arr[3]);
                 check = h3;

            }else{
                check = h2;
            }
        }else{
          check = h1;
        }


        if(check == -1){
            check = checkS(arr);
            if(check == -1){
                check = checkX(arr);
            }

        }

        if(check == -1){
            check = 0;

        }

        if(check == 0){
            check = -1;

        }


        return check;

    }



    //检查横向数值是不是相等
    function checkH(int[] h) private   returns (int)  {
        if(h[0] == h[1] && h[1] == h[2]){
            return h[0];
        }
        return -1;//平局
    }

    //检查竖向的
    function checkS(int[3][] board) private   returns (int)  {
        if(board[0][0] == board[1][0] && board[1][0] == board[2][0]){
            return board[1][0];
        }
        if(board[0][1] == board[1][1] && board[1][1] == board[2][1]){
            return board[1][0];
        }
        if(board[0][2] == board[1][2] && board[1][2] == board[2][2]){
            return board[1][0];
        }
        return -1;//平局
    }

    //检查斜向的
    function checkX(int[3][] board) private   returns (int)  {
        if(board[0][0] == board[1][1] && board[1][1] == board[2][2]){
            return board[0][0];
        }
        if(board[0][2] == board[1][1] && board[1][1] == board[2][0]){
            return board[0][2];
        }
        return -1;//平局
    }

}

Error

/home/codewarrior/solidity/contracts/solution.sol:18:15: TypeError: Type int256[3] memory[] memory is not implicitly convertible to expected type uint256[3] storage ref[] storage ref.
        arr = board;
              ^---^
,/home/codewarrior/solidity/contracts/solution.sol:22:26: TypeError: Invalid type for argument in function call. Invalid implicit conversion from uint256[3] storage ref to int256[] memory requested.
        int h1 =  checkH(arr[1]);
                         ^----^
,/home/codewarrior/solidity/contracts/solution.sol:25:30: TypeError: Invalid type for argument in function call. Invalid implicit conversion from uint256[3] storage ref to int256[] memory requested.
            int h2 =  checkH(arr[2]);
                             ^----^
,/home/codewarrior/solidity/contracts/solution.sol:27:34: TypeError: Invalid type for argument in function call. Invalid implicit conversion from uint256[3] storage ref to int256[] memory requested.
                int h3 =  checkH(arr[3]);
                                 ^----^
,/home/codewarrior/solidity/contracts/solution.sol:39:28: TypeError: Invalid type for argument in function call. Invalid implicit conversion from uint256[3] storage ref[] storage ref to int256[3] memory[] memory requested.
            check = checkS(arr);
                           ^-^
,/home/codewarrior/solidity/contracts/solution.sol:41:32: TypeError: Invalid type for argument in function call. Invalid implicit conversion from uint256[3] storage ref[] storage ref to int256[3] memory[] memory requested.
                check = checkX(arr);
                               ^-^

Compiliation failed. See above.

help me please!

  • Test case is ` contract('TicTacToe', _ => { const TicTacToe = artifacts.require('TicTacToe'); it('should have a function "isSolved" which should return the correct result given a valid 3 by 3 tic-tac-toe board (Example Test)', async function () { const t = await TicTacToe.deployed(); assert.equal((await t.isSolved.call([ [0, 0, 1], [0, 1, 2], [2, 1, 0] ])).valueOf(), -1); }); }); ` – Xiaoyu Li Oct 17 '17 at 9:16
2

TL;DR;

Copy the values individually as you cannot copy from one storage type to another and you cannot cast a fixed length array to a dynamic length array.

Casting arrays from different storage mechanisms

First things first, you cannot directly cast a calldata/memory array to a storage array due to storage being a reference to a storage value and memory is a reference to memory (calldata is copied to memory). What you will have to do is iterate over the array and copy values one at a time as they are two different storage mechanisms and they interact with data in different ways.

/home/codewarrior/solidity/contracts/solution.sol:18:15: TypeError: Type int256[3] memory[] memory is not implicitly convertible to expected type uint256[3] storage ref[] storage ref. arr = board; ^---^

Casting fixed length to dynamic arrays

Secondly, you can't cast a fixed length array to a dynamic array as they are completely different data types. A fixed length array has no length property because it has a deterministic length.

,/home/codewarrior/solidity/contracts/solution.sol:22:26: TypeError: Invalid type for argument in function call. Invalid implicit conversion from uint256[3] storage ref to int256[] memory requested. int h1 = checkH(arr[1]);

This is how the arrays look in memory:

Fixed length array

uint[2] fixedArray;

The memory for a fixed length array is reserved and the length cannot be modified.

-----------------------------------
|     Element    |     Element    |
|       n1       |        n2      |
-----------------------------------
|    32 bytes    |    32 bytes    |
-----------------------------------
|      0x01      |      0x02      |
-----------------------------------

Just a sequence of elements of their data type length.

Dynamic array in memory/storage

Although they use different storage mechanisms (storage is stored as part of the blockchain data and memory in temporary memory on execution), they have the same structure. As we already know that they are a uint256 we know their data size and only need to store the length and the values.

----------------------------------------------------
|   Length of    |     Element    |     Element    |
|     array      |       n1       |        n2      |
----------------------------------------------------
|    32 bytes    |    32 bytes    |    32 bytes    | 
----------------------------------------------------
|       0x02     |       0x01     |      0x02      |
----------------------------------------------------

This time we have an extra length value, but again still a sequence of elements. The only key difference is that this sequence is mutable.

It's probably worth also mentioning call data.

Dynamic array in call data

When handling call data it has a prefix of the data type size which is important if you're creating this value from assembly or such.

---------------------------------------------------------------------
|    Data Type   |    Length of   |     Element    |     Element    |
|      Size      |      array     |       n1       |        n2      |
---------------------------------------------------------------------
|     32 bytes   |    32 bytes    |    32 bytes    |    32 bytes    | 
---------------------------------------------------------------------
|       0x20     |       0x02     |       0x01     |      0x02      |
---------------------------------------------------------------------

Despite the extra 32 bytes of data for the data type length, it's still the same mutable sequence of data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.