|
Polski Portal COLOBOTa COLOBOT Polish Portal |
|
Problemy [programowanie] - Przekazywanie zmienniej między robotami?
FE4R - 28-11-2009, 22:46 Temat postu: Przekazywanie zmienniej między robotami? Hej,
Chciałem się zapytać, czy 2 roboty mogą przekazywać sobie liczby i je wykorzystywać.
Może przedstawię to na przykładzie, który chcę wykorzystać.
Jeden robot jeździ po okolicy, póki nie skończy mu się energia(nie pytajcie, po co jeździ...)
Drugi robot - WingedGrabber - czeka.
I teraz chciałem się zapytać, czy można zrobić tak, aby jeżdząc Bot wysłał do Grabbera numer, dajmy na to: '1555', typu int.
Grabber interpretuje 1555 jako wezwanie o nowe ogniwo elektryczne.
Tymczasem, gdy jeżdzący robot zostanie zaatakowany, wyśle numer 1556, typu int, dzięki któremu Grabber zrobi coś innego - podejmie jakąś akcję obronną... wyśle osłaniacza albo działo...
Miałem koncepcję prostego programu:
Kod: | int received; //nie wiem jak sprawić, żeby roboty się komunikowały i wysyłały zmienną między sobą
if(received == 1555)
{
instrukcje do zamiany ogniwa...
}
|
Jakieś propozycje?[/code]
shoter - 28-11-2009, 23:36
public class komunikat
{
static public int wartosc;
}
//teraz kod do funkcji glownej robota ktory se jezdzi(w petli jezdzacej)
komunikat robot ;
if(energyCell.energyLevel == 0) robot.wartosc = 1555;
//kod dla drugiego robota
komunikat robot;
while(robot.zmienna != 1555) {}
instrukcje_po_skonczeniu_energi();
//static powoduje ze niezalezenie od wywolywanej instnacji zmienna sie nie zmienia w zaleznosci od wybranej klasy
FE4R - 29-11-2009, 11:09
@EDIT: No i entuzjazm prysł. >.>
Pojawia się błąd: Obiekt nieznany. Od razu w robocie Grabberze i po skończeniu się energii u robota wykonującego pętlę.
Zrobiłem to tak:
Robot jeżdżący:
Kod: | public class komunikat
{
static public int wartosc;
}
extern void object::Main()
{
while(true)
{
goto(tam i tutaj); // ;)
komunikat robot;
if(energyCell.energyLevel == 0) robot.wartosc = 1555;
}
} |
Kod Grabbera:
Kod: | extern void object::Secondary()
{
while(true)
{
komunikat robot;
while(robot.zmienna != 1555) wait(1);
Instrukcje do zmiany ogniwa...
}
} |
@EDIT2:
Czy jest jakiś sensowny poradnik, tłumaczący, co naprawdę znaczy 'klasa', do czego służy, dlaczego funkcje nazywają się metodami, na jakich zasadach to funkcjonuje i kiedy wraca pipok?
shoter - 29-11-2009, 14:38
polceam książke symfonia c++ (lepsze)
lub : http://xion.org.pl/files/texts/mgt/html/1_6.html (gorsze)
FE4R - 29-11-2009, 16:18
To wcale nie rozwiązało problemu takiego, że wyświetla mi błąd w Colobocie...
shoter - 29-11-2009, 19:21
juz wiem w czym problem!!
zmienne nie zostały zainicjalizowane wartościami
second :
komunikat robot();
while(robot.zmienna != 1555) wait(1);
main :
komunikat robot();
if(energyCell.energyLevel == 0) robot.wartosc = 1555;
reszta jest dobrze tylko te linijki sa zle .amen!
adiblol - 29-11-2009, 20:34
Tym się pobaw: http://www.colobot.yoyo.p...php?p=6042#6042
FE4R - 29-11-2009, 20:46
Linki do kodów nie istnieją.
Ale pobawię się save'm.
adiblol - 29-11-2009, 21:16
W save'ie są wszystkie kody, w pastebinie były nieaktualne
FE4R - 29-11-2009, 23:31
Trochę to trudno zrozumieć w kontekście mojego problemu.
A shoter dodałem nawiasy i tym razem jest błąd, że zmienna nie została zainicjalizowana.
shoter - 30-11-2009, 08:37
zmien definicje klasy
public class komunikat
{
static public int wartosc = 0;
}
zainicjalizujemy w takim razie zmienna =D
FE4 - 30-11-2009, 08:42
To będzie dłuuuuuuuga edukacja o klasach.
No cóż. Dzięki shoter. ^_^ Jestem wdzięczny.
Berserker - 30-11-2009, 13:52
Klasy sa proste, beznadziejne i potrafia wywalic gre O_O.
-- wiem, ze spam, ale musialem dodac swoje 3 grosze
shoter - 30-11-2009, 15:42
Berserker napisał/a: | Klasy sa proste, beznadziejne i potrafia wywalic gre O_O.
-- wiem, ze spam, ale musialem dodac swoje 3 grosze |
hmm...w tym problem że klasy są złożone i zajebsite...Gratuluje jeśli tylko w CBocie programujesz tylko li wyłącznie funkcyjnie.Mi nigdy nie zdarzały się problemy z obiektami ^^.Raz zrobiłem klase która zapisywała wszystkie dane o przeciwnikach na dysk i wykorzystywała je dla patrolów dla kilku robotów(mam nadal ten program).
Berserker - 30-11-2009, 15:57
Cytat: | hmm...w tym problem że klasy są złożone i zajebsite...Gratuluje jeśli tylko w CBocie programujesz tylko li wyłącznie funkcyjnie. |
Klasy sa proste - nauczylem sie nimi poslugiwac w 1 dzien.
Beznadziejne - potrafia stworzyc mnostwo problemow a byle bledu mozna szukac w programach trzech robotow.
Potrafia wywalic gre - mi czesto wywalaja przy wczytywaniu save'a, potrafi to zdenerwowac.
Ale przyjemnie sie oglada gonitwe 6 dzial na kolach goniacych w jakistam zorganizowany sposob jednego transportera. Chyba, ze sie spartoli program do uciekania.
FE4R - 30-11-2009, 17:12
Chyba muszę sobie kupić podr. do C++'a, to może coś zakumam, bo nie idzie mi zrozumienie klasy w ogólnym aspekcie (nie tylko programowania obiektowego)...
Berserker - 30-11-2009, 17:39
Na chlopski rozum: klasa to taki typ ktory jest tworzony przez ciebie, co oznacza, ze musisz stworzyc zmienna w programie aby otrzymac dostep do klasy.
Kod: |
public class klasa
{
}
extern void object::Bla()
{
klasa test();
}
|
Ale pusta klasa nikomu nie jest potrzebna, wiec dodajmy do niej jakas zmienna.
Kod: |
public class klasa
{
static object target = null;
}
|
W ten sposob mamy w niej zmienna typu object. Malo komu sie przydaje zmienna z 'null' w srodku, wiec warto by bylo dac w niej np info o mrowce.
Kod: |
test.target = radar(AlienAnt);
|
Mamy mrowke. Mrowki nie moga se lazic bezkarnie, wiec trzeba ja eksterminowac. Jesli masz batalion robotow chetnych do zabicia jakiejs mrowki, to nie znajdujesz im celu poleceniem
Kod: |
object p;
p = radar(AlienAnt);
|
tylko
W ten sposob roboty nie beda latac po mapie w pogoni za mrowkami, tylko wszystkie pojda na ta biedna jedyna.
Ale zeby wszystkie roboty po prostu szarzowaly na jedna mrowke to takie troche... nieinteligentne, wiec poprzydzielamy im imiona w postaci cyferek. Zakladajac, ze to beda 4 roboty, nadamy im imiona 1...4. Najpierw warto ustalic, jakie imie dostanie 1 robot.
Kod: |
public class klasa
{
static object target = null;
static int name = 1;
}
|
Mamy imie dla pierwszego bota, pozostaje przydzielic imiona nastepnym
Kod: |
public class klasa
{
static object target = null;
static int name = 1;
synchronized int getname()
{
int ret;
ret = name;
name = name + 1;
return ret;
}
}
|
'synchronized' w funkcji sprawia, ze kazdy robot bedzie ja wykonywal osobno, wiec nie ma obaw, ze dwa roboty beda mialy jednakowe imiona.
Pozostaje zapoznac boty z ich nowiutkimi mianami.
Kod: |
int name;
name = test.getname();
|
Napisalbym jeszcze jak pozycje dobrac, ale to nie jest poradnik 'jak zabic mrowke majac do dyspozycji 4 zaprogramowane roboty'.
FE4R - 30-11-2009, 22:16
Aha. No dobrze.
A czy lepiej jest, aby robot 'zarządca' stworzył klasę czy może robot, który będzie jeździł w pętli.
Według mojej teorii - robot, któremu wyczerpało się ogniwo - nadaje zmiennej w klasie numer 1555. Robot zbierak interpretuje numer, jako włącznik dla zamiany ogniwa robotowi.
To już wykonałem poprawnie.
Ale jest problem - numer został wysłany tylko przez jednego robota o tej jednego kategorii - a co z innymi? Stworzyłem coś takiego:
Kod: | public class Codes
{
public int cat = 0; // kategoria obiektu
} |
Gdy robotowi wyczerpuje się ogniwo, nadaje zmiennej 'cat' wartość WheeledOrgaShooter, bo akurat tak się nazywa. Wtedy robot zbierak wykorzystuje daną kategorię, aby przy funkcji radar znaleźć robota. Tylko, że może znaleźć niewłaściwego, bo ten właściwy nie będzie ani najbliższy, ani najdalszy. Czy jest jakiś sposób, aby wszystkie właściwości(pozycja, energyCell.energyLevel i inne) robota wysyłającego kod 1555 był zapisany i wtedy abierak mógłby to wykorzystać?
Coś na obraz - ktoś ci coś wysyła, a ty znasz jego IP i dobierasz się do niego.
Kolejny problem to jest destruktor - coś, co by resetowało 'kod 1555', wezwanie o pomoc do 0. Bo przecież nie chciałbym, aby robot zbierak zrobił swoje, a zmienna w klasie nadal by pozostała 1555 i wracałby cały czas do tego robota...
Wiem, że trochę mi to trudno opisać, ale zaczynam coś kumać, więc mam nadzieję, że będę w stanie to łatwiej wytłumaczyć?
Berserker - 01-12-2009, 00:21
Cytat: | A czy lepiej jest, aby robot 'zarządca' stworzył klasę czy może robot, który będzie jeździł w pętli. |
Ja zawsze albo daje klase robotowi zarzadzajacemu, albo wszystkie klasy daje w jednym robocie.
Kod: | ]public int cat = 0; // kategoria obiektu |
Pierwszy blad, zmienna musza byc statyczne, nie rozumiem po co (wg opisu po to, by mogly ja zmieniac/czytac wszystkie roboty ktore uzywaja klasy).
Cytat: | Kolejny problem to jest destruktor - coś, co by resetowało 'kod 1555', wezwanie o pomoc do 0. Bo przecież nie chciałbym, aby robot zbierak zrobił swoje, a zmienna w klasie nadal by pozostała 1555 i wracałby cały czas do tego robota... |
Da sie po prostu wpisujac 'test.kod = 0;'. Ja proponuje odrazu resetowac zmienna a info o tym, ze kots absolutnie niezbednie potrzebuje naszej pomocy zapisac do jakiejs zmiennej ktora juz jest w funkcji.
Cytat: | Gdy robotowi wyczerpuje się ogniwo, nadaje zmiennej 'cat' wartość WheeledOrgaShooter, bo akurat tak się nazywa. Wtedy robot zbierak wykorzystuje daną kategorię, aby przy funkcji radar znaleźć robota. Tylko, że może znaleźć niewłaściwego, bo ten właściwy nie będzie ani najbliższy, ani najdalszy. Czy jest jakiś sposób, aby wszystkie właściwości(pozycja, energyCell.energyLevel i inne) robota wysyłającego kod 1555 był zapisany i wtedy abierak mógłby to wykorzystać? |
Sa 2 sposoby, jeden jest beznadziejny a drugi jest pro.
1) Po prostu czytasz odleglosc tych robotow od siebie, a pozniej w radarze wpisujesz np.
Kod: | radar(test.cat, 0, 360, test.dist-1, test.dist+1); |
Wtedy bedzie wykrywac w bardzo cieniutkim pierscieniu kolowym, i raczej wykryje akurat twojego bota.
2) Zamiast
Piszesz
Kod: |
static object me = null;
|
A w robocie podajesz
W ten sposob jakby radarem potraktowales siebie i zapisujesz info o sobie w postaci zmiennej test.me. Pamietaj, ze ta zmienna musi byc stale aktualizowana.
shoter - 01-12-2009, 12:56
klas na forum nie zrozumiesz nie trudź sie...Ja klasuje wszystkiego.Klasa to obiekt.Obiekt to cegła.Co robi objekt robota zbieracza?Zbiera...Czyli klase piszemy tak aby mogła coś zbierać ew. porozumiewać się z innymi robotami.(Ja najczęściej w klasach jakiś mały problem sobie opisuje.program bardziej opieram niestety funkcyjnie z powodu języka CBOT.)
Np klasa robota zbieraka
Kod: | public class zbierak
{
int ile_tytan;
void zbierz_tytan()
{
//robot zbiera tytan
ile_tytan++;
message("Zebralem juz " + ile_tytan + " kostek tytanu.",DisplayInfo);
}
} |
widzisz?Klase definiujemy np tak zbierak robotA();
uzywajmy jej tak robotA.zbierz_tytan();.
no i to byłoby na tyle...klasy mogą opisywać jakieś mniejsze zagadnienie,np odbieranie informacji ze stacji przekaznikowej
Klasa może robić wszystko...
np w moim programie kazdemu robotowi przypisywala dana liczbe.Program był bardzo fajny ^^
Kod: |
public class numer
{
public int nr;
static public int ktory=0;
void numer()
{
ktory += 1;
ktory %= 10;
nr = ktory;
} }
|
FE4R - 01-12-2009, 18:40
Już mniej więcej rozumiem, na jakiej zasadzie działa to, co mi przedstawiliście. To dużo w porównaniu do kilku dni wcześniej, gdy o klasach nie wiedziałem nic.
Prawdopodobnie niedługo odkryję jakieś ciekawsze zastosowania dla klas.
Ale póki co - jest problem (tak, kolejny, ), z którym nie potrafię sobie poradzić.
Nie wynika on z błędu z klasami, ale z natury gry.
A mianowicie...
Practice Bot jeździ sobie, póki nie wyczerpie mu się ogniwo. Gdy tak się stanie - zamienia wartość zmiennej w klasie na 1555, podaje swoją pozycję, a zbierak interpretuje kod 1555 jako wezwanie o pomoc przez robota, który go wysłał. Leci po nowe, pełne ogniwo, potem do robota, wyciąga zużyte i...
Practice Bot przerywa działanie programu bez wysyłania komunikatu o błędzie. Czy jest jakiś sposób, aby PracticeBot nie przerywał?
Kod użyty do czekania na załadowanie:
do{
wait(1);
}while(energyCell.energyLevel != 1);
shoter - 01-12-2009, 18:55
czy ty zauważyłeś że podczas gdy wyjmiesz ogniwo to energyCell = null?a skoro nic tam nie ma to proba wyciagniecia stamtad energyLevel konczy sie bledem ?
jak to ma wygladac :
Kod: | //wyczerpujemy energie
do
{
motor(1,1);
}while(energyCell.energyLevel != 0);
//czekamy na wyjecie ogniwa
do
{wait(1);
}while(energyCell == null)
//czekamy na ogniwo
do{
wait(1);
}while(energyCell != null)
//tutaj juz masz ogniwo |
proste?Nieprawdaz?Nie mozna zagladac do srodka klasy(energyCell w jakims tam sensie jest klasa ) gdy jest ona pusta...(to tak jakby chcial wejsc do szybu windy gdy jej nie ma ,co sie stanie?Spadniesz...XD)
Berserker - 01-12-2009, 19:46
Albo po prostu
Kod: |
while(energyCell == null or energyCell.energyLevel != 1) wait(1);
|
Po co sie meczyc z 10 linijkami kodu
shoter - 01-12-2009, 20:00
ehhh o samym while() zapomniałem ,ale zrozumiałeś istote(poczware xD) swojego problemu?ya?
FE4R - 13-12-2009, 14:07
Chciałem odświeżyć temat.
Co prawda rozwiązałem problemy z ogniwem oraz z przekazywaniem numeru kodu w klasie, jak również jak zresetować kod po zmianie ogniwa.
Jednak jeszcze nie próbowałem zrobić tego, gdy dwa roboty jednocześnie będą chciały wysłać 'kod 1555'. Myślałem, żeby zastosować metodę z synchronized, żeby drugi robot bez ogniwa poczekał, aż pierwszy zresetuje kod do 0, a wtedy drugi poda swoje dane, ale niestety coś mi z tym synchronized nie wyszło.
Czy jest jakiś prosty sposób, aby rozwiązać ten problem?
Berserker - 14-12-2009, 09:05
Tablice. Za pomocą tablic kolejkujesz sobie obiekty do "pomocenia im" . Jakbym miał w domu neta i nie pisał tego na ipodzie to bym napisał sam to, tak to sam se musisz poradzić sam
|
|