Witam wszystkich.
Piszę program w którym obiekty (każdy jest osobnym wątkiem) poruszają się na mapie robiąc ruch w górę, prawo, dół lub lewo - o jedną pozycję. Swoją mapę zorganizowałem na dwuwymiarowej tablicy intów, którą opakowałem klasą Przestrzen. Wszystkie metody klasy Przestrzen które operują na tablicy są synchronizowane, a zadania takie jak wykonanie kroku polegające na zmianie swojej pozycji i zwolnieniu poprzedniej zamknięte są w pojedyncze metody, aby tablica nie utraciła spójności.
Problem polega jednak na tym, że pomimo tego wszystkiego obiekty "wchodzą na siebie". Nie umiem stwierdzić czy problem leży po stronie logiki programu (i synchronizacji) czy może np. po stronie GUI?
Poniżej zamieszczam możliwe najkrótszy kod czterech klas, aby zaprezentować sytuację.
Utworzona plansza ma wymiar 3x2 i tworzę 5 obiektów, zatem zawsze dokładnie tylko jedno pole powinno być wolne.
Klasa Glowna
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Glowna extends JFrame {
Rysowanie mojPanel;
public Glowna() {
initUI();
}
public void initUI() {
mojPanel = new Rysowanie();
getContentPane().add(mojPanel);
setTitle("Przyklad");
setSize(300, 300);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
new Thread(mojPanel).start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Glowna obj = new Glowna();
}
});
}
}
Klasa Rysowanie:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Rysowanie extends JPanel implements Runnable{
int pozycja;
Przestrzen przestrzen;
public Rysowanie() {
przestrzen = new Przestrzen(3, 2);
for (int i=0; i < 5; i++) {
new Kura(this, przestrzen);
}
}
public void nowaPozycja(int pozycja) {
this.pozycja = pozycja;
System.out.println(pozycja);
}
public void paintComponent (Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int kodObiektu;
System.out.println(przestrzen.y);
for (int i=0; i < przestrzen.x; i++) {
for (int j=0; j < przestrzen.y; j++) {
kodObiektu = przestrzen.pobierzKodObiektuZPozycji(i,j);
if (kodObiektu == 0){
// tlo
g2d.setColor(Color.GRAY);
g2d.fillRect(30 * i, 30 * j, 30, 30);
}
else if (kodObiektu == 1) {
// kura
g2d.setColor(Color.GREEN);
g2d.fillRect(30 * i, 30 * j, 30, 30);
}
}
}
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
repaint();
}
}
}
Klasa Przestrzen:
import java.util.Random;
public class Przestrzen {
int x;
int y;
int plansza[][];
Random generator;
public Przestrzen(int x, int y) {
this.x = x;
this.y = y;
plansza = new int[x][y];
generator = new Random();
}
public synchronized int[] utworzObiektNaPlanszy(int typObiektu) {
int pozycjaX = -1;
int pozycjaY = -1;
boolean wolneMiejsce = false;
while(!wolneMiejsce) {
pozycjaX = generator.nextInt(x);
pozycjaY = generator.nextInt(y);
if (plansza[pozycjaX][pozycjaY] == 0) {
wolneMiejsce = true;
}
}
int uzyskanaPozycja[] = new int[2];
uzyskanaPozycja[0] = pozycjaX;
uzyskanaPozycja[1] = pozycjaY;
// Po znalezieniu wolnego miejsca obiekt jest umieszczany na planszy
plansza[pozycjaX][pozycjaY] = typObiektu;
return uzyskanaPozycja;
}
public synchronized int pobierzKodObiektuZPozycji(int x, int y) {
return plansza[x][y];
}
public synchronized int[] wykonajKrokNaPlanszy(int typObiektu, int[] poprzedniaPozycja) {
int poprzedniX = poprzedniaPozycja[0];
int poprzedniY = poprzedniaPozycja[1];
int nowaPozycja[] = new int[2];
// przepisanie poprzednich wartosci, ktore w razie powodzenia zostana nadpisane
nowaPozycja[0] = poprzedniX;
nowaPozycja[1] = poprzedniY;
int kierunek = generator.nextInt(4);
/*
* 0 - gora
* 1 - prawo
* 2 - dol
* 3 - lewo
*/
if (kierunek == 0) {
if (poprzedniX - 1 >= 0){
nowaPozycja[0]--;
}
}
else if (kierunek == 1) {
if (poprzedniY + 1 < y) {
nowaPozycja[1]++;
}
}
else if (kierunek == 2) {
if (poprzedniX + 1 < x) {
nowaPozycja[0]++;
}
}
else if (kierunek == 3) {
if (poprzedniY - 1 >= 0) {
nowaPozycja[1]--;
}
}
// Zwolenienie poprzedniego miejsca
plansza[poprzedniX][poprzedniY] = 0;
// Przeniesienie na nowa pozycje
plansza[nowaPozycja[0]][nowaPozycja[1]] = typObiektu;
return nowaPozycja;
}
}
Klasa Kura:
import java.util.Random;
public class Kura extends Thread {
Rysowanie panel;
Przestrzen przestrzen;
int[] wlasnaPozycja;
public Kura(Rysowanie panel, Przestrzen przestrzen) {
this.panel = panel;
this.przestrzen = przestrzen;
wlasnaPozycja = new int[2];
wlasnaPozycja = przestrzen.utworzObiektNaPlanszy(1);
System.out.println(wlasnaPozycja[0] + "=" + wlasnaPozycja[1]);
start();
}
public void run() {
while(true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
wlasnaPozycja = przestrzen.wykonajKrokNaPlanszy(1, wlasnaPozycja);
System.out.println("Watek uruchomiony");
}
}
}