Wątek przeniesiony 2017-01-06 22:15 z Delphi i Pascal przez furious programming.

Stworzenie losowanej tablicy w aplikacji okienkowej.

0

Witam, mam taki problem. Otóż próbuję stworzyć tablice 8x8, która będzie losowana 1 lub 0. Próbowałem z zwykłymi buttonami, ale nie mam pojęcia jak 64 buttony wylosować 1 i 0. W późniejszej fazie przy kliknięciu w tą 1 lub 0, ma się ona zamieniać z 1 na 0 i na odwrót. Czy mógłby ktoś z tym pomóc?

0

Otóż próbuję stworzyć tablice 8x8, która będzie losowana 1 lub 0.

Tablica będzie losowana, czy wartości dla komórek tej tablicy?

Próbowałem z zwykłymi buttonami, ale nie mam pojęcia jak 64 buttony wylosować 1 i 0.

A po polsku?

W późniejszej fazie przy kliknięciu w tą 1 lub 0, ma się ona zamieniać z 1 na 0 i na odwrót.

Przy kliknięciu na co? Czym ma być to 1 lub 0?

Czy mógłby ktoś z tym pomóc?

Jak normalnie napiszesz w czym problem to na pewno pomożemy.

0

Przepraszam bardzo, już piszę.

furious programming napisał(a):

Tablica będzie losowana, czy wartości dla komórek tej tablicy?

Wartości komórek dla tej tablicy.

A po polsku?

Próbowałem umieścić 64 buttony i wylosować do nich liczbę 1 lub 0, ale nie udało mi się to.

Przy kliknięciu na co? Czym ma być to 1 lub 0?

Generalnie chodzi o to, że w tablicy 8x8 losujemy każdą komórkę. Osiem cyfr w pionie i poziomie utworzy liczbę binarną, złożoną z 1 i 0 jak wiadomo. Jeżeli kliknie się na jakąś komórkę, to jej wartość jeżeli jest równa '1' ma się zamienić na '0' i na odwrót.

1

No, teraz już wiadomo o co chodzi;

Najpierw połóż na formularzu te przyciski - nazwij je w sposób sensowny dla ich ułożenia; Możesz je wszystkie umieścić w komponencie grupującym, np. w TPanel lub TGroupBox;

Zakładając, że przyciski posiadają nazwy od CDigit0 do CDigit63 i że ułożone są na kontrolce CDigitsGroup typu TGroupBox, metoda losująca treści wyświetlane w przyciskach (cyfry 0 lub 1) może wyglądać tak:

procedure TForm.RandomDigitCaptions();
var
  LButton: TControl;
  LIndex: Integer;
begin
  for LIndex := 0 to 63 do
  begin
    LButton := CDigitsGroup.FindChildControl(Format('CDigit%d', [LIndex]));
    LButton.Caption := IntToStr(Random(2));
  end;
end;

Metoda ta sześćdziesiąt cztery razy szuka przycisku o nazwie CDigit*, gdzie * to numer przycisku, znajdującego się wewnątrz komponentu grupującego; Po znalezieniu przycisku wpisuje do jego Caption wylosowaną cyferkę po przekonwertowaniu jej na ciąg znaków;

Druga sprawa to zachowanie po klikaniu w przyciski - wygeneruj zdarzenie OnClick pierwszego przycisku, czyli według tego co napisałem wcześniej, przycisku o nazwie CDigit0 i wpisz poniższy kod:

procedure TForm.CDigit0Click(Sender: TObject);
var
  LButton: TControl absolute Sender;
  LDigit: Integer;
begin
  LDigit := StrToInt(LButton.Caption);
  LButton.Caption := IntToStr((LDigit + 1) mod 2);
end;

Do zmiennej LDigit wpisujemy bieżącą cyfrę z klikniętego przycisku, konwertując ją na liczbę; Następnie używając pomocniczej zmiennej LButton (która zawiera referencję do obiektu klikniętego przycisku, za sprawą jej deklaracji z absolute), wpisujemy do Caption klikniętego przycisku nową wartość, przekonwertowaną z powrotem na ciąg znaków;

Nowa wartość pozyskiwana jest przez dodanie 1 do bieżącej wartości i wyciągnięcie z tej sumy reszty z dzielenia przez 2 (można to zapisać jako (LDigit + 1) and 1); Dzięki temu jeśli na początku było 0 to dostaniemy w wyniku 1, a jeśli było 1 to dostaniemy 0;

Ostatnią czynnością jest zaznaczenie w designerze wszystkich sześćdziesięciu czterech przycisków i w oknie Object Inspector, w zakładce Events, ustawienie zdarzenia OnClick na CDigit0Click - dzięki temu wszystkie przyciski z cyferkami będą używały tego samego zdarzenia; Rozróżnienie tego który przycisk wciśnięto realizowane jest na podstawie parametru Sender;

To wszystko - zrób i pobaw się, tylko nie zapomnij gdzieś na początku wywołać Randomize.

0

Dziękuje bardzo, jakby Pan mógł to proszę nie zamykać tematu, bo pewnie jeszcze jakieś pytania będę miał, z góry dziękuje.

Teraz pojawił się kolejny problem, otóż chciałbym te 8 cyfr wczytać do jakiegoś stringa. Powiedzmy, że mamy ciąg '11001010' potem ten ciąg cyfr zamienić na liczbę dziesiętną i ją wypisać. Oraz jeżeli na tej tablicy ktoś zmieni tą '1' na '0' lub na odwrót to zmienić tą wyświetlaną dziesiętną liczbę. Tylko nie mam pojęcia jak to napisać.

0

Jeśli coś tam ma się aktualizować po każdorazowym kliknięciu w przycisk cyferki to ten dodatkowy kod także musisz umieścić w zdarzeniu OnClick przycisku o nazwie CDigit0;

Powiedzmy, że mamy ciąg '11001010' potem ten ciąg cyfr zamienić na liczbę dziesiętną i ją wypisać.

A których przycisków dotyczy ta liczba? Brać pod uwagę poziomy zapis na ekranie, czy pionowy? Przyciski układają się w macierz 8x8, więc liczby można odczytywać ze wszystkich czterech stron, z góry na dół, z dołu do góry, z lewej do prawej i z prawej do lewej; Dobrze by było wrzucić obiekty przycisków do pomocniczej macierzy, bo jeśli dużo różnych operacji będziesz chciał wykonywać na wartościach tych przycisków to ciągłe szukanie kontrolek za pomocą FindChildControl będzie uciążliwe;

Jeśli nie chcesz dodatkowej macierzy pomocniczej to można odczytywać wartości z przycisków tak jak poprzednio; Aby odczytać liczbę poziomo z lewej do prawej i zamienić ją na liczbę typu Integer, wystarczy poniższy kod:

function TForm.DigitsToNumber(AFirstIndex: Integer): Integer;
var
  LControl: TControl;
  LCaption: String;
  LIndex, LError: Integer;
begin
  LCaption := '%';

  for LIndex := AFirstIndex to AFirstIndex + 7 do
  begin
    LControl := CDigitsGroup.FindChildControl(Format('CDigit%d', [LIndex]));
    LCaption := LCaption + LControl.Caption;
  end;

  Val(LCaption, Result, LError);
end;

Ta metoda umożliwia odczyt liczby z dowolnego wiersza tabelki przycisków; W parametrze pobiera indeks pierwszego przycisku z lewej - aby odczytać liczbę z pierwszego wiersza, w parametrze trzeba podać 0, dla drugiego wiersza jest to 8, dla trzeciego 16 itd.; W pętli pobiera Caption znalezionego przycisku i dodaje go do bieżącej zawartości zmiennej LCaption; Ta zmienna początkowo posiada prefiks %, dlatego że jest on wymagany dla procedury Val, aby mogła rozróżnić system liczbowy w wejściowym ciągu znaków (dla heksadecymalnego to prefiks $, dla oktalnego &, a dla binarnego %);

Dopisz sobie nowy kod do zdarzenia OnClick przycisku CDigit0, pod tym co już w tym zdarzeniu jest; Tam też użyj powyższej metody DigitsToNumber i użyj otrzymanej liczby do czego tam potrzebujesz.

0

Potrzebuję od lewej do prawej i od góry do dołu, czyli z prawej strony macierzy i pod macierzą.
Potem jedynie te wartości chcę do siebie dodawać, więc chyba nie trzeba tworzyć macierzy osobnej.

LControl := CDigitsGroup.FindChildControl(Format('CDigit%d', [LIndex]));

Do czego to kliknięcie to podstawia? Tzn co oznacza CdigitsGroup, to jest nazwa tej kontrolki w której ułożone są te buttony?

Dopisz sobie nowy kod do zdarzenia OnClick przycisku CDigit0, pod tym co już w tym zdarzeniu jest;

Wewnątrz procedury nie mogę dodać tej funkcji, a pod spodem wyrzuca błąd, że właśnie nie rozpoznaje kontrolki CdigitsGroup (pod moją nazwą). A i mam pytanie czy ta liczba dziesiętna jest wypisywana gdziekolwiek? Bo nie widzę w kodzie, żeby gdzieś ją umieszczał kompilator.

0

Potrzebuję od lewej do prawej i od góry do dołu, czyli z prawej strony macierzy i pod macierzą.

Czyli potrzebujesz jednej metody, która odczyta i doda do siebie Caption przycisków ułożonych w poziomie i drugą, która wykona to samo, tyle że w pionie; Metodę odczytującą liczbę w poziomie już masz (podałem w poprzednim poście), trzeba jeszcze napisać drugą;

Potem jedynie te wartości chcę do siebie dodawać, więc chyba nie trzeba tworzyć macierzy osobnej.

Dodatkowa macierz była by przydatna - można by od razu dostać się do konkretnego przycisku, zamiast w kółko używać FindChildControl; Oczywiście możesz całość zapisać bez dodatkowej macierzy;

Do czego to kliknięcie to podstawia? Tzn co oznacza CdigitsGroup, to jest nazwa tej kontrolki w której ułożone są te buttony?

Tak, takie informacje podałem w swoim poprzednim poście;

Wewnątrz procedury nie mogę dodać tej funkcji, a pod spodem wyrzuca błąd, że właśnie nie rozpoznaje kontrolki CdigitsGroup (pod moją nazwą).

Możesz użyć DigitToNumber, pod warunkiem, że będzie ona metodą klasy formularza; Zobacz jak wygląda nagłówek tej metody w moim poprzednim poście - przed jej nazwą jest prefiks TForm, co oznacza, że jest to metoda klasy TForm; Nie podałem deklaracji nagłówka tej metody w klasie okna, bo założyłem, że sam sobie ją dodasz;

A i mam pytanie czy ta liczba dziesiętna jest wypisywana gdziekolwiek? Bo nie widzę w kodzie, żeby gdzieś ją umieszczał kompilator.

Procedura Val wpisuje wynik konwersji do Result.

0
procedure TForm1.TablicaClick(Sender: TObject);
var
  LButton: TControl;
  LIndex: Integer;
begin
  Randomize;
  for LIndex := 0 to 63 do
  begin
    LButton := Tablica.FindChildControl(Format('CDigit%d', [LIndex]));
    LButton.Caption := IntToStr(Random(2));
  end;
end;                  
procedure TForm1.Cdigit0Click(Sender: TObject);
var
  LButton: TControl absolute Sender;
  LDigit: Integer;
begin
  LDigit := StrToInt(LButton.Caption);
  LButton.Caption := IntToStr((LDigit + 1) mod 2);
end;
function TForm.DigitsToNumber(AFirstIndex: Integer): Integer;
var
  LControl: TControl;
  LCaption: String;
  LIndex, LError: Integer;
begin
  LCaption := '%';
  for LIndex := AFirstIndex to AFirstIndex + 7 do
  begin
    LControl := Tablica.FindChildControl(Format('CDigit%d', [LIndex]));
    LCaption := LCaption + LControl.Caption;
  end;
  Val(LCaption, Result, LError);
end;

To ten kawałek kodu z tą TGroup oraz procedurą i funkcją.
W tym miejscu wyrzuca błąd

function TForm.DigitsToNumber(AFirstIndex: Integer): Integer;

oraz

LControl := Tablica.FindChildControl(Format('CDigit%d', [LIndex])); 

0

W tym miejscu wyrzuca błąd

Jaka jest treść błędu?

0

screenshot-20170113174534.png

0

Bo kopiujesz kody z postów zupełnie bez zastanowienia - to jest głównym błędem;

Metoda DigitsToNumber ma być składową klasy formularza - Twoją klasą formularza jest TForm1, więc po pierwsze dodaj nagłówek tej metody w deklaracji klasy formularza, np. w sekcji private:

type
  TForm1 = class(TForm)
  {...}
  private
    function DigitsToNumber(AFirstIndex: Integer): Integer;
  {...}
  end;

A po drugie, popraw nazwę klasy formularza w nagłówku definicji tej metody:

function TForm1.DigitsToNumber(AFirstIndex: Integer): Integer;
{...}

Poza tym, dziesięć linijek niżej masz drugi błąd - nieznany identyfikator Tablica.

0

Problem w tym, że po prostu nigdy nie miałem styczności z programowaniem, a mój profesor jako zaliczenie przedmiotu wymyślił dla mnie o taki projekt.

Usunąłem te błędy.

Jakbym teraz chciał ten Result gdzieś wypisać to
napisać w pętli po prostu for i:=0 to i:=7 do
Label.Caption:=Result
?

0

Jakbym teraz chciał ten Result gdzieś wypisać to napisać w pętli po prostu [...]

Result czego?

0

Tej procedury Val.

0

Nie procedury Val, bo ona konwertuje łańcuch znaków na liczbę, a wynik tej konwersji wrzucany jest do Result metody DigitsToNumber; Aby skorzystać z wyniku konwersji, musisz rezultat tej metody przypisać do jakiejś zmiennej:

var
  LNumber: Integer;
begin
  LNumber := DigitsToNumber(0);

Według powyższego, przykładowego wywołania, w zmiennej LNumber znajdzie się wynik konwersji wartości spod Caption przycisków od CDigit0 do CDigit7, czyli wynik konwersji liczby binarnej na decymalną;

Zmiennej tej możesz użyć do czego chcesz.

0

A do czego polecasz do zapisać, żeby w tej zmiennej była zaraz wyświetlana wartość tego danego wiersza zaraz po wylosowaniu na konsoli?

0

Napisz konkretnie o co Ci chodzi, bo nie chce mi się zgadywać.

0

W jakim komponencie wyświetlać result metody DigitsToNumber;

0

W jakim komponencie i w którym momencie?

0

Chciałbym żeby to wyglądało tak:

Tablica już wypełniona dowolnie

1 0 1 0 1 1 1 1 -> 175
1 0 1 0 1 1 0 1 -> (w tym miejscu jakiś komponent, który będzie wyświetlał ten result procedury DigitsToNumber dla tego wiersza.
1 0 1 1 1 1 0 1 ->
1 0 1 0 1 1 0 1 ->
1 0 1 0 1 1 0 1 ->
1 1 1 0 1 1 0 0 ->
1 0 1 0 0 1 0 1 ->
1 0 1 0 1 1 0 1 ->
|
w tym miejscu jakiś komponent, który będzie wyświetlał ten result procedury DigitsToNumber dla tej kolumny

0

Jak potrzebujesz wyświetlać liczby pobierane z komponentów w poziomie i w pionie - musisz napisać dwie metody, które odczytają liczbę z przycisków i ją zamienią na natywną liczbę (np. typu Byte), możliwą do konwersji na łańcuch znaków i do wyświetlenia w komponencie;

Poprzednio podana metoda DigitsToNumber umożliwia jedynie pobranie liczby w poziomie - do pionu trzeba napisać drugą; Przyda się też sensowne ich nazwanie, tak aby było wiadomo co dokładnie robią; Jedną można nazwać HorzDigitsToNumber i będzie ona pobierać liczbę w poziomie, a drugą VertDigitsToNumber, która będzie pobierać liczbę w pionie;

Jedną już mamy, więc wystarczy tylko zmienić jej nazwę, ew. zmienić też nazwę parametru, aby był czytelniejszy i informował o podaniu indeksu wiersza; Nagłówki dwóch metod powinny wyglądać tak:

type
  TForm1 = class(TForm)
  {..}
  private
    function HorzDigitsToNumber(ARowIndex: Integer): Integer;
    function VertDigitsToNumber(AColIndex: Integer): Integer;
  {..}
  end;

Teraz przystosujmy metodę do pobierania liczby w poziomie:

function TForm1.HorzDigitsToNumber(ARowIndex: Integer): Integer;
var
  LControl: TControl;
  LCaption: String;
  LIndex, LError: Integer;
begin
  LCaption := '%';

  for LIndex := ARowIndex to ARowIndex + 7 do
  begin
    LControl := CDigitsGroup.FindChildControl(Format('CDigit%d', [LIndex]));
    LCaption := LCaption + LControl.Caption;
  end;

  Val(LCaption, Result, LError);
end;

Oraz napiszmy metodę do pobierania liczby w pionie:

function TForm1.VertDigitsToNumber(AColIndex: Integer): Integer;
var
  LControl: TControl;
  LCaption: String;
  LError: Integer;
begin
  LCaption := '%';
  
  while AColIndex <= 63 do
  begin
    LControl := CDigitsGroup.FindChildControl(Format('CDigit%d', [AColIndex]));
    LCaption := LCaption + LControl.Caption;
  
    Inc(AColIndex, 8);
  end;
  
  Val(LCaption, Result, LError);
end;

Metody są gotowe - można ich używać.

0

Dzisiaj próbowałem uruchomić program i wyskakuje mi taki bląd

Form resource TForm1 not found. For resourceless forms CreateNew constructor must be used. See the global variable RequireDerivedFormResource.

To nie jest związane tylko z jednym projektem tylko inne aplikacje okienkowe też nie działają.

0

Sprawdź, czy w pliku źródłowym z klasą formularza znajduje się dyrektywa {$R *.dfm} i jeśli nie - przywróć ją z powrotem, bo najpewniej przez przypadek skasowałeś ją.

0

Podziałało, dziękuje, gdzieś przypadkiem usunąłem.

No tak, mamy te dwie funkcje, tylko co jeszcze dopisać żeby wysłać wynik np VertDigitsToNumber dla danego wiersza to jakiegoś buttona albo czegokolwiek i żeby ten komponent wyświetlał dziesiętny wynik.

0

Spróbowałem stworzyć TGroupBoxa, w którym umieściłem buttony o nazwie Pion i próbowałem tak jak w poprzednim TGroupBoxie wykonać kilka poleceń na raz. Oto kod:

procedure TForm1.GroupBox1Click(Sender: TObject);
var
  LButton: TControl;
  i: Integer;
begin
  for i := 0 to 1 do
  begin
    LButton := Tablica.FindChildControl(Format('Pion%d', [i]));
    LButton.Caption:=IntToStr(DziesPoziom(i));
  end;

end; 

Po kliknięciu na TGroupBoxa wyrzuca błąd w postaci:

Projekt raised exception class External:SIGSEGV'.

Mógłbyś pomóc?

0

Miałeś wygenerować zdarzenie OnClick dla pierwszego przycisku (u Ciebie zapewne Pion0), a nie dla GroupBox...

0

No tak, zdarzenie zdołałem zrobić. Wypisało mi liczbę dziesiętną danego z wiersza lub kolumny.
Tylko, umieściłem je w buttonie i żeby ją wypisało, to muszę na niego kliknąć, a potrzebuję, żeby automatycznie po wylosowaniu tablicy od razu wypisało mi te wartości, a potem dynamicznie je zmieniało wraz ze zmianą dowolnego Cdgit. Przy okazji mialem problem, ponieważ ręcznie musiałem każdy button pisać i zmieniać dla niego wartość LIndex.
Dlatego pomyślałem, że zrobię to na wzór działania Cdgit. Czyli stworzę TGroupBox z wartościami wierszy, a drugiego z wartościami kolumn, tam będę wyszukiwał Pion lub Poziom i będę do niego wypisywał wartość funkcji przy okazji zwiększając LIndex odpowiednio dla kolumn o 8, a dla wierszy o 1.

Jestem laikiem i dlatego nie rozumiem co chcesz mi przekazać.

0

Tylko, umieściłem je w buttonie i żeby ją wypisało, to muszę na niego kliknąć, a potrzebuję, żeby automatycznie po wylosowaniu tablicy od razu wypisało mi te wartości, a potem dynamicznie je zmieniało wraz ze zmianą dowolnego Cdgit

W takim razie najpierw wylosuj tablicę, a następnie od razu dla każdego wiersza i kolumny wywołaj ręcznie metody odpowiedzialne za pobranie liczb z przycisków, ich konwersję na natwyną liczbę oraz konwersję na łańcuch znaków, w celu jej wyświetlenia na ekranie.

0

Ręcznie czyli poprzez kliknięcie na button? I mam stosować te TGroupBoxy?

Ale niekoniecznie muszą to być buttony, spróbowałem na nich, ale nie do końca spełniają to co chcę.
Szukam komponentu, który wyświetli mi te liczby od razu po wylosowaniu tablicy bez klikniecia na niego oraz będzie się dało z niego potem pobrać te liczby.
Jeżeli możesz to podpowiedz który spełniłby takie założenia.

Rozmawiałem z wykładowcą i mówił żeby umieścić tą dziesiętną wartość w ListBox, co Ty na to?

1 użytkowników online, w tym zalogowanych: 0, gości: 1