I am trying to create a dungeon crawler with a tile-based map. However, I get an error when creating the array of tiles. (Right now, Tile is a class with nothing but an empty constructor.)
class Map
{
Tile[][] Tiles;
static const int DefaultWidth = 640, DefaultHeight = 480;
Random rnd;
public Map(int? Width, int? Height, int? seed)
{
Tiles = new Tile[((Width == null) ? DefaultWidth : (int)Width)]
//This line gives the error "invalid rank specifier: expected ',' or ']'" after the first bracket
[((Height == null) ? DefaultHeight : (int)Height)];
Generate();
}
void Generate()
{
}
}
Why am I getting this error?
In C#, the right way to instantiate a 2D array is to use a comma instead:
int[,] array = new [3,2];
You can still make arrays such as int[][], but you'll need to use a for loop to create every individual array inside it (which can be of different lengths), and this is known as a jagged array. I would recommend, however, to use the comma syntax as it is idiomatic in C# and is the expected way to do things.
Related
This question already has answers here:
What is the difference between 'is' and '==' in Dart?
(2 answers)
Closed 11 months ago.
I'm new to dart and reading about dart operators. In the book fluter in Action by Eric Windmill (Chapter 2, 2.24, page 34) the auther says:
is and is! verify that two objects are of the same type. They are equivalent to == and !=.
Trying to implement this as shown in the code below
void main() {
int a = 7;
int b = 2;
bool z = a == b; // It works when I use the equals symbol
print('Result: $z');
}
But when I use the ```is`` keyword, I get an error
void main() {
int a = 7;
int b = 2;
bool z = a is b; // It doesn't work here
print('Result: $z');
}
Error
The name 'b' isn't a type and can't be used in an 'is' expression.
Try correcting the name to match an existing type.
Not sure what the context of that statement is but is and is! is not the same as == and != in the sense that they does the same. I guess what the want to explain, is that the opposite of is is is! like the opposite of == is !=.
== is used to check if two objects are equal (based on what this object at left side defines to be equal). So for int we return true when using == if both numbers have the same numeric value.
The is operator is used to test if a given object does implement a given interface. An example:
void main() {
Object myList = <int>[];
if (myList is List<int>) {
print('We have a list of numbers.');
}
}
The error you are getting are telling you that for using is you need to provide an actual type at the right side of the is and not an object instance.
I have a question.
When working with Dart, I can't check to see if 2 arrays are equal.
(in other languages, I can do with ==)
In fact, I just can do that == with String or number.
List arr1 = [1,2,3];
List arr2 = [1,2,3];
if (arr1 == arr2) {
print("equal");
} else {
print("not equal");
}
// Output: not equal.
So I wonder how does that make sense. I mean, How we can do if the == is just work for the cases of String or number (if the values compared are the same).
How do I have to do if I want to check that kind of comparison (equal) for List, Map, ..
It just work for String & number.
arr1 and arr2 are different instances of an object of type List. By default different instances are always different.
When a class implements a custom == operator it can override this behavior. Some classes have a custom implementation by default like int and String.
This can easily be done for immutable objects but not for mutable. One reason is that usually the hashCode is calculated from the values stroed in a class and the hashCode must not change for an instance because this can for example cause that an instance stored in a map can't be retrieved anymore when the hashcode of the key changed.
As a workaround there is a library that provides helper functions to compare lists/iterables.
import 'package:collection/equality.dart';
void main(List<String> args) {
if (const IterableEquality().equals([1,2,3],[1,2,3])) {
// if (const SetEquality().equals([1,2,3].toSet(),[1,2,3].toSet())) {
print("Equal");
} else {
print("Not equal");
}
}
How to get the length of a string array like
str 30 name[];//dynamic array
I used the following for getting the length,but it showing the error as "the variable is not of the type CLASS."
int len=name.get_length();
It sounds like you might be happier using the Array collection class.
http://msdn.microsoft.com/en-us/library/array.aspx
static void TestArray(Args _args)
{
Array strArray = new Array(Types::String);
;
strArray.value(1, 'abc');
strArray.value(2, 'def');
info(strfmt("%1", strArray.lastIndex()));
}
You need the dimOf function. Take a look to the reference:
http://msdn.microsoft.com/en-us/library/aa597117.aspx
Sorry, there is no build-in function to return the string array size. Since you are in full control what you put in the array, there need not be any!
The built-in function dimof returns the allocated size of the array, which is only of practical value for a fixed size array like str 30 name[20], where dimof(name) returns 20.
A clean way to remain in control, is to use a setter function:
static void TestArray(Args _args)
{
str 30 name[];
int n = 0;
int i;
void nameSet(int _i, str 30 _name)
{
n = max(n,_i);
name[_i] = _name;
}
;
nameSet(2,'abc');
nameSet(4,'def');
for (i = 1; i <= n; i++)
info(name[i]);
}
There is no upper bound index limit, so accessing name[7] is perfectly valid and in this case returns a blank value. This may be used to your advantage, if you always use all holes and never stores a blank:
static void TestArray(Args _args)
{
str 30 name[];
int i;
name[1] = 'abc';
name[2] = 'def';
for (i = 1; name[i]; i++)
info(name[i]);
}
Beware that accessing a higher index (in this case higher than 2) may in fact increase the allocated size of the array.
Is there a generic way to retrieve PropertyInfo based on a string value alone, when deeper than one level.
I assume this is probably simple enough, but my search results are only as good as my search criteria, and I think I am having an issue articulating the proper keywords to get search results for what I am after.
I would like to be able to do something like the following (which works perfect if the key is for a direct property / one level - ie key = 'firstName'):
public static PropertyInfo (this HtmlHelper htmlHelper, string key) {
PropertyInfo pInfo = htmlHelper.ViewData.Model.GetType().GetProperty(key);
return pInfo;
}
But is there a way for me to return the PropertyInfo based on a string alone
when Key equals something more complex, such as nested classes, objects, lists, etc...:
key = "somelist[0].myproperty"
key = "Items[0].someotherlist[1].someproperty" (where Items is defined as List<Item> Items {get; set;}, someotherlist is defined similarly)
Can the method be generic enough to essentially drill down as many levels as needed (defined)?
So here is what I came up with... this is about to get wordy, and mostly 'stream of thought'
I have custom HtmlHelperExtension, and within it :
PropertyInfo[] pInfoArray = htmlHelper.ViewData.Model.GetType().GetProperties();
PropertyInfo pInfo = GetPropertyInfo(pInfoArray, key);
This GetPropertyInfo() method takes the key, and the PropertyInfo array, cycles through the properties, until the keypart (using regex to remove any indication of an array from the string, so I am left with only the property) matches the property name. On Match, determine if this is the first cycle in the loop, and if so assign the matched property to my Temp Type and PropertyInfo variables. If keyParts are remaining to loop through, subsequent loops now use previously set temp variables and the for loop index [i] to iterate / drill down the class structure. Each time setting the pInfoTemp variable, and then pTypeTemp so the next loop can use where it left off.
private static PropertyInfo GetPropertyInfo(PropertyInfo[] pInfoArray, string key)
{
PropertyInfo pInfo = null;
string[] keyParts = key.Split('.');
Regex arrayRgx = new Regex("\\[\\d*\\]");
PropertyInfo pInfoTemp = null;
Type pTypeTemp = null;
foreach (PropertyInfo prop in pInfoArray)
{
string keyPartsTrimmed = arrayRgx.Replace(keyParts[0], ""); // removes '[#]' from string
if (keyPartsTrimmed == prop.Name) // match property name
{
for (int i = 0; i < keyParts.Count(); i++)
{
if (i == 0) // initial item [0]
{
pTypeTemp = prop.PropertyType; // gets [0]'s type
pInfoTemp = prop; // assigns [0]'s property info
}
else
{
pInfoTemp = GetNestedPropertyInfo(pTypeTemp, arrayRgx.Replace(keyParts[i], "")); // gets [i]'s property info for return or next iteration
pTypeTemp = pInfoTemp.PropertyType; // gets [i]'s type for next iteration
}
}
pInfo = pInfoTemp;
break;
}
}
return pInfo;
}
This next method is invoked by the previous for grabbing nested property info, more importantly for detecting whether the passedItemType is a List (without this, it fails to work correctly as it is unable to find the property asked for in a List<> Type. I need to know what the List item Type is.
private static PropertyInfo GetNestedPropertyInfo(Type passedItemType, string passedProperty)
{
PropertyInfo pInfoOut = null;
if (passedItemType.IsGenericType && passedItemType.GetGenericTypeDefinition() == typeof(List<>))
{
Type itemType = passedItemType.GetGenericArguments()[0];
pInfoOut = itemType.GetProperty(passedProperty);
}
else
{
pInfoOut = passedItemType.GetProperty(passedProperty);
}
return pInfoOut;
}
This currently suits my requirements as they are today, and I have tested it with the following properties, lists, subclasses, subclasses with lists, etc.. to 4 levels deep, but should function properly no matter the depth:
firstName
lastName
Items[1].sprocket
subClass.subClassInt
subClass.mySubClassObj.sprocketObj
subClass.ItemsInMySubClass[1].sprocket
subClass.ItemsInMySubClass[0].mySubClassObj.widgetObj
subClass.ItemsInMySubClass[2].mySubClassObj.sprocketObj
If anyone has a better solution, or see any potential issues with what I have, I welcome the feedback.
The best way in your case is to make a parser that split that expression.
What is the best practice in Dart when dealing with classes as data records?
To Elaborate: When writing an app, it is likely that a class for a table row will be created. As in
class Item { int itemid, String itemName, double score }
Item item = new Item();
This allows compile time catching of any typos etc. in Dart. (Unlike using a class that relies on NoSuchMethod.)
It will also need a corresponding string structure to bind to the HTML such as
<input id="itemname" type="text" bind-value="itemEdit.itemName">
So the Dart would be:
class ItemEdit { String itemId, String itemName, String score }
ItemEdit itemEdit = new ItemEdit();
Next we need a way to get from one to the other, so we add a method to Item
fromStrings(ItemEdit ie) {
itemid = ie.itemId == null ? null : int.parse(ie.itemId);
itemName = ie.ItemName;
score = ie.score == null ? null : double.parse(ie.score);
}
And the other way around:
toStrings(ItemEdit ie) {
ie.itemid = itemId == null ? '' : ie.itemId.toString();
ie. itemName = itemName == null ? '' : itemname; // Web_ui objects to nulls
ie.score = score == null ? null : score.toStringAsFixed(2);
}
Also, we get jason data from a database, so we need to add another method to Item:
fromJson(final String j) {
Map v = JSON.parse(j);
itemid = v['itemid'];
itemname = v['itemname'];
score = v['score'];
}
And we need to be able to revert to default values:
setDefaults() { itemId = 0; itemName = "New item"; score = 0; }
This verbosity gets me feeling like I am writing COBOL again!
There is something fundamental missing here - either in my understanding, or in the Dart/WebUI libraries.
What I would like to write is something like
class Item extends DataRecord {
int itemid = 0,
String itemName = 'New item',
double score = 0.0;
}
Then, without further coding, to be able to write code such as
item.toStrings();
...
item.fromStrings();
...
item.fromJson(json);
...
item.setDefaults(); // results in {0,'New item',0.0}
And to be able to write in the HTML:
value="{{item.strings.score}}"
If this was possible, it would be quicker, simpler, clearer, and less error prone than the code I am writing at the moment.
(Full disclosure, this answer is written with the assumption that at least one bug will be fixed. See below)
Three suggestions that might help.
Use named constructors to parse and create objects.
Take advantage of toJson() when encoding to JSON.
Use bind-value-as-number from Web UI
1) Named constructors
import 'dart:json' as json;
class Item {
int itemid;
String itemName;
double score;
Item.fromJson(String json) {
Map data = json.parse(json);
itemid = data['itemid'];
itemName = data['itemName'];
score = data['score'];
}
}
2) Encoding to JSON
The dart:json library has a stringify function to turn an object into a JSON string. If the algorithm encounters an object that is not a string, null, number, boolean, or collection of those, it will call toJson() on that object and expect something that is JSON-encodable.
class Item {
int itemid;
String itemName;
double score;
Map toJson() {
return {'itemid':itemid, 'itemName':itemName, 'score':score};
}
}
3) Now, having said that, sounds like you want to easily bind to HTML fields and get primitive values back, not just strings. Try this:
<input type="number" min="1" bind-value-as-number="myInt" />
(Note, there seems to be a bug with this functionality. See https://github.com/dart-lang/web-ui/issues/317)
(from https://groups.google.com/a/dartlang.org/forum/#!topic/web-ui/8JEAA5OxJOc)
Just found a way to perhaps help a little in the this situation:
class obj {
int gapX;
String get gapXStr => gapX.toString();
set gapXStr(String s) => gapX = int.Parse(s);
...
Now, from the HTML you can use, for example
bind-value="gapXStr"
and in code you can use
x += ob.gapX;