» »

Programiranje "Šah-a" v Javi

Programiranje "Šah-a" v Javi

Vlady ::

Ok mal butasto tole zveni ampak jaz poizkušam sprogramirati malo drugačno "verzijo" navadnega šah-a. Sem še bolj začetnik v Javi in se učim programirati programe z grafiko.

Vse skupaj izdelujem z awt in swing-om. Rišem na panel in potem generiram objekt tipa JFrame. Panel rišem s pomočjo JPanel. Izrisal sem že šahovnico na zaslon in to velkosti 20*20 pik na polje. Vsega skupaj je 16*16polj (256). Ja mal čudno za šah ampak jaz poizkušam svoj sistem >:D
Figurice imam narejene kot bitmap (slikce) velikosti 20*20 pik.
Sedaj me zanima, kako naj te figure "postavim" na šahovnico in jih namestim točno na polja (da ne bodo stali postrani kot pijane neveste). ???

Figurice sem mislil narediti kot objekte tipa figurice in potem za vsako vrsto narediti podedovan razred. V vsakem takem razredu je opisano ime figurice, njen začetni položaj in območje premikanja (torej kako se figurica premika).
Kako naj potem "povežem" te objekte z temi figuricami na šahovnici???
Prosil bi za pomoč kakega strokovjaka v Javi, ki ima kako fajn idejo glede tega, meni namreč ne pade nič na pamet. :\
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Vlady ::

Aja pa še to: rad bi, da lahko "uporabnik" te figurice premika. Torej se mora program odzivati na miško. Pri neveljavni potezi program izpiše sporočilo v novem oknu z enim gumbom in figurico vrne v njen prejšnji položaj.
Zaenkrat bi naredil brez "računalniškega" igralca. Torej da bi samo človek premikal fgurice.
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Gemm ::

Problem pozicioniranja boš najlažje rešil tako, da za šahovnico uporabiš LayoutManager tipa GridLayout, ki je kot nalašč za to. Ko imaš enkrat to, lahko s tem narediš tudi sistem premikanja figuric (v ActionListenerju ugotoviš, na katero polje je uporabnik kliknil, naprej pa po želji).
JPanel sahovnica = new JPanel(new LayoutManager(new GridLayout(16,16)));

Predlagam ti, da daj vsaki figurici en JPanel, na katerega nariši sliko figure, tega pa nato premikaš po ustreznih poljih v gridu.
public class Figura {
  private String ime;
  private int x,y;  // tuki je sicer dovolj ena sama spremenjlivka ampak za ilustracijo naj bosta 2 
  private JPanel podoba; // sem gor ob inicializaciji narisi ustrezno sliko, sam JPanel pa vstavi na šahovnico.
  ... 
  public void setPolozaj(int _x, int _y) {
    x = _x;
    y = _y;
    Container sahovnica = podoba.getParent(); // osveži položaj tudi na šahovnici
    if (sahovnica!= null) {
      sahovnica.remove(podoba);
      sahovnica.add(podoba, 16*x+y); 
    }
  }
}

Vlady ::

Samo eno vprašanje:
zakaj si dal v tej vrstici
JPanel sahovnica = new JPanel(new LayoutManager(new GridLayout(16,16))); kot argument 16,16???

Glede figuric pa sem mislil najprej narediti glavni abstraktni razred figura in potem izpeljanke za vsako figuro posebej.
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Vlady ::

Aja pa za LayoutManager mi javi napako:
Okno.java:14: java.awt.LayoutManager is abstract; cannot be instantiated
JPanel panel1 = new JPanel(new LayoutManager(new GridLayout(16,16)));
Moram v tej vrstici:

public class Okno extends JFrame
Dodat še kak vmesnik? :\
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Gemm ::

Ups, moja napaka: dovolj je, če napišeš
JPanel p = new JPanel(); 
p.setLayout(new GridLayout(16,16));

Argumenta 16,16 sta tam, ker si prej omenil, da delaš šahovnico velikosti 16*16, torej bo panel s tem managerjem urejen v mrežo 16*16 celic.

Drugače je pa res najbolj elegantno narediti razred Figura abstrakten, ja.

Zgodovina sprememb…

  • spremenil: Gemm ()

Vlady ::

Ja evo naredu. Ej sorry sm pol šele pozn zvečer odkril napako, ko sm bral dokumentacijo... Naporn del najdt tm določeno stvar. :\

No Grid sm zdej naredu in mi lepo izriše vse. Sedaj imam tri datoteke:

Okno.java: v njej naredim "Frame":

public class Okno extends JFrame
Potem izpišem še naslov v title, nastavim velikost okna, setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); za zapiranje okna, generiram nov kontejner, in potem:
		JPanel panel1 = new Panel1();		//generiram nov panel na katerega potep "pripopam" kontejner
		panel1.setLayout(new GridLayout(16,16)); //naredim grilayout
		vsebina.add(panel1);		//dodam vsebino



Potem imam datoteko risanje.java:
public static void main(String[] args)
	{
		JFrame okno = new Okno();	//generiram kno iz razreda JFrame 
		okno.show();	//prikaz okna na zaslon
	}



Potem pa še panel1.java:
public void paintComponent(Graphics g)		
	{
		super.paintComponent(g);	//kličemo kontruktor za privzete vrednosti
		setBackground(Color.white);	//nastavimo barvo ozadja
		
                int v, k;	//vrstice in kolone
                int pomikx=0;	//spremenljivki za pomik v smeri x in y
                int pomiky=0;
		
		//zanka v kateri "rišemo"
		//pretečemo vse vrstice in znotraj vrstične zanke pretečemo kolone
                for (v=1; v(manjši ali enak od) 16; ++v)   
                {  
                        for (k=1; k(manjši ali enak od)16; ++k)
                        {
                                if ((v+k)%2==0) 	//z if stavkom realizirana rešitev: če je vsota pozicije vrstice + kolone deljiva z 2 nariše bel kvadrat
                                {
                                        g.setColor(Color.white); //izbira barve, risati ni potrebno zaradi ozadja
                                }
                                else
                                {
                                        g.setColor(Color.black);	//če vsota ni deljiva z 2 izriše črn kvadrat - tu izberemo barvo
                                        g.fillRect(pomikx+1,pomiky+1,40,40);	//rišemo "poln" kvadrat in ne samo obrobe!!!
                                }
                                
				//pomikanje "kurzorja" da ne rišemo samo na enem mestu
                                if (k==1)
                                {
                                        pomikx=0; 	//če pridemo na začetek (na levo stran) vrne pomik v smeri x na vrednost 0
                                }
                                else
                                {
                                        pomikx=pomikx+40;	//če nismo na začetku prišteva po vsakem izrisu kvadrata nov pomik
                                }
                        }
                        pomiky=pomiky+40;	//pomikanje "kurzorja" v smeri y
                }

No to je moja rešitev za izris šahovnice. Zraven so še moji pametni komentarji. :D Jz tko lažji razumem pol ko študiram vsako vrstico. Bi se dal tole zadevo rešit na kak krajši način? Brez if stavka? (mislim na optimizacijo kode).

Jaz nisem vedel kako povezati objekte iz razreda figura z grafiko. :\ Torej da ima bel kmet bitmap belkmet.bmp in ga prikaže ustrezno na šahovnico.

Pa ne vem kako bo potem, ko bo postavil figurice na šahovnico z ozadjem polja na katerem bo figurica. recimo črne figure na črnem polju ne bom videl verjetno. Se da naredit kako "prozorno"??

[izbolšal izpis kode -OwcA]
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Zgodovina sprememb…

  • spremenilo: OwcA ()

Gemm ::

Optimizirati ti najbrž ni treba, ker kakšnih pohitritev niti ni možno dobiti, poleg tega pa izrisovanje ni časovno kriično.. traja kako milisekundo, izrisuješ pa bolj poredko.

Za risanje figur maš pa nekaj možnosti - ena je ta, da ima vsaka figura svoj JPanel, na katerem je narisana slika, ta JPanel pa nato rišeš v šahovnico (ta primer sem napisal prejle).
sahovnica.add(figura.getPodoba(), polozaj);

Druga je, da Figura kar razširja JPanel (ali vsaj JComponent), tako da lahko delaš kar v stilu:
sahovnica.add(figura, polozaj);

Tretja pa je, da sama figura nima veze z grafiko, hrani le položaj, nato pa ob vsakem repaintu kličeš funkcijo, ki gre skozi seznam vseh figur in jih nariše na primerno mesto na šahovnici.

To, da bi bila črna slika na črnem polju je pa bolj problem same bitne slike.. najbolj enostavna rešitev je da ko boš risal figure, da jih obrobiš s sivo al kaj podobnega.

Vlady ::

Dons delam razrede za figurce.
Za lovca je gibanje povsem enostavno. Lihe ali nelihe diagonale. Za trdnjavo pač samo po vrti ali koloni. Konj mi dela probleme. :\ :|
predlogi?
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Thomas ::

Look up tabela, kam iz vsakega polja vsaka figura laho gre, pa potem naprej look up tabela, katera polja bi jo utegnila tam ovirati ...

Če resno programiraš šah, boš naredil tako.

Quikee ::

Pomoje tak boljse... naredis matrixo 16x16 (recimo int Polje[16][16]) pa not oznacis z 1 ce je katera figura na polju ali o ce je polje prazno.. Potem pa se eno matriko, kjer so zapisane mozne poteze trenutne figure z 1 in 0 za tiste katere trenutna figura ne more it. Moze poteze pa isces recimo tako:
Kralj:
for (i=-1;i<=1;i++)
for (j=-1;j<=1;j++)
if (Polje[trenutno+i][trenutno+j] == 0)
MoznePoteze[trenutno+i][trenutno+j] = 1;

Potem mas za Kraljico isto samo da se en for stavek dodas in da prekine nadaljno iskanje v tej smeri ko pride do prve 1 v matriki. Za lovca spet isto kot kraljica samo da recimo ignoriras smeri kjer je i==0 && j==0, za trdnjavo pa ignoriras ravno nasprotno. Za konja pa pac posebej napises vse njegove mozne poteze. Treba se malo izpilit to ampak v principu je tak najlazje naredit. =)

Thomas ::

> naredis matrixo 16x16

Velika šahovnica .. orng šah!

Quikee ::

Thomas_
"Izrisal sem že šahovnico na zaslon in to velkosti 20*20 pik na polje. Vsega skupaj je 16*16polj (256). Ja mal čudno za šah ampak jaz poizkušam svoj sistem >:D"

Jah.. tak sah hoce naredit kaj te naj jaz. hehe =)

Thomas ::

No, jest mislim, da je vsakokratno izračunavanje možnih potez neoptimalno.

Quikee ::

Sej lahko naredi, da se to izracuna ob inicializaciji za vsa polja in tvori lookup tabele kot si ti predlagal. Aja.. pa na zacetku spet ne rabi bit vse optimalno... optimiziras potem.. ko enkrat stvar deluje.

snow ::

GameDev article o iskanju možnih potez v šahu. Bitboard is the answer :D
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Vlady ::

No gre za eno malj bolj drugačno izvedenko šaha. Pač en kitajc je izumu mal drgačno igro. U bistvu imaš poleg šahovskih figur v zadnji vrsti spredi še dve vrsti nekakšnih "vojakov". Eni se premikajo tako kot dame (poševno in izločijo nasprotnika če ga preskočijo eni pa se premikajo kot "kralji" in se premikajo po eno polje. Zarad tega se uporablja šahovnica velikosti 16*16 in igra je tud mal bolj zanimiva. :D No jz sm špilu tisto verzijo od kitajca sam je bla polna bugov, ker jo je napisu u C-ju. Pa sm reku da bom jz si "sposodu" idejo in jo naredu u javi, ker nima memory leak-ov pa podobnega shit-a. No projekt je kakopak open-source in če bi rad kdo pomagu, lahko dam vse zadeve na ftp in potem naredi vsak svojo verzijo :D
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Vesoljc ::

> sam je bla polna bugov, ker jo je napisu u C-ju

mnja, take izjave niso glih brihtne...
če program vsebuje buge, je skoraj zagotovo kriv programer in ne jezik ;)
Abnormal behavior of abnormal brain makes me normal...

Vlady ::

Hja je, sam fora je pr c-ju, ko morš za pomnilnik skrbet sam in pr večji stvari to rata problem. Pa še diagnostike ni mel, ker je zadevo delu v linux-u in potem z gcc-jem prevaju. Recimo igral si zadevo in je pr določenih stvareh začel izginjat figurce pa take podobne. Tud meniji so bli zelo buggy.
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

snow ::

Hm, a v javi se ti pa ne more zgodit da ti zmanjka figurica, ker ti skrbi za memory leake? :\


Drugače zanimiva varianta s šahovnico in figurami za šah je arimaa.
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

drejc ::

Ma java kr vredu ai specialista za higijeno vdelanga, ja.

Vlady ::

Hehehe tale arimaa je prov smešna :D Sam je kr fajn če si dobr v tem.
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Vlady ::

Evo mene že nazaj z novimi problemi >:D

No zdej sm končal z risanjem in figurcami. En screenshot kako izgleda:



Zdej če malo bolj raložim ob sliki kako to "deluje".
Šahovske figure se pač premikajo kot se, tu ni izjem razen pri kmetih, ki se lahko premikajo v vse smeri razen nazaj. TOrej gre lahko kmet v levo ali v desno ali po diagonala, ne da bi koga "jedel". Potem rdeči in modri se premikajo kot dame, samo za eno polje diagonalno in izločijo nasprotnika s tem, da ga preskočijo. Lahko preskočijo več figur in lahko pri skakanju čez več figur skačejo tako čez svoje in nasprotnikove in medtem papajo nasprotnikove.
Zeleni in rumeni pa se premikajo kot kralj pri šahu, le da se te lahko "poje".

Ok zdej pa moji problemi: Kako nardit, da bom lahko z miško prekamnu figure po "mreži" (gridlayout 16x16)?

Vse figure so izpeljane iz abstraktnega razreda Figure in vsaka figura ima kot objekt samo svojo slikco.
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Zgodovina sprememb…

  • zavarovalo slike: OwcA ()

Vlady ::

Se nobenmu nič ne sanja? Plz help, ker sm se nekak zataknu pr temu actionlistenerju. Oz. bolj mouse listener. :\
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

Quikee ::

Najlazje je da ko kliknes na figuro.. ugotovis koordinate.. izracunas kateri figuri pripadajo. Drugic pa kliknes na prazno polje in se figura tja premakne... torej iz stare pozicije izbrises in das na novo pozicijo. Seveda se mors pogledat ce je veljavna poteza ali ne.

Vlady ::

Živjo!
Evo mene nazaj s svežimi problemi. Mal mi je manjkal časa, zato nism velik delu na temu šahu ampak zdej sm že kar daleč.

Naredu sem že poslušalce za miško in lahko figure premikam in jem (svojih ne morem). Danes sem pisal logiko za veljavne poteze in sm padu na nov problem. In sicer pri trdnjavi, lovecu in kraljici ne pogruntam kako bi jih "omejil" da nebi preskakovali figur.

Vsaka figura ima takole metodo, ki vrača vrednost boolean glede na veljavnost poteze. Metoda dobi kot argumente začetni koordinati figure v mreži x in y in končni koordinati figure kamor figuro spustim x in y. No spodaj je primer metode za kraljico. Kak predlog, kako bi "omejil" kraljico da nebi preskakovala figur?

public boolean poteza(int zacX, int zacY, int konX, int konY)
{
if (Math.abs(Math.abs(konX-konY)==Math.abs(zacX-zacY) || Math.abs(konX+konY)==Math.abs(zacX+zacY) || konX==zacX || konY==zacY)
{
return true;
}
else
{
return false;
}
}

Svoje predloge bi prosu, da mi podate že kot "narejeno" metodo. Hvala za pomoč! :D
"Lotereya - naibolee točnyj sposob učeta količestva optimistov"

OwcA ::

Ni tako preprosto. Veljavna poteza je tudi funkcija trenutnega stanja na šahovnici, ne le figure. Najprej pogledaš, če je premik veljaven (figura), potem pa še, če je mogoč (šahovnica).
Otroška radovednost - gonilo napredka.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[java]problem z Throws

Oddelek: Programiranje
221600 (1129) killa bee
»

[Java] Ne zažene appleta

Oddelek: Programiranje
51206 (1139) iggy
»

[Java] Zagon appleta v HTML

Oddelek: Programiranje
161539 (1361) Bela01
»

[JAVA] branje iz datoteke

Oddelek: Programiranje
242405 (2040) Bela01
»

[Java]Vprašanja

Oddelek: Programiranje
242103 (1571) Bela01

Več podobnih tem