csharp 發表於 2021-7-12 11:13:36

memory game ok code

本帖最後由 csharp 於 2021-7-16 13:47 編輯

五十張消消樂,有音效,全代碼,適應各不同大小的螢幕。




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;
using System.Media;

namespace memorygame_0
{
    public partial class Form1 : Form
    {
      Rectangle currentScreen = Screen.PrimaryScreen.WorkingArea;//得出所使用螢幕之長寬值
      int w, h;//卡片的長和寬,本例二者是一樣高的,其實可以只用一個變數

      PictureBox[] pImage = new PictureBox;
      PictureBox[] pShow = new PictureBox;
      PictureBox[] pRandom = new PictureBox;
      bool[] matched = new bool;//記錄是否已翻之牌已和另一張相符
      bool[] isClicked = new bool;
      Random rnd = new Random();
      int[] a = new int;//用於亂數之用
      Timer mytimer = new Timer();
      PictureBox temp1 = new PictureBox();//可以不要有其他設定,但一定要有實體化設定
      PictureBox temp2 = new PictureBox();//可以不要有其他設定,但一定要有實體化設定
      PictureBox pBack = new PictureBox();//存放背卡圖
      int tempN1, tempN2;//用於每輪翻牌時存入該二張牌的格數
      SoundPlayer flip = new SoundPlayer(Properties.Resources.touch);
      SoundPlayer error = new SoundPlayer(Properties.Resources.error);
      SoundPlayer gamewin = new SoundPlayer(Properties.Resources.applaud);
      SoundPlayer correct = new SoundPlayer(Properties.Resources.correct);
      Button reStart = new Button();
      public Form1()
      {
            this.WindowState = FormWindowState.Maximized;//每次都將螢幕開最大
            this.BackgroundImage = Properties.Resources.form_bg;
            this.BackgroundImageLayout = ImageLayout.Stretch;
            InitializeComponent();
            
            master();
      }

      void master()
      {
            setAll();
            randomPicture();
      }

      int t;//計算時間
      int flipCount = 0;//計算每次一輪翻牌次數,最多二次


      void setAll()
      {
            w = currentScreen.Width / 12;//寬度是目前螢幕的十二分之一
            h = currentScreen.Width / 12;
            //重新按鈕
            reStart.Size = new Size(80, 40);
            reStart.Location = new System.Drawing.Point(w * 5 + w / 2 + w / 40 * 5, w * 5 + w / 2 + w / 40 * 6);
            reStart.BackColor = Color.Aqua;
            reStart.Text = "restart";
            reStart.Click += new EventHandler(restart_click);
            Controls.Add(reStart);

            //背卡圖片設定
            pBack.Image = Properties.Resources.bg;

            //計時器間隔和方法
            mytimer.Interval = 100;
            mytimer.Tick += new EventHandler(mytimer_tick);

            void restart_click(object sender, EventArgs e)
            {
                flip.Play();
                startOver();
            }

            //重新開始的方法
            void startOver()
            {
                temp1.Image = null;//以防點開一張未匹配之前就重玩時,會殘留第一張圖像
                for (int i = 0; i < 50; i++)
                {
                  pShow.Image = pBack.Image;
                  matched = false;
                  isClicked = false;
                }
                randomPicture();
            }//重新開始的方法end

            void mytimer_tick(object sender, EventArgs e)
            {
                t++;//計時開始
                if (t == 4)
                {
                  //目前翻開的二張圖格回到背卡
                  pShow.Image = pBack.Image;
                  pShow.Image = pBack.Image;
                  isClicked = false;
                  isClicked = false;
                  mytimer.Stop();//計時器停止
                  t = 0;//時間歸零
                }
            }



            for (int i = 0; i < 25; i++)
            {
                pImage = new PictureBox();
                pImage.Image = (Image)Properties.Resources.ResourceManager.GetObject("a" + i);
                pImage.Size = new Size(w, h);

            }

            for (int i = 0; i < 50; i++)
            {
                matched = new bool();
                isClicked = new bool();
                isClicked = false;
                pShow = new PictureBox();//主要圖形顯示格位
                //卡片位置排列是以所用螢幕長寬來決定,w/40是卡片與卡片的間隔空白
                pShow.Location = new System.Drawing.Point(w + i % 10 * (w + w / 40), w / 2 + i / 10 * (h + w / 40));//中間有留白
                pShow.Size = new Size(w, h);//卡片尺寸
                pShow.SizeMode = PictureBoxSizeMode.StretchImage;//卡片依螢幕而放大或縮小
                pShow.Image = pBack.Image;
                Controls.Add(pShow);
                pShow.Click += new EventHandler(pShow_click);

                //pRandom用來接納亂序之後的各圖形
                pRandom = new PictureBox();
                pRandom.Size = new Size(w, h);

            }
      }

      //判定是否贏的方法
      void doYouWin()
      {
            bool win = true;
            //如果中間有任何一個matched不是true,則win就變成false
            foreach (bool b in matched)
            {
                if (b != true) win = false;
                //break;
            }

            if (win) gamewin.Play();
      }

      //主顯示圖形陣列被點擊時的方法
      void pShow_click(object sender, EventArgs e)
      {
            PictureBox p = (PictureBox)sender;
            whichPic(sender);//取得目前滑鼠點擊的格子是幾號格
            if (matched != true && t == 0 && isClicked == false)//如果點到圖格還未被matched,而且計時器的t已歸零,才能進行本次的翻牌
            {
                pShow.Image = pRandom.Image;//將原本的背卡圖換成本圖
                flip.Play();
                temp();//進行翻牌後的方法

                //已翻了二次牌,如果二牌圖形相等,則二個格子所對應數字的matched都變成true
                if (temp1.Image == temp2.Image)
                {
                  matched = true;
                  matched = true;
                  correct.Play();

                }
                else if (flipCount == 2)//如果不相等而且翻牌的次數已是二次。(如果只有一次自然會不相等)
                {
                  error.Play();
                  mytimer.Start();//計時開始,好讓被翻開但不相同牌色的二張卡都回到背卡狀態
                }
            }
            doYouWin();//每次都檢查你贏的條件是否達成,如果是就顯示訊息
      }

      //翻牌時進行的方法
      void temp()
      {
            if (temp1.Image != null && temp2.Image != null)//如果二個臨時圖都已有放圖了
            {
                //將翻牌次數以及二個臨時存放的圖格歸零
                flipCount = 0;
                temp1.Image = null;
                temp2.Image = null;
            }

            if (temp1.Image == null)//如果第一個臨時存圖格是空的
            {
                flipCount = 1;//翻牌次數算一次
                isClicked = true;
                temp1.Image = pShow.Image;
                tempN1 = whichOne;
            }
            else//如果第一個已有圖檔存入,就放進第二個
            {
                flipCount = 2;//翻牌次數算第二次
                isClicked = true;
                temp2.Image = pShow.Image;
                tempN2 = whichOne;
            }
      }
      //翻牌時進行的方法end

      //被點擊的圖片是哪一格位
      int whichOne;
      void whichPic(object sender)
      {
            PictureBox p = (PictureBox)sender;
            for (int i = 0; i < 50; i++)
                if (p.Location == pShow.Location)
                  whichOne = i;
      }
      //被點擊的圖片是哪一格位end

      //將圖片亂排
      void randomPicture()
      {
            void randomPickNoRepeat(int[] a)
            {

                for (int i = 0; i < a.Length; i++)
                {
                  a = rnd.Next(a.Length);

                  for (int j = 0; j < i; j++)
                        if (a == a)
                        {
                            i--;
                            break;
                        }
                }
            }

            //第一次亂數,每隔一格子插入一個圖片
            randomPickNoRepeat(a);
            for (int i = 0; i < 25; i++)
            {

                pRandom.Image = pImage].Image;
            }

            //第二次亂數,每隔一格子插入一個圖片
            randomPickNoRepeat(a);
            for (int i = 0; i < 25; i++)
            {

                pRandom.Image = pImage].Image;

            }

      }
      //將圖片亂排end
    }
}



頁: [1]
查看完整版本: memory game ok code