So, habe gerade das ganze in C# fertiggestellt.
Dieses mal war das ganze etwas einfacher, finde ich aber auch besser
Meine Lösung stellt das ganze grafisch dar und hat ein paar weitere Sachen mit dabei.
Vielleicht werde ich dann noch irgendwann anders ein paar Erweiterungen dazumachen.
Kommentiert ist es dieses mal nicht so toll, da ich dafür jetzt keine Zeit mehr habe..
Program.cs:
MainForm.cs:
MainForm.Designer.cs (Designer-Code von Visual Studio zu MainForm.cs):
Feld.cs (das Feld):
Edit: Habe das ganze noch schnell etwas geändert, damit es nicht mehr so flackert.
MfG
Fabsch
Dieses mal war das ganze etwas einfacher, finde ich aber auch besser

Meine Lösung stellt das ganze grafisch dar und hat ein paar weitere Sachen mit dabei.
Vielleicht werde ich dann noch irgendwann anders ein paar Erweiterungen dazumachen.
Kommentiert ist es dieses mal nicht so toll, da ich dafür jetzt keine Zeit mehr habe..
Program.cs:
Code:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace QUIZ_7_SpielDesLebens
{
static class Program
{
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
MainForm.cs:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace QUIZ_7_SpielDesLebens
{
public partial class MainForm : Form
{
/// <summary>
/// Anzahl der Generationen, die noch berechnet werden sollen.
///
/// </summary>
private int GenerationsLeft = -1;
public MainForm()
{
InitializeComponent();
}
private void btnNextGen_Click(object sender, EventArgs e)
{
feld1.NextGen();
}
private void btnApply_Click(object sender, EventArgs e)
{
this.Controls.Remove(feld1);
Size oldSize = this.feld1.Size;
this.feld1 = new Feld((int)this.nudFieldWidth.Value, (int)this.nudFieldHeight.Value);
this.feld1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
this.feld1.Location = new System.Drawing.Point(13, 13);
this.feld1.Size = oldSize;
this.Controls.Add(feld1);
}
private void btnStart_Click(object sender, EventArgs e)
{
if (btnApply.Enabled)
{
//läuft noch nicht
// Apply-Button deaktivieren
btnApply.Enabled = false;
// NextGen-Button deaktivieren
btnNextGen.Enabled = false;
//Text auf dem Start/Stop-Button ändern
btnStart.Text = "Stop";
this.GenerationsLeft = (int)(nudGenerations.Value == 0 ? -1 : nudGenerations.Value);
tmrTicker.Interval = (int)nudDelay.Value;
tmrTicker.Start();
}
else
{
// läuft bereits -> anhalten
// Apply-Button aktivieren
btnApply.Enabled = true;
// NextGen-Button aktivieren
btnNextGen.Enabled = true;
//Text auf dem Start/Stop-Button ändern
btnStart.Text = "Start";
tmrTicker.Stop();
}
}
private void tmrTicker_Tick(object sender, EventArgs e)
{
if (GenerationsLeft == -1 || GenerationsLeft > 0)
{
feld1.NextGen();
if (GenerationsLeft > 0)
{
GenerationsLeft--;
}
}
else
{
btnStart_Click(sender, e);
}
}
}
}
MainForm.Designer.cs (Designer-Code von Visual Studio zu MainForm.cs):
Code:
namespace QUIZ_7_SpielDesLebens
{
partial class MainForm
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Windows Form-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.btnNextGen = new System.Windows.Forms.Button();
this.btnStart = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.nudFieldWidth = new System.Windows.Forms.NumericUpDown();
this.label2 = new System.Windows.Forms.Label();
this.nudFieldHeight = new System.Windows.Forms.NumericUpDown();
this.label3 = new System.Windows.Forms.Label();
this.nudGenerations = new System.Windows.Forms.NumericUpDown();
thisInfo = new System.Windows.Forms.ToolTip(this.components);
this.btnApply = new System.Windows.Forms.Button();
this.nudDelay = new System.Windows.Forms.NumericUpDown();
this.label4 = new System.Windows.Forms.Label();
this.tmrTicker = new System.Windows.Forms.Timer(this.components);
this.feld1 = new QUIZ_7_SpielDesLebens.Feld();
((System.ComponentModel.ISupportInitialize)(this.nudFieldWidth)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudFieldHeight)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudGenerations)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudDelay)).BeginInit();
this.SuspendLayout();
//
// btnNextGen
//
this.btnNextGen.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnNextGen.Location = new System.Drawing.Point(382, 274);
this.btnNextGen.Name = "btnNextGen";
this.btnNextGen.Size = new System.Drawing.Size(200, 23);
this.btnNextGen.TabIndex = 1;
this.btnNextGen.Text = "Nächste Generation";
thisInfo.SetToolTip(this.btnNextGen, "Berechnet eine Generation weiter.");
this.btnNextGen.UseVisualStyleBackColor = true;
this.btnNextGen.Click += new System.EventHandler(this.btnNextGen_Click);
//
// btnStart
//
this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnStart.Location = new System.Drawing.Point(383, 245);
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(199, 23);
this.btnStart.TabIndex = 2;
this.btnStart.Text = "Start";
thisInfo.SetToolTip(this.btnStart, "Startet/Stoppt die Berechnung über die angegebene Anzahl an Generationen.");
this.btnStart.UseVisualStyleBackColor = true;
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(379, 15);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(37, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Breite:";
//
// nudFieldWidth
//
this.nudFieldWidth.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.nudFieldWidth.Location = new System.Drawing.Point(422, 13);
this.nudFieldWidth.Maximum = new decimal(new int[] {
1000,
0,
0,
0});
this.nudFieldWidth.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.nudFieldWidth.Name = "nudFieldWidth";
this.nudFieldWidth.Size = new System.Drawing.Size(56, 20);
this.nudFieldWidth.TabIndex = 4;
thisInfo.SetToolTip(this.nudFieldWidth, "Die Breite des Spielfeldes in Feldern");
this.nudFieldWidth.Value = new decimal(new int[] {
30,
0,
0,
0});
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(484, 15);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(36, 13);
this.label2.TabIndex = 5;
this.label2.Text = "Höhe:";
//
// nudFieldHeight
//
this.nudFieldHeight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.nudFieldHeight.Location = new System.Drawing.Point(526, 13);
this.nudFieldHeight.Maximum = new decimal(new int[] {
1000,
0,
0,
0});
this.nudFieldHeight.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.nudFieldHeight.Name = "nudFieldHeight";
this.nudFieldHeight.Size = new System.Drawing.Size(56, 20);
this.nudFieldHeight.TabIndex = 6;
thisInfo.SetToolTip(this.nudFieldHeight, "Die Höhe des Spielfeldes in Feldern.");
this.nudFieldHeight.Value = new decimal(new int[] {
20,
0,
0,
0});
//
// label3
//
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(380, 74);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(74, 13);
this.label3.TabIndex = 7;
this.label3.Text = "Generationen:";
//
// nudGenerations
//
this.nudGenerations.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.nudGenerations.Location = new System.Drawing.Point(462, 72);
this.nudGenerations.Maximum = new decimal(new int[] {
10000,
0,
0,
0});
this.nudGenerations.Name = "nudGenerations";
this.nudGenerations.Size = new System.Drawing.Size(120, 20);
this.nudGenerations.TabIndex = 8;
thisInfo.SetToolTip(this.nudGenerations, "Gib hier die Anzahl der Generationen an, die berechnet werden sollen.\r\nBei 0 wird" +
" solange weiterberechnet, bis wieder auf Stop gedrückt wird.");
//
// btnApply
//
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnApply.Location = new System.Drawing.Point(382, 39);
this.btnApply.Name = "btnApply";
this.btnApply.Size = new System.Drawing.Size(200, 23);
this.btnApply.TabIndex = 9;
this.btnApply.Text = "Anwenden";
thisInfo.SetToolTip(this.btnApply, "Wendet die Größe auf das Spielfeld an.\r\nAlle enthaltenen Felder werden zurückgese" +
"tzt!");
this.btnApply.UseVisualStyleBackColor = true;
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
//
// nudDelay
//
this.nudDelay.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.nudDelay.Location = new System.Drawing.Point(462, 106);
this.nudDelay.Maximum = new decimal(new int[] {
5000,
0,
0,
0});
this.nudDelay.Minimum = new decimal(new int[] {
50,
0,
0,
0});
this.nudDelay.Name = "nudDelay";
this.nudDelay.Size = new System.Drawing.Size(120, 20);
this.nudDelay.TabIndex = 11;
thisInfo.SetToolTip(this.nudDelay, "Zeit, die nach dem Berechnen einer Generation gewartet werden soll, bis die nächs" +
"te berechnet wird (in Millisekunden).");
this.nudDelay.Value = new decimal(new int[] {
100,
0,
0,
0});
//
// label4
//
this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(383, 106);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(70, 13);
this.label4.TabIndex = 10;
this.label4.Text = "Verzögerung:";
//
// tmrTicker
//
this.tmrTicker.Tick += new System.EventHandler(this.tmrTicker_Tick);
//
// feld1
//
this.feld1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.feld1.Location = new System.Drawing.Point(13, 13);
this.feld1.Name = "feld1";
this.feld1.Size = new System.Drawing.Size(364, 284);
this.feld1.TabIndex = 0;
this.feld1.Text = "feld1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(594, 310);
this.Controls.Add(this.nudDelay);
this.Controls.Add(this.label4);
this.Controls.Add(this.btnApply);
this.Controls.Add(this.nudGenerations);
this.Controls.Add(this.label3);
this.Controls.Add(this.nudFieldHeight);
this.Controls.Add(this.label2);
this.Controls.Add(this.nudFieldWidth);
this.Controls.Add(this.label1);
this.Controls.Add(this.btnStart);
this.Controls.Add(this.btnNextGen);
this.Controls.Add(this.feld1);
this.DoubleBuffered = true;
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.nudFieldWidth)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudFieldHeight)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudGenerations)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudDelay)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Feld feld1;
private System.Windows.Forms.Button btnNextGen;
private System.Windows.Forms.Button btnStart;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.NumericUpDown nudFieldWidth;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.NumericUpDown nudFieldHeight;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.NumericUpDown nudGenerations;
private System.Windows.Forms.ToolTip ttInfo;
private System.Windows.Forms.Button btnApply;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.NumericUpDown nudDelay;
private System.Windows.Forms.Timer tmrTicker;
}
}
Feld.cs (das Feld):
Code:
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace QUIZ_7_SpielDesLebens
{
public partial class Feld : Control
{
private int m_width = 30;
private int m_height = 20;
private int m_fieldsizeW = 10;
private int m_fieldsizeH = 10;
private float m_linewidth = 1;
private char[,] m_fields = new char[30, 20];
private char[,] m_fieldsOld = new char[30, 20];
private Bitmap m_grid = null;
/// <summary>
/// Gibt an, ob alles neu gezeichnet werden soll, wenn ein Feld geändert wird.
/// </summary>
private bool RedrawAll = false;
public Feld()
{
this.BackColor = SystemColors.Control;
this.m_fields = new char[this.m_width, this.m_height];
ResetAll();
this.m_fieldsOld = (char[,])this.m_fields.Clone();
this.MouseUp += new MouseEventHandler(Feld_MouseUp);
this.Resize += new EventHandler(Feld_Resize);
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}
public Feld(int width, int height)
{
this.BackColor = SystemColors.Control;
this.m_width = width;
this.m_height = height;
this.m_fields = new char[this.m_width, this.m_height];
ResetAll();
this.m_fieldsOld = (char[,])this.m_fields.Clone();
this.MouseUp += new MouseEventHandler(Feld_MouseUp);
this.Resize += new EventHandler(Feld_Resize);
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}
public void ResetAll()
{
for (int x = 0; x < this.m_width; x++)
{
for (int y = 0; y < this.m_height; y++)
{
this.m_fields[x, y] = 'x';
}
}
this.Refresh();
}
void Feld_Resize(object sender, EventArgs e)
{
this.m_fieldsizeW = (int)Math.Floor((decimal)((this.Width - (this.m_width + 1) * this.m_linewidth) / this.m_width));
this.m_fieldsizeH = (int)Math.Floor((decimal)((this.Height - (this.m_height + 1) * this.m_linewidth) / this.m_height));
this.Refresh();
}
void Feld_MouseUp(object sender, MouseEventArgs e)
{
try
{
KeyValuePair<int, int> field = GetFieldByPosition(e.X, e.Y);
int x = GetPositionByField(field.Key, true);
int y = GetPositionByField(field.Value, false);
char curVal = this.m_fields[field.Key, field.Value];
this.m_fields[field.Key, field.Value] = (curVal == 'o' ? 'x' : 'o');
if (this.RedrawAll)
{
this.Refresh();
}
else
{
InvalidateCell(field.Key, field.Value);
}
}
catch { }
}
private void InvalidateCell(int x, int y)
{
x = GetPositionByField(x, true);
y = GetPositionByField(y, false);
this.Invalidate(new Rectangle(x + 1, y + 1, this.m_fieldsizeW, this.m_fieldsizeH));
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
//if (this.m_grid != null)
//{
// g.DrawImage(this.m_grid, new Point(0, 0));
//}
//else
{
int width_px = GetPositionByField(this.m_width, true);
int height_px = GetPositionByField(this.m_height, false);
for (int x = 0; x <= (int)Math.Max(this.m_width, this.m_height); x++)
{
if (x <= this.m_width)
{
// von oben nach unten zeichnen
int curX = GetPositionByField(x, true);
g.DrawLine(new Pen(Brushes.Black, this.m_linewidth), new Point(curX, 0), new Point(curX, height_px));
}
if (x <= this.m_height)
{
// von links nach rechts zeichnen
int curY = GetPositionByField(x, false);
g.DrawLine(new Pen(Brushes.Black, this.m_linewidth), new Point(0, curY), new Point(width_px, curY));
}
}
for (int x = 0; x < this.m_width; x++)
{
for (int y = 0; y < this.m_height; y++)
{
int curFieldPosX = GetPositionByField(x, true) + (int)this.m_linewidth;
int curFieldPosY = GetPositionByField(y, false) + (int)this.m_linewidth;
Rectangle rect = new Rectangle(curFieldPosX, curFieldPosY, this.m_fieldsizeW, this.m_fieldsizeH);
if (this.m_fields[x, y] == 'o')
{
// eine Zelle
g.FillRectangle(Brushes.Aqua, rect);
}
else
{
// leer
g.FillRectangle(Brushes.White, rect);
}
}
}
//this.m_grid = new Bitmap(this.Width, this.Height);
//this.DrawToBitmap(this.m_grid, new Rectangle(0, 0, this.Width, this.Height));
}
}
private int GetPositionByField(int field, bool W)
{
if (W)
{
return field * this.m_fieldsizeW + field * (int)this.m_linewidth;
}
else
{
return field * this.m_fieldsizeH + field * (int)this.m_linewidth;
}
}
private KeyValuePair<int, int> GetFieldByPosition(int x, int y)
{
int key = x / (this.m_fieldsizeW + (int)this.m_linewidth);
int value = y / (this.m_fieldsizeH + (int)this.m_linewidth);
return new KeyValuePair<int, int>(key, value);
}
public void NextGen()
{
this.m_fieldsOld = (char[,])this.m_fields.Clone();
for (int x = 0; x < this.m_width; x++)
{
for (int y = 0; y < this.m_height; y++)
{
char curField = this.m_fieldsOld[x, y];
int livingNeighbors = 0;
// Nachbar links oben
livingNeighbors = GetFieldValue(x - 1, y - 1, true) == 'o' ? livingNeighbors + 1 : livingNeighbors;
// Nachbar oben
livingNeighbors = GetFieldValue(x, y - 1, true) == 'o' ? livingNeighbors + 1 : livingNeighbors;
// Nachbar rechts oben
livingNeighbors = GetFieldValue(x + 1, y - 1, true) == 'o' ? livingNeighbors + 1 : livingNeighbors;
// Nachbar rechts
livingNeighbors = GetFieldValue(x + 1, y, true) == 'o' ? livingNeighbors + 1 : livingNeighbors;
// Nachbar rechts unten
livingNeighbors = GetFieldValue(x + 1, y + 1, true) == 'o' ? livingNeighbors + 1 : livingNeighbors;
// Nachbar unten
livingNeighbors = GetFieldValue(x, y + 1, true) == 'o' ? livingNeighbors + 1 : livingNeighbors;
// Nachbar unten links
livingNeighbors = GetFieldValue(x - 1, y + 1, true) == 'o' ? livingNeighbors + 1 : livingNeighbors;
// Nachbar links
livingNeighbors = GetFieldValue(x - 1, y, true) == 'o' ? livingNeighbors + 1 : livingNeighbors;
switch (livingNeighbors)
{
case 0:
case 1:
// hier ist in jedem Fall eine tote Zelle
this.m_fields[x, y] = 'x';
break;
case 2:
case 3:
// bleibt leben oder lebt wieder (nur bei 3)
this.m_fields[x, y] = (curField == 'x' ? (livingNeighbors == 3 ? 'o' : 'x') : 'o');
break;
default:
// stirbt an Überbevölkerung
this.m_fields[x, y] = 'x';
break;
}
if (curField != this.m_fields[x, y])
{
this.InvalidateCell(x, y);
}
}
}
//this.Refresh();
//this.Invalidate();
}
private char GetFieldValue(int x, int y, bool old)
{
if (x < 0 || x >= this.m_width || y < 0 || y >= this.m_height)
{
return 'x';
}
else
{
return (old ? this.m_fieldsOld[x, y] : this.m_fields[x, y]);
}
}
}
}
Edit: Habe das ganze noch schnell etwas geändert, damit es nicht mehr so flackert.
MfG
Fabsch
Anhänge
Zuletzt bearbeitet: