Dart: create multiple objects at once - dart

How can I create multiple objects in 1 Step in Dart? Something like:
Class Player{
var Health;
var Level; .... }
Somewhere else:
Player[] player = new Player[20];
How can I do that in Dart?

If you wanna create a lot "Players"... Try this:
var players = List.generate(20, (i) => Player(/* properties */));
Filling in from any source, you can use the "i" as the index.
var players = List.generate(20, (i) {
var sourceRef = source[i];
return Player(
health: sourceRef["health"]
);
});

You can create a list of Player using the following line:
List<Player> player = new List(20);
And then initialize each object of your player list :
for (var i in jsonResponse['participants']) {
player[x] = new Player() ; // add this to your code
var fill = player[x];
fill.health = i['health'];
x++;
}
You can find more information about the proper way of building and initializing list in the official Dart Documentation.

Related

Combine/merge multiple maps into 1 map

How can I combine/merge 2 or more maps in dart into 1 map?
for example I have something like:
var firstMap = {"1":"2"};
var secondMap = {"1":"2"};
var thirdMap = {"1":"2"};
I want:
var finalMap = {"1":"2", "1":"2", "1":"2"};
you can use addAll method of Map object
var firstMap = {"1":"2"};
var secondMap = {"2":"3"};
var thirdMap = {};
thirdMap.addAll(firstMap);
thirdMap.addAll(secondMap);
print(thirdMap);
Or
var thirdMap = {}..addAll(firstMap)..addAll(secondMap);
Update
Since dart sdk 2.3
You can use spread operator ...
final firstMap = {"1":"2"};
final secondMap = {"2":"3"};
final thirdMap = {
...firstMap,
...secondMap,
};
alternate syntax using Map.addAll, Iterable.reduce and cascading operator, for combining a lot of maps:
var combinedMap = mapList.reduce( (map1, map2) => map1..addAll(map2) );
live dartpad example
https://dartpad.dartlang.org/9cd116d07d2f45a9b890b4b1186dcc5e
Another option is using CombinedMapView from package:collection:
new CombinedMapView([firstMap, secondMap])
It doesn't create a merged map, but creates a Map that is a view of both.
I came up with a "single line" solution for an Iterable of Maps:
var finalMap = Map.fromEntries(mapList.expand((map) => map.entries));
var firstMap = {"1":"5"};
var secondMap = {"1":"6"};
var thirdMap = {"2":"7"};
var finalMap = {...firstMap, ...secondMap, ...thirdMap};
// finalMap: {"1":"6", "2":"7"};
Notice that key "1" with value "5" will be overwritten with "6".

How to manage Lists with Future in dart?

I am new at Dart; and, I created a List of playing card objects called Deck. I am trying to select a random card, then remove the card from the deck. I am getting duplicates, as it appears subsequent cards are picked before the deck is reduced. How would I handle a future chain of events that will pick 10 unique random cards from the deck?
class Card{
String face;
String suit;
String rank;
String imgSrc;
String holdImgSrc;
Card(
this.face,
this.suit,
this.rank,
this.imgSrc,
this.holdImgSrc
);
}
import 'dart:math' show Random;
Random indexGen = new Random();
getCard1(){
card1 = deck[indexGen.nextInt(deck.length)];
deck.removeWhere((item) => item == card1);
return card1;
}
getCard2(){
card2 = deck[indexGen.nextInt(deck.length)];
deck.removeWhere((item) => item == card2);
return card2;
}
When I try to return a Card Object as a future I get:
new Future((getCard1()))
.then((getCard2()))
.then((getCard3()));
type 'Card' is not a subtype of type '() => dynamic' of 'computation'.
When I try to return the deck List I get:
type 'List' is not a subtype of type '() => dynamic' of 'computation'.
Am i missing the right syntax, flaw in my logic, or do I need to handle the list differently, by maybe watching for changes?
edit to add: The futures syntax works, however, the deletes do not appear to be happening correctly.
I changed the code, to the code suggested by Jim-Y below, except for preloading new Card objects from a List using the second named constructor. The amended code and printout is as follows:
fullDeck[
...
var tenC = new Card.full(17,'10_of_clubs','c','10','10_of_clubs.png','10_of_clubs_h.png');
var tenD = new Card.full(18,'10_of_diamonds','d','10','10_of_diamonds.png','10_of_diamonds_h.png');
var tenS = new Card.full(19,'10_of_spades','s','10','10_of_spades.png','10_of_spades_h.png');
var tenH = new Card.full(20,'10_of_clubs','c','10','10_of_clubs.png','10_of_clubs_h.png');
...]
Deck<Card> deck = new Deck<Card>();
Random indexGen = new Random();
for(var c = 0; c < 20; ++c) {
var card = new Card(c);
deck.add(fullDeck[c]);//List of 52 full card objects
}
for(var i = 0; i < 10; ++i) {
var rnd = indexGen.nextInt(deck.size());
print('${deck.get(rnd).face} Deck size: ${deck.size()}');
}
}
4_of_clubs Deck size: 19
10_of_diamonds Deck size: 18
5_of_clubs Deck size: 17
4_of_spades Deck size: 16
5_of_spades Deck size: 15
10_of_clubs Deck size: 14
10_of_clubs Deck size: 13
3_of_spades Deck size: 12
5_of_diamonds Deck size: 11
3_of_diamonds Deck size: 10
As you can see the 10 of Clubs is printed twice. So, If the 10 was removed in pass 6, why is it still there in pass 7?
If you want to chain the calls this way the methods must return a future:
Caution: I have not tested the code:
// I don't see what type 'Card' actually is from your code
Future<Card> getCard1(){
return new Future(() {
card1 = deck[indexGen.nextInt(deck.length)];
deck.removeWhere((item) => item == card1);
return card1;
});
}
the same for getCard2()
Future<Card> getCard2(){
return new Future(() {
card2 = deck[indexGen.nextInt(deck.length)];
deck.removeWhere((item) => item == card2);
return card2;
});
}
you call it with
getCard1().then((c) => getCard2()).then((c) => print(c));
as getCard1 and getCard2 are essentially the same methods you could combine them to one
List<Card> cards = [];
Future<Card> getCard(int i){
return new Future(() {
cards[i] = deck[indexGen.nextInt(deck.length)]; // not clear what card is
deck.removeWhere((item) => item == card[i]);
return card[i];
});
}
.
getCard(1).then((c) => getCard(2)).then((c) => print(c));
I can't see now why you need to use Futures for this. In the following code, i will try to address a possibly better approach of removing a Card from a deck using Dart's generic features :)
Your original Card class, I extended it for demonstrational purpose:
class Card {
int id;
String face;
String suit;
String rank;
String imgSrc;
String holdImgSrc;
Card(this.id);
Card.full(this.id, this.face, this.suit, this.rank, this.imgSrc, this.holdImgSrc);
}
Then, you could make a generic container for your cards instead of using a simple List.
class Deck<T extends Card> {
List<T> _container = new List<T>();
T get(int index) => _container.removeAt(index);
void add(T item) => _container.add(item);
int size() => _container.length;
}
This would make your example easier to extend later, and you gain much expression power with it.
Then, you could write something like this, to remove 10 random elements from the deck.
void main() {
Deck<Card> deck = new Deck<Card>();
Random indexGen = new Random();
for(var c = 0; c < 20; ++c) {
var card = new Card(c);
deck.add(card);
}
for(var i = 0; i < 10; ++i) {
var rnd = indexGen.nextInt(deck.size());
print('${deck.get(rnd).id} Deck size: ${deck.size()}');
}
}
On this simple example, with these simple card objects there are no duplicates. However, if you need to, you could extend your Deck class with a(n) fGet method what could be a method returning a Future as mentioned before by #Günter.
I hope i gave you some good ideas :)
Cheers

Setting Actionscript Object Keys

If I have an array, I can set the keys by doing the following:
var example:Array = new Array();
example[20] = "500,45";
example[324] = "432,23";
If I want to do something with Objects, how would I achieve this?
I tried the following:
var example:Object = [{x:500, y:45}, {x:432, y:23}]; // Works but keys are 0 and 1
var example:Object = [20: {x:500, y:45}, 324: {x:432, y:23}]; // Compile errors
var example:Object = [20]: {x:500, y:45}, [324]: {x:432, y:23}; // Compile errors
var example:Object = [20] {x:500, y:45}, [324] {x:432, y:23}; // Compile errors
Is there a good way to achieve this?
I understand I could do this:
var example:Object = {id20 : {x:500, y:45}, id324: {x:432, y:23} };
But it doesn't suit me.
The [] notation has the same meaning of doing a new Array() so when you are doing:
var example:Object = [{x:500, y:45}, {x:432, y:23}];
you are in fact creating an array with two elements who are object {x:500, y:45} and {x:432, y:23}.
If you want to create an object with key 20 and 324 use the {} notation who is the same a new Object()
So your example became =>
var example:Object = {20: {x:500, y:45}, 324: {x:432, y:23}};
You can do the same as your first example using an Object instead of an Array:
var example:Object = new Object();
example[20] = "500,45";
example[324] = "432,23";

Actionscript 2 functions

I'm an experienced programmer but just starting out with Flash/Actionscript. I'm working on a project that for certain reasons requires me to use Actionscript 2 rather than 3.
When I run the following (I just put it in frame one of a new flash project), the output is a 3 rather than a 1 ? I need it to be a 1.
Why does the scope of the 'ii' variable continue between loops?
var fs:Array = new Array();
for (var i = 0; i < 3; i++){
var ii = i + 1;
fs[i] = function(){
trace(ii);
}
}
fs[0]();
Unfortunately, AS2 is not that kind of language; it doesn't have that kind of closure. Functions aren't exactly first-class citizens in AS2, and one of the results of that is that a function doesn't retain its own scope, it has to be associated with some scope when it's called (usually the same scope where the function itself is defined, unless you use a function's call or apply methods).
Then when the function is executed, the scope of variables inside it is just the scope of wherever it happened to be called - in your case, the scope outside your loop. This is also why you can do things like this:
function foo() {
trace( this.value );
}
objA = { value:"A" };
objB = { value:"B" };
foo.apply( objA ); // A
foo.apply( objB ); // B
objA.foo = foo;
objB.foo = foo;
objA.foo(); // A
objB.foo(); // B
If you're used to true OO languages that looks very strange, and the reason is that AS2 is ultimately a prototyped language. Everything that looks object-oriented is just a coincidence. ;D
Unfortunately Actionscript 2.0 does not have a strong scope... especially on the time line.
var fs:Array = new Array();
for (var i = 0; i < 3; i++){
var ii = i + 1;
fs[i] = function(){
trace(ii);
}
}
fs[0]();
trace("out of scope: " + ii + "... but still works");
I came up with a kind of strage solution to my own problem:
var fs:Array = new Array();
for (var i = 0; i < 3; i++){
var ii = i + 1;
f = function(j){
return function(){
trace(j);
};
};
fs[i] = f(ii);
}
fs[0](); //1
fs[1](); //2
fs[2](); //3

Is there a better way to get hold of a reference to a movie clip in actionscript using a string without eval

I have created a bunch of movie clips which all have similar names and then after some other event I have built up a string like:
var clipName = "barLeft42"
which is held inside another movie clip called 'thing'.
I have been able to get hold of a reference using:
var movieClip = Eval( "_root.thing." + clipName )
But that feels bad - is there a better way?
Movie clips are collections in actionscript (like most and similar to javascript, everything is basically key-value pairs). You can index into the collection using square brackets and a string for the key name like:
_root.thing[ "barLeft42" ]
That should do the trick for you...
The better way, which avoids using the deprecated eval, is to index with square brackets:
var movieClip = _root.thing[ "barLeft42" ]
But the best way is to keep references to the clips you make, and access them by reference, rather than by name:
var movieClipArray = new Array();
for (var i=0; i<45; i++) {
var mc = _root.thing.createEmptyMovieClip( "barLeft"+i, i );
// ...
movieClipArray.push( mc );
}
// ...
var movieClip = movieClipArray[ 42 ];
You can use brackets and include variables within them... so if you wanted to loop through them all you can do this:
for (var i=0; i<99; i++) {
var clipName = _root.thing["barLeft"+i];
}

Resources