Tarvitsen Apua!

Uuppi

Hei, tarvitsisin ohjelmaani 5 kolmenumeroista lukua jotka eivät saa olla samoja, mutta en oikein tiedä kuinka sen tekisin.

Esimerkki jossa voi mahdollisesti tulla samoja:
begin
Label1.Caption := inttostr(randomrange(1,200));
Label2.Caption := inttostr(randomrange(1,200));
Label3.Caption := inttostr(randomrange(1,200));
Label4.Caption := inttostr(randomrange(1,200));
Label5.Caption := inttostr(randomrange(1,200));
end;

osaan kyllä kahdella luvulla tehdä ettei tule samoja mutta useammalla en.

repeat
Label2.Caption := inttostr(randomrange(1,200));
until Label2.Caption Label1.Caption;

apua, kiitos :)

13

693

    Vastaukset

    Anonyymi (Kirjaudu / Rekisteröidy)
    5000
    • L A R A

      Ongelman voi ratkaista usealla tavalla. Esitän seuraavanlaisen tavan siksi että se antaa vinkkejä mitä voisi olla ja sen lisäksi kun kokeilet koodia niin haluanet kehittää sitä (Yksinkertaisempiakin ratkaisuja on mutta ...)

      Tee uusi projekti. Lisää formille Button, Edit ja Memo -komponentit.
      Luo Buttonille onClick-tapahtuma ja formille onCreate-tapahtuma.

      Liisää tyypin (type sanan jälkeinen lohko) esittelyyn Tmjono-luokka.
      ...

      { Tmjono }

      Tmjono = class(TStringList)
      public
      constructor Create;
      procedure PoistaSamat;
      function maara(kpl:integer):boolean;
      end;

      ...

      Tuo luokka periytyy TStringList-luokasta (TStringList luokasta löytyy mm. tällä keskustelualueella lisätietoja). Huomaa että tuota luokkaa voi käyttää muuassakin
      tarkoituksessa kuin satunnaisluvuilla ja sillä on paljon toimintoja!

      Lisäksi RandomRange funktion voi tehdä näin jos sitä ei ole vanhemmissa versioissa:

      function randomrange(eka,vika:integer):integer;
      var
      vali,satluku:integer;
      begin
      vali := vika-eka 1;
      satluku:=random(vali);
      result := satluku eka;
      end;


      Koodin voi täydentää vaikkapa tälläiseksi:


      { TForm1 }

      procedure TForm1.Button1Click(Sender: TObject);
      var
      kpl:integer;
      Satunnaisluvut:Tmjono;
      begin
      Satunnaisluvut:=Tmjono.Create;
      kpl := StrToInt(Edit1.Text);
      repeat
      Satunnaisluvut.Add(inttostr(randomrange(1,200)));
      Satunnaisluvut.PoistaSamat;
      until Satunnaisluvut.Maara(kpl);
      Memo1.Lines.Assign(Satunnaisluvut);
      FreeAndNil(Satunnaisluvut);
      end;

      procedure TForm1.FormCreate(Sender: TObject);
      begin
      Randomize;
      end;

      { Tmjono }

      constructor Tmjono.Create;
      begin
      inherited Create;
      self.Sorted:= true;
      end;

      procedure Tmjono.PoistaSamat;
      var
      i:integer;
      begin
      i := 0 ;
      while i < self.Count-2 do
      begin
      if self.Strings[i] = self.Strings[i 1] then self.Delete(i 1);
      inc(i);
      end;
      end;

      function Tmjono.maara(kpl: integer): boolean;
      begin
      result:= self.Count> kpl;
      end;

      • Uuppi

        Kiitos paljon nopeasta ja hyvästä vastauksesta. Nyt sain toimimaan


      • Uuppi

        Taas avulle tarvetta. Muokkailin vähän koodia ja nyt tulee virhe:
        'Operation not allowed on sorted list'. Luulen että se johtuu siitä kun koodissani on mm. nämä:

        Satunnaisluvut.Assign(Memo.Lines);

        Satunnaisluvut.Insert(1,randomcrd randomclr);

        Olisiko jotain keinoa korjata? En löytänyt googlesta mitään tuosta 'Operation not allowed on sorted list' virheestä.


      • Uuppi
        Uuppi kirjoitti:

        Taas avulle tarvetta. Muokkailin vähän koodia ja nyt tulee virhe:
        'Operation not allowed on sorted list'. Luulen että se johtuu siitä kun koodissani on mm. nämä:

        Satunnaisluvut.Assign(Memo.Lines);

        Satunnaisluvut.Insert(1,randomcrd randomclr);

        Olisiko jotain keinoa korjata? En löytänyt googlesta mitään tuosta 'Operation not allowed on sorted list' virheestä.

        Sainkin ehkä toimimaan: Satunnaisluvut.Sorted := false;


      • Uuppi

        Hmm.. huomasinkin että tuolla keinolla tulee silti välillä samoja.


        begin
        Satunnaisluvut:=Tmjono.Create;
        randomize;
        kpl := 4;
        repeat
        randomclr := Clrs[randomrange(0,4)];
        randomcrd := Crds[randomrange(0,13)];
        Satunnaisluvut.Add(randomcrd randomclr);
        Satunnaisluvut.PoistaSamat;

        until Satunnaisluvut.maara(kpl);
        memo.Lines.Assign(satunnaisluvut);
        end;

        Haluaisin myös tietää miten saan tehtyä niin, että esim. kun 5 eri stringiä on listattu, ja listaa uudestaan, niin se ei vaihda vaikka ensimmäistä kolmea stringiä ja vaihtaa vain viimeiset 2 eikä ne saa olla samoja kuin jotkut kolmesta ensimmäisestä :D monimutkaista, mutta toivottavasti ymmärsitte.. Toivottavasti joku voi auttaa :


      • huomaa
        Uuppi kirjoitti:

        Hmm.. huomasinkin että tuolla keinolla tulee silti välillä samoja.


        begin
        Satunnaisluvut:=Tmjono.Create;
        randomize;
        kpl := 4;
        repeat
        randomclr := Clrs[randomrange(0,4)];
        randomcrd := Crds[randomrange(0,13)];
        Satunnaisluvut.Add(randomcrd randomclr);
        Satunnaisluvut.PoistaSamat;

        until Satunnaisluvut.maara(kpl);
        memo.Lines.Assign(satunnaisluvut);
        end;

        Haluaisin myös tietää miten saan tehtyä niin, että esim. kun 5 eri stringiä on listattu, ja listaa uudestaan, niin se ei vaihda vaikka ensimmäistä kolmea stringiä ja vaihtaa vain viimeiset 2 eikä ne saa olla samoja kuin jotkut kolmesta ensimmäisestä :D monimutkaista, mutta toivottavasti ymmärsitte.. Toivottavasti joku voi auttaa :

        Huomaa että Randomize rutiinia ei saane suorittaa kuin kerran koko ohjelman käytön aikana.


      • Delphi_again

        Terve,

        Toivottavasti ymmärsin oikein kysymyksesi,
        alla on pieni esimerkki siitä kuinka tuon tekee nopeasti/helposti,
        pitäisi olla aika virhe vapaa/yksinkertainen esimerkki, eli siitä vaan jalostamaan...
        (Ei ole optimoitu yms, kuhan päästäni heitin esimerkin, josta varmaan saat taidolla ja tunteella paremman/nopeamman)

        procedure TForm1.Button1Click(Sender: TObject);
        var
        i : Integer;
        MyRndNumber : String;
        RndNumberCount : Integer;
        begin
        Memo1.Clear;
        RndNumberCount := 5;

        // Random seed
        Randomize;

        while true do
        begin
        // Time to other threads
        Application.ProcessMessages;
        Sleep(1);

        MyRndNumber := GetRandomNumbers(3);

        // Validate
        for I := 0 to Memo1.Lines.Count do
        begin
        if (Memo1.Lines[I] = MyRndNumber) then
        begin
        MyRndNumber := '';
        Break;
        end;
        end;

        // Add to my list if valid
        if MyRndNumber '' then
        Memo1.Lines.Add(MyRndNumber);

        // Check if ready
        if Memo1.Lines.Count >= RndNumberCount then
        Break;
        end;
        end;

        function TForm1.GetRandomNumbers(const ANumberCount : Cardinal) : String;
        var
        Rnd : Integer;
        begin
        // Invalid return value
        Result := '';

        while (Length(Result) < ANumberCount) do
        begin
        // Get random values
        Rnd := Random(10);

        // Set result
        Result := Result IntToStr(Rnd);
        end;
        end;


      • Uuppi
        Delphi_again kirjoitti:

        Terve,

        Toivottavasti ymmärsin oikein kysymyksesi,
        alla on pieni esimerkki siitä kuinka tuon tekee nopeasti/helposti,
        pitäisi olla aika virhe vapaa/yksinkertainen esimerkki, eli siitä vaan jalostamaan...
        (Ei ole optimoitu yms, kuhan päästäni heitin esimerkin, josta varmaan saat taidolla ja tunteella paremman/nopeamman)

        procedure TForm1.Button1Click(Sender: TObject);
        var
        i : Integer;
        MyRndNumber : String;
        RndNumberCount : Integer;
        begin
        Memo1.Clear;
        RndNumberCount := 5;

        // Random seed
        Randomize;

        while true do
        begin
        // Time to other threads
        Application.ProcessMessages;
        Sleep(1);

        MyRndNumber := GetRandomNumbers(3);

        // Validate
        for I := 0 to Memo1.Lines.Count do
        begin
        if (Memo1.Lines[I] = MyRndNumber) then
        begin
        MyRndNumber := '';
        Break;
        end;
        end;

        // Add to my list if valid
        if MyRndNumber '' then
        Memo1.Lines.Add(MyRndNumber);

        // Check if ready
        if Memo1.Lines.Count >= RndNumberCount then
        Break;
        end;
        end;

        function TForm1.GetRandomNumbers(const ANumberCount : Cardinal) : String;
        var
        Rnd : Integer;
        begin
        // Invalid return value
        Result := '';

        while (Length(Result) < ANumberCount) do
        begin
        // Get random values
        Rnd := Random(10);

        // Set result
        Result := Result IntToStr(Rnd);
        end;
        end;

        Kiitoksia, luulenpa että sain juuri toimimaan omalla tekniikalla, mutta sillointällöin tulee virhe: 'List index out of bounds(4)'. Sen varmaan saan korjattua itse.


      • afdsa
        Uuppi kirjoitti:

        Hmm.. huomasinkin että tuolla keinolla tulee silti välillä samoja.


        begin
        Satunnaisluvut:=Tmjono.Create;
        randomize;
        kpl := 4;
        repeat
        randomclr := Clrs[randomrange(0,4)];
        randomcrd := Crds[randomrange(0,13)];
        Satunnaisluvut.Add(randomcrd randomclr);
        Satunnaisluvut.PoistaSamat;

        until Satunnaisluvut.maara(kpl);
        memo.Lines.Assign(satunnaisluvut);
        end;

        Haluaisin myös tietää miten saan tehtyä niin, että esim. kun 5 eri stringiä on listattu, ja listaa uudestaan, niin se ei vaihda vaikka ensimmäistä kolmea stringiä ja vaihtaa vain viimeiset 2 eikä ne saa olla samoja kuin jotkut kolmesta ensimmäisestä :D monimutkaista, mutta toivottavasti ymmärsitte.. Toivottavasti joku voi auttaa :

        No tuo loppuosa vaatimuksistasi voidaan lisätä vaikka näin

        Lisää luokan TForm1 määrittelyyn private ja public osien väliin luokan
        aliohjelma Sailyta3ekaajaArvo2Lisaa
        siis näin

        ...
        private
        { private declarations }
        procedure Sailyta3ekaajaArvo2Lisaa;
        public
        ...


        Täydennä koodi osaa vaikkapa näin


        procedure TForm1.Sailyta3ekaajaArvo2Lisaa;
        var
        i,ekatkpl,kaikkiaan:integer;
        sl:TStringList;
        s:string;
        jatka, olijo:boolean;
        begin
        sl:=TStringList.Create;
        i := 0;
        ekatkpl := 3;
        kaikkiaan := ekatkpl 2;
        jatka := i < Memo1.Lines.Count;
        while jatka do
        begin
        sl.Add(Memo1.Lines[i]);
        inc(i);
        jatka := i < ekatkpl;
        if jatka then jatka := i < Memo1.Lines.Count;
        end;
        repeat
        s:=inttostr(randomrange(1,200));
        olijo := false;
        for i:= 0 to sl.Count-1 do
        if s = sl[i] then olijo := true;
        if olijo = false then sl.Add(s);
        until sl.Count >= kaikkiaan;
        Memo1.Lines.Assign(sl);
        FreeAndNil(sl);
        end;
        ...

        Tuota voit testata vaikkapa niin että luot uuden painikkeen
        ja täydennät sitä vaikkapa näin:

        procedure TForm1.Button2Click(Sender: TObject);
        begin
        Sailyta3ekaajaArvo2Lisaa;
        end;


    • Polullakulkija

      Tässä yksi ratkaisu lisää. Ideana tässä on mm se että jos luvut hylätään niin
      ne ei ole mukana uudessa arvonnassa. Lisäksi toteutus on sellainen että voit
      valita mitkä tahansa arvotuista pois. Arvotut laitetaan ListBox1:n josta voit
      esim hiirellä valita poistettavat. Poisto tapahtuu button2:lla.

      Button1:n painaminen on eräänlainen peruskäyttö ja Button3:n ratkaisu hyödyntää
      nuo erikoisuudet. Button2:n painaminen tuo myös näytölle(Memo1) näkyviin
      ne arvot mitkä on kielletty.


      Luokkien esittely on siis tälläinen

      TForm1 = class(TForm)
      Button1: TButton;
      Button2: TButton;
      Button3: TButton;
      Edit1: TEdit;
      ListBox1: TListBox;
      Memo1: TMemo;
      procedure Button1Click(Sender: TObject);
      procedure Button2Click(Sender: TObject);
      procedure Button3Click(Sender: TObject);
      procedure FormCreate(Sender: TObject);
      procedure FormDestroy(Sender: TObject);
      private
      { private declarations }
      EiSallitut:TStringList;
      public
      { public declarations }
      end;


      { TSatunnaisluvut }

      TSatunnaisluvut = class
      private
      FKielletytArvot,FSaadutArvot:TStringList;
      FKpl, FMin, FMax:integer;
      function OnkoKielletty(arvo:string):boolean;
      public
      constructor Create;
      procedure AsetaKielletytArvot(const ASl:TStringList);
      procedure AsetaMaara(kpl:integer);
      procedure AsetaRajaArvot(AMin,AMax:integer);
      procedure ArvoLuvut;
      procedure LueArvotut(var ASl:TStringList);
      procedure LueKielletytJaArvotut(var ASl:TStringList);
      destructor Destroy; override;
      end;


      Ja koodin osuus on seuraavanlainen

      procedure TForm1.Button1Click(Sender: TObject);
      var
      Satunnaisluvut:TSatunnaisluvut;
      sl:TStringList;
      begin
      Satunnaisluvut:=TSatunnaisluvut.Create;
      Satunnaisluvut.AsetaMaara(StrToInt(Edit1.Text));
      Satunnaisluvut.AsetaRajaArvot(1,200);
      sl:=TStringList.Create;
      Satunnaisluvut.ArvoLuvut;
      Satunnaisluvut.LueArvotut(sl);
      ListBox1.Items.AddStrings(sl);
      FreeAndNil(sl);
      FreeAndNil(Satunnaisluvut);
      end;

      procedure TForm1.Button2Click(Sender: TObject);
      var
      i:integer;
      begin
      i:= ListBox1.Count-1 ;
      while i >= 0 do
      begin
      if ListBox1.Selected[i] then
      begin
      EiSallitut.Add(ListBox1.Items[i]);
      ListBox1.Items.Delete(i);
      end;
      dec(i);
      end;
      Memo1.Lines.Assign(EiSallitut);
      end;

      procedure TForm1.Button3Click(Sender: TObject);
      var
      kpl:integer;
      Satunnaisluvut:TSatunnaisluvut;
      sl:TStringList;
      begin
      Satunnaisluvut:=TSatunnaisluvut.Create;
      kpl := StrToInt(Edit1.Text);
      kpl := kpl - ListBox1.Items.Count;
      Satunnaisluvut.AsetaMaara(kpl);
      Satunnaisluvut.AsetaRajaArvot(1,200);
      sl:=TStringList.Create;
      sl.AddStrings(ListBox1.Items);
      sl.AddStrings(EiSallitut);
      Satunnaisluvut.AsetaKielletytArvot(sl);
      Satunnaisluvut.ArvoLuvut;
      Satunnaisluvut.LueArvotut(sl);
      ListBox1.Items.AddStrings(sl);
      FreeAndNil(sl);
      FreeAndNil(Satunnaisluvut);
      end;

      procedure TForm1.FormCreate(Sender: TObject);
      begin
      Randomize;
      EiSallitut:=TStringList.Create;
      end;

      procedure TForm1.FormDestroy(Sender: TObject);
      begin
      FreeAndNil(EiSallitut);
      end;



      { TSatunnaisluvut }

      function TSatunnaisluvut.OnkoKielletty(arvo: string): boolean;
      var
      oli_kielletty:boolean;
      i :integer;
      begin
      oli_kielletty := false;
      for i:= 0 to FKielletytArvot.Count-1 do
      if arvo = FKielletytArvot[i] then oli_kielletty := true;
      result := oli_kielletty;
      end;

      constructor TSatunnaisluvut.Create;
      begin
      FKielletytArvot:=TStringList.Create;
      FSaadutArvot:=TStringList.Create;
      FKielletytArvot.Sorted:=True;
      end;

      procedure TSatunnaisluvut.AsetaKielletytArvot(const ASl: TStringList);
      begin
      FKielletytArvot.Assign(ASl);
      end;

      procedure TSatunnaisluvut.AsetaMaara(kpl: integer);
      begin
      FKPl:=kpl;
      end;

      • Uuppi

        :D Vieläkin oli ongelmia uusien lukujen arvonnassa, tuli silti samoja. Tällä tavalla saan sen vihdoin toimimaan :) Mitä hyötyä tosta .sorted arvosta muuten on?


      • yhdessä oli merkitystä
        Uuppi kirjoitti:

        :D Vieläkin oli ongelmia uusien lukujen arvonnassa, tuli silti samoja. Tällä tavalla saan sen vihdoin toimimaan :) Mitä hyötyä tosta .sorted arvosta muuten on?

        Tuossa "Samojen arvojen estäminen" -viestissä
        sillä oli merkitystä (samat arvot tulivat vierekkäiksi jolloin on helppo löytää
        samat arvot).

        Mutta tässä missä kysyt sillä ei taida olla merkitystä (Koodihan voi olla
        otettu jostain isommasta kokonaisuudesta mutta sitä ei ole tuotu esille)


      • Delphiguru
        yhdessä oli merkitystä kirjoitti:

        Tuossa "Samojen arvojen estäminen" -viestissä
        sillä oli merkitystä (samat arvot tulivat vierekkäiksi jolloin on helppo löytää
        samat arvot).

        Mutta tässä missä kysyt sillä ei taida olla merkitystä (Koodihan voi olla
        otettu jostain isommasta kokonaisuudesta mutta sitä ei ole tuotu esille)

        1. TStringlist.Sorted:

        tästä ON hyötyä, tietyissä tapauksissa...

        eli:

        SL.Sorted := True;

        tämän jälkeen voit:

        SL.Duplicates := dupIgnore;

        tällöin voit yksinkertaisesti:

        N := SL.add(jotakin);

        jos merkkijono jotakin ON jo listassa, niin tuo ei tee mitään, muuten se lisätään listaan.

        Tuossa N saa arvokseen indeksin, johon jotakin lisättiin, tai -1 jos sitä EI lisätty.

        mutta, onhan toinenkin tapa:

        1. Tee merkkijono, jossa on halutut arvot, siis näin:

        St1 := St1 char(arvo);

        huomaa: Delphi2009:ssä arvo voi olla 0..65535, mutta vanhemmissa delpheissä arvon on oltava välillä 0..255.

        sitten voit:

        N := Random(length(St1)) 1;

        Merkki := St1[N];

        system.delete(St1,N,1); // estää saman arvon uudelleenkäytön

        ja satunnaislukusi:

        char(SLuku) := merkki;

        Tämä taktiikka hyödyntää merkkijonoa toimii siis kaikissa Delpheissä, jos satunnaislukusi ovat välillä 0..255, mutta jos käytät Delphi2009:ää, niin arvot 0..65535 ovat sallittuja.

        Ero johtuu tästä:

        sz := sizeOf(char);

        Delphi2009:ssä sz=2, aiemmissa Delpheissä sz=1; tämä johtuu siitä, että merkkijonoissa on siirrytty unicode -aikaan (Delphi2009)

        Jos vanhemmissa Delpheissä lukualue 0..255 ei riitä, löytyy 2 vaihtoehtoa:

        a) käytä WideChar ja WideString -tyyppejä

        TAI

        b) älä käytä STRINGejä, vaan dynaamisia taulukoita:

        var

        Arvot : Array of Integer;

        begin

        SetLength(Arvot, 1000);

        // täytä taulukko Arvot[0..999] 1000:lla haluamallasi luvulla, jotka toimivat satunnaislukuna (älä käytä tähän randomia !)

        system.delete pitäisi toimia myös dynaamisiin taulukoihin kuten merkkijonoihin, eli:

        system.delete(Arvot,N,1);

        tuo EI kuitenkaan toimi, jos olet määritellyt taulukkosi staattiseksi, sii snäin:

        var

        Arvot : Array[0..999] of Integer;

        SetLength kun toimii vain merkkijonoihin ja dynaamisiin taulukoihin mutta EI staattisiin taulukoihin.


    Ketjusta on poistettu 0 sääntöjenvastaista viestiä.

    Luetuimmat keskustelut

    1. Miehille kysymys

      Onko näin, että jos miestä kiinnostaa tarpeeksi niin hän kyllä ottaa vaikka riskin pakeista ja osoittaa sen kiinnostukse
      Tunteet
      132
      3787
    2. Miksi kaivattusi on

      erityinen? ❤️‍🔥
      Ikävä
      85
      1885
    3. Olen tosi outo....

      Päättelen palstajuttujen perusteella mitä mieltä minun kaipauksen kohde minusta on. Joskus kuvittelen tänne selkeitä tap
      Ikävä
      15
      1731
    4. Haluaisin jo

      Myöntää nämä tunteet sinulle face to face. En uskalla vain nolata itseäni enää. Enkä pysty elämäänkin näiden kanssa jos
      Ikävä
      54
      1402
    5. Ylen uutiset Haapaveden yt:stä.

      Olipas kamalaa luettavaa kaupungin irtisanomisista. Työttömiä lisää 10 tai enempikin( Mieluskylän opettajat). Muuttavat
      Haapavesi
      123
      1264
    6. VENÄJÄ muuttanut tänään ydinasetroktiinia

      Venäjän presidentti Vladimir Putin hyväksyi tiistaina päivitetyn ydinasedoktriinin, kertoo uutistoimisto Reuters. Sen mu
      Maailman menoa
      95
      1251
    7. Kotkalainen Demari Riku Pirinen vangittu Saksassa lapsipornosta

      https://www.kymensanomat.fi/paikalliset/8081054 Kotkalainen Demari Riku Pirinen vangittu Saksassa lapsipornon hallussapi
      Kotka
      35
      1209
    8. Nainen olet valoni pimeässä

      valaiset tietäni tietämättäsi ❤️
      Ikävä
      69
      1134
    9. Mitä toivot

      Tulevilta päiviltä?
      Ikävä
      68
      1014
    10. Hommaatko kinkkua jouluksi?

      Itse tein pakastimeen n. 3Kg:n murekkeen sienillä ja juustokuorrutuksella. Voihan se olla, että jonkun pienen, valmiin k
      Sinkut
      102
      985
    Aihe