greyBow
greyBow

Reputation: 1348

Converting from a List to a Dictionary, trouble with foreach statement

I started poking at switching a list structure over to a dictionary and i'm having some trouble. I'm in the middle of modifying my foreach statement foreach (KeyValuePair <int, Player> p in players) to work with my dictionary but I'm having difficulty in understanding how I then go about accessing variables in my player object using the key value pair.

And I'm currenty stuck on this line using a dictionary : moveMsg += p.connectionId.ToString() + '%' + p.playerPosition.x.ToString() + '%' + p.playerPosition.y.ToString() + '|';

The error I'm getting is: Assets/Scripts/Server.cs(118,18): error CS1061: Type System.Collections.Generic.KeyValuePair<int,Player>' does not contain a definition for connectionId' and no extension method connectionId' of type System.Collections.Generic.KeyValuePair<int,Player>' could be found. Are you missing an assembly reference?

How do I make the modification?

Declare dictionary: public Dictionary<int, Player> players = new Dictionary<int, Player>();

Dictionary

// Ask player for their position

if (Time.time - lastMovementUpdate > movementUpdateRate)
{
    lastMovementUpdate = Time.time;
    string moveMsg = "ASKPOSITION|";
    foreach (KeyValuePair <int, Player> p in players)
        moveMsg += p.connectionId.ToString() + '%' + p.playerPosition.x.ToString() + '%' + p.playerPosition.y.ToString() + '|';
    moveMsg = moveMsg.Trim('|');
    Send(moveMsg, unreliableChannel, players);
}

Player class

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Player
{
    public string PlayerName;
    public GameObject Avatar;
    public int ConnectionId;
    public byte[] Tex;          // data coming from CanvasController
    public string Type;         // data coming from CanvasController
    public string Id;           // data coming from GameManager
    public int Strength;        // data coming from PlayerController
    public int Hitpoints;       // data coming from PlayerController
    public bool IsAlive;        // data coming from PlayerController

    // Initial method takes base arguments for testing
    public Player(string playerName, GameObject avatar, int connectionID)
    {
        PlayerName = playerName;
        Avatar = avatar;
        ConnectionId = connectionID;
    }
    // Overload method takes all animal arguments
    public Player(string playerName, GameObject avatar, int connectionID, byte[] tex, string type, string id, int strength, int hitpoints, bool isAlive)
    {
        PlayerName = playerName;
        Avatar = avatar;
        ConnectionId = connectionID;

        Tex = tex;
        Type = type;
        Id = id;
        Strength = strength;
        Hitpoints = hitpoints;
        IsAlive = isAlive;

        Debug.Log(id + " : " + type + " created with strength " + strength + ", hit points " + hitpoints + ", and a texture the size of " + tex.Length);
    }
}

Upvotes: 1

Views: 89

Answers (3)

user4478810
user4478810

Reputation:

KeyPairValue contains only two properties Key and Value

https://msdn.microsoft.com/en-us/library/5tbh8a42(v=vs.110).aspx

Did you try with: p.Key instead of p.ConnectionId and p.Value instead of of p.PlayerPosition

Edit: I wrote a small lambda to simply your code using the Aggregate fct. I pass the default value and then for each items in your dict, it will concact another string. I also use string Interpolation to avoid string concatenation ($"{variable}").

    class Player
    {
        public Point Position { get; set; }
    }

    public void Test()
    {
        var players = new Dictionary<int, Player>();
        var msg = players.Aggregate(
              string.Empty, 
             (current, p) => current + 
                       $"{p.Key}%{p.Value.Position.X}%{p.Value.Position.Y}|");
    }

Upvotes: 1

Serkan Pek&#231;etin
Serkan Pek&#231;etin

Reputation: 693

Since your variable p is a KeyValuePair<int, Player> you can not access to ConnectionId directly with p.ConnectionId. You should access it with p.Value.ConnectionId, because in an <int, Player> KeyValuePair, Player corresponds to the Value. You can also access to the key in a similar fashion.

Upvotes: 4

Oleg Skripnyak
Oleg Skripnyak

Reputation: 311

You have a ConnectionId in yr Player class, but access to connectionId. PS. Strangely why its compiled. Btw, you may use players.Join - a linq extension

Upvotes: 1

Related Questions