Autor Beitrag
RB92
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Do 27.06.19 11:29 
Hallo zusammen,
ich habe ein Problem mit dem Game of Life und komme nicht weiter. Es soll so sein, dass ich mit der Maus in den Zeichenbereich klicke, ein schwarzer Punkt erscheint, und wenn ich wieder klicke ein weiterer Punkt nach den Regeln vom Game of Life erscheinen soll. Nun zu meinem Problem, zur Zeit ist es bei meinem Programm so, dass der Punkt nicht da erscheint, wo ich hinklicke, sondern etwas weiter rechts daneben. Und wenn ich klicke, kommt der Punkt und geht dann aber wieder weg, also es kommen keine Neuen hinzu. Also irgendetwas stimmt da nicht und ich hoffe, dass mir jemand helfen kann. Ich habe noch nicht sehr viel Erfahrung, möchte aber gerne dazu lernen. Ich möchte dann auch später noch weitere Dinge einbauen, die Buttons dafür sind schon vorhanden. Das Programm hänge ich an.

Viele Grüße und ich hoffe, ich bekomme Hilfe

hier ist der Code:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
public Form1()
{
  InitializeComponent();
  IniLiveArea();

  this.Paint += new System.Windows.Forms.PaintEventHandler(this.DrawCell);
  this.Invalidate();

  timer_1.Tick += new EventHandler(timer_1_Tick);
}

private Cell[,] LiveArea;

private void IniLiveArea()
{
  LiveArea = new Cell[160116];
  for (int i = 0; i < 160; i++)
  {
    for (int l = 0; l < 116; l++)
    {
      LiveArea[i, l] = new Cell();
    }
  }
}

private void pictureBox1_Click(object sender, EventArgs e)
{
  this.Invalidate();

  Point p = new Point();
  p = MouseIni(Control.MousePosition);
  if (LiveArea[p.X, p.Y].GetState())
  {
    LiveArea[p.X, p.Y].SetState(false);
  }
  else
  {
    LiveArea[p.X, p.Y].SetState(true);
  }
}

public Point MouseIni(Point p)
{   //Die Mausposition wird auf das Zeichenfeld normiert; Es wird in ein 5x5-Raster geteilt, links oben ist 0/0//Die Location der Piocture Box wurde auf 260;10 (Punkt der linken oberen Ecke)
  int KoordX = (p.X - this.Location.X - 120 - 8) / 5//-8entstehen durch den linken Rand des Fensters
  int KoordY = (p.Y - this.Location.Y - 10 - 31) / 5//-31 entstehen durch den oberen Rand des Fensters
  p.X = KoordX;
  p.Y = KoordY;
  return p;
}

public void DrawCell(object sender, System.Windows.Forms.PaintEventArgs e)
{
  Graphics draw = e.Graphics;
  SolidBrush brush = new SolidBrush(Color.Black);

  for (int i = 0; i < 160; i++)
  {
    for (int l = 0; l < 116; l++)
    {
      if (LiveArea[i, l].GetState())
      {
        draw.FillRectangle(brush, i * 5 + 260, l * 5 + 1055);
      }
    }
  }
}

private void timer_1_Tick(object sender, EventArgs e)
{
  animation();
}

public static System.Windows.Forms.Timer timer_1 = new System.Windows.Forms.Timer();

private void buttonStart_Click(object sender, EventArgs e)
{
  if (!timer_1.Enabled)
  {
    timer_1.Enabled = true;
    timer_1.Start();

    buttonStart.Text = "Stopp";
  }
  else
  {
    timer_1.Enabled = false;
    timer_1.Stop();
    buttonStart.Text = "Start";
  }
}

private void animation()
{
  this.Invalidate();
  for (int i = 0; i < 160; i++)
  {
    for (int k = 0; k < 116; k++)
    {
      int x, y, count = 0;
      for (int a = -1; a <= 1; a++)
      {
        for (int b = -1; b <= 1; b++)
        {
          x = (i + 160 + a) % 160;
          y = (k + 116 + b) % 116;
          if (!(a == 0 && b == 0))
          {
            if (LiveArea[x, y].GetState()) count++;
          }
        }
      }
      LiveArea[i, k].SetEnv(count);
    }
  }

  for (int i = 0; i < 160; i++)
  {
    for (int k = 0; k < 116; k++)
    {
      if ((LiveArea[i, k].GetEnv() == 3) && !LiveArea[i, k].GetState())
      {
        LiveArea[i, k].SetState(true);
      }
      else
      {
        if (LiveArea[i, k].GetEnv() < 2 || LiveArea[i, k].GetEnv() > 3
        && LiveArea[i, k].GetState())
        {
          LiveArea[i, k].SetState(false);

        }
      }
    }
  }
}


Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Moderiert von user profile iconTh69: Code überarbeitet (überflüssige [leere] Funktionen entfernt).
Einloggen, um Attachments anzusehen!


Zuletzt bearbeitet von RB92 am Do 27.06.19 12:51, insgesamt 1-mal bearbeitet
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 27.06.19 12:24 
Hallo und :welcome:

bitte poste hier relevanten Code, der dein Problem umfassend beschreibt (die wenigsten User werden deine ZIP-Datei herunterladen und das Projekt ausführen wollen, um sich dann deinen gesamten Code anzusehen).
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 27.06.19 18:15 
Ich habe mal deinen obigen, editierten Code auf die notwendigen Methoden gekürzt (ich schrieb ja extra: relevanten Code)!

An dem Code gibt es einiges zu verbessern, insbesondere deine Mauspositionsberechnung (weswegen du wohl auch bisher falsche Ergebnisse erhältst).
Statt des Click-Ereignis, nimm besser MouseDown (bzw. MouseUp), da diese in den MouseEventArgs die auf das Steuerelement bezogene Mausposition zurückliefern: MouseEventArgs (X und Y).

Dann solltest du sog. Magic-Code vermeiden, d.h. keine Literale (z.B. Zahlen) direkt verwenden, sondern entsprechen benannte Konstanten dafür anlegen, z.B.
ausblenden C#-Quelltext
1:
2:
const int MaxCellX = 160;
const int MaxCellY = 116;

Und diese Konstanten dann durchgehend in dem Code verwenden.

Und (auch als Anfänger) solltest du Logik und UI voneinander trennen, d.h. lagere die reine Logik (d.h. die Datenstruktur und die Regeln vom "Game of Life") in eine eigene Klasse aus und verwende diese dann nur in der UI-Klasse (Form).

Für diesen Beitrag haben gedankt: RB92
RB92 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Sa 29.06.19 15:47 
Hallo,danke für die Verbesserungsvorschläge.
Ich habe es jetzt nochmal anders gemacht, da funktioniert jetzt schon wesentlich mehr als bei dem anderen Programm.
Wie kann ich mir denn da auch die toten Zellen farbig anzeigen lassen?es sind ja jezt nur die lebenden violett und der Rest ist immer schwarz?
Ich bekomme es auch irgendwie nicht hin, den Hintergrund nicht mehr schwarz zu haben, sondern von dem die Farbe zu ändern, weil wenn ich eine Farbe einstelle bei den picturebox Einstellungen, z.B. transparent oder weiß, dann bleibt sie immernoch schwarz.
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
namespace Game_of_Life_C
{
    public partial class Form1 : Form
    {
        bool[,] LiveArea;
        int environment = 12;
        bool isDrawing = false;
        bool drawColor;

        public Form1()
        {
            InitializeComponent();
            IniLiveArea();
        }
        private void IniLiveArea()
        {
            LiveArea = new bool[160116];
            LiveArea[2312] = true;
            LiveArea[2413] = true;
            LiveArea[2314] = true;
            guiField.Size = new Size(LiveArea.GetLength(0) * environment, LiveArea.GetLength(1) * environment);
        }

        private void pictureBox2_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Brush alive = Brushes.Violet;
            Brush dead = Brushes.black;

            for (int i = 0; i < LiveArea.GetLength(0); i++)
            {
                for (int I = 0; I < LiveArea.GetLength(1); I++)
                {
                    Brush b;
                    if (LiveArea[i, I])
                        b = alive;
                    else
                        b = dead;
                    g.FillRectangle(b, i * environment, I * environment, environment, environment);
                }
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Einzelschritt();
        }
        private void Einzelschritt()
        {
            LiveArea = NextGeneration(LiveArea);
            guiField.Invalidate();
        }
        private bool[,] NextGeneration(bool[,] feld)
        {
            bool[,] nyplan = new bool[feld.GetLength(0), feld.GetLength(1)];
            for (int i = 0; i < feld.GetLength(0); i++)
            {
                for (int y = 0; y < feld.GetLength(1); y++)
                {
                    int neighbors = getAliveNeighbors(feld, i, y);
                    if (feld[i, y])
                    {

                        nyplan[i, y] = (neighbors >= 2 && neighbors <= 3);
                    }
                    else

                    {
                        nyplan[i, y] = neighbors == 3;

                    }
                }
            }
            return nyplan;
        }
        private int getAliveNeighbors(bool[,] plan, int x, int y)
        {
            int neighbors = 0;
            int maxX = plan.GetLength(0);
            int maxY = plan.GetLength(1);

            for (int dx = -1; dx <= 1; dx++)
            {
                for (int dy = -1; dy <= 1; dy++)
                {
                    int cx = x + dx;
                    int cy = y + dy;
                    if (cx == x && cy == y)
                        continue;
                    if (cx < 0 || cx >= maxX)
                        continue;
                    if (cy < 0 || cy >= maxY)
                        continue;

                    if (plan[cx, cy])
                    {
                        neighbors++;
                    }
                }
            }
            return neighbors;
        }

        private void guiField_MouseDown(object sender, MouseEventArgs e)
        {
            int x = e.X / environment;
            int y = e.Y / environment;
            isDrawing = true;
            drawColor = !LiveArea[x, y];
            guiField.Invalidate();
        }

        private void guiField_MouseMove(object sender, MouseEventArgs e)
        {
            if (!isDrawing)
                return;
            int x = e.X / environment;
            int y = e.Y / environment;
            if (x < 0 || x >= LiveArea.GetLength(0))
                return;
            if (y < 0 || y >= LiveArea.GetLength(1))
                return;

            LiveArea[x, y] = drawColor;
            guiField.Invalidate();
        }

        private void guiField_MouseUp(object sender, MouseEventArgs e)
        {
            isDrawing = false;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (!stepTimer.Enabled)
            {
                stepTimer.Enabled = true;
                stepTimer.Start();
                btnStart.Text = "Stopp";
            }
            else
            {
                stepTimer.Enabled = false;
                stepTimer.Stop();
                btnStart.Text = "Start";
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Einzelschritt();
        }

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            stepTimer.Interval = speedBar.Value;
        }
    }
}


Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 29.06.19 17:27 
Die Farbe von den toten Zellen hast du ja mittels
ausblenden C#-Quelltext
1:
Brush dead = Brushes.Black; // mit Großbuchstaben, nicht black					
bestimmt.
Und du hast ja keinen freien Hintergrund bei der PictureBox, denn in der Paint-Methode zeichnest du ja jeden Pixel (da du die Größe ja vorher entsprechend der Größe der LiveArea passend setzt).
Wenn du ein Raster sehen möchtest, dann zeichne (in der Schleife) vorher mittels DrawRectangle (oder FillRectangle) jeweils in einer anderen Farbe (und verkleinere dann nachfolgenden FillRectangle-Aufruf um z.B. je 1 Pixel).
RB92 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Sa 29.06.19 18:28 
Achso okay,das war mir noch gar nicht so richtig klar. Vielen Dank