本帖最後由 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[25];
- PictureBox[] pShow = new PictureBox[50];
- PictureBox[] pRandom = new PictureBox[50];
- bool[] matched = new bool[50];//記錄是否已翻之牌已和另一張相符
- bool[] isClicked = new bool[50];
- Random rnd = new Random();
- int[] a = new int[25];//用於亂數之用
- 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[i].Image = pBack.Image;
- matched[i] = false;
- isClicked[i] = false;
- }
- randomPicture();
- }//重新開始的方法end
- void mytimer_tick(object sender, EventArgs e)
- {
- t++;//計時開始
- if (t == 4)
- {
- //目前翻開的二張圖格回到背卡
- pShow[tempN1].Image = pBack.Image;
- pShow[tempN2].Image = pBack.Image;
- isClicked[tempN1] = false;
- isClicked[tempN2] = false;
- mytimer.Stop();//計時器停止
- t = 0;//時間歸零
- }
- }
- for (int i = 0; i < 25; i++)
- {
- pImage[i] = new PictureBox();
- pImage[i].Image = (Image)Properties.Resources.ResourceManager.GetObject("a" + i);
- pImage[i].Size = new Size(w, h);
- }
- for (int i = 0; i < 50; i++)
- {
- matched[i] = new bool();
- isClicked[i] = new bool();
- isClicked[i] = false;
- pShow[i] = new PictureBox();//主要圖形顯示格位
- //卡片位置排列是以所用螢幕長寬來決定,w/40是卡片與卡片的間隔空白
- pShow[i].Location = new System.Drawing.Point(w + i % 10 * (w + w / 40), w / 2 + i / 10 * (h + w / 40));//中間有留白
- pShow[i].Size = new Size(w, h);//卡片尺寸
- pShow[i].SizeMode = PictureBoxSizeMode.StretchImage;//卡片依螢幕而放大或縮小
- pShow[i].Image = pBack.Image;
- Controls.Add(pShow[i]);
- pShow[i].Click += new EventHandler(pShow_click);
- //pRandom用來接納亂序之後的各圖形
- pRandom[i] = new PictureBox();
- pRandom[i].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[whichOne] != true && t == 0 && isClicked[whichOne] == false)//如果點到圖格還未被matched,而且計時器的t已歸零,才能進行本次的翻牌
- {
- pShow[whichOne].Image = pRandom[whichOne].Image;//將原本的背卡圖換成本圖
- flip.Play();
- temp();//進行翻牌後的方法
- //已翻了二次牌,如果二牌圖形相等,則二個格子所對應數字的matched都變成true
- if (temp1.Image == temp2.Image)
- {
- matched[tempN1] = true;
- matched[tempN2] = 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[whichOne] = true;
- temp1.Image = pShow[whichOne].Image;
- tempN1 = whichOne;
- }
- else//如果第一個已有圖檔存入,就放進第二個
- {
- flipCount = 2;//翻牌次數算第二次
- isClicked[whichOne] = true;
- temp2.Image = pShow[whichOne].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[i].Location)
- whichOne = i;
- }
- //被點擊的圖片是哪一格位end
- //將圖片亂排
- void randomPicture()
- {
- void randomPickNoRepeat(int[] a)
- {
- for (int i = 0; i < a.Length; i++)
- {
- a[i] = rnd.Next(a.Length);
- for (int j = 0; j < i; j++)
- if (a[j] == a[i])
- {
- i--;
- break;
- }
- }
- }
- //第一次亂數,每隔一格子插入一個圖片
- randomPickNoRepeat(a);
- for (int i = 0; i < 25; i++)
- {
- pRandom[i * 2 + 1].Image = pImage[a[i]].Image;
- }
- //第二次亂數,每隔一格子插入一個圖片
- randomPickNoRepeat(a);
- for (int i = 0; i < 25; i++)
- {
- pRandom[i * 2].Image = pImage[a[i]].Image;
- }
- }
- //將圖片亂排end
- }
- }
複製代碼 |