Avatar billede ahara Nybegynder
13. november 2004 - 16:34 Der er 21 kommentarer og
1 løsning

Array i Objekt

Hej igen

Jeg har tidligere spurgt om ovenstående men har aldrig fået det til at virke ordentligt.

Jeg ønsker at kunne oprette et objekt indeholdende en brikværdi, samt et array der har pointere til 4 nabofelter.

Koden virker ikke perfekt, da jeg ikke ved hvad der skal stå i oprettelsen af objektet "se spørgsmåltegn".

******Kode******

enum brikker{Tom, Sort, Hvid};

class felt
{
private:
    brikker brik;
    felt *nabo[4];
public:
    felt(){}
    felt(brikker brik_x, felt *nabo_x[2])
    {
        brik=brik_x;
        nabo[4]=nabo_x[4];
    }
};

int main()
{
    felt *nr[2][2];

    nr[0][0]=new felt(Tom,????);
    nr[0][1]=new felt(Tom,????);
    nr[1][0]=new felt(Tom,????);
    nr[1][1]=new felt(Tom,????);

    return 0;
}

Mvh
AHR
Avatar billede arne_v Ekspert
13. november 2004 - 16:57 #1
Måske noget lige som:

felt(brikker brik_x, felt *nabo_1, felt *nabo_2, felt *nabo_3, felt *nabo_4)
{
  brik=brik_x;
  nabo[0]=nabo_1;
  nabo[1]=nabo_2;
  nabo[2]=nabo_3;
  nabo[3]=nabo_4;
}

og

    nr[0][0]=new felt(Tom,NULL,NULL,nr[0][1],nr[1][0]);
    nr[0][1]=new felt(Tom,NULL,nr[0][0],NULL,nr[1][1]);
    nr[1][0]=new felt(Tom,nr[0][0],NULL,nr[1][1],NULL);
    nr[1][1]=new felt(Tom,nr[0][1],nr[1][0],NULL,NULL);

men det er ikke helt nemt at gennemkue hvad du har brug for og hvad der er den
bedste løsning.
Avatar billede ahara Nybegynder
13. november 2004 - 17:06 #2
Sorry, hvis det er lidt "sort". Det jeg har brug for er en 4x4 spilleplade (16 felter). Hvert felt på spillepladen oprettes som et objekt. Hvert felt skal have oplysninger om hvem der er deres nabo/er.

Den måde du gør det på skal jeg skrive:

felt(brikker brik_x, felt *nabo_1, felt *nabo_2, felt *nabo_3, felt *nabo_4)

Hvis der nu var 50 eller 100 naboer, havde det været nemmere at kunne oprette et array for hvert objekt indeholdende adresser til deres naboer, så kunne koden se således ud:

felt(brikker brik_x, felt *nabo[])

Men kan det lade sig gøre?

AHR
Avatar billede arne_v Ekspert
13. november 2004 - 17:09 #3
Du kunne sagtens lave de 4 naboer til et argument af array fremfor 4 argumenter.
Det ville spare 3 linier i constructoren.

Men det bille kræve 4-5 linier for hver eneste felt du skal oprette !
Avatar billede arne_v Ekspert
13. november 2004 - 17:09 #4
Men det ville kræve ...
Avatar billede stormy Nybegynder
13. november 2004 - 20:55 #5
Som jeg umiddelbart læser det, er der et stort problem, i den løsning arne_v har skitseret ( sjældent at se en sådan, fra hans hånd ! )

Nemlig i en linie som :

nr[0][0]=new felt(Tom,NULL,NULL,nr[0][1],nr[1][0]);

På dette tidspunkt er konstruktoren for nr[0][1} og nr[1][0] endnu ikke blevet kaldt. Så nr[0][1] og nr[1][0] er uinitialiseret.

Dette løses nemmest ved at lave to gennemløb af spillepladen.
Først oprettes hvert felt, dernæst kan man finde dets naboer.
En mulig løsning kunne se sådan ud :

#include <cstdio>

const int DIM_X = 4;
const int DIM_Y = 4;

enum brikker{Tom, Sort, Hvid};

class felt
{
private:
  brikker brik;
  felt *nabo[4];
public:
  felt(brikker brik_x)
  {
    brik=brik_x;
    int i;
    for(int i=0;i<4;i++)
      nabo[i] = NULL;
  }
  void tilfoej_naboer( felt * nabo_0, felt * nabo_1, felt * nabo_2, felt * nabo_3)
  {
    nabo[0] = nabo_0;
    nabo[1] = nabo_1;
    nabo[2] = nabo_2;
    nabo[3] = nabo_3;
  }
};

void initialiser( felt *braet[DIM_X][DIM_Y] )
{
  int x,y;

  for(x=0;x<DIM_X;x++)
    for(y=0;y<DIM_Y;y++)
      braet[x][y] = new felt(Tom);

  for(x=0;x<DIM_X;x++)
    for(y=0;y<DIM_Y;y++)
      braet[x][y]->tilfoej_naboer(  ( (x==0) ? NULL : braet[x-1][y] ),
                                    ( (y==0) ? NULL : braet[x][y-1] ),
                                    ( (x+1 == DIM_X) ? NULL : braet[x+1][y] ),
                                    ( (y+1 == DIM_Y) ? NULL : braet[x][y+1] ));
}


int main()
{
  felt *nr[DIM_X][DIM_Y];

  initialiser(nr);

  return 0;
}
Avatar billede arne_v Ekspert
13. november 2004 - 20:58 #6
ups

ja det var jo lige en lille vigtig detalje
Avatar billede ahara Nybegynder
13. november 2004 - 21:07 #7
Tak Arne. Ser næsten ud til at virke nu, men hvordan finder jeg f.eks. et givent felt nabos brik "indviklet"?

Kunne det være "getNabo funktion oprettes og så":

nr[1][1]->getNabo()->getBrik()

Eller hvordan gøres det?

AHR
Avatar billede stormy Nybegynder
13. november 2004 - 21:22 #8
Det kunne være en mulighed, men du skal jo være opmærksom på at et felt har optil 4 naboer.. Derfor får du brug for en parameter, der kan fortælle hvilken nabo du ønsker at undersøge.

Så en mulig syntaks kunne være noget i stil med :

nr[1][1]->getNabo(0)->getBrik()
..
nr[1][1]->getNabo(3)->getBrik()

For at undersøge alle naboer..


En anden mulighed kunne være at droppe ideen om at hvert felt skal kende sine naboer - og istedet sige, at du udfra tabellen kan finde en nabo til en given koordinat. F.eks med en funktion som :

felt *getNabo(
Avatar billede stormy Nybegynder
13. november 2004 - 21:31 #9
Sorry, fortsættes her :

enum nabopos { hoejre, venstre, op, ned };

felt *getNabo( felt *braet[DIM_X][DIM_Y], int pos_x, int pos_y, nabopos naboid)
{
  switch(naboid)
  {
    case hoejre :
      if(pos_x + 1 == DIM_X)
        return NULL;
      return braet[pos_x+1][pos_y];
      break;
    case venstre :
      if(pos_x == 0)
        return NULL;
      return braet[pos_x-1][pos_y];
      break;
    case op :
      if(pos_y + 1 == DIM_Y)
        return NULL;
      return braet[pos_x][pos_y+1];
      break;
    case ned :
      if(pos_y == 0)
        return NULL;
      return braet[pos_x][pos_y-1];
      break;
    default :
      return NULL;
  }
  return NULL;
}

Den vil så kunne bruges således :

felt *nabo = getNabo( nr, 1, 1, op );
if(nabo)
  // check på nabo->getBrik(); ...

felt *nabo = getNabo( nr, 1, 1, ned );
if(nabo)
  // check på nabo->getBrik(); ...

etc.

Det er muligt at du bliver nødt til at omdefinerer hvad der et op, ned, højre og venstre - ifht. Hvordan du mener brættet er opbygget..
Avatar billede ahara Nybegynder
13. november 2004 - 22:04 #10
All set. Mangler blot at vide hvorfor min getBrik() returnerer en 0,1,2 værdi. Gør en enum altid det? Skal man så selv lave f.eks. en switch sætning?

Tak
AHR
Avatar billede stormy Nybegynder
13. november 2004 - 22:08 #11
Ja. Enums er bygget ind i syntaksen for at det er læseligt for mennesker - maskinen giver blot hver af dem et nummer..
Avatar billede ahara Nybegynder
13. november 2004 - 22:09 #12
Og et svar fra jer begge :-)
Avatar billede arne_v Ekspert
13. november 2004 - 22:11 #13
jeg tror at points må tilfalde stormy her
Avatar billede stormy Nybegynder
13. november 2004 - 22:11 #14
Fortsat held og lykke!
Avatar billede ahara Nybegynder
14. november 2004 - 20:00 #15
Hej igen

Ved ikke om i ser denne besked, men håber i kan finde en lille fejl jeg har kigget i timer efter. Jeg har nedenstående kode. Koden legalMove kommer til at ligge i klassen felt og nr vil blive initialiseret som i forklarede ovenstående, men håber i kan abstrahere fra dette og hjælpe med koden.

Banen ser sådanne ud:

o er felterne man kan stå på.

****
*oo*
*oo*
****

Problemet er at programmet går ned efter at have udskrevet 5 x Nul og når feltet 0,1 skal udskrives crasher den.

enum brikker{Tom, Sort, Hvid};

class felt
{
private:
    brikker brik;
    felt *nabo[9];
public:
    felt(){}
    felt(brikker brik_x, felt *nabo0, felt *nabo1, felt *nabo2, felt *nabo3,
        felt *nabo4, felt *nabo5, felt *nabo6, felt *nabo7, felt *nabo8)
    {
        brik=brik_x;
        nabo[0]=nabo0;
        nabo[1]=nabo1;
        nabo[2]=nabo2;
        nabo[3]=nabo3;
        nabo[4]=nabo4;
        nabo[5]=nabo5;
        nabo[6]=nabo6;
        nabo[7]=nabo7;
        nabo[8]=nabo8;
    }

    brikker getBrik()
    {
        return brik;
    }

    felt *getNabo(int i)
    {
        return nabo[i];
    }
};

void legalMove(felt *nr, int i)
{
    if(i==9)
    {
        cout<<"Slut";
    }

    else if(nr->getNabo(i)==NULL)
    {
        cout<<i<<": Nul"<<endl;
        i++;
        legalMove(nr,i);
    }

    else if(nr->getNabo(i)!=NULL)
    {
        cout<<i<<": "<<nr->getNabo(i)->getBrik()<<endl;
        i++;
        legalMove(nr,i);
    }
}

int main()
{
    int i=0;
    felt *nr[2][2];

    nr[0][0]=new felt(Tom,NULL,NULL,NULL,NULL,NULL,nr[0][1],NULL,nr[1][0],nr[1][1]);
    nr[0][1]=new felt(Tom,NULL,NULL,NULL,nr[0][0],NULL,NULL,nr[1][0],nr[1][1],NULL);
    nr[1][0]=new felt(Tom,NULL,nr[0][0],nr[0][1],NULL,NULL,nr[1][1],NULL,NULL,NULL);
    nr[1][1]=new felt(Tom,nr[0][0],nr[0][1],NULL,nr[1][0],NULL,NULL,NULL,NULL,NULL);

    legalMove(nr[0][0],i);

    return 0;
}

Mvh
AHR
Avatar billede ahara Nybegynder
14. november 2004 - 20:28 #16
if(i==9) skal selvfølgelig være if(i==8), men det hjælper ikke da fejlen indtræder før der gås ind i denne if-sætning.

AHR
Avatar billede ahara Nybegynder
14. november 2004 - 21:29 #17
Skal selvfølgelig nok sørge for lidt ekstra point :-)
Avatar billede stormy Nybegynder
14. november 2004 - 22:21 #18
Som jeg umiddelbart læser det, er der et stort problem, i den løsning arne_v har skitseret ( sjældent at se en sådan, fra hans hånd ! )

Nemlig i en linie som :

nr[0][0]=new felt(Tom,NULL,NULL,nr[0][1],nr[1][0]);

På dette tidspunkt er konstruktoren for nr[0][1} og nr[1][0] endnu ikke blevet kaldt. Så nr[0][1] og nr[1][0] er uinitialiseret.

Og hvis man tilgår hukommelse, som ikke er initialiseret så : ....

Problemet er at programmet går ned efter at have udskrevet 5 x Nul og når feltet 0,1 skal udskrives crasher den.
Avatar billede stormy Nybegynder
14. november 2004 - 22:25 #19
I denne linie, hvor du rent faktisk første gang bruger en uinitialiseret værdi :

cout<<i<<": "<<nr->getNabo(i)->getBrik()<<endl;
Avatar billede stormy Nybegynder
14. november 2004 - 23:07 #20
I din initialiseringskode sker følgende :

nr[0][0]=new felt(Tom,NULL,NULL,NULL,NULL,NULL,nr[0][1],NULL,nr[1][0],nr[1][1]);

Nu er værdien af nr[0][1], nr[1][0] og nr[1][1] gemt i nr[0][0] - men de har endnu ikke fået nogen værdi det sker først i de næste 3 linier :

nr[0][1]=new felt(Tom,NULL,NULL,NULL,nr[0][0],NULL,NULL,nr[1][0],nr[1][1],NULL);
nr[1][0]=new felt(Tom,NULL,nr[0][0],nr[0][1],NULL,NULL,nr[1][1],NULL,NULL,NULL);
nr[1][1]=new felt(Tom,nr[0][0],nr[0][1],NULL,nr[1][0],NULL,NULL,NULL,NULL,NULL);

Så du kan enten bruge mit tidligere forslag som løsning.. Eller du kan ændre felt til at se således ud :

class felt
{
private:
    brikker brik;
    felt *nabo[9];
public:
    felt(){}
    void update(brikker brik_x, felt *nabo0, felt *nabo1, felt *nabo2, felt *nabo3, felt *nabo4, felt *nabo5, felt *nabo6, felt *nabo7, felt *nabo8)
    {
        brik=brik_x;
        nabo[0]=nabo0;
        nabo[1]=nabo1;
        nabo[2]=nabo2;
        nabo[3]=nabo3;
        nabo[4]=nabo4;
        nabo[5]=nabo5;
        nabo[6]=nabo6;
        nabo[7]=nabo7;
        nabo[8]=nabo8;
    }

    brikker getBrik()
    {
        return brik;
    }

    felt *getNabo(int i)
    {
        return nabo[i];
    }
};

Og så initialiserer således :

nr[0][0]=new felt();
nr[0][1]=new felt();
nr[1][0]=new felt();
nr[1][1]=new felt();

/* Nu er alle oprettet, nu kan de forbindes : */

nr[0][0]->update(Tom,NULL,NULL,NULL,NULL,NULL,nr[0][1],NULL,nr[1][0],nr[1][1]);
nr[0][1]->update(Tom,NULL,NULL,NULL,nr[0][0],NULL,NULL,nr[1][0],nr[1][1],NULL);
nr[1][0]->update(Tom,NULL,nr[0][0],nr[0][1],NULL,NULL,nr[1][1],NULL,NULL,NULL);
nr[1][1]->update(Tom,nr[0][0],nr[0][1],NULL,nr[1][0],NULL,NULL,NULL,NULL,NULL);
Avatar billede stormy Nybegynder
21. november 2004 - 06:13 #21
Har du stadig behov for hjælp ?!
Avatar billede ahara Nybegynder
21. november 2004 - 10:36 #22
Sorry. Havde helt glemt dine point. Har lige set din besked. Ligger nogle point til dig i C++ gruppen.

Alt virker efter planen.

Tak
AHR
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester