# Ampel implementieren



## ThommyTom (7. Nov 2013)

Hi,
ich möchte eine Ampel implementieren und habe folgendes:

```
class Ampel
{
    private boolean rot;
    private boolean gelb;
    private boolean gruen;

    public Zmpel()
    {
        rot = false;
        gelb = false;
        gruen = true;
    }
    
    public void schalteWeiter()
    {
        gruen = rot && gelb;
        rot = gelb || rot; 
        gelb = gruen || rot;
    }
}
```

Soll heißen: Die nächste Phase leuchtet grün, wenn zuvor rot und gelb lechten. 
In der nächsten Phase leuchtet rot, wenn zuvor  orange oder rot leuchtet.
In der nächsten Phase leuchtet gelb, wenn zuvor grün oder rot leuchtet.

Das Programm funktioniert so aber natürlich noch nicht.
Beim ersten Durchlauf bekommt gruen den Wert false und gelb und rot auch. Wie kann ich das richtig implementieren? 

Ich hoffe, ihr versteht was ich meine bzw. mein Problem.
Danke!
Ich bin übrigens totaler Anfänger, also bitte nur mit den einfachsten Mitteln kommen 
Danke! 
Lieben Gruß,
Thomas


----------



## Phash (8. Nov 2013)

Schreib dir erst mal alle möglichen Kombinationen aus, 
Schreib alle Abläufe auf.

Überlege dir,  welches Ereignis die Ampel umschalten soll.

Dann überlege die,  wie du den Zustand einer Ampel beschreiben kannst - das hat du ja schon mit den 3 bools gewünscht,  aber wie könntest du heraus finden,  in welcher phase Du bist?


----------



## ThommyTom (8. Nov 2013)

Ich habe mir schon alles einmal aufgeschrieben. Das Problem ist, dass ich glaube ich kein neues Feld, wie z.B. "phase" setzen darf. Es soll alleine damit gehen.
Auch soetwas wie eine switch-Anweisung soll vermieden werden.

Wäre das alles erlaubt, hätte ich kein Problem mit der Aufgabe.

Damit geht es aber:

```
public void schalteWeiter()
    {
        _phase = (_phase + 1) % 4;

        switch(_phase)
        {
            case 0: _gruen = _gelb && _rot;
                    _gelb = false;
                    _rot = false;
                    break;
            
            case 1: _gelb = _gruen || _rot;
                    _gruen = false;
                    break;
        
            case 2: _rot = _gelb || _rot;
                    _gelb = false;
                    break;
       
            case 3: _gelb = _gruen || _rot;
                    break;
       }
    }
```

Aber wie gesagt, darf ich nicht so machen.
Hast du eine alternative Idee?


----------



## geqoo (8. Nov 2013)

Mit der Konstellation ohne Phase kann man nur schwer heraus finden, in welcher man sich gerade befindet.


```
public void schalteWeiter()
{
  if (gruen) {
    gruen = false;
    gelb = true;
    rot = false;
  }
  else if (gelb && !rot) {
    gruen = false;
    gelb = false;
    rot = true;
  }
  else if (rot && !gelb) {
    gruen = false;
    gelb = true;
    rot = true;
  }
  else if (rot && gelb) {
    gruen = true;
    gelb = false;
    rot = false;
  }
}
```


----------



## ThommyTom (8. Nov 2013)

Ja, aber if-Anweisungen sind auch verboten.
Geht es denn mit phase und ohne switch?


----------



## Phash (8. Nov 2013)

Ohne if?
Dann ist es eben sehr dumm,  aber du brauchst dann ja nur alle phasen durchgehen und weiter von vorn anfangen.


----------



## ThommyTom (8. Nov 2013)

Wie meinst du das?


----------



## Phash (8. Nov 2013)

eine schleife, die einfach alle ampelphasen der Reihe nach durchschaltet...
und dann wieder von vorn anfängt


----------



## ThommyTom (8. Nov 2013)

Schleifen sind auch tabu 
Ich lass das jetzt einfach so. Wenn die mit dem switch unzufrieden sind, bin ich mal gespannt, wie sie es haben wollte ...

Danke dir!


----------



## redJava99 (8. Nov 2013)

Der ursprüngliche Ansatz war doch gar nicht schlecht, nur nicht ganz zuende gedacht.

Das Problem ist, dass nach der ersten Veränderung in Z. 16

```
gruen = rot && gelb;
```
bereits der neue grün-Wert für die anderen Signale herangezogen wird, da die Befehle sequenziell abgearbeitet werden und nicht parallel.

Eine Möglichkeit wäre daher, die vohrigen Werte zu speichern und damit zu arbeiten.

Analytischer wäre es, wenn man sich überlegt, welches Signal von welchem abhängt:
Gelb ändert z.B. bei jedem umschalten seinen Zustand, hängt also nur von sich selbst ab.

Es folgt:


```
gelb = !gelb;
```

Grün ist einfach: Es leuchtet nur, wenn vorher rot und gelb leuchten.


```
gruen= rot && gelb;
```

Es ist  zu beachten, dass hier der alte Zustand von gelb gebraucht wird. Daher muss grün vor gelb berechnet werden:


```
gruen= rot && gelb
gelb = !gelb;
```

Zum Schluss fehlt noch rot, was immer nach "nur gelb" und nach "nur rot" leuchten muss, also:

```
rot = (!rot && gelb) || (rot && !gelb);
```
... oder kurz mit dem XOR-Operator:

```
rot = rot^gelb;
```

Achtung: Wieder so zwischen die anderen Befehle einbauen, dass der alte Wert von gelb betrachtet wird.

Es folgt insgesamt:


```
public void schalteWeiter()
    {
        gruen = rot && gelb;
        rot = rot^gelb;
        gelb=!gelb;
    }
```

hope that helps =)


----------



## ThommyTom (9. Nov 2013)

Das ist super!!!!
Danke


----------



## klauskarambulut (9. Nov 2013)

Wenn man auf if und switch verzichten möchte und Schleifen etc. tabu sind dann kann man auch ganz einfach Java verwenden.

Eine typische Standard-4-Phasen-Ampel sieht dann so aus

```
public class Ampel {
    enum Phase {
	GRUEN(false,false,true) {
	    public Phase schalteWeiter() {
		return GELB;
	    } 
	},GELB(false,true,false) {
	    public Phase schalteWeiter() {
		return ROT;
	    }
	},ROT(true,false,false) {	
	    public Phase schalteWeiter() {
		return ROT_GELB;
	    }
	},ROT_GELB(true,true,false){
	    public Phase schalteWeiter() {
		return GRUEN;
	    }
	};
	private final boolean rot;
	private final boolean gelb;
	private final boolean gruen;
	public abstract Phase schalteWeiter();
	
	private Phase(boolean rot,boolean gelb,boolean gruen) {
	    this.rot = rot;
	    this.gelb = gelb;
	    this.gruen = gruen;
	}
	public boolean rot() {
	     	    return rot;   
	}	     
	public boolean gelb(){
	    return gelb;	
	}
	public boolean gruen(){
	    return gruen;
	}
    };
    
    private Phase aktuell = Phase.GRUEN;
    
    public void schalteWeiter(){
       	      aktuell = aktuell.schalteWeiter();
    }

    public void zeigeAn(){
	System.out.printf("Rot %s, Gelb %s, Grün %s%n",aktuell.rot(),aktuell.gelb(),aktuell.gruen());
    }

    public static void main(String[] args) {
	Ampel ampel = new Ampel();
	for(int i = 0; i<10; i++){
	    ampel.schalteWeiter();
	    ampel.zeigeAn();
	}
    }
}
```


----------



## njans (10. Nov 2013)

Oder man verwendet eine Map. Die erfüllt die Abbildungseigenschaften genauso.


----------

