Wielowątkowość - dziwna sytuacja

0

Program to okno aplikacji w którym podane są pola które zależnie od prawdopodobieństwa zmieniają swój kolor w jakiś sposób. Nie wiem dlaczego niektóre piksele umierają. Można to sprawdzić przy podanym prawdopodobieństwie równym 0, oraz o to dlaczego tak dziwnie się one zmieniają, gdy brana jest średnia kolorów sąsiadów. Pewnie chodzi tutaj o synchronizacje. Nie potrafię poradzić sobie z tym problemem.

import java.awt.*;
import java.util.*;

import javax.swing.*;

/**
 * 
 * Glowna klasa tworzaca watki
 *
 */
public class Plansza extends JPanel {
	/**
	 * Generator liczb losowych
	 */
	Random generator = new Random();
	/**
	 * obiekty watkow
	 */
	pole pola[][];
	/**
	 * Pamiec liczby wierszy i kolumn
	 */
	int maxx,maxy;
	
	/**
	 * 
	 * Klasa watkow
	 *
	 */
	public class pole extends Thread{
		/**
		 * obiekt okienka
		 */
		JLabel figura;
		/** obiekt panelu to ktorego dodwane sa okna*/
		JPanel panel;
		/** czas zmieniania sie koloru okna*/
		int czas;
		/** prwdopodobienstwo zmiany koloru*/
		double prawdo;
		/** zmienna sluzaca do synchronizacji*/
		boolean running;
		/** zmienne zapisujace polozenie okienka w panelu */
		int m, n, k;
		/**
		 * Konstruktor pola
		 * @param x zmienna panelu do ktorego sie odwoluje
		 * @param k zmienna czasu zmiany koloru
		 * @param p prawdopodobienstwo zmiany koloru
		 * @param m wiersz w ktorym znajduje sie okno
		 * @param n kolumna w ktorej znajduje sie okno
		 */
		pole(JPanel x,int k, double p,int m,int n){
			this.m=m;
			this.n=n;
			this.k=k;
			panel=x;
			figura = new JLabel();
			figura.setOpaque(true);
			figura.setBackground(new Color(generator.nextInt(255),generator.nextInt(255),generator.nextInt(255)));
			panel.add(figura);
			czas = ((int)(((generator.nextDouble()+0.5)*1000))*k);
			prawdo=p;
			running = true;
			
		}
		/**
		 * funckcja uruchamiajaca watki
		 */
		public void run(){
			while(running){
				if(generator.nextDouble()<=prawdo){
					figura.setBackground(new Color(generator.nextInt(255),generator.nextInt(255),generator.nextInt(255)));
				}else {
					Color a,b,c,d;
					int p1,p2,p3,p4;
					
					if(n<maxx-1) p1=n+1;
					else p1=0;
					
					if(n!=0) p2=n-1;
					else p2=maxx-1;
							
					if(m<maxy-1) p3=m+1;
					else p3=0;
					
					if(m!=0) p4=m-1;
					else p4=maxy-1;
					pola[m][p1].running=false;
					pola[m][p2].running=false;
					pola[p3][n].running=false;
					pola[p4][n].running=false;
					
					a=pola[m][p1].figura.getBackground();
					b=pola[m][p2].figura.getBackground();
					c=pola[p3][n].figura.getBackground();
					d=pola[p4][n].figura.getBackground();
					
					figura.setBackground(new Color((a.getRed()+b.getRed()+c.getRed()+d.getRed())/4,(a.getBlue()+b.getBlue()+c.getBlue()+d.getBlue())/4,(a.getGreen()+b.getGreen()+c.getGreen()+d.getGreen())/4));
					
					pola[m][p1].running=true;
					pola[m][p2].running=true;
					pola[p3][n].running=true;
					pola[p4][n].running=true;
				}
				
				try {
					sleep(pola[m][n].czas);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				czas = ((int)(((generator.nextDouble()+0.5)*1000))*k);
			}
		}
	}
	/**
	 * konstruktor planszy tworzaca okna
	 * @param m liczba wierszy
	 * @param n liczba kolumn
	 * @param k czas zmiany
	 * @param p prawdopodobienstwo zmiany koloru
	 */
	Plansza(int m,int n, int k,double p){
		this.maxy=m;
		this.maxx=n;
		setLayout(new GridLayout(m,n));
		pola = new pole[m][n];
		for (int i=0;i<m;++i){
			for(int j=0;j<n;++j){
				pola[i][j]=new pole(this,k,p,i,j);
			}
		}
		for (int i=0;i<m;++i)
			for(int j=0;j<n;++j)
				pola[i][j].start();
				
	}

		
}
/**
* @author  kamaz08
* @version 1.1
* @since   2015-06-01 
*/
import java.awt.*;
import java.util.*;

import javax.swing.*;

/**
 * Klasa uruchamiajaca aplikacje i pobierajaca argumenty 
 * 
 *
 */
public class ProgramGUI extends JApplet {
	/** Obiekt planszy */
	Plansza x;
	/** Obiekt okna */
	JFrame rama;
	
	/**
	 * Funkcja uruchamiajaca aplikacje
	 * @param m liczba wierszy
	 * @param n	liczba kolumn
	 * @param k czas zmiany
	 * @param p prawdopodobienstwo wybrania koloru
	 */
	public ProgramGUI(int m, int n, int k, double p){
		rama=new JFrame("kamaz08");
		rama.setSize(500,500);
		rama.setVisible(true);
		rama.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		rama.setLocationRelativeTo(null); //tworzy okno na srodku ekranu
		x = new Plansza(m,n,k,p);
		rama.add(x);
	}
	/**
	 * Funkcja startowa aplikacji pobierajaca parametry
	 * @param args argumenty uruchomienia
	 */
	public static void main(String args[]){
		int n,m,k;
		double p;
		if(args[0]==null) m=10;
		else m=Integer.parseInt(args[0]); //liczba wierszy
		if(args[1]==null) n=10;
		else n=Integer.parseInt(args[1]); //liczba kolumn
		if(args[2]==null) k=10;
		else k=Integer.parseInt(args[2]);
		if(args[3]==null) p=0.8;
		else p=Double.parseDouble(args[3]);
		ProgramGUI okno = new ProgramGUI(m,n,k,p);
	}

}
0

dosc nieciekawa historia musze przyznac, paskudny kod z wieloma problemami. domyslam sie ze jednak nie chodzilo ci o wyrazy wspolczucia, napisz jakie masz pytanie (pytania?), ale bardziej konkretnie.

0

Dobra to może mi powiesz jakie błędy są, to od razu się nauczę ich nie popełniać.

A więc do rzeczy przejdę. W parametrach uruchamiających są 4 liczby ilość kolumn, wierszy, czas co jaki ma się zmieniać oraz prawdopodobieństwo. Z prawdopodobieństwem p zmieniamy kolor na losowy, a z prawdopodobieństwem 1-p na średnią kolorów sąsiadów.
I jeżeli ustawimy p=0. Czyli na kolor sąsiadów to robi się taka kratka, a nie rozmycie.

Tutaj załatwiłem ten problem w taki sposób. Po prostu nie uwzględniłem jednej rzeczy. Jeżeli zablokuję sąsiada i pobiorę kolor, to nie wiedziałem czy już ktoś też od tego sąsiada nie pobiera koloru.

0

Z podobnym problemem spotkał się pan z tego nagrania >

W dużym skrócie każda komórka powinna posiadać "pamięć" swoich stanów.

0

ok:

  1. podziel to jakos sensownie na metody a nie ze robisz copy-paste i/lub pakujesz wszystko w jedna duza metode
  2. pole jest watkiem? mysle ze nie powinno, niech watek bedzie watkiem a pole polem (t.j. rozdziel te dwie odpowiedzialnosci)
  3. pogogluj jak w swingu aktualizowac kontrolki w srodowisku wielowatkowym
  4. a najlepiej to nie operuj na elementach UI tylko na polach, gui aktualizuj niezaleznie
  5. sensownie nazywaj skladowe zamiast pisac komentarze, a takie typu 'konstruktor' albo 'generator liczb losowych' sobie po prostu daruj bo nic nie wnosza
  6. co sie da zrob final
0

Metoda main to jeden wielki wtf. args[0] nigdy nie jest nullem.

    public static void main(String args[])
    {
        int n,m,k;
        double p;
        if(args.length == 0) m=10;
        else m=Integer.parseInt(args[0]); //liczba wierszy
        if(args.length < 2) n=10;
        else n=Integer.parseInt(args[1]); //liczba kolumn
        if(args.length < 3) k=10;
        else k=Integer.parseInt(args[2]);
        if(args.length < 4) p=0.8;
        else p=Double.parseDouble(args[3]);
        ProgramGUI okno = new ProgramGUI(m,n,k,p);
    }

Wypadałoby jeszcze dodać obsługę błędów i sformatować kod.

0

Błędem okazało się źle wprowadzane dane. Ustawiając kolor, podawałem RBG zamiast RGB i wynikiem tego była ta siatka. Wiem że przyczyną tego był sposób zapisu mojego programu. Teraz co nieco pozmieniałem. Nic nie znalazłem o tych kontrolkach w swingu :(

import javax.swing.JApplet;
import javax.swing.JFrame;
public class ProgramGUI extends JApplet {
	Plansza x;
	JFrame rama;
	
	public ProgramGUI(int m, int n, int k, double p){
		rama=new JFrame("XYX");
		rama.setSize(500,500);
		rama.setVisible(true);
		rama.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		rama.setLocationRelativeTo(null); //tworzy okno na srodku ekranu
		x = new Plansza(m,n,k,p);
		rama.add(x);
	}
	public static void main(String args[]){
		int n,m,k;
		double p;
		if(args.length == 0) m=10;
        else m=Integer.parseInt(args[0]); //liczba wierszy
        if(args.length < 2) n=10;
        else n=Integer.parseInt(args[1]); //liczba kolumn
        if(args.length < 3) k=1;
        else k=Integer.parseInt(args[2]);
        if(args.length < 4) p=0;
        else p=Double.parseDouble(args[3]);
        new ProgramGUI(m,n,k,p);
	}

}
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Plansza extends JPanel{
	double prawdo;
	Pole pole[][];
	JLabel Label[][];
	int y,x;
	
	Plansza(int m, int n, int k, double p){
		setLayout(new GridLayout(m,n));
		y=m;
		x=n;
		prawdo=p;
		pole=new Pole[m][n];
		Label=new JLabel[m][n];
		for (int i = 0; i < n; i ++) {
            for (int j = 0; j < m; j++) {
                    Label[i][j] = new JLabel();
                    Label[i][j].setOpaque(true);
                    pole[i][j] = new Pole(this, k, i, j);
                    add(Label[i][j]);
            }
		}

		for (int i=0;i<m;++i)
			for(int j=0;j<n;++j)
				pole[i][j].start();
	}
	
	public void Ustawkolor(Color kolor,int y, int x){
		Label[y][x].setBackground(kolor);
	}
	
	public Color Pobierzsredni(int y, int x){
		int p1,p2,p3,p4;	
		
		if(x<this.x-1) p1=x+1;
		else p1=0;
		
		if(x!=0) p2=x-1;
		else p2=this.x-1;
				
		if(y<this.y-1) p3=y+1;
		else p3=0;
		
		if(y!=0) p4=y-1;
		else p4=this.y-1;
		
		Color a,b,c,d;
		
		a=pole[y][p1].kolor;
		b=pole[y][p2].kolor;
		c=pole[p3][x].kolor;
		d=pole[p4][x].kolor;
		
		int R,G,B;
		R=(a.getRed()+b.getRed()+c.getRed()+d.getRed())/4;
		G=(a.getGreen()+b.getGreen()+c.getGreen()+d.getGreen())/4;
		B=(a.getBlue()+b.getBlue()+c.getBlue()+d.getBlue())/4;
		return new Color(R,G,B);
	}
}
import java.awt.Color;
import java.util.Random;

public class Pole extends Thread{
	Random generator = new Random();
	Plansza plansza;
	boolean running;
	int x,y;
	int czas;
	Color kolor;
	Pole(Plansza plan,int k, int y,int x){
		this.x=x;
		this.y=y;
		plansza=plan;
		czas = ((int)(((generator.nextDouble()+0.5)*1000))*k);
		running = true;
        kolor=losujkolor();
		plansza.Ustawkolor(kolor,y,x);
	}
	public synchronized void run(){
		while(running){
				try {
					Thread.sleep(czas);
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
				if(generator.nextDouble() > plansza.prawdo){	
					kolor=plansza.Pobierzsredni(y,x);
					plansza.Ustawkolor(kolor, y, x);
				}
				else{
					kolor=losujkolor();
                    plansza.Ustawkolor(kolor, x, y);	  
				}
		}
	}
	public Color losujkolor(){
		int r = generator.nextInt(256);
        int g = generator.nextInt(256);
        int b = generator.nextInt(256);
        return new Color(r,g,b);
	}
}
	

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