Schiffe versenken - Wie prüfen, ob ein Schiff genau daneben ist?



  • Gute Kristallkugel!

    Was meinst du? ich hatte in srand() kein time(0) drin!



  • helpplease schrieb:

    ...tatsächlich (temporär) goto, wenn du wirklich goto meinst.

    Wie kommst du jetzt auf goto? Davon hab ich nichts erwähnt!

    Mit goto kannst Du aber bequem aus einer inneren Schleife von mehreren verschachtelten Schleifen springen.
    Mit continue und break ist das nicht so einfach. Siehe zum Beispiel Deinen Code:

    for(i = 0; i < schiff; i++)
      if(index[start+i])
        continue;  // quark
    

    Gemeint hast Du wohl:

    while(true){
        loop:
          start=zufall();
          //...
          for(i = 0; i < schiff; i++)
            if(index[start+i])
              goto loop;
        //...
      }
    

    Und ganz eigentlich wolltest Du das testen der einzelnen Felder in eine eigene Funktion auslagern. 🙂


  • Mod

    void SchiffPlatzieren(short schiff, bool lage) // schiff == Länge,  lage == horizontal/vertkal?
    {
    	int start, i; // Definition besser erst später
    
    	while(true)
    	{
    		start = zufall();
    		if(lage == 0)
    		{
    			if(sperre[start])
    				continue;
    // prüft, ob Schiffsfelder schon durch anderes Schiff belegt
    // was ist, wenn es sich um benachbarte Felder (sperre) handelt?
    			for(i = 0; i < schiff; i++)
    				if(index[start+i])
    					continue;  // wurde schon kritisiert
    // im Allg. mehr als 4 benachbarte Felder
    // und warum genau sollte die Belegung fehlschlagen, wenn ein freies Feld zufällig schon Nachbar eines anderen Schiffes ist?
    			if(sperre[start-1] || sperre[start+schiff-1] || sperre[start-12] || sperre[start+12])
    				continue;
    			for(i = 0; i < schiff; i++)
    			{
    				index[start+i] = true;
    			}
    // das ist seltsam: ein Schiff hat ja in der Regel mehr als 4 benachbarte Felder eher: 2*Länge+2 od 2*Länge+6 falls Ecken zählen
    			sperre[start-1] = true;	
    			sperre[start+schiff-1] = true;
    			sperre[start-12] = true;
    			sperre[start+12] = true;
    
    			break;
    		}
    	}
    }
    

    Die Verwendung zweier Felder scheint nicht besonders sinnvoll. Ein einzelnes Feld mit 3 Zuständen je Feld (leer, benachbart, belegt) dürfte sinnvoller sein. Das vereinfacht auch die Logik: damit ein Schiff gesetzt werden kann, müssen alle Felder, die es belegt, leer sein.



  • und warum genau sollte die Belegung fehlschlagen, wenn ein freies Feld zufällig schon Nachbar eines anderen Schiffes ist?

    Weil das nunmal die Regeln sind 😕


  • Mod

    hustbaer schrieb:

    und warum genau sollte die Belegung fehlschlagen, wenn ein freies Feld zufällig schon Nachbar eines anderen Schiffes ist?

    Weil das nunmal die Regeln sind 😕

    Gemeint ist, das ein Feld ja durchaus Nachbar zweier Schiffe sein kann (also z.B. zwei Schiffe parallel mit dem Abstand 2). Etwas anderes kann ich aus der Beschreibung nicht herauslesen.



  • volkard schrieb:

    Laufzeit ist hier völlig irrelevant. Ob der Benutzer 100 oder 500 Mikrosekunden warten muss, er kann es nicht bemerken.

    Also interessiert der Algo nicht, der für n Schiffe nur O(1) pro Setzen benötigt (unabhängig von Schifflänge und Feldgrösse) und dabei O(n) Speicher benötigt.



  • camper schrieb:

    hustbaer schrieb:

    und warum genau sollte die Belegung fehlschlagen, wenn ein freies Feld zufällig schon Nachbar eines anderen Schiffes ist?

    Weil das nunmal die Regeln sind 😕

    Gemeint ist, das ein Feld ja durchaus Nachbar zweier Schiffe sein kann (also z.B. zwei Schiffe parallel mit dem Abstand 2). Etwas anderes kann ich aus der Beschreibung nicht herauslesen.

    Ah 💡
    Ja, dass er das doppelt macht, und dadurch 2 freie Felder zwischen Schiffen sein müssten hab' ich übersehen.
    (Abgesehen von dem "das ist seltsam" Fehler)



  • camper schrieb:

    Die Verwendung zweier Felder scheint nicht besonders sinnvoll. Ein einzelnes Feld mit 3 Zuständen je Feld (leer, benachbart, belegt) dürfte sinnvoller sein. Das vereinfacht auch die Logik: damit ein Schiff gesetzt werden kann, müssen alle Felder, die es belegt, leer sein.

    Jo, schon.
    Andererseits wird das sperre-Feld nur ganz kurz mal während des Schiffe-Platzierens gebraucht und dab dann für den Rest des Spiels ist der dritte Zustand ein Bißchen störend.



  • ...


  • Mod

    volkard schrieb:

    camper schrieb:

    Die Verwendung zweier Felder scheint nicht besonders sinnvoll. Ein einzelnes Feld mit 3 Zuständen je Feld (leer, benachbart, belegt) dürfte sinnvoller sein. Das vereinfacht auch die Logik: damit ein Schiff gesetzt werden kann, müssen alle Felder, die es belegt, leer sein.

    Jo, schon.
    Andererseits wird das sperre-Feld nur ganz kurz mal während des Schiffe-Platzierens gebraucht und dab dann für den Rest des Spiels ist der dritte Zustand ein Bißchen störend.

    Im Prinzip ändert das ja nichts an der Komplexität des Problems. Der Algorithmus sollte im Prinzip so aussehen

    1. würfle Position
    2. Falls nicht jedes Feld des Schiffskörpers frei ist (frei==kein anderes Schiff und auch kein Nachbarfeld eines anderen Schiffes), gehe zu 1.
    3. Markiere Schiffsfelder als belegt
    4. Markiere Nachbarfelder als solche
    

    Zwei Felder bedeutet doppelte Arbeit im 2. Schritt aber sicher keinen wesentlichen Nachteil.
    Oder aber man verzichtet auf die Erfassung der Nachbarfelder und prüft eben intensiver im 2. Schritt

    1. würfle Position
    2. Falls nicht jedes Feld des Schiffskörpers als auch jedes benachbarte Feld frei ist (frei==kein anderes Schiff), gehe zu 1.
    3. Markiere Schiffsfelder als belegt
    

    Offenbar bedeutet diese Variante mehr Arbeit, falls eine gewürfelte Position nicht verwendbar ist. Dafür wird der Algorithmus kürzer.



  • Gemeint hast Du wohl:

    while(true){
        loop:
          start=zufall();
          //...
          for(i = 0; i < schiff; i++)
            if(index[start+i])
              goto loop;
        //...
    }
    

    Und ganz eigentlich wolltest Du das testen der einzelnen Felder in eine eigene Funktion auslagern.

    Ja, gemeint hab ich es so, aber goto werde ich nicht dafür benutzen, da es mir
    nicht gefällt. Das mit "coninue;" war ein Denkfehler von mir. Das erklärt auch,
    warum nicht alle Schiffe richtig platziert wurden 😮 !
    Das Testen der Felder werd ich noch in ne Funktion packen.

    Die Verwendung zweier Felder scheint nicht besonders sinnvoll. Ein einzelnes Feld mit 3 Zuständen je Feld (leer, benachbart, belegt) dürfte sinnvoller sein. Das vereinfacht auch die Logik: damit ein Schiff gesetzt werden kann, müssen alle Felder, die es belegt, leer sein.

    Ist nur blöd, das bei bool keine 3 Zustände gehen. Ich müsste also int oder so
    nehmen.

    Gemeint ist, das ein Feld ja durchaus Nachbar zweier Schiffe sein kann (also z.B. zwei Schiffe parallel mit dem Abstand 2). Etwas anderes kann ich aus der Beschreibung nicht herauslesen.

    Du hast vollkommen recht. So, wie ich das habe, würden 2 Kästchen zwischen
    Schiffen frei sein. Ich denke, ich werde das so machen, das ich das Nachbarfeld
    abfrage, und nur als "nicht geeignet" für eine Schiffplatzierung setze, wenn das
    Feld einem anderen Schiff gehört. Wenn das Nachbarfeld nur eine Markierung
    (blauer "Tupfen") ist, so kann das Schiff platziert werden.

    Ja, dass er das doppelt macht, und dadurch 2 freie Felder zwischen Schiffen sein müssten hab' ich übersehen.

    Hab ich leider am Anfang auch 😃 !

    volkard schrieb:
    [...] für den Rest des Spiels ist der dritte Zustand ein Bißchen störend.

    Warum? !Schiff == !getroffen

    Wieso? ob getroffen, oder nicht, dafür braucht man nicht unbedingt einen
    dritten Zustand.

    Fazit:
    - Das blöde mit dem continue;(Denkfehler 👎 ) muss ich ändern!
    - Das mit dem Feld mit 2/3 Zuständen werd ich mal genauer durchdenken. Zum einen
    wären 3 Zustände vielleicht besser, zum anderen werde ich den 3 Zustand ja
    wirklich nur für die umliegenden Felder benötigen. Ich werd drüber nachdenken!
    - Das mit den umliegenden Feldern(so, das 2 Kästchen frei sind), ist natürlich
    quatsch. Werd es noch ändern!



  • helpplease schrieb:

    - Das mit dem Feld mit 2/3 Zuständen werd ich mal genauer durchdenken. Zum einen
    wären 3 Zustände vielleicht besser, zum anderen werde ich den 3 Zustand ja
    wirklich nur für die umliegenden Felder benötigen. Ich werd drüber nachdenken!

    3 Zustände?
    Ich sehe Wasser/unsichtbarerBlauerTupfen/Schiff/TrefferAufSchiff/SchussInsWasser. Evtl noch VersenktesSchiff und um versenkte Schiffe herum sichtbare blaue Tupfen.



  • 3 Zustände?
    Ich sehe Wasser/unsichtbarerBlauerTupfen/Schiff/TrefferAufSchiff/SchussInsWasser. Evtl noch VersenktesSchiff und um versenkte Schiffe herum sichtbare blaue Tupfen.

    Ersmal, ich bezog mich auf die Funktion SchiffePlatzieren. Die Zustände sind
    für das Abfragen der umliegenden Kästchen und die Schiffsplatzierung da.

    Wasser(blaue "Tupfen") -> Zustand 1
    Schiff -> Zustand 2
    Treffer usw... -> Das braucht man nicht in der Funktion. Das mach ich in der
    WndProc


Anmelden zum Antworten