Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers DBPro Corner / To use UDT or 2D String Array

Author
Message
Burning Feet Man
16
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 14th Jan 2011 06:12 Edited at: 14th Jan 2011 23:06
EDIT: I've got updated code a few posts down, so please comment on that rather than my first attempt in this post.

Hello! I'm slowly but surely getting through this array business. For those who've missed my other thread,

http://forum.thegamecreators.com/?m=forum_view&t=178859&b=7

I've now moved onto a slightly different problem with importing my Master Inventory List.CSV file, in that I'm not too sure whether I should load it into a User Defined Type, or load it into a 2D String array.

Are there any pro's or con's to using either or that you're aware of? My current code is as per below which uses a 2D String Array, as UDT's appear to be much more work. I've also attached the CSV file to this thread. Note that the creation of the CSV file was via Google Docs.




As you can see, my first attempt at using a 2D String Array seems to work. I also tried a User Defined Type solution, but things got very manual very fast!

Questions start to arise, such as, should I split my CSV data up so that I have a;

ItemsString(0,0) as String
ItemsInteger(0,0) as Integer

and use two arrays to control my game? Or should I constantly do number conversions to and from the string array?

Any help is greatly appreciated!

Cheers,
BFM

EDIT: For new comers, you'll need to download and install Matrix1's Utilities for DBPro.

EDIT 2: An example of how I'll be working the data. Is this acceptable? Or should I be approaching this problem differently...


Attachments

Login to view attachments
baxslash
Valued Member
Bronze Codemaster
17
Years of Service
User Offline
Joined: 26th Dec 2006
Location: Duffield
Posted: 14th Jan 2011 12:09
UDT would allow you to store different variable types in one array, I use them that way all the time. If you are only using integer values I would just convert the answer to a string using "str$" when you need to display it. If you're only using "print" you don't even need to convert the values just as you have shown.

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 14th Jan 2011 12:58 Edited at: 14th Jan 2011 12:58
Definitely use a UDT for that. You have several values in the CSV that appear you'd want to keep as integers but also you want the description to be a string.

I would not suggest trying to keep multiple arrays in parallel like this:
ItemsString(0,0) as String
ItemsInteger(0,0) as Integer

It's just bad practice.

A UDT isn't more work and in fact can make your code much easier to work with since it can be more descriptive.



Hmm, taking another look I think I might see why you think using a UDT is more difficult. You seem to be using specific CSV commands that I'm not aware of. You using a plugin?

"Only the educated are free" ~Epictetus
"Imagination is more important than knowledge..." ~Einstein
Burning Feet Man
16
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 14th Jan 2011 13:27
Quote: "UDT would allow you to store different variable types in one array, I use them that way all the time. If you are only using integer values I would just convert the answer to a string using "str$" when you need to display it. If you're only using "print" you don't even need to convert the values just as you have shown."


I understand how UDT's work, but I think everyone's under the assumption that I've got 6 attributes... but eventually I could have 20, or 30... or more! I'm finding that I can control a 2D String Array, using constants and loops, much easier than writing out lines of code to manipulate a UDT system. To clarify my technique as well, I'm only using 2d string array, not 2d integer array.



I thought this was the case, so didn't actually implement it. So far, all I've tested is a UDT system and compared it to the one that I've posted. And yes, I'm using the free to download & use Matrix1's Utilities. It's got some very handy commands, but not the best help file.
Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 14th Jan 2011 22:43
If you're unsure of the size of attributes, then I'd agree a 2D array will be your best option. Creating a UDT with 20 or more attributes may sound tedious, but it's much easier to work with in the long run because it can describe the data. I'd have a hard time remember what each of the 20 indices represent without using constants.

"Only the educated are free" ~Epictetus
"Imagination is more important than knowledge..." ~Einstein
Burning Feet Man
16
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 14th Jan 2011 23:04 Edited at: 14th Jan 2011 23:08
Quote: "I'd have a hard time remember what each of the 20 indices represent without using constants."


I'll be working on a solution for this very problem. Constants are my first thoughts as to controling just what exactly array(27,36) is!!! (as an example).

To further highlight what I'm doing, I've created another example. This time, with CSV data driving a games menu system.



If you compare this to my last code, it's much easier to read, in that I've renamed the variables to reflect the CSV spreadsheet.

A question: How can I be more efficient with my code? Are there other commands that I should be using? Is my code a viable solution, or just a messy work around?

Attachments

Login to view attachments
Agent
20
Years of Service
User Offline
Joined: 7th Sep 2004
Location: Sydney, Australia
Posted: 15th Jan 2011 00:48 Edited at: 15th Jan 2011 00:50
I think you should use a UDT to describe your entity data if you're going to have lots of attributes. You certainly don't want to do this:



This is readable and functional, but there's the possibility of a nightmare bug hunt if you typo one of the constants; you won't generate an error of any kind, since zero is a valid array index, and the null or zero value that's in that element will create confusing behaviour in your code.

You also don't want to do something like this:



Although this method will throw an error if you typo something, it's not as easy to read, and that's as big a reason as any other to find a better way.

Use UDT's:



That's easy to read and will throw an error right off the bat if you typo something, so you won't need to worry about dead elements. I have to submit that this is the standard method used by programmers today when dealing with assorted entity attributes.

With your progress reporting ("Resizing was successful!"), make sure you actually do the resizing before you report success to the user. The array dimensioning hasn't been successful until you call your dynamic DIM command, so move your PRINT statement beyond the DIM statement.

Also, at first glance it looks like this resizing code will produce an array of size one greater than the size of the file, since you have to account for element zero as the first element in your array, and the first element in the file is increasing your counter to 1. Doesn't that mean that a file size of 1 will result in an array upper bound of 1? That's an array size of two. Just an observation.

With that said, I have to say that I still don't like the dynamic array sizing at all. Unless you're talking about an array whose size you cannot know in advance (and you will, in the case of a menu) *and* that size needs to have wildly flexible bounds, *and* you're going to get more than a tenth of a percent better memory efficiency from it (which you're not here), you're wasting time loading the array twice. Just dimension the array to size 10 (you'll never have more options than that in a main menu), as the amount of memory wasted if you only use 6 options instead of the 10 you've allowed for is negligible.

I feel like you're convoluting your code, generating opportunities for logic errors and getting no benefit for it whatsoever. It's an interesting process to learn from, but you won't do something like this in an actual menu system.

I know you're just practicing skills here, but for the record in a real menu system you won't read the options from a file. Since the actions taken when the user selects any given option will be hardcoded, you'll also hardcode the menu options themselves (otherwise the user can destroy your menu by making any changes at all to the file containing the options).

For these reasons, if you used this code in an actual menu system I'd call every step in what you've done here a complete waste of time. However, it's an excellent learning project and it's good to see that you are capable of this kind of process.
Burning Feet Man
16
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 15th Jan 2011 13:20
Ok, so I sat down tonight and wrote the same code, but using a UDT array, instead of a 2D string array. Off the record, I also did some theory upon a 3D array too, just for learning, but found it inappropriate for what I'm doing here.

Code as per below; CSV data attached to this post.



To be honest, unless I'm doing something seriously wrong with them, I found UDT's to be very troublesome, a very tight juggling act.

I've written some points below, in particular they focus on the below examples;

2D Array:

Quote: "Open to Read 1, "Options.csv"
For YCSVscan = 1 to YCSV
Read String 1, TempCell
Split Csv String TempCell
For XCSVscan = 1 to XCSV
Menu(XCSVscan, YCSVscan) = Get Split Word$(XCSVscan)
Next XCSVscan
Next YCSVscan"


Compared to this UDT Array:

Quote: "Open to Read 1, "Master Item List.csv"
XCSVscan = 1
For YCSVscan = 1 to YCSV
Read String 1, TempCell
Split Csv String TempCell

Item(YCSVscan).ID = VAL(Get Split Word$(XCSVSCAN)) : INC XCSVscan
Item(YCSVscan).Name = Get Split Word$(XCSVscan) : INC XCSVscan
Item(YCSVscan).Description = Get Split Word$(XCSVscan) : INC XCSVscan
Item(YCSVscan).Value = VAL(Get Split Word$(XCSVscan)) : INC XCSVscan
Item(YCSVscan).Weight = VAL(Get Split Word$(XCSVscan)) : INC XCSVscan
Item(YCSVscan).Size = VAL(Get Split Word$(XCSVscan)) : INC XCSVscan
Item(YCSVscan).Smallicon = Get Split Word$(XCSVscan) : INC XCSVscan
Item(YCSVscan).Largeicon = Get Split Word$(XCSVscan) : INC XCSVscan

XCSVscan = 1
Next YCSVscan
Close File 1
"


- Look at all the typing required for the UDT! And this isn't even a game yet, it's just me messing around.

- If the CSV file differs from this hardcoded UDT, things break.

- Toggling an incorrect 2D array dimension to the correct value is easy. But cutting and pasting UDT data then checking for typo's was very time consuming.

- With the 2D Array only being able to hold string data, this meant that all calculations had to be processed using VAL(data). But with a UDT, I had to remember which items were strings, and which were integers. Then if the spreadsheet changes, again breakage!

- When loading a lot of game data into my game engine via CSV Google Docs, anyone can log on, add their own stuff to the spreadsheet, then upon the next compile it's instantly in the game. Another, is that anyone can use spreadsheets but not everyone can code, and not to forget that Google Docs is collaborative. The other day, I had 3 friends all logged into the same spreadsheet, adding weird and wonderful game ideas which I could then directly feed into the game with out any further programming required!

- Not everyone speaks English. Translating a CSV document to a different language would be easier than trawling through code.

With the above points, I'm obviously still learning. Agent remind`s me with every discussion that I'm yet to even program tic-tac-toe.

But I appreciate everyone's patience on my learning, and I'm hoping that others are learning through what we're discussing here.

Attachments

Login to view attachments
Agent
20
Years of Service
User Offline
Joined: 7th Sep 2004
Location: Sydney, Australia
Posted: 15th Jan 2011 14:54 Edited at: 15th Jan 2011 15:05
Since we're talking about a training project here, I absolutely insist that you use UDT's for this problem. Learning how to operate with UDT's is just as essential for your core skills as learning how to operate with arrays.

Quote: "- Look at all the typing required for the UDT! And this isn't even a game yet, it's just me messing around. "


The extra code is only required once, when you load the array. 8 lines isn't a lot of code. My Tic Tac Toe game is 706 lines of code, and Starstrike (which you saw a while ago) is 14772 lines of code. You shouldn't fret over over a few lines of code any more than you should fret over 100% memory efficiency, especially when most of those extra lines are a cut and paste job, adjusting a property each time. Easy.

Quote: "- If the CSV file differs from this hardcoded UDT, things break. "


If you change the format of the CSV, any code you have written to read it will break, regardless of the technique you're using.

Quote: "- Toggling an incorrect 2D array dimension to the correct value is easy. But cutting and pasting UDT data then checking for typo's was very time consuming. "


Toggling an incorrect UDT is an identically simple matter. If you're using UDT's, the compiler will check for typo's for you by throwing an error if you use a property that hasn't been defined. If you use constants you won't get an error, so your point seems to argue the case for UDT's. Also I'm not sure why you're checking for typo's if the code was cut&paste, since you didn't type anything...

Quote: "- With the 2D Array only being able to hold string data, this meant that all calculations had to be processed using VAL(data). But with a UDT, I had to remember which items were strings, and which were integers. Then if the spreadsheet changes, again breakage! "


You already have to remember which are strings and which are ints. You seem to know when VAL() is required - that means you know it's an int. In practice you will not forget which properties are strings and integers and even if you do, the program will throw a type mismatch error when you use the wrong data type, even giving you the line in which the error transpired.

Moreover, given the memory-management freak that you are, you absolutely must not use strings at all unless there is no alternative - always use integers where possible, and floats where it's not and you're dealing only in numbers. Strings use far, far more memory than integers or floats. Relative to the amount of system memory available to your average computer we're talking about negligibly small amounts of memory here, but so we are when you "size up" your arrays, which is a total waste of time (there is no situation in which it's a good idea to do this). If you're insisting on doing so anyway, that position requires you to avoid using strings in every possible case (which is an equally ridiculous thing upon which to insist).

Back to the matter at hand: If you change the format of the spreadsheet, all code will break, whether you've used constants or UDT's (or any other possible technique, for that matter). This is why proper planning is required before you commence coding, and a perfect example of why "game design" is an entire field of expertise, entirely separate from the field of "game development".

Quote: "- When loading a lot of game data into my game engine via CSV Google Docs, anyone can log on, add their own stuff to the spreadsheet, then upon the next compile it's instantly in the game. Another, is that anyone can use spreadsheets but not everyone can code, and not to forget that Google Docs is collaborative. The other day, I had 3 friends all logged into the same spreadsheet, adding weird and wonderful game ideas which I could then directly feed into the game with out any further programming required!"


I'm struggling to find an argument for or against UDT's in this point. The type of read code you're using doesn't seem to affect whether or not people can collaborate on your spreadsheet. In all cases, your co-conspiritors will have to abide by the correct format in the spreadsheet, regardless of whether you're using constants or UDT's to read the data into your program.

Quote: "- Not everyone speaks English. Translating a CSV document to a different language would be easier than trawling through code. "


Ditto. Why would the language spoken by your users make any difference towards your decision between constants and UDT's? In commercial game development studios, entire departments are dedicated to a process called 'localisation' (I'm sure you've heard the term). Just in case you aren't familiar, their job is to translate all the strings used in the game to the local language (hence the naming of their job). This process takes place no matter what read code is used to access the data in question.

Even if it did make a difference, I strongly dispute your suggestion that localisation in a simpler matter than "trawling through lines of code" when you know exactly where the code in question lies in your program. Localisation for a commercial game takes months; adding a new property to a UDT takes somewhere in the general vicinity of four to five seconds, give or take a few milliseconds.

Quote: "Agent remind`s me with every discussion that I'm yet to even program tic-tac-toe."


It doesn't matter what game you make. The point is, making something practical will teach you far more than experimenting with purposeless practice projects. It's good to learn a few bare bones basics with practice projects, but by the time you've learned what an array even is (let alone advanced manipulation) you are ready to make your first game. It'll be far more productive to actually make something useful because you'll discover what skills you lack as you run into problems along the way, which will direct your learning along the most practical path. You are far beyond the stage where you should've started an actual project; I'd have a disciple commence work on their first actual game within a few days of learning basics.
Burning Feet Man
16
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 15th Jan 2011 22:51
In further testing of UDT and 2D arrays, from what I can tell the programs are the same with the exception of one using 2D arrays & the other using a UDT, yet the compiled UDT code uses 8500K memory (according to task manager) and the 2D String Array only uses 2500K.

I would expect the UDT to be the same, if not smaller due to the fact that integers are being used.

I've attached a screenshot.

Attachments

Login to view attachments
Agent
20
Years of Service
User Offline
Joined: 7th Sep 2004
Location: Sydney, Australia
Posted: 16th Jan 2011 02:33
That's a massive discrepancy. It cannot be accounted for by using UDT's instead of the 2D array. You'd have to have arrays of size far greater than this to occupy that much additional memory. I think there must be some other factor responsible for that - show me the complete code for both projects?
Burning Feet Man
16
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 16th Jan 2011 04:10 Edited at: 16th Jan 2011 11:02
Here is the UDT Code:



And here is the 2D String Array code:



I've checked both codes side by side, and can't see anything obvious which would cause the difference in memory usage.

Interesting stuff though.

EDIT: I've spent most of today actually writing some code that plugs into this system, and I must say, it's working an absolute treat!!! Will hopefully have an EXE to attached to a post sooner than later.
Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 16th Jan 2011 14:49
Here's a more visual example. Which line is easier to read?

doStuff((array(1,5), array(1,8), array(1,9), array(1,10)))


doStuff((array(1).id, array(1).x, array(1).y, array(1).z))



The only case where I'd say to use an array instead is if you were making a spreadsheet program and had an unknown number of columns.

"Only the educated are free" ~Epictetus
"Imagination is more important than knowledge..." ~Einstein
Burning Feet Man
16
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 19th Jan 2011 08:07
I tried a 3d array last night... The results were... Interesting. It felt kinda like driving a big bus around small city streets with only 3 passengers.

The good news is, I've just discovered array pointers, which will solve all of my 2d array griefs! They look like they can pass 2d arrays into functions, so I can avoid rewriting the same function over and over! Perfect!
Agent
20
Years of Service
User Offline
Joined: 7th Sep 2004
Location: Sydney, Australia
Posted: 20th Jan 2011 00:25
Yes, pointers are great for this sort of stuff. Passing values that can't normally be passed to functions are pretty much the main thing I use pointers for. They're a little more complicated to work out, but they'll be useful to know.
Burning Feet Man
16
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 20th Jan 2011 02:27 Edited at: 20th Jan 2011 03:21
I got the pointer functions found in Matrix1 Utilities working with 1D arrays, but I get errors when attempting 2D arrays.

Whilst thinking about this problem of processing arrays with functions, I wrote this, which doesn't use pointers or plugins. It works well with 2D arrays too.



Hopefully IanM will give a better insight on how his plug in can or can't work with 2D arrays.

EDIT: W00t! I got pointers working with 2D arrays outside of the function. Almost getting it.

EDIT 2: OK, I think I got it working. I had a typo one little variable that was breaking the work flow. Problem solved!

Login to post a reply

Server time is: 2024-09-29 00:26:15
Your offset time is: 2024-09-29 00:26:15