C# :: Aufgabe #207

3 Lösungen Lösungen öffentlich

Minesweeper, der zündende Klassiker

Fortgeschrittener - C# von Exception - 16.05.2018 um 19:49 Uhr
Dieses Spielchen kennt sicher jeder...
...ein X * Y großes Spielfeld und die ein oder andere explosive Überraschung #boom ... :)

Ihr kennt Minesweeper nicht? Dann klickt hier!

Die Anforderungen:
1) Grafische Umsetzung
2) Das Spielfeld soll eine variable Größe haben (konfigurierbar vor dem Start)
3) Die einzelnen Minen sollen zufällig verteilt werden
4) Felder, die keine Mine enthalten zeigen nachdem sie angeklickt wurden die Anzahl der Minen, die sich im direkten Umkreis befinden.
5) Mit der rechten Maustaste kann der Spieler auf das Feld eine Fahne setzen, über dem er gerade mit dem Mauszeiger hovert und auf dem er eine Mine vermutet. Bei erneutem Rechtsklick wird die gesetzte Fahne wieder entfernt (Aufpassen dass nicht mehr Fahnen platziert werden können als es Minen gibt!)

Das Spiel endet...
... wenn ein Minenfeld angeklickt wurde / "explodiert" ist => Verloren
... oder bestenfalls, wenn alle Minen mit Fahnen markiert wurden => Sieg

Nice to have (optional):
- Ein Timer der anzeigt wie lange gebraucht wurde
- Bestenliste
- Anzahl der Minen kann eingestellt werden, sonst muss die Anzahl eben abhängig von der Feldgröße berechnet werden.
- Sound: Beim Feld anklicken, wenn Mine getroffen wurde, ...... #Kreativität

Lösungen:

vote_ok
von daniel59 (4260 Punkte) - 29.05.2018 um 14:58 Uhr
MainWindow.xaml.cs
Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Media;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace WpfMineSweeper
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        const int size = 25;
        const string mine = "bombe.jpg";
        const string flag = "flag.png";
        static readonly Random rnd = new Random();

        private List<Button> field;

        private List<Postion> positions;
        private DispatcherTimer timer;

        private int fieldWidth;
        private int fieldHeight;
        private int mines;
        public int LeftFlags => mines - positions.Count(a => a.HasFlag);
        private bool started = false;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void CreateField(int width, int height, int mines)
        {
            positions = new List<Postion>();
            canvas.Children.Clear();
            field = new List<Button>();

            fieldWidth = width;
            fieldHeight = height;
            this.mines = mines;
            canvas.Width = size * width;
            canvas.Height = size * height;
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Button but = new Button()
                    {
                        Content = "",
                        Width = size,
                        Height = size,
                        Name = $"but_{x}_{y}",
                        FontWeight = FontWeights.Bold
                    };
                    positions.Add(new Postion() { X = x, Y = y });
                    but.PreviewMouseLeftButtonDown += But_PreviewMouseLeftButtonDown;
                    but.PreviewMouseRightButtonDown += But_PreviewMouseRightButtonDown;

                    Canvas.SetLeft(but, x * size);
                    Canvas.SetTop(but, y * size);

                    canvas.Children.Add(but);
                    field.Add(but);
                }
            }

            while (positions.Count(a => a.IsMine) < mines)
            {
                var temp = positions.Where(a => !a.IsMine);
                temp.ElementAt(rnd.Next(0, temp.Count())).IsMine = true;
            }
            for (int i = 0; i < positions.Count; i++)
            {
                Postion cur = positions[i];

                var temp = positions.Where(a => (Math.Abs(cur.X - a.X) == 1 && Math.Abs(cur.Y - a.Y) == 0)
                 || (Math.Abs(cur.X - a.X) == 0 && Math.Abs(cur.Y - a.Y) == 1)
                 || (Math.Abs(cur.X - a.X) == 1 && Math.Abs(cur.Y - a.Y) == 1));

                positions[i].Mines = temp.Count(a => a.IsMine);
            }

            textBlockFlagsLeft.Text = $"Verbleibende Flaggen: {LeftFlags}";
        }

        private void StartGame()
        {
            timer = new DispatcherTimer();
            DateTime startTime = DateTime.Now;
            timer.Tick += delegate { textBlockTime.Text = (DateTime.Now - startTime).ToString("h'h 'm'm 's's'"); };
            timer.Interval = new TimeSpan(0, 0, 1);

            int w, h, m;
            if (int.TryParse(textBoxWidth.Text, out w) && w > 0 && int.TryParse(textBoxHeight.Text, out h) && h > 0 && int.TryParse(textBoxMines.Text, out m) && m > 0 && m < w * h)
            {
                CreateField(w, h, m);
            }
            else
            {
                MessageBox.Show("Falsche Eingaben");
                return;
            }
            started = true;
            buttonStartStop.Content = "Beenden";
            textBlockTime.Text = (new TimeSpan()).ToString("h'h 'm'm 's's'");
            timer.Start();
        }

        private void EndGame()
        {
            timer.Stop();
            started = false;
            buttonStartStop.Content = "Starten";
        }

        private void ExplosionSound()
        {
            Task.Factory.StartNew(delegate
            {
                SoundPlayer player = new SoundPlayer(Properties.Resources.bombExplosion);
                player.Play();
            });
        }

        private void ShowMines()
        {
            foreach (Postion pos in positions)
            {
                Button button = field.Single(a => a.Name == $"but_{pos.X}_{pos.Y}");
                if(pos.IsMine)
                {
                    button.Content = GetImage(mine);
                }

                else
                {
                    button.Content = pos.Mines.ToString(); 
                }
            }
        }

        static Image GetImage(string file)
        {
            Image img = new Image();
            BitmapImage source = new BitmapImage();
            source.BeginInit();
            source.UriSource = new Uri(file, UriKind.Relative);
            source.EndInit();

            img.Source = source;

            return img;
        }

        private void buttonStartStop_Click(object sender, RoutedEventArgs e)
        {
            if (!started)
            {
                StartGame();
            }
            else
            {
                EndGame();
            }
        }

        private void But_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (started)
            {
                Button caller = (Button)sender;

                int x, y;
                var split = caller.Name.Split('_');
                x = int.Parse(split[1]);
                y = int.Parse(split[2]);

                var pos = positions.SingleOrDefault(a => a.X == x && a.Y == y);

                if (pos.HasFlag)
                {
                    pos.HasFlag = false;
                    caller.Content = null;
                }
                else if (!pos.HasFlag && LeftFlags > 0)
                {
                    pos.HasFlag = true;

                    caller.Content = GetImage(flag);

                    if (positions.Where(a => a.HasFlag && a.IsMine).Count() == mines)
                    {
                        EndGame();
                        MessageBox.Show("Du hast alle Minen gefunden. Das Spiel ist vorbei!");
                    }
                }

                textBlockFlagsLeft.Text = $"Verbleibende Flaggen: {LeftFlags}";
            }
        }

        private void But_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (started)
            {
                Button caller = (Button)sender;

                int x, y;
                var split = caller.Name.Split('_');
                x = int.Parse(split[1]);
                y = int.Parse(split[2]);

                var pos = positions.SingleOrDefault(a => a.X == x && a.Y == y);
                if (pos.HasFlag)
                {
                    pos.HasFlag = false;
                    textBlockFlagsLeft.Text = $"Verbleibende Flaggen: {LeftFlags}";
                }
                if (pos.IsMine)
                {
                    caller.Content = GetImage(mine);
                    EndGame();
                    ExplosionSound();
                    ShowMines();
                    MessageBox.Show("Du bist leider auf eine Mine getreten. Das Spiel ist vorbei!");
                }
                else
                {
                    caller.Content = pos.Mines;
                }
            }
        }
    }

    class Postion
    {
        public int X { get; set; }
        public int Y { get; set; }

        public bool IsMine { get; set; }
        public int Mines { get; set; }
        public bool HasFlag { get; set; }

        public override bool Equals(object obj)
        {
            Postion p = (Postion)obj;

            return X == p.X && Y == p.Y;
        }

        public override int GetHashCode()
        {
            int hash = 13;
            hash = (hash * 7) + X.GetHashCode();
            hash = (hash * 7) + Y.GetHashCode();
            return base.GetHashCode();
        }
    }
}


MainWindow.xaml
Quellcode ausblenden XML-Code
<Window x:Class="WpfMineSweeper.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfMineSweeper"
        mc:Ignorable="d"
        Title="MainWindow" Height="550" Width="725" x:Name="main">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid Margin="0,10,0,0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>
            <Grid Grid.Column="0">
                <TextBlock Text="Spielfeldbreite" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,3,0,0"/>
                <TextBox x:Name="textBoxWidth" Width="50" Text="10" TextAlignment="Center" Margin="91,0,0,0"/>
            </Grid>
            <Grid Grid.Column="1">
                <TextBlock Text="Spielfeldhöhe" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,3,0,0"/>
                <TextBox x:Name="textBoxHeight" Width="50" Text="10" TextAlignment="Center" Margin="86,0,0,0"/>
            </Grid>
            <Grid Grid.Column="2">
                <TextBlock Text="Minen" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,3,0,0"/>
                <TextBox x:Name="textBoxMines" Width="50" Text="10" TextAlignment="Center" Margin="49,0,0,0"/>
            </Grid>
            <Button x:Name="buttonStartStop" Content="Start" Grid.Column="3" HorizontalAlignment="Left" Margin="10,2,0,0" VerticalAlignment="Top" Width="75" Click="buttonStartStop_Click"/>
        </Grid>
        <ScrollViewer Grid.Row="1" Margin="10" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto"> 
            <Canvas x:Name="canvas" Background="LightGray"/>
        </ScrollViewer>
        <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="10,0,10,0" Background="LightGray">
            <TextBlock x:Name="textBlockTime" Margin="10,10"/>
            <TextBlock x:Name="textBlockFlagsLeft" Margin="10,10"/>
        </StackPanel>
    </Grid>
</Window>
vote_ok
von Z3RP (1020 Punkte) - 05.06.2018 um 08:20 Uhr
Die Win Form
Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MinesSweeperwForms
{
    public partial class Form1 : Form
    {
        Random rnd = new Random(DateTime.Now.Millisecond);
        int sizeX;
        int sizeY;
        int bombsCount;
        int flagCount;
        Bitmap MSFlag;
        Bitmap MSBomb;
        bool alive;
        bool wonGame;
        public Form1()
        {
            InitializeComponent();
            MSFlag = (Bitmap)Image.FromFile(@"C:\Users\npreen.CARGOSOFT\Pictures\MSFlag.png");
            MSBomb = (Bitmap)Image.FromFile(@"C:\Users\npreen.CARGOSOFT\Pictures\MSBomb.png");
            alive = true;
        }

        TextBox sizeXTb;
        TextBox sizeYTb;
        TextBox bombsTb;
        Form settings;
        private void Form1_Load(object sender, EventArgs e)
        {
            settings = new Form();
            settings.Location = new Point(Location.X, Location.Y);
            settings.Width = 300;
            settings.Height = 150;
            settings.FormBorderStyle = FormBorderStyle.FixedSingle;
            settings.ControlBox = false;

            Label sizeLbl = new Label();
            sizeLbl.Text = "Size: X / Y";
            sizeLbl.Bounds = new Rectangle(50, 20, 100, 20);

            Label bombsLbl = new Label();
            bombsLbl.Text = "Bombs:(16%)";
            bombsLbl.Bounds = new Rectangle(50, 70, 100, 20);

            sizeXTb = new TextBox();
            sizeXTb.Bounds = new Rectangle(50, 40, 50, 20);
            sizeXTb.KeyPress += textBox_KeyPress;
            sizeXTb.Text = "10";

            sizeYTb = new TextBox();
            sizeYTb.Bounds = new Rectangle(110, 40, 50, 20);
            sizeYTb.KeyPress += textBox_KeyPress;
            sizeYTb.Text = "10";

            bombsTb = new TextBox();
            bombsTb.Bounds = new Rectangle(50, 90, 50, 20);
            bombsTb.KeyPress += textBoxBomb_KeyPress;
            bombsTb.Text = "";

            Button generateBtn = new Button();
            generateBtn.Bounds = new Rectangle(100, 120, 100, 20);
            generateBtn.Text = "Generate";
            generateBtn.Click += GenerateMap;


            settings.Controls.Add(generateBtn);
            settings.Controls.Add(sizeLbl);
            settings.Controls.Add(sizeXTb);
            settings.Controls.Add(sizeYTb);
            settings.Controls.Add(bombsLbl);
            settings.Controls.Add(bombsTb);
            settings.ShowDialog();
        }

        MSButton[,] buttons;
        List<MSButton> bombButtons = new List<MSButton>();

        private void GenerateMap(object sender, EventArgs e)
        {
            sizeX = Convert.ToInt32(sizeXTb.Text);
            sizeY = Convert.ToInt32(sizeYTb.Text);
            if(bombsTb.Text.Length > 0)
            {
                bombsCount = Convert.ToInt32(bombsTb.Text);
            }
            else
            {
                bombsCount = (int)((sizeX * sizeY) * 0.16);
            }
            
            settings.Close();

            Width = sizeX * 20 + 30;
            Height = sizeY * 20 + 50;

            buttons = new MSButton[sizeX, sizeY];

            for (int x = 0; x < sizeX; x++)
            {
                for (int y = 0; y < sizeY; y++)
                {
                    buttons[x, y] = new MSButton(x, y, this);
                    Controls.Add(buttons[x, y].btn);
                }
            }

            List<MSButton> tempButtons = buttons.OfType<MSButton>().ToList();


            for (int i = 0; i < bombsCount; i++)
            {
                MSButton msb = tempButtons[rnd.Next(tempButtons.Count)];
                buttons[msb.gridX, msb.gridY].isBomb = true;
                setButtonValue(msb);
                bombButtons.Add(msb);
                tempButtons.Remove(msb);
            }

            gameTime.Enabled = true;
        }

        private void setButtonValue(MSButton msb)
        {
            if (msb.gridX > 0)
            {
                buttons[msb.gridX - 1, msb.gridY].addOne();
            }
            if (msb.gridX > 0 && msb.gridY > 0)
            {
                buttons[msb.gridX - 1, msb.gridY - 1].addOne();
            }
            if (msb.gridY > 0)
            {
                buttons[msb.gridX, msb.gridY - 1].addOne();
            }
            if (msb.gridY > 0 && msb.gridX < (sizeX - 1))
            {
                buttons[msb.gridX + 1, msb.gridY - 1].addOne();
            }
            if (msb.gridX < (sizeX - 1))
            {
                buttons[msb.gridX + 1, msb.gridY].addOne();
            }
            if (msb.gridY < (sizeY - 1) && msb.gridX < (sizeX - 1))
            {
                buttons[msb.gridX + 1, msb.gridY + 1].addOne();
            }
            if (msb.gridY < (sizeY - 1))
            {
                buttons[msb.gridX, msb.gridY + 1].addOne();
            }
            if (msb.gridY < (sizeY - 1) && msb.gridX > 0)
            {
                buttons[msb.gridX - 1, msb.gridY + 1].addOne();
            }
        }
        private void checkAdjacented(MSButton msb)
        {
            MSButton tempButton;

            if (msb.gridX > 0)
            {
                tempButton = buttons[msb.gridX - 1, msb.gridY];
                checkButton(tempButton);
            }
            if (msb.gridX > 0 && msb.gridY > 0)
            {
                tempButton = buttons[msb.gridX - 1, msb.gridY - 1];
                checkButton(tempButton);
            }
            if (msb.gridY > 0)
            {
                tempButton = buttons[msb.gridX, msb.gridY - 1];
                checkButton(tempButton);
            }
            if (msb.gridY > 0 && msb.gridX < (sizeX - 1))
            {
                tempButton = buttons[msb.gridX + 1, msb.gridY - 1];
                checkButton(tempButton);
            }
            if (msb.gridX < (sizeX - 1))
            {
                tempButton = buttons[msb.gridX + 1, msb.gridY];
                checkButton(tempButton);
            }
            if (msb.gridY < (sizeY - 1) && msb.gridX < (sizeX - 1))
            {
                tempButton = buttons[msb.gridX + 1, msb.gridY + 1];
                checkButton(tempButton);
            }
            if (msb.gridY < (sizeY - 1))
            {
                tempButton = buttons[msb.gridX, msb.gridY + 1];
                checkButton(tempButton);
            }
            if (msb.gridY < (sizeY - 1) && msb.gridX > 0)
            {
                tempButton = buttons[msb.gridX - 1, msb.gridY + 1];
                checkButton(tempButton);
            }
        }

        private void checkButton(MSButton tempButton)
        {
            if (!tempButton.isChecked)
            {
                tempButton.isChecked = true;
                if (tempButton.value == 0)
                {
                    tempButton.btn.Enabled = false;
                    checkAdjacented(tempButton);
                }
                else
                {
                    tempButton.btn.Text = tempButton.value.ToString();
                }
                tempButton.btn.BackColor = Color.DarkGray;
            }
        }

        private void textBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
                (e.KeyChar != '.'))
            {
                e.Handled = true;
            }

            // only allow one decimal point
            if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
            {
                e.Handled = true;
            }
        }

        private void textBoxBomb_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
                (e.KeyChar != '.'))
            {
                e.Handled = true;
            }

            // only allow one decimal point
            if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
            {
                e.Handled = true;
            }

            if (!char.IsControl(e.KeyChar) && bombsTb.Text.Length > 0)
            {
                if ((Convert.ToInt32(bombsTb.Text) + e.KeyChar) > Convert.ToInt32(sizeXTb.Text) * Convert.ToInt32(sizeYTb.Text))
                {
                    e.Handled = true;
                }
            }
            else
            {
                if (e.KeyChar > Convert.ToInt32(sizeXTb.Text) * Convert.ToInt32(sizeYTb.Text))
                {
                    e.Handled = true;
                }
            }

        }

        public void leftClickButton(MSButton msBtn)
        {
            if (alive)
            {
                if (msBtn.isBomb)
                {
                    GameOver();
                }
                else
                {
                    if (msBtn.value == 0)
                    {
                        msBtn.btn.Enabled = false;
                        checkAdjacented(msBtn);
                    }
                    else
                    {
                        msBtn.btn.Text = msBtn.value.ToString();
                    }
                    msBtn.btn.BackColor = Color.DarkGray;
                }
            }
        }

        private void GameOver()
        {
            alive = false;
            gameTime.Enabled = false;
            foreach (MSButton btn in bombButtons)
            {
                btn.btn.BackgroundImage = MSBomb;
            }
            gameState.Text = "Lost!";
        }

        private void GameWon()
        {
            alive = false;
            gameTime.Enabled = false;
            gameState.Text = "Won!";
        }

        public void rightClickButton(MSButton msBtn)
        {
            if (alive && flagCount < bombsCount)
            {
                if (msBtn.isFlagged)
                {
                    msBtn.btn.BackgroundImage = null;
                    msBtn.isFlagged = false;
                    flagCount--;

                }
                else
                {
                    msBtn.btn.BackgroundImage = MSFlag;
                    msBtn.isFlagged = true;
                    flagCount++;

                    bool allFlagged = true;
                    foreach (MSButton btn in bombButtons)
                    {
                        allFlagged = btn.isFlagged;
                    }

                    if (allFlagged)
                    {
                        GameWon();
                    }
                }

                flagLabel.Text = flagCount.ToString();
            }
        }

        private int time;
        private void gameTime_Tick(object sender, EventArgs e)
        {
            time++;
            timeLabel.Text = time.ToString();
        }
    }
}


Der Designer
Quellcode ausblenden C#-Code
namespace MinesSweeperwForms
{
    partial class Form1
    {
        /// <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.timeLabel = new System.Windows.Forms.Label();
            this.flagLabel = new System.Windows.Forms.Label();
            this.gameState = new System.Windows.Forms.Label();
            this.gameTime = new System.Windows.Forms.Timer(this.components);
            this.SuspendLayout();
            // 
            // timeLabel
            // 
            this.timeLabel.AutoSize = true;
            this.timeLabel.Location = new System.Drawing.Point(38, 3);
            this.timeLabel.Name = "timeLabel";
            this.timeLabel.Size = new System.Drawing.Size(0, 13);
            this.timeLabel.TabIndex = 0;
            // 
            // flagLabel
            // 
            this.flagLabel.AutoSize = true;
            this.flagLabel.Location = new System.Drawing.Point(103, 3);
            this.flagLabel.Name = "flagLabel";
            this.flagLabel.Size = new System.Drawing.Size(0, 13);
            this.flagLabel.TabIndex = 0;
            // 
            // gameState
            // 
            this.gameState.AutoSize = true;
            this.gameState.Location = new System.Drawing.Point(190, 3);
            this.gameState.Name = "gameState";
            this.gameState.Size = new System.Drawing.Size(0, 13);
            this.gameState.TabIndex = 0;
            // 
            // gameTime
            // 
            this.gameTime.Interval = 1000;
            this.gameTime.Tick += new System.EventHandler(this.gameTime_Tick);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(700, 489);
            this.Controls.Add(this.gameState);
            this.Controls.Add(this.flagLabel);
            this.Controls.Add(this.timeLabel);
            this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.Name = "Form1";
            this.Text = "MinesSweeper";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label timeLabel;
        private System.Windows.Forms.Label flagLabel;
        private System.Windows.Forms.Label gameState;
        private System.Windows.Forms.Timer gameTime;
    }
}



MSButton

Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MinesSweeperwForms
{
    public class MSButton
    {
        public Button btn { get; set; }
        public int gridX { get; set; }
        public int gridY { get; set; }
        public Form1 parent { get; set; }
        public bool isFlagged { get; set; }
        public bool isBomb { get; set; }
        public int value { get; set; }
        public bool isChecked { get; set; }

        public MSButton(int gridX, int gridY, Form parent)
        {
            this.parent = (Form1)parent;
            this.gridX = gridX;
            this.gridY = gridY;

            isFlagged = false;
            isChecked = false;
            isBomb = false;
            value = 0;

            btn = new Button();
            btn.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            btn.BackgroundImageLayout = ImageLayout.Stretch;
            btn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            btn.Location = new System.Drawing.Point(gridX*20 +12, gridY * 20 + 12);
            btn.Size = new System.Drawing.Size(20, 20);
            btn.UseVisualStyleBackColor = true;
            btn.MouseDown += MouseDown;
        }

        public void addOne()
        {
            value++;
        }

        private void MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                parent.leftClickButton(this);
            }
            if (e.Button == MouseButtons.Right)
            {
                parent.rightClickButton(this);
            }
        }
    }
}
vote_ok
von Mexx (2370 Punkte) - 11.11.2018 um 20:13 Uhr
Hi, hier mal meine Lösung. Von der Funktionsweise und dem Design habe ich mich am Original orientiert.

Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Minesweeper_Clone
{
    public partial class Form1 : Form
    {
        Spielfeld sf;
        public Form1()
        {
            InitializeComponent();
        }

        private void F_Click(object sender, EventArgs e)
        {
            Feld f = sender as Feld;
            if (f.IsBorder)
                return;

            if (f.IsBomb && (e as MouseEventArgs).Button == MouseButtons.Left && !f.IsFahne)
            {
                f.Clicked((e as MouseEventArgs).Button);
                MessageBox.Show("Verloren");
                return;
            }

            f.Clicked((e as MouseEventArgs).Button);

            if (Spielfeld.Completed)
                MessageBox.Show("Gewonnen");
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            sf = null;
            sf = new Spielfeld((int)nudSize.Value, (int)nudSize.Value, (int)nudBombs.Value);

            foreach (Feld f in sf.Gamepannel)
            {
                f.Click += F_Click;
                scPanel.Panel2.Controls.Add(f);
            }
            this.Invalidate();
        }
    }
}


Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Minesweeper_Clone
{
    class Spielfeld
    {
        static Feld[,] gamepannel;
        static int openFields;
        static int felderCount;
        static int bombCount;
        static bool completed;

        public Feld[,] Gamepannel
        {
            get { return gamepannel; }
        }

        public static int OpenFields
        {
            get { return openFields; }
            set
            {
                openFields = value;
                if (openFields == felderCount - bombCount)
                    completed = true;
            }
        }

        public static bool Completed
        {
            get { return completed; }
        }
        public Spielfeld(int breite, int länge, int bombs)
        {
            bombCount = bombs;
            felderCount = breite * länge;
            openFields = 0;
            completed = false;
            gamepannel = new Feld[breite + 2, länge + 2];

            for (int i = 0; i < breite + 2; i++)
                gamepannel[0, i] = new Feld(0, i, true);
            for (int i = 0; i < länge + 2; i++)
                gamepannel[i, 0] = new Feld(i, 0, true);
            for (int i = 0; i < breite + 2; i++)
                gamepannel[breite + 1, i] = new Feld(breite + 1, i, true);
            for (int i = 0; i < länge + 2; i++)
                gamepannel[i, länge + 1] = new Feld(i, länge + 1, true);

            for (int i = 1; i <= breite; i++)
                for (int y = 1; y <= länge; y++)
                    gamepannel[i, y] = new Feld(i, y, false);

            for (int i = 0; i < bombCount; i++)
            {
                Random ran = new Random();
                int rx = ran.Next(1, breite + 1);
                int ry = ran.Next(1, länge + 1);

                if (gamepannel[rx, ry].IsBomb)
                {
                    i--;
                    continue;
                }

                gamepannel[rx, ry].IsBomb = true;
            }

            foreach (Feld f in gamepannel)
            {
                if (!f.IsBorder && !f.IsBomb)
                {
                    for (int i = f.X - 1; i <= f.X + 1; i++)
                        for (int y = f.Y - 1; y <= f.Y + 1; y++)
                            if (!gamepannel[i, y].IsBorder)
                                if (gamepannel[i, y].IsBomb)
                                    f.BombCount++;
                }
            }
        }
        public static void Freilegen(Feld f)
        {
            for (int i = f.X - 1; i <= f.X + 1; i++)
                for (int y = f.Y - 1; y <= f.Y + 1; y++)
                    if (!gamepannel[i, y].IsBorder)
                        gamepannel[i, y].Clicked(MouseButtons.Left);
        }
    }

    class Feld : PictureBox
    {
        const int rand = 30;
        const int feldgrösse = 30;
        bool isBomb;
        bool isBorder;
        bool isFahne;
        bool isOpened;
        int bombCount;
        int x;
        int y;

        public bool IsBomb
        {
            get { return isBomb; }
            set { isBomb = value; }
        }

        public bool IsBorder
        {
            get { return isBorder; }
            set
            {
                isBorder = value;
                if (value)
                    this.BackColor = Color.Black;
            }
        }

        public bool IsFahne
        {
            get { return isFahne; }
        }
        public int BombCount
        {
            get { return bombCount; }
            set { bombCount = value; }
        }

        public int X
        {
            get { return x; }
        }

        public int Y
        {
            get { return y; }
        }
        public Feld(int x, int y, bool boarder)
        {
            this.isOpened = false;
            this.isFahne = false;
            this.BackColor = Color.Gray;
            this.BackgroundImageLayout = ImageLayout.Stretch;
            this.x = x;
            this.y = y;
            this.Location = new Point(x * feldgrösse + rand, y * feldgrösse + rand);
            this.BorderStyle = BorderStyle.FixedSingle;
            this.Width = feldgrösse;
            this.Height = feldgrösse;
            this.IsBorder = boarder;
            this.IsBomb = false;
        }

        public void Clicked(MouseButtons b)
        {
            if (this.isOpened)
                return;

            if (b == MouseButtons.Left && !this.isFahne)
            {
                this.isOpened = true;
                Spielfeld.OpenFields++;

                if (isBomb)
                {
                    this.BackgroundImage = Image.FromFile(@"images/bomb.jpg");
                    return;
                }

                switch (bombCount)
                {
                    case 0:
                        this.BackColor = Color.White;
                         Spielfeld.Freilegen(this);
                        break;
                    case 1:
                        this.BackgroundImage = Image.FromFile(@"images/eins.jpg");
                        break;
                    case 2:
                        this.BackgroundImage = Image.FromFile(@"images/zwei.jpg");
                        break;
                    case 3:
                        this.BackgroundImage = Image.FromFile(@"images/drei.jpg");
                        break;
                    case 4:
                        this.BackgroundImage = Image.FromFile(@"images/vier.jpg");
                        break;
                    case 5:
                        this.BackgroundImage = Image.FromFile(@"images/fuenf.jpg");
                        break;
                    case 6:
                        this.BackgroundImage = Image.FromFile(@"images/sechs.jpg");
                        break;
                    case 7:
                        this.BackgroundImage = Image.FromFile(@"images/sieben.jpg");
                        break;
                    case 8:
                        this.BackgroundImage = Image.FromFile(@"images/acht.jpg");
                        break;
                    default:
                        break;
                }
            }

            if (b == MouseButtons.Right)
                if (!isFahne)
                {
                    this.isFahne = true;
                    this.BackgroundImage = Image.FromFile(@"images/fahne.png");
                }
                else
                {
                    this.isFahne = false;
                    this.BackgroundImage = null;
                    this.BackColor = Color.Gray;
                }
        }
    }
}