Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Advice on how to organize my class's?
Index -> Programming, Turing -> Turing Help
Goto page 1, 2  Next
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
GreatPumpkin




PostPosted: Sat Feb 22, 2014 1:50 am   Post subject: Advice on how to organize my class's?

What is it you are trying to achieve?
I'm working on my overhead civilization-like game after taking a break for a little while. I've decided to rewrite my code again completely, switching certain aspects of it into functions, classes and modules.


What is the problem you are having?
My problem is that I am unsure of how to organize my code. Before my rewrite I had a large class which contained cities, along with the units (and soon to be farms) that belong to the city. It doesn't seem proper to have two separate sets of objects in the same class, but the units belong to the cities. I originally had an array of a custom record type called cityType; containing the cities x, y, maxUnits etc. along with an array of another custom type called units; containing an x and y. This large class was called playerObjects, however I was also going to use it in the long run for the enemy units.
This was working fine but like I said seems somewhat improper.

So it's kind of like the units are a child of the cities, they are reliant on the cityType and it's information.

I have no Idea how to separate them into different classes, or if I even should. Any input would be appreciated.


Describe what you have tried to solve this problem
<Answer Here>


Post any relevant code (You may choose to attach the file instead of posting the code if it is too long)
<Answer Here>

Turing:


<Add your code here>



Please specify what version of Turing you are using
4.1.1
Sponsor
Sponsor
Sponsor
sponsor
Insectoid




PostPosted: Sat Feb 22, 2014 12:36 pm   Post subject: RE:Advice on how to organize my class\'s?

You could include a pointer to city in the unit class, which points to the parent city. Any information the units need from the city should be available in the public functions of the city, which are accessed via the pointer. The city needs only an array of units.
GreatPumpkin




PostPosted: Sat Feb 22, 2014 7:21 pm   Post subject: RE:Advice on how to organize my class\'s?

So the unitsClass holds only the variables of the stats, methods of interaction and a pointer to the citiesClass, with no arrays inside?

and by pointer do you mean the "pointer to" or a variable that holds the number of the city it belongs to ?
evildaddy911




PostPosted: Sat Feb 22, 2014 7:41 pm   Post subject: RE:Advice on how to organize my class\'s?

you could probably do either one. however, insectoid most likely meant "pointer to"
Insectoid




PostPosted: Sat Feb 22, 2014 8:53 pm   Post subject: RE:Advice on how to organize my class\'s?

Quote:
So the unitsClass holds only the variables of the stats, methods of interaction and a pointer to the citiesClass, with no arrays inside?


The unit class contains any variables and functions that it requires. The pointer gives it access to all of the city class's public variables and functions.
GreatPumpkin




PostPosted: Sat Feb 22, 2014 10:40 pm   Post subject: Re: Advice on how to organize my class's?

I don't understand what you mean by an array of units in the city in your first post.
If my citiesClass comes before my unitsClass, and the record for the type unitsType is within the unitsClass, how do I make an array of unitsType? Also if theres only a pointer from unitsClass to citiesClass, how do I manipulate the array of units in the city with methods in unit's class?

Nor do I understand what you mean by "a pointer to city in the unit class, which points to the parent city"
Is the pointer to the citiesClass? or is it a pointer to the array of cityTypes inside the citiesClass?

I really don't understand at all, can you give me an example ?
Here is the code for my unitsClass I've made.

Turing:
class citiesClass
    import cursor, pics
    export addCity, drawCities

    var cityTiles : array 0 .. 59, 0 .. 59 of int
    for x : 0 .. 59
        for y : 0 .. 59
            cityTiles (x, y) := 0
        end for
    end for

    type cityType :
        record
            cityNo : int %City No./ Active Flag
            x : int     %X
            y : int     %Y
            adjLand : int
            maxUnits : int
            units : array 1 .. 8 of int
        end record
    var cities : array 1 .. 15 of cityType


    var selectedCity : int := 1
    var openCityPointer : int := 1



    for i : 1 .. 15
        cities (i).cityNo := 0 %City No./ Active Flag
        cities (i).x := 0 %X
        cities (i).y := 0 %Y
        cities (i).adjLand := 0 %Number of adjacent land tiles
        cities (i).maxUnits := 0  %#of units
    end for


    procedure checkForOpenCity
        openCityPointer := 1  %variable to check through attackArray
        for i : 1 .. 15 %cityInfo (selectedCity).maxCitys
            if cities (openCityPointer).cityNo = 0 then                 %if pointing to open space exit, openCityPointer will = open unit
                exit
            else
                openCityPointer := openCityPointer + 1
            end if
        end for %%% openCityPointer will now be pointing t0 the first available unit space.
    end checkForOpenCity

    proc addCity
        checkForOpenCity
        cities (openCityPointer).cityNo := openCityPointer
        cities (openCityPointer).x := (cursor.adjustXdiv)
        cities (openCityPointer).y := (cursor.adjustYdiv)
        cityTiles (cities (openCityPointer).x, cities (openCityPointer).y) := openCityPointer

    end addCity

    proc adjustCityTiles
        for i : 1 .. 15
            if cities (i).cityNo > 0 then
                cityTiles (cities (i).x, cities (i).y) := cities (i).cityNo
            end if
        end for
    end adjustCityTiles

    proc drawCities
        for x : 0 .. 60 - 1
            for y : 0 .. 60 - 1
                if cityTiles (x, y) > 0 then
                    Pic.Draw (pics (8), x * 10 - 10, y * 10 - 10, picMerge)
                end if
            end for
        end for
    end drawCities

end citiesClass
var playerCities : ^citiesClass
new citiesClass, playerCities


class unitsClass

    import cursor, pics
    export addUnit, drawUnits

    var unitTiles : array 0 .. 59, 0 .. 59 of int
    for x : 0 .. 59
        for y : 0 .. 59
            unitTiles (x, y) := 0
        end for
    end for

    type unitType :
        record
            unitNo : int %City No./ Active Flag
            x : int     %X
            y : int     %Y
        end record


    var selectedUnit : int := 1
    var openUnitPointer : int := 1
    var units : array 1 .. 8 of unitType


     for i : 1 .. 8
         units (i).unitNo := 0 %City No./ Active Flag
         units (i).x := 0 %X
         units (i).y := 0 %Y
     end for


    procedure checkForOpenUnit
        openUnitPointer := 1  %variable to check through attackArray
        for i : 1 .. 8 %unitInfo (selectedCity).maxCitys
            if units (openUnitPointer).unitNo = 0 then                 %if pointing to open space exit, openCityPointer will = open unit
                exit
            else
                openUnitPointer := openUnitPointer + 1
            end if
        end for %%% openCityPointer will now be pointing t0 the first available unit space.
    end checkForOpenUnit

    proc addUnit
        checkForOpenUnit
        units (openUnitPointer).unitNo := openUnitPointer
        units (openUnitPointer).x := (cursor.adjustXdiv)
        units (openUnitPointer).y := (cursor.adjustYdiv)
        unitTiles (units (openUnitPointer).x, units (openUnitPointer).y) := openUnitPointer

    end addUnit

    proc adjustUnitTiles
        for i : 1 .. 8
            if units (i).unitNo > 0 then
                unitTiles (units (i).x, units (i).y) := units (i).unitNo
            end if
        end for
    end adjustUnitTiles

    proc drawUnits
        for x : 0 .. 60 - 1
            for y : 0 .. 60 - 1
                if unitTiles (x, y) > 0 then
                    Pic.Draw (pics (7), x * 10, y * 10, picMerge)
                end if
            end for
        end for
    end drawUnits


end unitsClass
Dreadnought




PostPosted: Sun Feb 23, 2014 2:20 am   Post subject: Re: Advice on how to organize my class's?

GreatPumpkin wrote:

I don't understand what you mean by an array of units in the city in your first post.
If my citiesClass comes before my unitsClass, and the record for the type unitsType is within the unitsClass, how do I make an array of unitsType? Also if theres only a pointer from unitsClass to citiesClass, how do I manipulate the array of units in the city with methods in unit's class?
I'll get to this in a bit.

GreatPumpkin wrote:

Nor do I understand what you mean by "a pointer to city in the unit class, which points to the parent city"
Is the pointer to the citiesClass? or is it a pointer to the array of cityTypes inside the citiesClass?
You want the unit to know which city it is in, so it should have a pointer which points to it (or some of its data)

GreatPumpkin wrote:

I really don't understand at all, can you give me an example ?
I'll try, but first, how does one have classes which mutually reference one another? (your first question)
Well in the ugly beast that is Turing's OOP that's not very obvious since we can't use forward declarations for types. So we get
Turing:

class A
import% this will fail (undeclared)

end A

class B
import A

end B

Putting each class in its own unit doesn't get us much farther since Turing will complain about circular dependency. So what can we do?
My solution (and I encourage anyone else with a nice solution to post it) is to have some kind of type that will store sufficient information about B so that A can use it. Like a parent class for B that contains everything A will need. (I don't really find this to be an elegant solution but I can't come up with something better for now)

Here's an example (in multiple files)

CityData.tu
Turing:
unit
class CityData
    % Contains what Citizen needs to know about a city
    export var Name

    var Name : string

end CityData


Citizen.tu
Turing:
unit
class Citizen
    import CityData
    export var Name, SetParentCity, Action

    var parentCity : ^CityData := nil

    var Name : string

    proc SetParentCity (p : ^CityData)
        parentCity := p
    end SetParentCity

    proc Action ()
        if (parentCity ~= nil) then
            put "    Action() was called on " + Name + ", citizen of " + parentCity -> Name + "."
        else
            put "    Action() was called on " + Name + ", which is not a citizen of any city"
        end if
    end Action
end Citizen


City.tu
Turing:
unit
class City
    inherit CityData
    import Citizen
    export AddCitizen, PerformActionOnAllCitizens, ListCitizens, ClearCitizens

    % I use a flexible array but you can use any container you want
    var citizens : flexible array 1 .. 0 of ^Citizen
    var citizenCount : int := 0

    proc AddCitizen (c : ^Citizen)
        if (upper(citizens) <= citizenCount) then
            if (upper(citizens) < 1) then
                new citizens, 1
            else
                new citizens, upper(citizens) * 2
            end if

            assert (upper(citizens) > citizenCount)
        end if
        citizenCount += 1
        citizens (citizenCount) := c
        c -> SetParentCity (self)
    end AddCitizen

    proc PerformActionOnAllCitizens ()
        for i : 1 .. citizenCount
            citizens (i) -> Action ()
        end for
    end PerformActionOnAllCitizens

    proc ListCitizens ()
        put "    --- Citizens of " + Name + " ---"
        for i : 1 .. citizenCount
            put citizens (i) -> Name
        end for
    end ListCitizens

    proc ClearCitizens ()
        for i : 1 .. citizenCount
            free citizens (i)
        end for
        citizenCount := 0
    end ClearCitizens
end City


main.t (main program, call the file what you want)
Turing:
import City, Citizen

% So we can see everything
View.Set("text")

% Just a little helper function
fcn MakeCitizen (name : string) : ^Citizen
    var c : ^Citizen
    new Citizen, c
    c -> Name := name
    result c
end MakeCitizen

var city1, city2 : ^City
new City, city1
new City, city2

city1 -> Name := "Toronto"
city2 -> Name := "Ottawa"

city1->AddCitizen(MakeCitizen("Rob Ford"))
city1->AddCitizen(MakeCitizen("Kathleen Wynne"))
city1->AddCitizen(MakeCitizen("Tim Hudak"))
city1->AddCitizen(MakeCitizen("Andrea Horwath"))
city1->AddCitizen(MakeCitizen("Rick Mercer"))

city2->AddCitizen(MakeCitizen("Steven Harper"))
city2->AddCitizen(MakeCitizen("Jim Flaherty"))
city2->AddCitizen(MakeCitizen("Mike Duffy")) % Is he still a senator?
city2->AddCitizen(MakeCitizen("Justin Trudeau"))
city2->AddCitizen(MakeCitizen("Tom Mulcair"))


% Now the fun stuff
put "city1->ListCitizens()"
put ""
city1->ListCitizens()
put ""
put "==================================="
put "city2->ListCitizens()"
put""
city2->ListCitizens()
put ""
put "==================================="
put "city1->PerformActionOnAllCitizens()"
put ""
city1->PerformActionOnAllCitizens()
put ""
put "==================================="
put "city2->PerformActionOnAllCitizens()"
put ""
city2->PerformActionOnAllCitizens()
put ""
put "==================================="

% Clean up
city1->ClearCitizens()
city2->ClearCitizens()
free city1
free city2


Note that this is an example of how I might do it (although I split City into two pieces you might find it easier to split Citizen or do something else entirely). Another way would be using implement instead of inherit for the relation of CityData (or whatever we want to call it) and City.
Basically, this is the nicest thing I can come up with for now, but I find it clunky.
GreatPumpkin




PostPosted: Sun Feb 23, 2014 2:36 pm   Post subject: Re: Advice on how to organize my class's?

Dreadnought @ Sun Feb 23, 2014 2:20 am wrote:

Well in the ugly beast that is Turing's OOP that's not very obvious since we can't use forward declarations for types.

This makes me feel alot better about not understanding this.

Dreadnought @ Sun Feb 23, 2014 2:20 am wrote:

Basically, this is the nicest thing I can come up with for now, but I find it clunky.

Your example and solution make a bit of sense to me, I'll play around with it later, but it seems somewhat straightforward.
Do you think it would be poor practice to continue with a single class that encompasses an individual players (user/ai enemy/second player) cities, units, and farms?
Sponsor
Sponsor
Sponsor
sponsor
Tony




PostPosted: Sun Feb 23, 2014 3:07 pm   Post subject: Re: Advice on how to organize my class's?

GreatPumpkin @ Sun Feb 23, 2014 2:36 pm wrote:

Do you think it would be poor practice to continue with a single class that encompasses an individual players (user/ai enemy/second player) cities, units, and farms?

Yes, because that's an anti-pattern described by https://en.wikipedia.org/wiki/God_object
Latest from compsci.ca/blog: Tony's programming blog. DWITE - a programming contest.
GreatPumpkin




PostPosted: Sun Feb 23, 2014 6:56 pm   Post subject: Re: Advice on how to organize my class's?

So the majority of methods for the citizens are actually held in the city.tu class is your example ?
Theres some vocabulary I haven't encountered there, and was wondering if you could give me a run down of what happens during a few parts:

Turing:
    proc AddCitizen (c : ^Citizen)
        if (upper(citizens) <= citizenCount) then
            if (upper(citizens) < 1) then
                new citizens, 1
            else
                new citizens, upper(citizens) * 2
            end if

            assert (upper(citizens) > citizenCount)
        end if
        citizenCount += 1
        citizens (citizenCount) := c
        c -> SetParentCity (self)
    end AddCitizen


self and assert


Turing:
    var parentCity : ^CityData := nil

    var Name : string

    proc SetParentCity (p : ^CityData)
        parentCity := p
    end SetParentCity

    proc Action ()
        if (parentCity ~= nil) then
            put "    Action() was called on " + Name + ", citizen of " + parentCity -> Name + "."
        else
            put "    Action() was called on " + Name + ", which is not a citizen of any city"
        end if
    end Action


nil.

I will research them when I get back home though.
evildaddy911




PostPosted: Sun Feb 23, 2014 7:32 pm   Post subject: RE:Advice on how to organize my class\'s?

self: when you use self, you are referencing the object you are in. in this case, you are saying Set Parent City to "this city"
assert: this checks to see if the following statement is true. if it is false (if upper(citizens) < citizenCount), then the program will crash. its purpose is for detecting exactly where a problem originated
nil: its a null reference. it tells the program that parentCity doesnt have any data yet
GreatPumpkin




PostPosted: Sun Feb 23, 2014 10:16 pm   Post subject: Re: Advice on how to organize my class's?

Ok I think my problems are coming from not understanding pointers.
I've looked up as many tutorials and guides about them but I just can't grasp them and it's really starting to bug me. All I know is that they're a variable that holds the information of the address of another variable. I don't really understand how it ties into all of this or how it's used.

Could somebody give me as simple dumbed down explanation of pointers with an example of how and where they'd be used? Like I said I have looked up tutorials and I'm still extremely lost.

If you had a string that read "text" and a pointer to the string, put both the string and the pointer they should both put out as "text" ?

I tried that but it can only be used with collection's, class's, and types.. So I made a little object named textContainer. Pretty much it's just a string of text that has a method to write the text into the string and to put the string.


Turing:
class textContainer
export getContainedText, putContainedText
    type textContained :
        record
            text : string
        end record
    var firstTextContainer : textContained

    proc getContainedText (TEXT : string)
        firstTextContainer.text := TEXT
    end getContainedText


    proc putContainedText
        put firstTextContainer.text
    end putContainedText

end textContainer



var myTextContainer : ^textContainer
new textContainer, myTextContainer

myTextContainer -> getContainedText ("This is my text")
myTextContainer -> putContainedText




Can somebody please dissect and explain this part for me :

var myTextContainer : ^textContainer
new textContainer, myTextContainer

the pointer to and the new, I just don't understand those concepts, I've tried to but I can't.

If the pointer just points to the address of the class, and not the class and information in it, how is it put to use?

I really need somebody to help me understand this, because I'm clearly not going to get anywhere by myself.

Also, if somebody could show me how I could complete my bolded example above using the textContainer I've made, it might help me? I'm feeling extremely lost and like quitting all together if I can't grasp these obviously important concepts soon.
Raknarg




PostPosted: Sun Feb 23, 2014 10:36 pm   Post subject: RE:Advice on how to organize my class\'s?

Well I can give it a go. Correct me if I'm wrong.

So you have things like int, real, char, etc. Those all take a very tiny amount of information. So, variables can actually store the info. Think of these like a box that you put stuff in. You just look at the box, and there it is. However, these boxes can only hold one item at a time.

A pointer is different. Imagine your box still only holds one item, but inside your box there's a card that tells you where you can find a warehouse full of other boxes that store information. These are what pointers are (things like arrays and objects). The primitive data types are a box which holds info, and the pointers are boxes that hold the info of where you can find all the other boxes (those boxes being items in your array, or data fields in a class). This is because, like I said, your box can only hold one item at a time. You can't cram in all those pieces of info together, so instead you just store it somewhere else.

In this case, you're creating an item which holds direction for the computer to find all the information of that object. Lets take your example:

var myTextContainer : ^textContainer
new textContainer, myTextContainer

First, you make a pointer to a text container. This means that myTextContainer is going to hold info for the directions of where the computer can find a copy of textContainer. It doesn't yet, but the program is saying that's what it will be.

Then you initialize it. Now textContainer is actually pointing to that information.


Understanding pointers is important when managing your information. You're used to doing this:

var x : int := 5
var y : int := x
x := 7

Normally this would mean that y copies whatever is in x's box and put it in its own. In this case, x is now 7 and y is now 5. However, you cannot do the same things with pointers, because they don't contain the object itself, they contain directions to the object. So:

var x : ^SomeObject := makeNewObject()
new SomeObject, x
x -> someNumberInSomeObject := 5
var y : ^SomeObject := x
x -> someNumberInSomeObject := 7

that data field, someNumberInSomeObject is now the same for x and y, because they're both actually using the same object, as they both have the same directions.
Dreadnought




PostPosted: Sun Feb 23, 2014 11:47 pm   Post subject: Re: Advice on how to organize my class's?

Raknarg wrote:
So you have things like int, real, char, etc. Those all take a very tiny amount of information. So, variables can actually store the info.

There isn't really a problem with variables taking up space in Turing (but it is an issue in other languages like C), for example this runs fine on my computer
Turing:
var s : string
put sizeof(s) % 256
var as : array 1..5000000 of string
put sizeof(as) % 1280000000  (yes, that's 1,280,000,000 bytes or 1.28 GB)


Here's my "concrete" example of the difference between a value and a pointer. (Raknarg's example with boxes works too but this one feels more intuitive to me)
If I tell Alice "Your number is 5." and tell Bob "Your number is 5.", then tell Alice "Double your number.", Bob's number is still 5 but Alice's is 10
Now, lets say I tell Alice "Your table is this" (as I point my finger at a table) then tell Bob "Your table is this" (pointing my finger at the same table), then I tell Alice "Paint your table red". Now Bob's table is red and Alice's table is red (since they are the same table).

The idea is that in Object Oriented Programming, objects represent some kind of entity. So if I give Alice and Bob the same object, then any changes Alice makes to her object affect Bob's object (since they are the same object).

So how do we translate that into a computer program? (this is where Raknarg's example with boxes is more intuitive)
You create new objects by setting aside space in memory (making room in your warehouse) for the object you want (box of the right size). In Turing this is done using new.
Then you have pointers which tell you where the object is in memory (cards telling you where to look in the warehouse).
This means that if Alice and Bob have cards that tell them to look at the same spot in the warehouse, and Alice paints the object in her box there red, Bob's object will also be red (again, it's the same object).


Raknarg wrote:

var x ^SomeObject = makeNewObject()
new SomeObject, x
x -> someNumberInSomeObject = 5
var y ^SomeObject = x
x -> someNumberInSomeObject = 7

I assume the "makeNewObject()" is not intended to be there since there is a new right after.


I'd like to add a few things:

nil: Basically an invalid location in memory (usually 0), think of it as a blank card (in Raknarg's warehouse of boxes example).
It's good practice to set pointers to nil when they do not point to a valid object.

free: So you set aside all this space in memory for objects, but when you're done with objects you should call free on a pointer to tell the computer you no longer need that space in memory (so the computer can reuse it). Otherwise the computer will continue to assume you are using it, even if you don't have a pointer pointing to that location in memory.
You should always free objects, otherwise you might "leak memory". (Note that when your program finished all memory set aside for it is returned to the OS, but it's still good practice to avoid memory leaks)
Raknarg




PostPosted: Mon Feb 24, 2014 12:16 am   Post subject: RE:Advice on how to organize my class\'s?

>I assume the "makeNewObject()" is not intended to be there since there is a new right after.

Right, im mixing up with java here.

Thank for the corrections.
Display posts from previous:   
   Index -> Programming, Turing -> Turing Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 2  [ 24 Posts ]
Goto page 1, 2  Next
Jump to:   


Style:  
Search: