Laden...

Matrix in Schlangenlinien befüllen

Erstellt von trib vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.758 Views
T
trib Themenstarter:in
708 Beiträge seit 2008
vor 11 Jahren
Matrix in Schlangenlinien befüllen

Guten Tag zusammen,

meine Anforderung könnte schon fast ins Programmier Spiel passen 😃

In einer von der Größe frei definierbaren Matrix (gegeben sei jetzt mal 3x3) wird ein Kabel verlegt. Bekannt ist quasi nur Start und Endpunkt.
Somit wird in Schlangenlinien das Raster von oben nach unten befüllt.


            for (int y = 0; y < gridHeight;y++)
            {           
                for (int x = 0; x < gridWidth; x++)
                {
                        if (y == 0 || y % 2 == 0)
                            xI = x;
                        else
                            xI = gridWidth-1 - x;

                    Rectangle myRectangle = new Rectangle(this.Padding.Left + (xI * pixelWidth) + (this.Padding.Right * xI), this.Padding.Top + (y * pixelHeight) + (this.Padding.Bottom * y), pixelWidth, pixelHeight);
                        _listgo.Add(new MyFilledRectangle(new SolidBrush(Color.Red, myRectangle));
                }
            }

Ergebis:

1 2 3
6 5 4
7 8 9

Prinzipiell kein Problem. Nun möchte ich aber alle 8 möglichen Start<>End Kombinationen darstellen und komme nicht so recht weiter.
Mit einer Hilfsvariablen yI könnte ich jetzt noch von unten nach oben darstellen, aber dann müsste ich schon anfangen die beiden Schleifen zu vertauschen und erst x zu durchlaufen und dann y durch zu iterieren.

Mein Enum für die Richtungen sieht aktuell so aus:

public enum FlowDirection
        {            
            UpperLeftToRight = 1,
            UpperLeftToBottom = 2,
            UpperRightToLeft = 3,
            UpperRightToBottom = 4,
            RightBottomUp = 5,
            RightBottomToLeft = 6,
            LeftBottomUp = 7,
            LeftBottomToRight = 8
        }

Hat jemand schonmal ein ähnliches Problem einigermaßen elegant gelöst?
Aktuell überlege ich schon ob ich einfach ein Konstrukt wie folgt baue damit wenigstens eine minimale Übersicht gewahrt bliebe:

for(i=0,i< gridWidth*gridHeight;i++)
  switch(flow)
{
  case FlowDirection.UpperLeftToRight:
    y++;
    x--;
 break;
}
DrawPixel(x,y);

(Eben aus dem Kopf hier hineingepfuscht)

Vielleicht sehe ich auch gerade nur den Wald vor Bäumen nicht. Freitag Mittag eben 😉

C
2.122 Beiträge seit 2010
vor 11 Jahren

Du musst dir eigentlich nur merken ob du zeilenweise nach oben/unten oder spaltenweise nach links/rechts laufen willst und in welche Richtung du gerade in der anderen Dimension läufst. Was der Startpunkt war ist dabei egal.

Beispiel. Du beginnst links oben und willst zeilenweise nach unten. Erst mal gehts nach rechts ... rechts ... rechts bis es nicht mehr weiter geht.
Dann geht es unten weiter, siehe Merker "zeilenweise nach unten".
Dann gehts nach links (weil nur links übrig bleibt), links, links ... bis wieder zum Rand.
Wenn du nicht mehr weiter runter kannst, bist du fertig.

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo trib,

also ich würde einfach folgendes machen:

int i = 0;
for (int y = 0; y < numLines; y++) {
   for (int x = 0; x < lineLength; x++) {
      DrawPixel (x, y, ++i);
   }
}

Wobei es um virtuelle Zeilen geht, die je nach Orientierung physische Zeilen oder physische Spalten sind. numLines entspricht also je nach Orientierung entweder der Höhe oder der Breite. Analog, nur andersherum für lineLength.

Und in DrawPixel machst du dann einen switch für das Umrechnen der virtuellen Koordinaten in die physischen Koordinaten. Zum Beispiel wäre bei UpperLeftToRight keine Umsetzung erforderlich, bei UpperLeftToBottom würden x und y einfach vertauscht und bei UpperRightToLeft würde x zu lineLength - x usw.

herbivore

C
168 Beiträge seit 2010
vor 11 Jahren

Hier mal so ganz grob wie es funktionieren müsste von der Logik her.

x=0
y=0

x++
y++
drawPixel

xmax = 10;
ymax = 100;

wenn ymax % 10 == 0 dann andere richtung
y++
x--
drawPixel

so müsstest du schon eine Vertikale Parabel erzeugen du muss halt nur noch eine if anweisung einfügen die darauf acht das du nach der ersten kurve immer 2x in die selbe richtung gehst. also sogesehen dann ymax % 20 == 0

Ich hoffe das hilft dir weiter 😉

Real programmers don't comment their code - it was hard to write, it should be hard to understand.

T
trib Themenstarter:in
708 Beiträge seit 2008
vor 11 Jahren

Guten Tag zusammen,

erstmal vielen Dank für die Antworten!

chilic´s klingt erstmal als die simpelste. Allerdings muss ich mir merken ob ich Spalten oder Zeilenweise vorgehe und wohin ich meinen Startpunkt setzen muss. Möchte ich nun über das Zeichen hinaus gehen und z.B. auf meinen Punkt klicken, muss ich aus der Position wieder zurückrechnen. Dafür eignet sich die Methode so nicht ganz.

Die Lösung von Crone habe ich auch schnell präferiert. Bis ich auf die Problematik gestoßen bin, wenn ich von der "norm" 10x10 abweiche und z.B. 11x9 als Matrix auswähle. Im Nachhinein gesehen war das aber nur ein Rechenfehler, den ich da eingebaut habe.
Dann stehe ich aber genauso vor dem Problem, keinen Pixel allein ansprechen zu können, sondern immer eine Schleife benötige.

Letztendlich hatte ich schon begonnen herbivore´s Vorschlag mit einer switch-Anweisung zu programmieren. Sieht zwar relativ unübersichtlich aus (wie ich schon vermutet hatte) aber ist dann schnell erledigt, wenn man das Prinzip verstanden hat.

private void DrawPixel(int pixelNo)
      {
        int x = 0;
        int y = 0;
        switch(pixelFlow)
        {
            case FlowDirection.UpperLeftToRight:
                y = pixelNo / gridWidth;
                if(y%2==0)
                    x = pixelNo % gridWidth;
                else
                    x = (gridWidth - 1) - pixelNo % gridWidth;
                break;
            case FlowDirection.UpperLeftToBottom:
                x = pixelNo / gridHeight;
                if(x%2==0)
                    y = pixelNo % gridHeight;
                else
                    y = (gridHeight - 1) - pixelNo %gridHeight;
                break;
            case FlowDirection.UpperRightToLeft:
                y = pixelNo / gridWidth;
                if (y % 2 == 0)
                    x = (gridWidth -1) - (pixelNo % gridWidth);
                else
                    x = pixelNo % gridWidth;
                break;
            case FlowDirection.UpperRightToBottom:
                x = (gridWidth -1) - pixelNo / gridHeight;
                if ((pixelNo / gridHeight) % 2 == 0)
                    y = pixelNo % gridHeight;
                else
                    y = (gridHeight - 1) - pixelNo % gridHeight;
                break;
            case FlowDirection.RightBottomUp:
                x = (gridWidth -1) - pixelNo / gridHeight;
                if ((pixelNo / gridHeight) % 2 == 0)
                    y = (gridHeight - 1) - pixelNo % gridHeight;
                else
                    y = pixelNo % gridHeight;
                break;
            case FlowDirection.RightBottomToLeft:
                 y = (gridHeight -1) - pixelNo / gridWidth;
                 if ((pixelNo / gridWidth) % 2 == 0)
                    x = (gridWidth -1) - (pixelNo % gridWidth);
                else
                    x = pixelNo % gridWidth;
                break;
            case FlowDirection.LeftBottomUp:
                x = pixelNo / gridHeight;
                if(x%2==0)
                    y = (gridHeight - 1) - pixelNo %gridHeight;
                else
                    y = pixelNo % gridHeight;
                break;
            case FlowDirection.LeftBottomToRight:
                y = (gridHeight -1) - pixelNo / gridWidth;
                if ((pixelNo / gridWidth) % 2 == 0)
                    x = pixelNo % gridWidth;
                else
                    x = (gridWidth - 1) - pixelNo % gridWidth;
                break;
            default:
                throw new Exception("Wrong PixelFlow!!!");
        }
   DrawRectangle[...]
}