本帖最後由 csharp 於 2021-11-28 11:32 編輯
- 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 memory_match_game
- {
- //This program is made by Sun Ying-Chi 2021/07/30
- public partial class Form2 : Form
- {
- //先給預設值,以免直接按入時出錯
- //底下有static的變數都是為了讓Form1能直接使用的
- public static int cardNumber = 8;//真正不重覆的牌數
- public static int myImageChoice = 3;//選擇哪個牌色
- public static bool musicOn = true;//設定音樂開關
- public static bool soundOn = true;//設定音效開關
- public Form2()
- {
- InitializeComponent();
- //表單關閉全程式
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form_FormClosing);
- //主體程式
- f2allSetting();
- }
- //設定表單關閉全程式的方式
- void Form_FormClosing(object sender, FormClosingEventArgs e)
- {
- Application.Exit();
- }
- void f2allSetting()
- {
- this.WindowState = FormWindowState.Maximized;//每次都將螢幕開最大
- this.BackgroundImage = Properties.Resources.form_bg_12;
- this.BackgroundImageLayout = ImageLayout.Stretch;
- //this.BackgroundImageLayout = ImageLayout.Tile;
- Rectangle currentScreen = Screen.PrimaryScreen.WorkingArea;//得出所使用螢幕之長寬值
- int w, h;//卡片的長和寬,本例二者是一樣高的,其實可以只用一個變數
- PictureBox[] pImage = new PictureBox[cardNumber];//真正的牌的數目
- PictureBox[] pShow = new PictureBox[cardNumber * 2];//真正有位置而會顯示的圖陣列
- PictureBox[] pRandom = new PictureBox[cardNumber * 2];//存放已亂數之後的牌卡
- bool[] matched = new bool[cardNumber * 2];//記錄是否已翻之牌已和另一張相符
- bool[] isClicked = new bool[cardNumber * 2];//記錄是否已翻之牌
- Random rnd = new Random();
- int[] array4random = new int[cardNumber];//用於亂數之用
- int whichOne = 0;//選擇到哪個數字
- PictureBox temp1 = new PictureBox();//可以不要有其他設定,但一定要有實體化設定
- PictureBox temp2 = new PictureBox();//可以不要有其他設定,但一定要有實體化設定
- PictureBox pBack = new PictureBox();//存放背卡圖,若要給不同花色之牌不同背卡,就需要pBack陣列
- int tempN1 = 0;//用於每輪翻牌時存入該二張牌的格數
- int tempN2 = 0;//用於每輪翻牌時存入該二張牌的格數
- SoundPlayer flip = new SoundPlayer(Properties.Resources.flip_0);//翻牌音效
- SoundPlayer error = new SoundPlayer(Properties.Resources.error);//配對不成功
- SoundPlayer gamewin = new SoundPlayer(Properties.Resources.applaud_0);//全部成功之結尾
- SoundPlayer correct = new SoundPlayer(Properties.Resources.correct);//配對成功
- PictureBox reStart = new PictureBox();
- PictureBox home = new PictureBox();
- PictureBox youWin = new PictureBox();//當靜音時才會出現awesome字樣的圖案表示贏了
- Timer mytimer = new Timer();//翻牌不配對之後回復背卡之計時器
- int time = 0;//計算時間//回復計時
- int flipCount = 0;//計算每次一輪翻牌次數,最多二次
- int row = 2;//多少張牌一列
- //主要是setAll和亂排牌卡
- setAll();
- randomPicture();
- //-----------主要牌卡設定以及被執行的功能------------
- void setAll()
- {
- tempN1 = 0;
- tempN2 = 0;
- w = currentScreen.Width / 12;//寬度是目前螢幕的十二分之一
- h = currentScreen.Width / 12;
- //you win shows
- youWin.Size = new Size(currentScreen.Width / 2, currentScreen.Width / 8);
- youWin.Location = new System.Drawing.Point(currentScreen.Width / 4, currentScreen.Height / 3);
- youWin.Image = Properties.Resources.awesome;
- youWin.SizeMode = PictureBoxSizeMode.StretchImage;
- youWin.BackColor = Color.Transparent;
-
- //you win end
- //重新按鈕
- reStart.Size = new Size(currentScreen.Width / 25, currentScreen.Width / 25);
- reStart.Location = new System.Drawing.Point(currentScreen.Width / 2 + w / 2, w * 5 + w / 40 * 6);
- reStart.Image = Properties.Resources.restart;
- reStart.SizeMode = PictureBoxSizeMode.StretchImage;
- reStart.BackColor = Color.Transparent;
- reStart.Click += new EventHandler(restart_click);
- Controls.Add(reStart);
- //回首頁按鈕
- home.Size = new Size(currentScreen.Width / 25, currentScreen.Width / 25);
- home.SizeMode = PictureBoxSizeMode.StretchImage;
- home.BackColor = Color.Transparent;
- home.Image = Properties.Resources.home;
- home.Location = new System.Drawing.Point(currentScreen.Width / 2 - w * 2, w * 5 + w / 40 * 6);
- home.Click += new EventHandler(home_click);
- Controls.Add(home);
- void home_click(Object sender, EventArgs e)
- {
- gamewin.Stop();
- Form1 f1 = new Form1();//這個要放前面,不然下一行的功效會慢一拍
- Form1.soundON = soundOn;//讓Form1的音效選擇圖案同步
- f1.Show();
- if (Form1.hasClicked2)//如果Form1已經有點選過張數,這裡再把傳過來的結果再傳回去,好讓那裡的張數選擇圖案繼續保持
- {
- if (cardNumber == 4) Form1.pNumberChoiceShow[0].Image = Form1.pNumberChoiceGo[0].Image;
- else if (cardNumber == 8) Form1.pNumberChoiceShow[1].Image = Form1.pNumberChoiceGo[1].Image;
- else if (cardNumber == 12) Form1.pNumberChoiceShow[2].Image = Form1.pNumberChoiceGo[2].Image;
- else if (cardNumber == 18) Form1.pNumberChoiceShow[3].Image = Form1.pNumberChoiceGo[3].Image;
- else if (cardNumber == 24) Form1.pNumberChoiceShow[4].Image = Form1.pNumberChoiceGo[4].Image;
- }
- if (Form1.hasClicked1)//如果Form1已經有點選過牌色,這裡再把傳過來的結果再傳回去,好讓那裡的牌色選擇圖案繼續保持
- {
- if (myImageChoice == 1) Form1.pThemeShow[0].Image = Form1.pThemeChoiceGo[0].Image;
- else if (myImageChoice == 2) Form1.pThemeShow[1].Image = Form1.pThemeChoiceGo[1].Image;
- else if (myImageChoice == 3) Form1.pThemeShow[2].Image = Form1.pThemeChoiceGo[2].Image;
- }
- Hide();
- }
- //--------回首頁按鈕end-----
- rowSetting();
- //---------設置牌尺寸及每列牌數------------
- void rowSetting()
- {
- if (cardNumber == 4)
- {
- w = currentScreen.Width / 8;
- h = currentScreen.Width / 8;
- row = 4;//每4張牌換列
- }
- else if (cardNumber == 8)
- {
- w = currentScreen.Width / 10;
- h = currentScreen.Width / 10;
- row = 8;//每8張牌換列
- }
- else if (cardNumber == 12)
- {
- w = currentScreen.Width / 10;
- h = currentScreen.Width / 10;
- row = 8;//每8張牌換列
- }
- else if (cardNumber == 18)
- {
- w = currentScreen.Width / 11;
- h = currentScreen.Width / 11;
- row = 9;//每9張牌換列
- }
- else if (cardNumber == 24)
- {
- w = currentScreen.Width / 14;
- h = currentScreen.Width / 14;
- row = 12;
- }
- }
- //---------設置牌尺寸及每列牌數 end------------
- //-------選擇牌色以及背卡的圖案------
- void imageChoice()
- {
- if (myImageChoice == 1)
- {
- pBack.Image = Properties.Resources.xmas_back;
- for (int i = 0; i < cardNumber; i++)
- {
- pImage[i] = new PictureBox();
- pImage[i].Image = (Image)Properties.Resources.ResourceManager.GetObject("x" + i);
- }
- }
- else if (myImageChoice == 2)
- {
- pBack.Image = Properties.Resources.number_back;
- for (int i = 0; i < cardNumber; i++)
- {
- pImage[i] = new PictureBox();
- pImage[i].Image = (Image)Properties.Resources.ResourceManager.GetObject("n" + i);
- }
- }
- else if (myImageChoice == 3)
- {
- pBack.Image = Properties.Resources.food_back;
- for (int i = 0; i < cardNumber; i++)
- {
- pImage[i] = new PictureBox();
- pImage[i].Image = (Image)Properties.Resources.ResourceManager.GetObject("f" + i);
- }
- }
- }
- //-------選擇牌色以及背卡的圖案 end------
- //計時器間隔和方法
- mytimer.Interval = 100;
- mytimer.Tick += new EventHandler(mytimer_tick);
- //----重新按鈕方法-----
- void restart_click(object sender, EventArgs e)
- {
- if (soundOn == true)
- flip.Play();
- gamewin.Stop();
- startOver();
- }
- //重新開始的方法
- void startOver()
- {
- Controls.Remove(youWin);
- temp1.Image = null;//以防點開一張未匹配之前就重玩時,會殘留圖像
- temp2.Image = null;//不加這個,如果連按二次restart後,翻開的前二張不符合也不會翻回去
- for (int i = 0; i < cardNumber * 2; i++)
- {
- pShow[i].Image = pBack.Image;
- matched[i] = false;
- isClicked[i] = false;
- }
- randomPicture();
- }//重新開始的方法end
- void mytimer_tick(object sender, EventArgs e)
- {
- time++;//計時開始
- if (time == 4)
- {
- //目前翻開的二張圖格回到背卡
- pShow[tempN1].Image = pBack.Image;
- pShow[tempN2].Image = pBack.Image;
- isClicked[tempN1] = false;
- isClicked[tempN2] = false;
- mytimer.Stop();//計時器停止
- time = 0;//時間歸零
- }
- }
- imageChoice();//選擇牌色以及背卡的圖案
- for (int i = 0; i < cardNumber * 2; i++)
- {
- matched[i] = new bool();
- isClicked[i] = new bool();
- isClicked[i] = false;
- pShow[i] = new PictureBox();//主要圖形顯示格位
- //卡片位置排列是以所用螢幕長寬來決定,w/40是卡片與卡片的間隔空白,並由列數來決定上面空白長度
- if (row == 4)
- pShow[i].Location = new System.Drawing.Point(w * 2 + i % row * (w + w / 40), w / 2 + i / row * (h + w / 40));//中間有留白
- else if (row == 8)
- pShow[i].Location = new System.Drawing.Point(w + i % row * (w + w / 40), w + i / row * (h + w / 40));//中間有留白
- else if (row == 9)
- pShow[i].Location = new System.Drawing.Point(w + i % row * (w + w / 40), w / 2 + i / row * (h + w / 40));//中間有留白
- else if (row == 12)
- pShow[i].Location = new System.Drawing.Point(w + i % row * (w + w / 40), w * 5 / 4 + i / row * (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);
- }
- }
- //----------------主要牌卡設定以及被執行的功能 end-------------------
- //判定是否贏的方法
- void doYouWin()
- {
- bool win = true;
- //如果中間有任何一個matched不是true,則win就變成false
- foreach (bool b in matched)
- {
- if (b != true) win = false;
- //break;
- }
- if (win)
- {
-
- if (soundOn == true)
- gamewin.Play();
- else
- {
- Controls.Add(youWin);
- youWin.BringToFront();
- }
- }
- }
- //主顯示圖形陣列被點擊時的方法
- void pShow_click(object sender, EventArgs e)
- {
- PictureBox p = (PictureBox)sender;
- whichPic(sender);//取得目前滑鼠點擊的格子是幾號格
- if (matched[whichOne] != true && time == 0 && isClicked[whichOne] == false)//如果點到圖格還未被matched,而且計時器的t已歸零,才能進行本次的翻牌
- {
- pShow[whichOne].Image = pRandom[whichOne].Image;//將原本的背卡圖換成本圖
- if (soundOn == true)
- flip.Play();
- temp();//進行翻牌後的方法
- //已翻了二次牌,如果二牌圖形相等,則二個格子所對應數字的matched都變成true
- if (temp1.Image == temp2.Image)
- {
- matched[tempN1] = true;
- matched[tempN2] = true;
- if (soundOn == true)
- correct.Play();
- }
- else if (flipCount == 2)//如果不相等而且翻牌的次數已是二次。(如果只有一次自然會不相等)
- {
- if (soundOn == true)
- 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
- //被點擊的圖片是哪一格位
- void whichPic(object sender)
- {
- PictureBox p = (PictureBox)sender;
- for (int i = 0; i < cardNumber * 2; i++)
- if (p.Location == pShow[i].Location)
- whichOne = i;
- }
- //被點擊的圖片是哪一格位end
- //---------------將圖片亂排 begin ---------------
- void randomPicture()//先設立一個函數
- {
- void randomPickNoRepeat(int[] array)
- {
- for (int i = 0; i < array.Length; i++)
- {
- array[i] = rnd.Next(array.Length);
- for (int j = 0; j < i; j++)
- if (array[j] == array[i])
- {
- i--;
- break;
- }
- }
- }
- //第一次亂數,每隔一格子插入一個圖片
- randomPickNoRepeat(array4random);
- for (int i = 0; i < cardNumber; i++)
- {
- pRandom[i * 2 + 1].Image = pImage[array4random[i]].Image;
- }
- //第二次亂數,每隔一格子插入一個圖片
- randomPickNoRepeat(array4random);
- for (int i = 0; i < cardNumber; i++)
- {
- pRandom[i * 2].Image = pImage[array4random[i]].Image;
- }
- }
- //----------將圖片亂排end-------------
- }
- }//---------public Form2() end ---------
- }
複製代碼 |