【问题标题】:How can I implement an array in a struct and initialize it?如何在结构中实现数组并对其进行初始化?
【发布时间】:2022-10-24 03:01:59
【问题描述】:

我在找出代码中的问题时遇到了一些麻烦。基本上,我有一个使用结构表示游戏的合同。我在那里存储了一些详细信息,例如 gameId、需要购买的游戏等。但我还想存储与特定游戏交互的玩家地址:(最好在游戏结构中的数组中)。我尝试在初始化时将它们附加到数组中,但这不起作用——我假设是由于数组的静态长度。我已经在网上阅读了有关增加播放器数组长度的信息,因为它们不是动态的,但老实说,我不确定在这种情况下如何实现它。 这是我的 Game 结构代码:

struct Game {
    address host; // Establishes host function access
    uint gameId; // Allows different games to be played concurrently
    uint buyinRequirement; // To establish minimum buyin amount for a game
    uint etherWithdrawalReqs; // Tracks # of ether in total from requests. If >/< than contract balance, throws error        
    uint gamePot; // Tracks how much ether is in the game's pot
    uint8 tableWithdrawalReqs; // Tracks how many players have requested a withdrawal
    uint8 playerCount; // Tracks # of of players in a game
    uint8 verifiedWithdrawalReqs; // Tracks # of verifs that withdrawal requests are valid
    bool endedBuyin; // Host function to end buyin stage
    address[] playerList; // Stores player addresses
}

这是我初始化结构的尝试:

function initializeGame(string memory name, uint buyinReq) public payable {
    idToGame[gameNumber] = Game(msg.sender, gameNumber, buyinReq, 0, 0, 0, 0, 0, false, playerList.push(msg.sender));
    games.push(idToGame[gameNumber]);
}  

这是我得到的错误:

DeclarationError: Undeclared identifier.

--> 合同/YourContract.sol:104:93: | 104 | idToGame[gameNumber] = Game(msg.sender, gameNumber, buyinReq, 0, 0, 0, 0, 0, false, playerList.push(msg.sender)); | ^^^^^^^^^^

错误 HH600:编译失败

最终,我只需要跟踪与特定游戏相关的地址,这样我就可以将这些地址与一些其他信息一起呈现给前端。如果有一种更简单的方法可以做到这一点,而我只是因为隧道视野而忽略了一些事情,那么我全心全意寻找替代解决方案。 蒂亚!

编辑:向 7Ony 大喊回应!

这是我现在的代码:

function initializeGame(string memory name, uint buyinReq) public payable isNotInGame {     
    require(initFee == .001 ether, "In order to prevent spam games that never resolve, each game initialization will cost  ether.");
    playerInfo[msg.sender] = Player(name, gameNumber, 0, 0, false, false, false, false, true);
    address[] memory add;
    idToGame[gameNumber] = Game(msg.sender, gameNumber, buyinReq, 0, 0, 0, 0, 0, false, true, add);
    idToGame[gameNumber].playerList.push(msg.sender);
    games.push(idToGame[gameNumber]);
    incGameNumber();
    addFeesPending();

}

编译此代码时没有错误,但是当我尝试通过 ethersjs 将游戏渲染到前端时,就像从未创建数组一样:

0x59D101AD9DdeA84C0e11DA137000Dd91A0b20c79,1,1000000000000000000,0,1000000000000000000,0,1,0,false,true (cuts off the playerList array, which should be the very last element)

控制台记录的输出:

Console-logged image of Game struct

我在这里做错了吗?

【问题讨论】:

    标签: javascript arrays blockchain ethereum solidity


    【解决方案1】:

    鉴于我没有完全了解您的代码(没有参考 idToGamegames 定义),我假设:

    • idToGamemapping(uint =&gt; Game)
    • gamesGame[]

    这是添加动态数组的正确方法,其中包含一个元素:

    1. 初始化动态数组
    2. 将其分配给游戏初始化
    3. 将元素推入其中

      所以你的代码应该看起来像

      function initializeGame(string memory name, uint buyinReq) public payable {
          address[] memory add;
          idToGame[gameNumber] = Game(msg.sender, gameNumber, buyinReq, 0, 0, 0, 0, 0, false, add);
          idToGame[gameNumber].playerList.push(msg.sender);
          games.push(idToGame[gameNumber]);
      }  
      

      只有在创建 Game 元素(并保存在 storage 中)时,您才能将项目 push() 放入数组中。在solidity 中,push() 方法仅适用于storage 变量,不适用于memory 变量。以下 sn-p 确实不是由于这个原因工作

      function initializeGame(string memory name, uint buyinReq) public payable {
          address[] memory add;
          add.push(msg.sender);
          idToGame[gameNumber] = Game(msg.sender, gameNumber, buyinReq, 0, 0, 0, 0, 0, false, add);
          games.push(idToGame[gameNumber]);
      }  
      

      边注: 为什么将game 元素同时保存在idToGamegames 中?这样,每次编辑都需要复制。最好有一个games 数组,而idToGame 应该是一个mapping(uint =&gt; uint),它告诉games 数组中通用游戏的位置。

    【讨论】:

    • 嗨,感谢您抽出宝贵的时间来写这篇文章 - 我真的很感激!我实现了您的解决方案并且没有错误或任何东西,但是当我尝试将 Game 结构呈现到相应的索引时,它只是忽略了该数组已创建,即使在我推送 msg.sender 之后也是如此。我将继续此回复作为对我原始帖子的编辑:
    猜你喜欢
    • 1970-01-01
    • 2019-02-01
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 2021-04-30
    相关资源
    最近更新 更多