NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: OOP problem

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
dzavatar.peto:4.9.2017 20:24

Ahojte,

snažím sa pochopiť princípu OOP, preto som si vymyslel že skúsim naprogramovať PACMANA. Vytvoril som si preto dve triedy - Gulicka (cize pacman) a HraciaPlocha (miesto kde sa pacman pohybuje) Hraciu plochu tvorí dvojrozmerné pole určitej veľkosti naplnené znakom "+". Miesto kde sa pacman nachádza si značím znakom "A". Ak teda šípkou pohnem pacmanom mapríklad doprava tak pacman sa pohne v poli z pozície [0][0] na pozíciu [0][1]. neviem ale kde mam chybu a stále keď stlačím dannú šípku tak dostanem chybu:

Exception in thread "AWT-EventQueue-0" java.lang.NullPo­interException
at pacman.Gulicka­.keyPressed(Gu­licka.java:47)
at java.awt.Compo­nent.processKe­yEvent(Componen­t.java:6491)
at javax.swing.JCom­ponent.proces­sKeyEvent(JCom­ponent.java:2832)
at java.awt.Compo­nent.processE­vent(Componen­t.java:6310)
at java.awt.Conta­iner.processE­vent(Container­.java:2236)
at java.awt.Compo­nent.dispatchE­ventImpl(Compo­nent.java:4889)
at java.awt.Conta­iner.dispatchE­ventImpl(Conta­iner.java:2294)
at java.awt.Compo­nent.dispatchE­vent(Componen­t.java:4711)
at java.awt.Keybo­ardFocusManager­.redispatchEven­t(KeyboardFocus­Manager.java:1954)
at java.awt.Defau­ltKeyboardFocus­Manager.dispat­chKeyEvent(De­faultKeyboardFo­cusManager.ja­va:806)
at java.awt.Defau­ltKeyboardFocus­Manager.preDis­patchKeyEvent(De­faultKeyboardFo­cusManager.ja­va:1074)
at java.awt.Defau­ltKeyboardFocus­Manager.typeA­headAssertion­s(DefaultKeybo­ardFocusManager­.java:945)
at java.awt.Defau­ltKeyboardFocus­Manager.dispat­chEvent(Defau­ltKeyboardFocus­Manager.java:771)
at java.awt.Compo­nent.dispatchE­ventImpl(Compo­nent.java:4760)
at java.awt.Conta­iner.dispatchE­ventImpl(Conta­iner.java:2294)
at java.awt.Window­.dispatchEven­tImpl(Window.ja­va:2746)
at java.awt.Compo­nent.dispatchE­vent(Componen­t.java:4711)
at java.awt.Even­tQueue.dispat­chEventImpl(E­ventQueue.java:758)
at java.awt.Even­tQueue.access$500(E­ventQueue.java:97)
at java.awt.Even­tQueue$3.run(E­ventQueue.java:709)
at java.awt.Even­tQueue$3.run(E­ventQueue.java:703)
at java.security­.AccessContro­ller.doPrivile­ged(Native Method)
at java.security­.ProtectionDo­main$JavaSecu­rityAccessImpl­.doIntersecti­onPrivilege(Pro­tectionDomain­.java:80)
at java.security­.ProtectionDo­main$JavaSecu­rityAccessImpl­.doIntersecti­onPrivilege(Pro­tectionDomain­.java:90)
at java.awt.Even­tQueue$4.run(E­ventQueue.java:731)
at java.awt.Even­tQueue$4.run(E­ventQueue.java:729)
at java.security­.AccessContro­ller.doPrivile­ged(Native Method)
at java.security­.ProtectionDo­main$JavaSecu­rityAccessImpl­.doIntersecti­onPrivilege(Pro­tectionDomain­.java:80)
at java.awt.Even­tQueue.dispat­chEvent(EventQu­eue.java:728)
at java.awt.Even­tDispatchThre­ad.pumpOneEven­tForFilters(E­ventDispatchThre­ad.java:201)
at java.awt.Even­tDispatchThre­ad.pumpEventsFor­Filter(EventDis­patchThread.ja­va:116)
at java.awt.Even­tDispatchThre­ad.pumpEventsFor­Hierarchy(Even­tDispatchThre­ad.java:105)
at java.awt.Even­tDispatchThre­ad.pumpEvents(E­ventDispatchThre­ad.java:101)
at java.awt.Even­tDispatchThre­ad.pumpEvents(E­ventDispatchThre­ad.java:93)
at java.awt.Even­tDispatchThre­ad.run(EventDis­patchThread.ja­va:82)

Stačilo by mi ak mi niekto vysvetlíte, ako dosiahnuť, aby sa mi to "A" prepísalo na poziciu ktorú mam natvrdo zadanú tak ako to robím v mojom príklade. Ja si to uz potom pomocou podmienok prisposobim podla seba.. Pomohol by mi aj nejaký článok alebo kniha kde je táto problematika zrozumiteľnejšie vysvetlená.

prikladám kódy jednotlivých tried a triedy main.

trieda main

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pacman;

/**
 *
 * @author peter.porubsky
 */
public class Okno extends javax.swing.JFrame {

    Gulicka gulicka1;

    public Okno() {
        initComponents();


        Gulicka gulicka1=new Gulicka(0,0, this);
        this.add(gulicka1);
        HraciePole pole1=new HraciePole(6,6);



        pole1.vypisHraciePole();





    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Okno.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Okno.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Okno.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Okno.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Okno().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify
    // End of variables declaration
}

trieda Gulicka

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pacman;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComponent;
import javax.swing.JFrame;

/**
 *
 * @author peter.porubsky
 */
public class Gulicka extends JComponent implements KeyListener{

    private JFrame mojeOkno;
    public HraciePole hraciePole;


     public Gulicka(int x,int y, JFrame mojeOkno) {
        setBounds(x, y, 30, 30);
        addKeyListener(this);
        setFocusable(true);
        this.mojeOkno = mojeOkno;



    }


    @Override
    public void keyTyped(KeyEvent ke) {

    }

    @Override
    public void keyPressed(KeyEvent ke) {
       int x=getX();
       int y=getY();
        switch (ke.getKeyCode()){
            case KeyEvent.VK_UP :
               hraciePole.nastavPolohu(0,3);
                break;


            case KeyEvent.VK_DOWN:

                 break;


            case KeyEvent.VK_RIGHT:

                break;


            case KeyEvent.VK_LEFT:

                break;
    }
    }

    @Override
    public void keyReleased(KeyEvent ke) {

    }

}

trieda HraciePole

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pacman;

/**
 *
 * @author peter.porubsky
 */
public class HraciePole {

    private final String[][] hraciePole;
    int indexI;
    int indexJ;


    public HraciePole(int a, int b){
        hraciePole=new String[a][b];
        for(int i=0;i<hraciePole.length;i++){
           for (int j=0;j<hraciePole.length;j++){

              hraciePole[i][j]="+";


           }
       }


    }

    public void vypisHraciePole(){
        for(int i=0;i<hraciePole.length;i++){
           for (int j=0;j<hraciePole.length;j++){

              System.out.print(hraciePole[i][j]);
            }
           System.out.println();
       }
    }

    public void nastavPolohu(int a, int b){
        hraciePole[a][b]="A";
    }

    public int zistiAktualneI(){

        for(int i=0;i<hraciePole.length;i++){
           for (int j=0;j<hraciePole.length;j++){

              if(hraciePole[i][j].equals("A")){
                 indexI=i;
              }
            }

       }
        return indexI;
    }

    public int zistiAktualneJ(){
         for(int i=0;i<hraciePole.length;i++){
           for (int j=0;j<hraciePole.length;j++){

              if(hraciePole[i][j].equals("A")){
                 indexJ=j;
              }
            }

       }
        return indexJ;
    }

}

Ďakujem za každú pomoc

Peter

 
Odpovědět
4.9.2017 20:24
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:4.9.2017 20:50

Čus,

tak si to zkouším u sebe, nějak mě to sice nejde, nicméně chyba je jednoznačná (dík za výpis)
Píše to, že ve třídě Gulicka na 47 řádku našel objekt null pointer. To je jasné - ve třídě Gulicka odkazuješ na atribut hraciePole, ale nikde jej nenaplňuješ a třída Gulicka jej jednoduše nezná - proto ta exceptiona

Nahoru Odpovědět
4.9.2017 20:50
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na dzavatar.peto
Atrament:4.9.2017 21:05

Nemáš ve třídě Gulicka nijak inicializovanou proměnnou hraciePole, takže když na řádku 47 provádíš

hraciePole.nastavPolohu(0,3);

tak to spadne s NullPointerEx­ception, protože hraciePole je v ten okamžik null. Což je to co ti říkají první dva řádky chybového výstupu co jsi postnul:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at pacman.Gulicka.keyPressed(Gulicka.java:47)

Musíš někde napřed vytvořit novou instanci třídy HraciePole a s tou pak pracovat - jednu takovou vytváříš ve třídě Okno - to pole1, stačilo by zřejmě pak provést tohle:

...třída Okno...
Gulicka gulicka1=new Gulicka(0,0, this);
this.add(gulicka1);
HraciePole pole1=new HraciePole(6,6);
gulicka1.hraciePole = pole1; //jelikož máš hraciePole v Gulicka definované jako public tak můžeš udělat takto

nicméně z hlediska OOP návrhu to celé nemáš zrovna dobře navržené, bohužel bych musel napsat docela obsáhlý elaborát co všechno je špatně a jak to udělat správně, a na to teď nemám bohužel čas mám na krku dost šibeniční deadline :) Ale on se určitě najde někdo kdo ti to vysvětli za mně (Lubor Pešek;)

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
4.9.2017 21:05
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:4.9.2017 21:14

Ale je tu spousta dalších věcí....
předně supr, že se snažíš o OOP, používáš balíky, dědičnost, rozhraní... všechno bezva
Ale mám minimálně 3 výhrady (projíždím to jen zběžně)

  1. nenech si generovat kód od netbeansů, je to blbost a pak ti to udělá neplechu. Je lepší si vše napsat a nastavit, jak potřebuješ
  2. nepoužívej posluchače, ale radši adapter

Adapter je návrhový vzor, který právě zpřehledňuje posluchače. Abys implementoval posluchače, musíš (protože je to rozhraní) implementovat všechny jeho metody. Ale jelikož je málo kdy využiješ úplně všechny, tak existuje tzv. Adaptér. Je to speciální případ abstraktní třídy, který je přímo v knihovně java.awt.event.
Jde o to, že adapter implementuje naprázdno všechny třídy, které rozhraní listenera vyžaduje. Ty si jen zavoláš tu metodu, kterou chceš už překrýt.

Navíc není třeba tuto abstraktní třídu na tvrdo dědit, stačí ji dobře definovat v kódu. Pochopitelně ti postnu i ukázku:

MOUSE ADAPTER

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComponent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.Color;
import java.awt.Graphics;

public class MouseAdapterExample extends JFrame {

    private JPanel panel;

    public MouseAdapterExample() {
        init();
        addMouseAdapter();
    }

    private void init() {
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 500);
        setLocationRelativeTo(null);

        panel = new JPanel();
        panel.setSize(500, 500);
        add(panel);
        panel.setLayout(null);
        panel.setBackground(Color.WHITE);
    }

    private void addMouseAdapter() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent evt) {
                Circle circle = new Circle();
                circle.setSize(10, 10);
                circle.setLocation(evt.getX() - circle.getWidth() / 2, evt.getY() - circle.getHeight() / 2);
                panel.add(circle);
                panel.repaint();
            }
        });
    }

    public static void main(String[] args) {
        new MouseAdapterExample();
    }

    private class Circle extends JComponent {

        @Override
        public void paint(Graphics g) {
            g.setColor(Color.GREEN);
            g.fillOval(0, 0, getWidth(), getHeight());
        }
    }
}

KEY ADAPTER

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComponent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Color;
import java.awt.Graphics;

public class KeyAdapterExample extends JFrame {

    private JPanel panel;
    private Circle circle;

    public KeyAdapterExample() {
        init();
        addKeyAdapter();
        circle = new Circle();
        circle.setSize(10, 10);
        circle.setLocation(250, 250);
        panel.add(circle);
    }

    private void init() {
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 500);
        setLocationRelativeTo(null);

        panel = new JPanel();
        panel.setSize(500, 500);
        add(panel);
        panel.setLayout(null);
        panel.setBackground(Color.WHITE);
    }

    private void addKeyAdapter() {
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent evt) {
                switch (evt.getKeyCode()) {
                    case 37:
                        circle.moveLeft();
                        break;
                    case 38:
                        circle.moveUp();
                        break;
                    case 39:
                        circle.moveRight();
                        break;
                    case 40:
                        circle.moveDown();
                        break;
                    default:
                        System.err.println("Tož sorry, tento pohyb neznám:(");
                }
            }
        });
    }

    public static void main(String[] args) {
        new KeyAdapterExample();
    }

    private class Circle extends JComponent {

        private int pohyb = 50;

        @Override
        public void paint(Graphics g) {
            g.setColor(Color.GREEN);
            g.fillOval(0, 0, getWidth(), getHeight());
        }

        private void moveLeft() {
            setLocation(getX() - pohyb, getY());
        }

        private void moveUp() {
            setLocation(getX(), getY() - pohyb);
        }

        private void moveRight() {
            setLocation(getX() + pohyb, getY());
        }

        private void moveDown() {
            setLocation(getX(), getY() + pohyb);
        }
    }
}
Nahoru Odpovědět
4.9.2017 21:14
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
dzavatar.peto:4.9.2017 22:17

Ďakujem za vaše rady. Budem sa snažiť použiť ich pri ďalších príkladoch. Ano snažím sa programovať objektovo ale zatiaľ mi to ešte nejak nejde. Prešiel som si lekcie aj príklady tu z ITNETWORK fora a teraz skušam pratkticky to dostať do hlavy. No začiatky sú ťažké.

Skúšal som spraviť zmeny ktoré poradil Atrament a fungujú, takže idem ďaľej zveľaďovať môjho Pacmana - nech už je objektovo aký je :) Budem múdrejší dobudúcna ;)

 
Nahoru Odpovědět
4.9.2017 22:17
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.