Diskuze: Problém
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
Napis to v XHTML a mas nejak malo casu ve switchy XAXA
Atrament:10.5.2016 12:12
Nemoh bys někam uploadnout ty obrázky těch karet, tak abych si to mohl u sebe spustit?
Možná vím. Když klikneš na druhou kartičku, která není shodná s onou předchozí, tak se otočí na svůj obrázek a a zase zakryje, to funguje správně. Jenom to proběhne během zlomku sekundy a není to vidět. Proto bych přidal něco takového...
/*Ak je počet otočených kariet dva, to znamená, že má program skontrolovať, či netvoria pár. Ak ho tvoria,
počet stlačených kariet sa nastaví na nulu a karty zostanú otočené.*/
if (pocetStlacenych == 2)
{
if ((napln[stlaceneObrazky[0]].cisloObrazku)==(napln[stlaceneObrazky[1]].cisloObrazku))
{
pocetStlacenych = 0;
napln[stlaceneObrazky[0]].najdenyPar = true;
napln[stlaceneObrazky[1]].najdenyPar = true;
kliknutaPozicia = -1;
}
//Ak karty netvoria pár, počet stlačených kariet sa nastaví na nulu a karty sa otočia do pôvodnej pozície
else
{
//přidaný kód
Thread.sleep(1000);
//přidaný kód
poleTlacidiel[stlaceneObrazky[0]].setIcon(obal);
poleTlacidiel[stlaceneObrazky[1]].setIcon(obal);
pocetStlacenych = 0;
kliknutaPozicia = -1;
}
}
no já bych spíš řešil to pexeso jinak - já bych si udělal novou
třídu karta, která by měla na starost otáčení a zobrazení karet. Další
třída plocha, na kterou by se karty naskládali a třetí třídu jak máš i
ty - porovnání, kde bych řešil, jestli jsou dvě karty, které jsou
otočené stejné (tím by sis i mohl případně pexeso rozšiřovat, že bys v
jedné třídě upravil podmínku shodnoti karet, třeba na tři stejné karty:)
prostě tvoje pravidla.
narvat všechno do jedné třídy.... není moc dobrý nápad. Jinak pěkný
kód;)
Jen dvě poznámky:
Když už chceš pole objektů, tak je lepší použít kolekci (arraylist nebo
list) JButton[] sice jde, ale není to moc čisté. Pole jako takové se
používá spíše na hodnoty (Integery nebo Stringy) a moc se nepočítá, že
by pak volali nějaké metody. Kolekce je na to i trošku líp stavěná.
Používáš moc polí. Je sice pěkné si všechno pamatovat, ale myslím, že na x věcí by ti stačilo zapamatovat si jen jednu hodnotu v jedné proměnné, Zkus na to jít trošku jinak.
A ještě jestli bys chtěl, tak bych ti řekl, jak bych na to šel osobně já - i když půlka členů z IT network asi nebude moc souhlasit:):
nejdřív bych si udělal ty tři třídy. Třída Plocha by řešila jen zobrazení plochy + rozhození karet, nic víc (možná ještě tak tlačítko nová hra - což by představovalo smazat nějaký panel, na kterém jsou všechny karty, promazat kolekci/e - tím že smažeš veškeré reference na objekty, tak je smažeš i z paměti - Java je v tomto bezvadná a vše za tebe řeší garbage collector:) v C bys to musel na vše pamatovat:D). Jo a třída Plocha by měla nějaký posluchač pro myšku pochopitelně:)
třídu Karta bych udělal jako potomka JComponent (nebo JComponents, teď to nevím úplně přesně). Kdybych dělal konstruktor, tak bych na každou kartu v něm nastavil velikost (tím bych řešil budoucí problém s různým rozlišením obrazovky). Každá karta by obsahovala jeden boolean, který by si ukládal stav karty - otočeno false/true. Na tento boolean bych vytvořil návratové metody isOtoceno() a setOtoceni(boolean). No a ve třídě paint(Graphics) bych už jen vykreslil obrázek.
Pozn.: není to sice úplně šikovné, kor když by ti někdo změnil názvy u karet, ale já si pojmenovávám v takovém případě karty 1.jpg 2.jpg 3.jpg atd. Potom můžu všechno narvat do for cyklu a jen si pohraju s textem:D např.: ImageIcon image = new ImageIcon(String.valueOf(i) + ".jpg"); a funguje to a je to kratší než všechno vypisovat:)
No a pak třeba třída Skore. Teď nám vlastně program vytvoří plochu,
na kterou rozhodí karty a otočí je rubem na líc. Třída Plocha má
posluchač na myšku a otáčí karty tím, že pomocí mouseEventu prostě
kartu otočí. Ještě si může max. pamatovat nějakou proměnnou, která bude
mít hodnotu 1 a 2. Když bude mít hodnotu 2, tak se karty otočí, když ne,
tak se nic nestane. To mě napadá, že by sis mohl ještě v nějaké
proměnné pamatovat otočenou kartu.
No a třída Skore by už jen mazala z plochy karty (to bys mohl udělat moc
krásně - protože kartu, kterou otočíš, tak vlastně voláš její
referenci tím otočením, tak by sis obě karty mohl ze třídy Plocha vymazat
(na co je někde uchovávat) a skor přičte k dotyčnému bod, dva, pět,
deset.... neznám tvá pravidla.
No a třída skore si bude sama prohazovat podle pravidel hráče. Když budou
obě karty špatně, přepni hráče najěkým booleanem. No a třída Skore by
měla v sobě nějaký delay, než by přepla hráče - tím bys ošetřil to,
že se i tak karty na chvilku zobrazí
A nepotřebuji žádné pole:)
pocitac770 toto som skúšal ako prvé a stane sa to, že sa druhá karta vôbec nezobrazí len nejde na sekundu nič iné stlačiť, teda asi tú kartu ani v danom kóde neodkryjem ale neviem kde je tá chyba.
Lubor Pešek dík za dobré rady, je jasné že každý by to naprogramoval po svojom. Bohužiaľ ten kód je už aspoň 5x dlhší tak už to asi nebudem meniť.
Atrament tu máš tieto http://cec.truni.sk/…esoKarty.rar
pocitac770:10.5.2016 20:09
Trochu bizardní řešení, ale zkus ještě tohle (nevím, jestli fungují klasická vlákna se Swingem, třeba u JavaFX jsou problémy, kdyžtak by se našla alternativní cesta...)
//V metóde actionPerformed povieme, čo sa má stať, keď stlačíme nejaké tlačidlo, teda ak klikneme na kartu pexesa.
public void actionPerformed(ActionEvent e)
{
//PŘIDANÝ KÓD
if(pocetStlacenych == 2)
return;
//PŘIDANÝ KÓD
// Vytvoríme si tlačidlo, do ktorého priradíme údaje o kliknutom tlačidle.
JButton tlačidlo = (JButton) e.getSource();
/*Pomocou cyklu for zistíme, ktoré tlačidlo, teda karta pexesa bola kliknutá. Ak táto karta ešte nie je odkrytá
a zároveň používateľ nekliká stále na tú istú, už otočenú kartu, tak sa nastaví pozícia poslednej kliknutej karty
práve na pozíciu tejto karty, na ktorú používateľ klikol. Karta sa otočí, to znamená že už nevidíme jej obal
ale vidíme jej hraciu časť. Na záver sa uloží, ktorá karta bola otočená, aby sme neskôr mohli zistiť, či nie
je odkrytý pár*/
for (int i = 0; i < 12; i++)
{
if (((tlačidlo).equals(poleTlacidiel[i])) && (napln[i].najdenyPar == false) && (i != kliknutaPozicia))
{
kliknutaPozicia = i;
tlačidlo.setIcon(napln[i].ikona);
if(pocetStlacenych == 0) stlaceneObrazky[0] = i;
if(pocetStlacenych == 1) stlaceneObrazky[1] = i;
pocetStlacenych++;
}
}
/*Ak je počet otočených kariet dva, to znamená, že má program skontrolovať, či netvoria pár. Ak ho tvoria,
počet stlačených kariet sa nastaví na nulu a karty zostanú otočené.*/
if (pocetStlacenych == 2)
{
if ((napln[stlaceneObrazky[0]].cisloObrazku)==(napln[stlaceneObrazky[1]].cisloObrazku))
{
pocetStlacenych = 0;
napln[stlaceneObrazky[0]].najdenyPar = true;
napln[stlaceneObrazky[1]].najdenyPar = true;
kliknutaPozicia = -1;
}
//Ak karty netvoria pár, počet stlačených kariet sa nastaví na nulu a karty sa otočia do pôvodnej pozície
else
{
//PŘIDANÝ KÓD
Thread thread = new Thread(()->{
Thread.sleep(1000);
poleTlacidiel[stlaceneObrazky[0]].setIcon(obal);
poleTlacidiel[stlaceneObrazky[1]].setIcon(obal);
pocetStlacenych = 0;
kliknutaPozicia = -1;
});
thread.start();
//PŘIDANÝ KÓD
}
}
pocitac770:10.5.2016 20:29
Píšu blbosti... to nebude fungovat.... Menší úprava s kompletně celým kódem...
//Importujeme si všetky knižnice, ktoré budeme potrebovať
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.util.*;
/*Trieda pexeso bude dediť z triedy JFrame, pretože budeme vytvárať Panel, a taktiež bude trieda
pexeso implementovať ActionListener, keďže budeme potrebovať udalosť stlačenia tlačidla */
public class Pexeso extends JFrame implements ActionListener
{
//Zadeklarujeme si premennú hlavný panel, ktorá bude reprezentovať naše hlavné hracie okno.
private JPanel hlavnýPanel;
//Zadeklarujeme si pole tlačidiel o veľkosti 12
private JButton[] poleTlacidiel = new JButton[12];
/*Zadeklarujeme si premennú "pocetStlacenych" a priradíme jej hodnotu nula.
Táto premenná bude slúžiť pre návrat dvoch otočených kariet pexesa do pôvodnej pozície.
Ak hráč otočí kartu pexesa, premenná sa zvýši, ak sú otočené dve karty a tieto karty nie sú rovnaké
tak táto premenná nám pomôže pri otáčaní týchto kariet do pôvodnej podoby */
private int pocetStlacenych = 0;
/*Zadeklarujeme a vytvoríme si pole stlaceneObrazky, do ktorého budeme uchovávať čísla dvoch kariet,
ktoré boli otočené.*/
private int[] stlaceneObrazky = new int[2];
//Zadeklarujeme si premennú "obal", ktorá bude uchovávať obrázok obalu pexesových kariet.
ImageIcon obal;
/*Zadeklarujeme a vytvoríme si pole "napln", ktoré nám bude slúžiť na naplnenie hracej plochy
kartami pexesa, kartami, ktoré sa budú odkrývať. Triedu "Naplnenie" si sami vytvoríme.*/
private Naplnenie[] napln = new Naplnenie[12];
/*Zadeklarujeme si premennú "kliknutaPozicia", ktorá bude uchovávať informáciu o tom, ktorá karta bola kliknutá.
Je to dôležité preto, aby hráč nemohol dva krát kliknúť na rovnakú kartu*/
int kliknutaPozicia;
//Vytvoríme si konštruktor Pexeso.
public Pexeso()
{
//Vytvoríme si hlavný panel, na ktorom bude prebiehať hra.
hlavnýPanel = new JPanel();
//Určíme rozloženie tlačidiel, tlačidlá budú predstavovať karty pexesa.
hlavnýPanel.setLayout(new GridLayout(4, 0, 0, 0));
//Načítame obal kariet pexesa.
obal = new ImageIcon(Pexeso.class.getResource("obal.jpg"));
/*Nastavíme kliknutú pozíciu na -1, pretože zatial nie je žiadna karta kliknutá, až keď používateľ
klikne na nejakú kartu, tak sa nastaví jej pozícia do tejto premennej.*/
kliknutaPozicia = -1;
/*Naplníme si pole "napln" objektami triedy Naplnenie. Túto triedu si vytvoríme. Táto trieda nám bude zabezpečovať
načítanie jednotlivých obrázkov pexesa. Vytvorenie objektu vyžaduje jeden číselný argument, pomocou ktorého
každému objektu priradíme číslo, každý objekt bude mať iné číslo.*/
for (int i = 0; i < 12; i++)
{
napln[i] = new Naplnenie(i);
}
/*Zamiešame obrázky v poli tak, že prevedieme naše pole na kolekciu a použijeme metódu kolekcie
pre zamiešanie prvkov.*/
Collections.shuffle(Arrays.asList(napln));
//Nastavíme vlastnosti hracej plochy, to znamená veľkosť a podobne.
add(hlavnýPanel, BorderLayout.CENTER);
setSize(600, 660);
setTitle("Puzzle");
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
//Vytvoríme si 12 tlačidiel a každému priradíme action listenera a ako ikonu mu priradíme načítaný obal.
//To znamená, že po spustení hry bude naše pexeso zakryté, všetky časti budú vyzerať rovnako.
for (int i = 0; i < 12; i++)
{
poleTlacidiel[i] = new JButton();
poleTlacidiel[i].addActionListener(this);
hlavnýPanel.add(poleTlacidiel[i]);
poleTlacidiel[i].setIcon(obal);
}
}
//V metóde main spustíme našu hru.
public static void main(String[] args)
{
new Pexeso();
}
//V metóde actionPerformed povieme, čo sa má stať, keď stlačíme nejaké tlačidlo, teda ak klikneme na kartu pexesa.
public void actionPerformed(ActionEvent e)
{
//PŘIDANÝ KÓD
if(pocetStlacenych == 2){
return;
}
//PŘIDANÝ KÓD
// Vytvoríme si tlačidlo, do ktorého priradíme údaje o kliknutom tlačidle.
JButton tlačidlo = (JButton) e.getSource();
/*Pomocou cyklu for zistíme, ktoré tlačidlo, teda karta pexesa bola kliknutá. Ak táto karta ešte nie je odkrytá
a zároveň používateľ nekliká stále na tú istú, už otočenú kartu, tak sa nastaví pozícia poslednej kliknutej karty
práve na pozíciu tejto karty, na ktorú používateľ klikol. Karta sa otočí, to znamená že už nevidíme jej obal
ale vidíme jej hraciu časť. Na záver sa uloží, ktorá karta bola otočená, aby sme neskôr mohli zistiť, či nie
je odkrytý pár*/
for (int i = 0; i < 12; i++)
{
if (((tlačidlo).equals(poleTlacidiel[i])) && (napln[i].najdenyPar == false) && (i != kliknutaPozicia))
{
kliknutaPozicia = i;
tlačidlo.setIcon(napln[i].ikona);
if(pocetStlacenych == 0) stlaceneObrazky[0] = i;
if(pocetStlacenych == 1) stlaceneObrazky[1] = i;
pocetStlacenych++;
}
}
/*Ak je počet otočených kariet dva, to znamená, že má program skontrolovať, či netvoria pár. Ak ho tvoria,
počet stlačených kariet sa nastaví na nulu a karty zostanú otočené.*/
if (pocetStlacenych == 2)
{
if ((napln[stlaceneObrazky[0]].cisloObrazku)==(napln[stlaceneObrazky[1]].cisloObrazku))
{
pocetStlacenych = 0;
napln[stlaceneObrazky[0]].najdenyPar = true;
napln[stlaceneObrazky[1]].najdenyPar = true;
kliknutaPozicia = -1;
}
//Ak karty netvoria pár, počet stlačených kariet sa nastaví na nulu a karty sa otočia do pôvodnej pozície
else
{
//PŘIDANÝ KÓD
Pexeso pex = this;
Thread thread = new Thread(()->{
try{
Thread.sleep(1000);
}
catch(Exception e){
}
pex.zakryt();
});
thread.start();
//PŘIDANÝ KÓD
}
}
}
//PŘIDANÝ KÓD
public void zakryt(){
poleTlacidiel[stlaceneObrazky[0]].setIcon(obal);
poleTlacidiel[stlaceneObrazky[1]].setIcon(obal);
pocetStlacenych = 0;
kliknutaPozicia = -1;
}
//PŘIDANÝ KÓD
}
+20 Zkušeností
+2,50 Kč
pocitac770:11.5.2016 7:30
Nemáš zač, docela se ale divím, že učení přímo oboru je tak jednoduché, vidno na vytvářených pracích
Ondřej Krsička:11.5.2016 8:13
Jen bych dodal, že komentářů je tam až moc a dost jich je zbytečných. Např.
//Vytvoríme si hlavný panel, na ktorom bude prebiehať hra.
hlavnýPanel = new JPanel();
no myslím, že komentářem nikdy nic nezkazíš. Když nechceš vidět
komentáře, otevři si zdroják v oracle dokumentaci:)
spíš je blbé, že používáš jen jeden druh komentáře - řádkový.
Dokumentační a obecný nemáš ani jeden:(
Zobrazeno 13 zpráv z 13.