Permalänk
Medlem

Hjälp med spelprojekt

Hej.
Jag har nu fastnat på ett problem. Jag har 1 klass som ärver från en annan klass. Däremot så kan jag inte komma åt variablerna i den ärvda klassen från mitt huvud projekt även om variablerna är "public".
Här är koden
Klasserna:

class Buildings
{
public bool built;
public int goldCost;
public int woodCost;
public int stoneCost;
public int buildingTier;

public Buildings()
{
built = false;
}
}

class MilitaryBuilding : Buildings
{
public int weeklyTroopProduction;
public int weeklyBoughtTroops;
public int troopCost;
int troopTier;
string troopName;
public MilitaryBuilding(int buildingTier, int weeklyTroopProduction, int troopTier, string troopName, int goldCost, int woodCost, int stoneCost)
{
this.buildingTier = buildingTier;
this.weeklyTroopProduction = weeklyTroopProduction;
this.troopTier = troopTier;
this.troopName = troopName;
this.goldCost = goldCost;
this.woodCost = woodCost;
this.stoneCost = stoneCost;
//Styckpriset av soldater
troopCost = 20 * this.troopTier;
}
}

Byggnaderna sätts in i en lista:
class Cities
{
//List with all the buildings in the city
protected List<Buildings> built = new List<Buildings>();
public Cities()
{

}

public List<Buildings> EnterTown()
{
//Sends the list of the buildings
return built;
}
}

class Town1 : Cities
{
public Town1()
{
//Adds the buildings
built.Add(new MilitaryBuilding(1, 30, 1, "Pugilist", 500, 2, 2));
built.Add(new MilitaryBuilding(2, 20, 2, "Slinger", 2500, 5, 5));
built.Add(new MilitaryBuilding(3, 15, 3, "Poison Master", 5000, 10, 10));
built.Add(new MilitaryBuilding(4, 10, 4, "Knight", 10000, 15, 15));
built.Add(new MilitaryBuilding(5, 5, 5, "Pyromancer", 15000, 20, 20));
}
}

Jag försöker kalla på en int men den hittar inte "weeklyTroopProduction"
Town1 town1 = new Town1();
town1.EnterTown()[0].weeklyTroopProduction

Skulle vara trevligt om någon hittade felet

Permalänk
Medlem

EnterTown returnerar en lista av basklassen Buildings. Du har implementerat propertyn på din derived klass MilitaryBuilding. Så du får antingen casta till MilitaryBuilding eller returera en List<MilitaryBuilding>.
Basklassen ska inte känna till hur subklasserna är implementerade. Basklassen ska endast vara en typ av kontrakt om vad som är absolut minimum för alla klasserna.

var weeklyTroopProduction = (town1.EnterTown()[0] as MilitaryBuilding).weeklyTroopProduction;

När du postar kod använd [code] taggar runt din kod för att göra det enklare att läsa.

[code-tag] (utan -tag)
// din kod här
[/code-tag] (utan -tag)

Edit:
Har du flera olika byggnader i din lista och vill få ut specifika kan du göra en query med LINQ.
Låt oss säga att EnterTown() returerar en lista av Buildings, men att den innehåller mer än bara MilitaryBuildings.
Vill du då få ut endast MilitaryBuildings kan du filtrera listan med en Where() om du vill ha många, eller FirstOrDefault() om du vill ha ut första byggnaden i listan.

// Många: Returerar en List<MilitaryBuilding> var militaryBuildings = town1.EnterTown().Where(b => b is MilitaryBuilding).ToList(); // Första byggnaden: Returerar ett object av MilitaryBuilding eller null om det inte finns var militaryBuilding = town1.EnterTown().FirstOrDefault(b => b is MilitaryBuiding);

Förtydligande med fler exempel.
Permalänk
Medlem

Jag skulle rekommendera att använda en get-funktion som returnerar variabeln/värdet istället för att gå till den direkt (om du försöker anropa den från en annan klass vill säga). Samt att då sätta variabeln till private och ha en set-funktion som lite god kod-sed.

Men håller med @zaibuf använd gärna [code]-taggar så blir det enklare att läsa din kod.

/Ullman

Permalänk

Döp även om din klass "Buildings" till "Building". Din militärbas är inte byggnader utan en byggnad.

Permalänk
Medlem

Tack så mycket för svaren, har suttit skitlänge och inte riktigt fattat varför det inte fungerar. Jag ska testa LINQ och se om det fungerar, så återkommer jag om det fortfarande inte fungerar
Det där med code-tag visste jag inte riktigt hur man gjorde på sweclockers men ska självklart använda det i framtiden.

Permalänk
Medlem
Skrivet av zaibuf:

EnterTown returnerar en lista av basklassen Buildings. Du har implementerat propertyn på din derived klass MilitaryBuilding. Så du får antingen casta till MilitaryBuilding eller returera en List<MilitaryBuilding>.
Basklassen ska inte känna till hur subklasserna är implementerade. Basklassen ska endast vara en typ av kontrakt om vad som är absolut minimum för alla klasserna.

var weeklyTroopProduction = (town1.EnterTown()[0] as MilitaryBuilding).weeklyTroopProduction;

När du postar kod använd [code] taggar runt din kod för att göra det enklare att läsa.

[code-tag] (utan -tag)
// din kod här
[/code-tag] (utan -tag)

Edit:
Har du flera olika byggnader i din lista och vill få ut specifika kan du göra en query med LINQ.
Låt oss säga att EnterTown() returerar en lista av Buildings, men att den innehåller mer än bara MilitaryBuildings.
Vill du då få ut endast MilitaryBuildings kan du filtrera listan med en Where() om du vill ha många, eller FirstOrDefault() om du vill ha ut första byggnaden i listan.

// Många: Returerar en List<MilitaryBuilding> var militaryBuildings = town1.EnterTown().Where(b => b is MilitaryBuilding).ToList(); // Första byggnaden: Returerar ett object av MilitaryBuilding eller null om det inte finns var militaryBuilding = town1.EnterTown().FirstOrDefault(b => b is MilitaryBuiding);

Jag testade att göra detta som du skrev

town1.EnterTown()[0] as MilitaryBuilding).AvailableTroops()

och sen ändrade lite i klassen

class MilitaryBuilding : Buildings { private int weeklyTroopProduction; private int weeklyBoughtTroops; public int troopCost; int troopTier; string troopName; public MilitaryBuilding(int buildingTier, int weeklyTroopProduction, int troopTier, string troopName, int goldCost, int woodCost, int stoneCost) { this.buildingTier = buildingTier; this.weeklyTroopProduction = weeklyTroopProduction; this.troopTier = troopTier; this.troopName = troopName; this.goldCost = goldCost; this.woodCost = woodCost; this.stoneCost = stoneCost; //Styckpriset av soldater troopCost = 20 * this.troopTier; } public int AvailableTroops() { if (built == true) { return weeklyTroopProduction - weeklyBoughtTroops; } else { return 0; } } }

Nu klagar den på att det är en tuple(antar jag) så jag behövde installera System.ValueTuple i nuget. Kan du förklara på vilket sätt det är en tuple? För jag förstår så att tuples kan användas om man vill ha flera världen från en metod utan att använda out-parameter, men kan inte koppla det till det här

Permalänk
Medlem
Skrivet av Masadan:

Jag testade att göra detta som du skrev

town1.EnterTown()[0] as MilitaryBuilding).AvailableTroops()

och sen ändrade lite i klassen

class MilitaryBuilding : Buildings { private int weeklyTroopProduction; private int weeklyBoughtTroops; public int troopCost; int troopTier; string troopName; public MilitaryBuilding(int buildingTier, int weeklyTroopProduction, int troopTier, string troopName, int goldCost, int woodCost, int stoneCost) { this.buildingTier = buildingTier; this.weeklyTroopProduction = weeklyTroopProduction; this.troopTier = troopTier; this.troopName = troopName; this.goldCost = goldCost; this.woodCost = woodCost; this.stoneCost = stoneCost; //Styckpriset av soldater troopCost = 20 * this.troopTier; } public int AvailableTroops() { if (built == true) { return weeklyTroopProduction - weeklyBoughtTroops; } else { return 0; } } }

Nu klagar den på att det är en tuple(antar jag) så jag behövde installera System.ValueTuple i nuget. Kan du förklara på vilket sätt det är en tuple? För jag förstår så att tuples kan användas om man vill ha flera världen från en metod utan att använda out-parameter, men kan inte koppla det till det här

Hm, jag har inte det problemet. Fungerar det om du kör Nuget för det då? Vilken runtime kör du i? Jag testade din kod i .NET Core 2.2 Console Applikation och allt fungerar utan något extra paket.

static void Main(string[] args) { Town1 town1 = new Town1(); var availableTroops = (town1.EnterTown()[0] as MilitaryBuilding)?.AvailableTroops(); Console.WriteLine(availableTroops); // Result: 0 }

Sen kan du förkorta din metod lite också

// Detta är samma sak som public int AvailableTroops() { if (built == true) // Räcker annars att skriva if (built) alternativt if (!built) om det inte ska vara byggt. { return weeklyTroopProduction - weeklyBoughtTroops; } else { return 0; } } // Detta public int AvailableTroops() => built ? weeklyTroopProduction - weeklyBoughtTroops : 0;

Tuplets är sorterad lista av blandade strongly typed data values.

var tuplet = ("Hello", "world", 1, true); // 2 strings, 1 int, 1 bool Console.WriteLine(tuplet.item1); // Hello Console.WriteLine(tuplet.item2); // world Console.WriteLine(tuplet.item3); // 1 Console.WriteLine(tuplet.item4); // true

Du behöver inte en instance av en klass utan kan bara deklarera upp det sådär. Jag har dock aldrig behövt använta det någon gång.

Permalänk
Medlem

@zaibuf: Det fungerade utmärkt när jag använde nuget. Jag kör då i monogame vilket inte automatiskt kommer med alla bibliotek och grejer som om man kör console application.

Tack för hjälpen med allt och förklaringen för tuples, samt förkortningen också, det hade jag glömt bort att man kunde göra

Permalänk
Avstängd

@Masadan: Tuples inom programmering är helt enkelt ett objekt med flera värden. Det underlättar i en hel del situationer då du slipper göra en klass eller struct för något om du exempelvis bara behöver returnera två integers eller så.

Säg att du behöver få ut en position i ett rutnät, alltså x och y. I din klass för det som befinner sig i rutnätet så kan du ha en metod för x och en för y, typ public int getXPosition() och public int getYPosition(), eller så kan du ha public Tuple(int, int) getPosition() som ger båda, eller så skapar du en klass, säg Position som innehåller x och y, vilket ju kräver lite mer jobb vilket är onödigt om allt du behöver är just positionen.