Java Swing, aplikacja kółko i krzyżyk, problem z przekazaniem wartości do JPanela

0

Cześć, próbuję napisać grę kółko i krzyżyk. Stworzyłem 9 JPaneli w których po kliknięciu rysuje się kółko lub krzyżyk. To czy pojawi się kółko czy krzyżyk zależy od licznika kliknięć (liczba parzysta krzyżyk, nieparzysta kółko. Problem z którym walczę to właśnie ten licznik. Najpierw zrobiłem go wewnątrz tych 9 paneli, zliczał kliknięcia a później przekazywał wartość do PaintComponent gdzie rysowało się kółko lub krzyżyk. Jednak problemem było to, że naciśnięcie każdego przycisku zliczało się osobno. Spróbowałem więc przenieść liczenie kliknięć w miejsce gdzie wywołuję te 9 paneli. Zadziałało nieźle, bo kliknięcia zliczają się odpowiednio.
W tym momencie mam problem z przekazaniem wartości kliknięć z powrotem do JPaneli na które klikam i w których wywołuję PaintComponent.

Zakładam, że to przez to, że każde kliknięcie od nowa wywołuje klasę MainPanel, jednak nie wiem jak przekazać tą wartość w inny sposób.

Bardzo proszę o pomoc.

package XO;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import javax.swing.JPanel;
/**
 *
 * @author MJ
 */
public class XOJPanel extends JPanel implements MouseListener{

    private int var;

    public XOJPanel() {
        addMouseListener(this);
    }

    @Override
    public void mouseClicked(MouseEvent me) {}    

    @Override
    public void mousePressed(MouseEvent me) {
        MainPanel mp = new MainPanel();
        mp.getVar();
        System.out.println(var);
        repaint();
    }

    @Override
    public void mouseReleased(MouseEvent me) {}

    @Override
    public void mouseEntered(MouseEvent me) {}

    @Override
    public void mouseExited(MouseEvent me) {}

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        if (var%2 == 0 && var > 0 ) {
            DrawX(g2d);
        }
        if (var%2 == 1) {
            DrawO(g2d);
        }

    }

    private void DrawX(Graphics2D g2d) {
        int x,y;
        x = this.getWidth();
        y = this.getHeight();
        g2d.draw(new Line2D.Double(0,0,x,y));
        g2d.draw(new Line2D.Double(0,y,x,0));
    }

    private void DrawO(Graphics2D g2d) {
        int x,y;
        x = this.getWidth();
        y = this.getHeight();
        g2d.draw(new Ellipse2D.Double(0,0,x-1,y-1));
    }

}
package XO;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.JPanel;
/**
 *
 * @author MJ
 */
public class MainPanel extends JPanel{

    private int var;

    ArrayList<XOJPanel> panels = new ArrayList<XOJPanel>();

    public MainPanel() {
        setLayout(new GridLayout(3, 3, 20, 20));
        setSize(300,300);
        setLocation(800/2 - 150, 600/2 - 150);

        for (int i = 0; i < 9; i++) {
            panels.add(new XOJPanel());
            add(panels.get(i));    
            panels.get(i).addMouseListener(new clickCounter());
        }
    }

    private class clickCounter implements MouseListener {

        @Override
        public void mouseClicked(MouseEvent me) {}

        @Override
        public void mousePressed(MouseEvent me) {
            var++;
            System.out.println(var);
            repaint();
        }

        @Override
        public void mouseReleased(MouseEvent me) {}

        @Override
        public void mouseEntered(MouseEvent me) {}

        @Override
        public void mouseExited(MouseEvent me) {}
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        Line2D line1 = new Line2D.Double(0, 100, 300, 100);
        Line2D line2 = new Line2D.Double(0, 200, 300, 200);
        Line2D line3 = new Line2D.Double(100, 0, 100, 300);
        Line2D line4 = new Line2D.Double(200, 0, 200, 300);

        g2d.draw(line1);
        g2d.draw(line2);
        g2d.draw(line3);
        g2d.draw(line4);
    }

    public int getVar() {
        return var;
    }

}
package XO;

import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 *
 * @author MJ
 */
public class MainFrame extends JFrame{

    public MainFrame() {
        super("Kółko i krzyżyk");
        setLayout(null);
        JPanel mainPanel = new MainPanel();
        add(mainPanel);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
        setSize(800,600);   
    }

}
package XO;
/**
 *
 * @author MJ
 */

import java.awt.EventQueue;

public class XO {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MainFrame();
            } 
        });

    }

}
1

W swingu to ja nie piszę ale pewnie jakbyś tak chamsko do konstruktora XOJPanel wrzucił MainPanel a potem robił tak w MainPanel:

 for (int i = 0; i < 9; i++) {
            panels.add(new XOJPanel(this));
            add(panels.get(i));    
            panels.get(i).addMouseListener(new clickCounter());
        }

to wywołując paintComponent w XOJPanel mógłbyś zrobić tak:

int count = mainPanel.getVar();

I potem już rysować na tej podstawie jak Ci to zwróci.

Natomiast moim zdaniem jest to słabe rozwiązanie i w ogóle sama idea z parzystością jest trochę słaba bo np.:

  1. Co się stanie jak ktoś kliknie 2 razy w to samo pole? Czy figura czasami się nie nadpisze a counter nie zrobi +2?
  2. Co jeśli chciałbyś wprowadzić bota do gry? On nie będzie klikał tylko rysował figury więc Twój counter nie zadziała (no chyba że będziesz kombinował i sam rzucał zdarzenia kliknięcia).
  3. Co jeśli chciałbyś ulepszyć gre i pozwolić użytkownikowi na starcie wybrać jakiego rodzaju figury/obrazki chce używać? Np. zamiast X i O grać kotem i psem lub innymi.

Nie korzystam ze Swinga ale wydaje mi się że XOJPanel w tym przypadki to tak naprawdę tylko komponent który ma narysować X lub Y (lub inne figury) i tu jego odpowiedzialność się kończy. Powinien wiedzieć jak ma coś narysować i tyle. Co będzie rysował powinno przyjść z góry jako gotowy element do narysowania. Wówczas nawet jak dodasz boty, różne figury, jakieś usprawnienia to XOJPanel będzie to nadal rysował tak jak ktoś mu nakaże (w tym przypadku MainPanel). Cała logika tego czyj teraz jest ruch (jednego z dwóch graczy, gracza lub bota) a co za tym idzie co narysować pozostaje w MainPanelu albo klasach wyodrębnionych do wykonywania tej logiki na potrzeby tego Panelu.

0

Stawiam pierwsze kroki w programowaniu i takie rady są bardzo cenne. Wielkie dzięki, przemyślę i spróbuję zrobić to inaczej.

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