TIA Fragen zum SCL-Code

Ich habe jetzt vor mir kein TIA erst morgen wieder.


Bisher konnte ich die Spalten und Zeilenauswertung

Bei denn diagonalen habe ich noch keine Plan. Ich wollte es mit einer For-Schleife aber das geht irgendwie nicht.
Ich denke ich werde es mit einer While schleife oder einer If abfrage machen.

Schlechte Idee??

gruss
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kommt auf das Grundgerüst an.
Und es gibt auch noch andere Schleifen/Möglichkeiten. Auch mal über'n Tellerrand schauen. Dafür machst Du doch das Ganze - um Dich weiter zu entwickeln, oder?


Und übrigens nochmal - man muss nicht nach jedem Spielzug alle Spalten auf Gewinn prüfen, man muss nicht jedem Spielzug alle Zeilen auf Gewinn prüfen und man muss nicht nach jedem Spielzug alle Diagonalen auf Gewinn prüfen!
Es reicht aus, diejenigen zu prüfen, die das Feld kreuzen, in das der letzte Spielstein gefallen ist. Und welche das sind, sagen Dir bei Deinem Code die Variablen #x und #y. Das spart einiges an Code und Laufzeit.
Z.B:
Code:
...
[COLOR=#ff0000]FOR #a := 1 TO 7  BY 1 DO[/COLOR]
 FOR #b := 0 TO 5 BY 1 DO
   IF #Rot_Speicher[#a,#b] = 1 THEN
     #Sieg_Rot := #Sieg_Rot + 1;
   ELSE
     #Sieg_Rot := 0;
   END_IF;
 END_FOR;
[COLOR=#ff0000]END_FOR;[/COLOR]
...
Die rot markierte FOR-Zeile brauchst Du eigentlich nicht. Du weißt doch bereits, das der letzte Stein in Spalte #x geworfen wurde. Dann reicht es auch aus, diese Spalte auf einen Gewinn zu prüfen:
Code:
...
[COLOR=#FF0000]#a := #x;[/COLOR]
 FOR #b := 0 TO 5 BY 1 DO
   IF #Rot_Speicher[#a,#b] = 1 THEN
     #Sieg_Rot := #Sieg_Rot + 1;
   ELSE
     #Sieg_Rot := 0;
   END_IF;
 END_FOR;
...
(Oder gleich #x anstelle von #a einsetzen.)


Was mir jetzt noch aufgefallen ist - wenn bei Dir ein Spielstein in eine bereits volle Spalte geworfen wird, wird der oberste einfach überschrieben:
Code:
#y:=0;
#Gefunden:= 0;

WHILE #Gefunden = 0  DO
 IF  #Grün_Speicher[#x,#y] = 0 AND #Rot_Speicher[#x,#y] = 0 THEN
      #Grün_Speicher[#x,#y] := 1;
         #Gefunden:= 1;
    ELSE
      #y:=#y+1;
[COLOR=#ff0000]      IF #y = 5 THEN
        #Gefunden:= 1;
      END_IF;[/COLOR]
    END_IF; 
  END_WHILE;
Das kann nicht richtig sein. Bediener machen Fehler - und der Programmierer muss diese möglichst abfangen und entsprechend behandeln!


Ebenso finde ich es nicht besonders schön, dass Du bei den Spalten von 1 bis 7 zählst, während Du bei den Zeilen mit 0 beginnst. Es ist eigentlich relativ egal, wofür Du Dich entscheidest, aber ohne besonderen Grund sollte man möglichst bei einer Logik bleiben. Ist was für's nächste Programm.


Und wie gesagt, das Du alles doppelt machst, würde ich als Lehrer überhaupt nicht durchgehen lassen. Auch wenn Du (warum auch immer) 2 Spielfelder brauchst, kann man die Abfrage der gewählten Spalte, die Suche nach dem leeren Feld, die Gewinnauswertung ... gemeinsam machen.
Ich kann schon verstehen, dass Du nicht nochmal anfangen willst, aber auch sowas gehört zum Lernprozess. Und man muss ja nicht alles verwerfen, sondern nur schauen, wo macht man eigentlich genau das Gleiche, nur mit einem anderen Variablenwert.
 
Hallo hucki

Ich weiss es gehört zum Lernprozess, weil ich keine Zeit habe neu anzufangen werde ich es einfach so zu verursachen.

Das war mein erstes programm mit SCL und es hat mir sehr viel Spass gemacht mir SCL zu arbeiten.
Für das nächste mal werde ich besser planen das habe ich bei diesem Projekt gelernt.

Gruss
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Bei denn diagonalen habe ich noch keine Plan. Ich wollte es mit einer For-Schleife aber das geht irgendwie nicht.

schau dir doch einfach meinen Code an:

-alle Strecken-Tests mit der selben Funktion abgedeckt (test_strecke)
-jeweils nur 1 Schleife (durchlaufe_belegung)
-kein Test von unnötigen Strecken (distanz check in test_strecke)
-Test für nicht erlaubtes Setzen (setzen_moeglich)
-keine Rand-Tests nötig (wird vor dem test geklärt)

und ob SCL, C, C++ usw. ist doch bei der Codemenge auch irgendwie egal - aka Hukis Tellerrand-Spruch
 
Zuletzt bearbeitet:
@LowLevelMahn,
ich persönlich wüßte jetzt mangels C-Kenntnissen auch nicht bei allen Stellen, wie ich Deinen Code zu SCL umsetzen soll. :(
Vlt. kannst Du das ja mal in einer ruhigen "Minute" übernehmen? :cool:

Wenn bkizilkaya sein Projekt für sich abgeschlossen und hier komplett vorgestellt hat, können wir unsere kompletten Programme dann ja auch mal posten.
Ich bin immer interessiert an anderen Lösungswegen.
Wobei wir das theoretisch auch jetzt schon machen könnten, denn er will ja eh' nicht nochmal neu beginnen.
:)
 
ich persönlich wüßte jetzt mangels C-Kenntnissen auch nicht bei allen Stellen, wie ich Deinen Code zu SCL umsetzen soll. :sad:
Vlt. kannst Du das ja mal in einer ruhigen "Minute" übernehmen? :cool:

geht mir genau so mit SCL - da habe ich gar keine Ahnung (wie bei den meisten SPS-Sachen, bin nur "kommunikativ" in dem Umfeld unterwegs - sonst nur C/C++...)
aber du könntest ja Aufzeigen welche Teile dir "Probleme" bereiten - dann lerne ich in der ruhigen "Minute" auch gleich noch was - und du auch :)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
wenn dieser SCL Code richtig nach C konvertiert ist würde ich behaupten das aus den funtionen: setzen_moeglich, belegung_durchlaufen, test_strecke, minimum und setzen
direkt "funktionsbloecke" werden koennen - ich weiss nur nicht wo die globalen variablen fuellhoehe, spielfeld und die konstanten BREITE, HOEHE, GEWINN_ANZAHL hingehoeren


Code:
in SCL

FUNCTION QUADRAT : INT 
VAR_INPUT 
  wert : INT; 
END_VAR 
VAR 
  ergebnis : INT;
END_VAR
VAR_OUTPUT
  ausgabe : INT;
END_VAR
BEGIN 
  ergebnis := 0;
  IF wert <= 181 THEN 
    ergebnis := wert * wert;
  ELSE 
    ergebnis := 32_767;
  END_IF; 
  ausgabe := 10;
  QUADRAT := ergebnis;
END_FUNCTION


in C/C++


int QUADRAT(int wert, int& ausgabe)
{
  int ergebnis = 0;
  if( wert <= 181 ){
    ergebnis = wert * wert;
  }else{
    ergebnis = 32767;
  }
  ausgabe = 10;
  return ergebnis;
}

Aufruf:
int die_ausgabe = 0;
int das_ergebnis = QUADRAT(10, die_ausgabe);

Ergebnis:
das_ergebnis == 100
die_ausgabe == 10
 
Zuletzt bearbeitet:
hallo zusammen
bin heute wieder an meinem Projekt an der reihe.
Ich habe immer noch folgende Fehler: Die diagonale funktionieren immer noch nicht.

Ein ausschnitt von meinem Programm:
Code:
// Diagonale Auswertung 
FOR #i := 4 TO 9 BY 1 DO
FOR #j := 0 TO 5 BY 1 DO
    #i_j:= #i-#j;
  IF #Rot_Speicher[#i,#j] = 1 THEN
       #Sieg_Rot := #Sieg_Rot + 1;
    IF #Sieg_Rot = 4 THEN
       #Rot_Sieg := 1;
    END_IF;
  ELSE
       #Sieg_Rot := 0;
  END_IF;
END_FOR;
END_FOR;

Ich habe das Array erweitert, weil man dann besser die diagonale-auswertung machen kann.
Könnt ihr mir vielleicht weiterhelfen?

Gruss
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
ich würde die Suchroutine so gar nicht machen.
Mein Vorschlag wäre :
- du fängst in der untersten Reihe an und kontrollierst die Farbe des Elementes mit dem aktuellen Index. Für den setzt du dann den Farbzähler auf 1.
- nun ermittelst du die Position des nächsten Nachbarn basierend auf deiner aktuellen Position. Ist die Position legal (also in deiner Matrix) und hat er die gleiche Farbe wie dein Ausgangsfeld dann erhöhst du den Zähler für die Farbe. Ist die Position illegal oder die Farbe nicht identisch dann brichst du ab, erhöhst den Index und fängst wieder von vorne an.
- war die Position legal und die Farbe die richtige dann checkst du den nächsten Nachbarn für dieses Feld und verfährst wie vorher.
- Ist dein Farbzähler[Farbe] irgendwann >= 4 dann hat die Farbe gewonnen.

Anmerkung:
bei der Vergabe von Variablennamen würde ich etwas fantasievoller vorgehen. Die Namen kosten nichts mehr, wenn sie Aufgabe der Variablen sinnvoll beschreiben und sie erfordern auch nicht mehr Bearbeitungszeit ...

Gruß
Larry
 
Sowas hatte ich ihm weiter oben auch schon vorgeschlagen, aber er möchte lieber seinen Weg weiter verfolgen (was ich auch legitim finde).
Zusätzlich erschwerend wirkt sich natürlich noch die Benutzung von 2 Spielfeldern statt nur einem aus.

Ich hab' ja auch schon des öfteren bemerkt, das es überflüssig ist, jedesmal das komplette Spielfeld auf einen Gewinn zu überprüfen.
Besonders für die Diagonalen fand' ich daher die FOR-Schleifen für eher ungeeignet und hab' in meiner Variante der Gewinnprüfung komplett auf sie verzichtet.
:cool:
 
Danke für eure antworten

Das programm funktioniert man kann gegeneinander spielen.
Ich werde das Programm irgendeinmal in einem neuen Thread vorstellen mit den Dokumentation.

Ich danke euch trotzdem mit euren genialen ideen ;)

gruss
 
Na denn:



Ist zwar sicher noch nicht alles Gold, was glänzt, aber das wird schon noch.
Einfach (wie bisher) am Ball bleiben.
:s12:


Übrigens, so hab' ich die Diagonalen (analog zu meiner Spaltenprüfung) geprüft:
3. Erste Diagonale:
Code:
[FONT=courier new]6 [/FONT]o o o o o o ?[FONT=courier new] 
[/FONT]5 o o o o o ? o
4 o o o o X o o
3 o o o ? o o o
2 o o ? o o o o
1 o [COLOR=#FF0000][B]?[/B][/COLOR] o o o o o
x 1 2 3 4 5 6 7
Auch hier kann der aktuelle Spielstein wieder ein mittlerer der Reihe sein. Also von ganz unten in Zeile 1 an prüfen. Die Spalte mit der begonnen wird, ist die aktuelle Spalte minus die aktuelle Zeile plus 1. Und dann nach oben arbeiten -> Zeile + 1 und Spalte + 1. die Prüfung kann abgebrochen werden, wenn Folge = 4 oder Spalte > 7 oder Zeile > 6.
Code:
  [FONT=Courier New]IF NOT Gewinn THEN
      Folge := 0;                                                              // Folge gleicher Spielsteine initieren
      Spalte:= [I]"aktuelle Spalte"[/I] [B][COLOR=#ff0000]-[/COLOR][/B] [I]"aktuelle Zeile"[/I] [COLOR=#ff0000][B]+ 1[/B][/COLOR];                       // Anfangsspalte der [COLOR=#ff0000]1. Diagonale[/COLOR] berechnen
      Zeile := 1;                                                              // [/FONT][FONT=Courier New]Anfangsz[/FONT][FONT=Courier New]eile festlegen
      REPEAT
          IF [COLOR=#ff0000]Spalte > 0[/COLOR] THEN                                                   // Nur wenn das berechnete Feld innerhalb des Spielfelds liegt
             Folge:= SEL (G:= SPIELFELD[Spalte, Zeile] = [I]"aktueller Spieler"[/I],  // Im Spielfeld der gleicher Spieler eingetragen?
                          IN0:= 0,                                             // nein: Folge gleicher Spielsteine auf 0 rücksetzen
                          IN1:= Folge + 1);                                    // ja:   Folge Spielsteine um 1 erhöhen
          END_IF;
          Spalte:= Spalte [B][COLOR=#ff0000]+[/COLOR][/B] 1;                                                 // letzten Wert für Spalte um eins erhöhen
          Zeile := Zeile  + 1;                                                 // letzten Wert für Zeile  um eins erhöhen
      UNTIL Folge = 4 OR [COLOR=#ff0000]Spalte > Spalten[/COLOR] OR Zeile > Zeilen                    // Schleife eventuell wiederholen
      END_REPEAT;
      Gewinn:= Folge = 4;                                                      // Gewinn setzen, wenn Folge=4
  END_IF;[/FONT]
Und dementsprechend, wie oben erklärt, die 2. Diagonale:
4. Zweite Diagonale:
Code:
[FONT=courier new]6 [/FONT]o o ? o o o o[FONT=courier new] 
[/FONT]5 o o o ? o o o
4 o o o o X o o
3 o o o o o ? o
2 o o o o o o ?
1 o o o o o o o [COLOR=#FF0000]?[/COLOR]
x 1 2 3 4 5 6 7 8
Wie man sieht, können die Diagonalen auch außerhalb des Spielfelds beginnen. Wenn also die Spalte einen Wert außerhalb des Spielfelds hat, muss die Prüfung übersprungen werden, Folge bleibt dann einfach noch bei 0.
Code:
  [FONT=Courier New]IF NOT Gewinn THEN
      Folge := 0;                                                              // Folge gleicher Spielsteine initieren
      Spalte:= [I]"aktuelle Spalte"[/I] [B][COLOR=#ff0000]+[/COLOR][/B] [I]"aktuelle Zeile"[/I] [COLOR=#ff0000][B]- 1[/B][/COLOR];                       // Anfangsspalte der [COLOR=#ff0000]2. Diagonale[/COLOR] berechnen
      Zeile := 1;                                                              // Anfangsz[/FONT][FONT=Courier New]eile festlegen[/FONT][FONT=Courier New]
      REPEAT
          IF [COLOR=#ff0000]Spalte <= Spalten[/COLOR] THEN                                            // [/FONT][FONT=Courier New]Nur wenn das berechnete Feld innerhalb[/FONT][FONT=Courier New] des Spielfelds
             Folge:= SEL (G:= SPIELFELD[Spalte, Zeile] = [I]"aktueller Spieler"[/I],  // Im Spielfeld der gleicher Spieler eingetragen?
                          IN0:= 0,                                             // nein: Folge gleicher Spielsteine auf 0 rücksetzen
                          IN1:= Folge + 1);                                    // ja:   Folge Spielsteine um 1 erhöhen
          END_IF;
          Spalte:= Spalte [B][COLOR=#ff0000]-[/COLOR][/B] 1;                                                 // letzten Wert für Spalte um eins erhöhen
          Zeile := Zeile  + 1;                                                 // letzten Wert für Zeile  um eins erhöhen
      UNTIL Folge = 4 OR [COLOR=#ff0000]Spalte < 1[/COLOR] OR Zeile > Zeilen                          // Schleife eventuell wiederholen
      END_REPEAT;
      Gewinn:= Folge = 4;                                                      // Gewinn setzen, wenn Folge=4
  END_IF;[/FONT]
 
Zuletzt bearbeitet:
Zurück
Oben