【程式設計】作業 2017-11-21

完成下面的程式:

  1. 輸入3個數字,輸出其中之最小值。
  2. 輸入2個數字,判斷是否相等。
  3. 輸入1個數字,判斷是奇數或是偶數。
  4. 輸入1個數字,判斷是正數或是負數。
  5. 輸入1個數字,輸出其絕對值。

答題示範:

 

private void button1_Click(object sender, EventArgs e)
{
    double a = 0, b = 0, c = 0;
    try
    {
        a = Convert.ToDouble(textBox1.Text);
        b = Convert.ToDouble(textBox2.Text);
        c = Convert.ToDouble(textBox3.Text);

    }
    catch {
        MessageBox.Show("輸入錯誤,請檢視!!");
    }

    label2.Text = "最大值是:";

    if (a > b && a > c) label2.Text += a; //為何可以直接用a,不用a.toString()? 
    if (b > a && b > c) label2.Text += b;
    if (c > a && c > b) label2.Text += c;
}

程式設計(一) 106學年度 日間部 期中考第1題

【程式說明及要求】

寫一個程式,上面有一個Label控制項,一開始,背景顯示藍色,文字顯示”藍色”,置中。

每按一下該label控制項,就會改變背景色及文字,順序如下:

藍色->紅色->黃色 (循環)


【程式解法邏輯】

依照題目要求,想法如下:

現在標籤背景如果是藍色的話,就切換成紅色,如果是紅色的話,就切換成黃色,如果是黃色的話,就切換成藍色…

因此,程式中判斷標纖背景顏色是藍色的話,寫法如下:

if (label1.BackColor == Color.Blue) {

//切換成黃色

} else if (……….)

 

【程式寫法】

在標籤label1的click事件函式中加上判斷標籤背景顏色等敘述(每按一下判斷一次切換一次):

private void label1_Click(object sender, EventArgs e)
{
    if (label1.BackColor == Color.Blue)
    {
        label1.BackColor = Color.Red;
        label1.Text = "紅色";
    }
    else if (label1.BackColor == Color.Red)
    {
        label1.BackColor = Color.Yellow;
        label1.Text = "黃色";
    }
    else if (label1.BackColor == Color.Yellow)
    {
        label1.BackColor = Color.Blue;
        label1.Text = "藍色";
    }
}

 

 

程式設計作業-匯率換算(一)

程式規範

1.二個PictureBox,放置中華民國與日本國旗

2.二個Label,新台幣與日圓

3.二個文字方塊,輸入新台幣,輸出等值日圓

4.一個按鈕,執行下面的程式:

private void button1_Click(object sender, EventArgs e)
{
    double twd = double.Parse(textBox1.Text);
    double jpy =  twd * 2.7;
    textBox2.Text = jpy.ToString();
}

 

【程式設計-C#】打磚塊遊戲 – 動作

【程式設計-C#】打磚塊遊戲 – 動作

【程式設計-C#】打磚塊遊戲 – 動作

(到上一篇【程式設計】打磚塊遊戲 – 處理物件及畫面美工)

打磚塊遊戲設計資源 (請按下面圖片):

接下來,在這個教學裏,我們要實現底下遊戲動作: 打磚塊專案檔20180522

  1. 球的移動及碰到邊界的處理
  2. 處理球拍的移動 (鍵盤 + 滑鼠)
  3. 球拍擊中球的判斷及處理
  4. 球擊中磚塊的判斷及處理
  5. 遊戲結束條件:1.球掉出下邊界;2.按ESC鍵
  6. 進入到下一關:擊中全部磚塊,所有磚塊消失。(你會怎麼做?)

首先,我們所有的動作皆透過計時器物件來實現,將計時器物件拖拉至程式主畫面,設定interval,依照人類視覺暫留特性,每秒只要高於16個影像,看起來的東西就會覺得是連貫的,電影的FPS為24,遊戲則要更高,至少30以上,所以,我們的計時器的interval  = 1 / 40  * 1000 =  25

一、球的移動及碰到邊界的處理 BrickBreakout – 2 – 1

程式一開始先宣告:

int X_Inc = 5, Y_Inc = 5;
// 水平移動增量 X_Inc (正:往右邊,負:往左邊)
// 垂直移動增量 Y_Inc(正:往下邊,負:往上面)

計時器的Tick事件:

private void timer1_Tick(object sender, EventArgs e)
{
    ball.Left += Y_Inc; //水平
    ball.Top += X_Inc; //垂直

    //邊界碰撞
    if (ball.Left < 0 || ball.Left > this.Bounds.Width) Y_Inc = -Y_Inc; //左右邊界
    if (ball.Top > this.Bounds.Height || ball.Top < 0) X_Inc = -X_Inc; //上下邊界
}

二、處理球拍的移動 (鍵盤 + 滑鼠)

在timer1的Tick事件中加入:

private void timer1_Tick(object sender, EventArgs e)
{
    //球的移動處理
    ball.Left += Y_Inc;
    ball.Top += X_Inc;

    //球的邊界碰撞
    if (ball.Left < 0 || ball.Left > this.Bounds.Width) Y_Inc = -Y_Inc; //左右邊界
    if (ball.Top > this.Bounds.Height || ball.Top < 0) X_Inc = -X_Inc; //上下邊界

    //球拍的移動
    if (Cursor.Position.X >= (this.Bounds.Width - racket.Width))//如果游標在右邊界處 
        racket.Left = this.Bounds.Width - racket.Width;//減去 球拍的水平位置,否則的話,球拍會在視窗 
    else racket.Left = Cursor.Position.X; //球拍的水平位置 = 游標的水平位置

}

除了使用滑鼠移動游標來移動球拍,我們另外抓取按鍵事件來移動球拍,作法是在Form表單中的KeyDown事件抓取左右按鍵:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Left) Cursor.Position = new Point(Cursor.Position.X  - 20, Cursor.Position.Y);
    if (e.KeyCode == Keys.Right) Cursor.Position = new Point(Cursor.Position.X + 20, Cursor.Position.Y);
}

三、球拍擊中球的判斷及處理 BrickBreakout – 2-2

判斷球拍是否擊中球,並且在確認擊中之後,球的垂直移動方向由往下變往上。

private void timer1_Tick(object sender, EventArgs e)
{
    //球的邊界碰撞
    if (ball.Left <= 0 || ball.Left >= (this.Bounds.Width - ball.Width)) X_Inc = -X_Inc; //左右邊界
    if (ball.Top >= (this.Bounds.Height - ball.Height) || ball.Top <= 0) Y_Inc = -Y_Inc; //上下邊界

    //球拍是否擊中球:
    if (ball.Left >= racket.Left && ball.Left <= (racket.Left + racket.Width) && ball.Top >= (racket.Top - ball.Height)) Y_Inc = -Y_Inc;

    //球拍的移動
    if (Cursor.Position.X >= (this.Bounds.Width - racket.Width))//如果游標在右邊界處 
        racket.Left = this.Bounds.Width - racket.Width;//減去 球拍的水平位置,否則的話,球拍會在視窗 
    else racket.Left = Cursor.Position.X; //球拍的水平位置 = 游標的水平位置

    //球移動
    ball.Left += X_Inc;
    ball.Top += Y_Inc;
}

四、球擊中磚塊的判斷及處理 BrickBreakout – 2-3

球擊中磚塊的判斷跟球拍是否擊中球作法類似,擊中確認後,我們只需要將該磚塊的Visible設為false,使磚塊看不見就好了!(簡單吧?!)

程式在timer1的Tick事件中加了這個部份的處理:

//一一測試每顆磚塊是否被球擊中
for (int i = 0; i < bricks.GetLength(0); i++)
{
    for (int j = 0; j < bricks.GetLength(1); j++)
    {
        if (bricks[i, j].Visible == true) // 若磚塊是可見的話…,表示磚塊尚未被擊中
        {
            if (ball.Left >= bricks[i, j].Left && ball.Left <= (bricks[i, j].Left + bricks[i, j].Width) && ball.Top <= (bricks[i, j].Top + bricks[i, j].Height))
            {
                Y_Inc = -Y_Inc;
                bricks[i, j].Visible = false; //判定擊中後,球的垂直移動方向改變,並將磚塊的Visible屬性設false,使其看不見
                goto HitBrickExit; //一旦擊中,就不用測試其他的磚塊…,跳離這個測試以節省時間
            }
        }
    }
}
HitBrickExit:

另外,再加上球掉出下邊界外的處理:

//球掉到下邊界外,也就是球拍沒擊中球…,遊戲結束
if (ball.Top >= (this.Bounds.Height - ball.Height))
{
    timer1.Enabled = false; //中止計時器1
    lblGameOver.Visible = true; //顯示出遊戲結束訊息
}

再加上幾個按鍵的處理:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Left) Cursor.Position = new Point(Cursor.Position.X - 20, Cursor.Position.Y);
    if (e.KeyCode == Keys.Right) Cursor.Position = new Point(Cursor.Position.X + 20, Cursor.Position.Y);
    if (e.KeyCode == Keys.Escape) this.Close(); //按Esc離開遊戲
    if (e.KeyCode == Keys.F1) //重新開始遊戲
    {
        ball.Left = (this.Bounds.Width - ball.Width) / 2; //球位置,置於視窗中心
        ball.Top = (this.Bounds.Height - ball.Height) / 2;
        timer1.Enabled = true; //重新啟動計時器1
        lblGameOver.Visible = false; //遊戲訊息隱藏
        place_bricsk(); //重新排列所有的磚塊
    }
}

遊戲錄影:

音效的處理請參考下一篇:【程式設計】打磚塊遊戲 – 播放背景音樂與音效 (同時)

問題、意見、遊戲改進提議等歡迎在文章下面的迴響交流。謝謝。

【程式設計-C#】記憶遊戲

【設計基礎一:排列圖片、發牌、洗牌】

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace plateDealing
{
    class Program
    {
        static void Main(string[] args)
        {
            Random rnd = new Random();
            int[] plateHoles = new int[16];
            for (int i = 0; i <= 7; i++) //將2副牌1~8編號的牌放在0~15編號的位置上
            {
                plateHoles[i] = i + 1;
                plateHoles[i + 8] = i + 1;
            }
            for (int k = 1; k <= 10; k++) //10副牌
            {
                Console.Write("第{0:D2}副牌:", k);
                for (int i = 0; i <= 15; i++) //將每1個位置的牌随機的和任一位置的牌進行交換
                {
                    int rndHole = rnd.Next(0, 15); //任選一個位置,進行牌的交換
                    int temp = plateHoles[i];
                    plateHoles[i] = plateHoles[rndHole];
                    plateHoles[rndHole] = temp;
                }

                for (int i = 0; i <= 15; i++) //印出牌
                {
                    Console.Write(plateHoles[i] + "   ");
                }
                Console.WriteLine();
            }
            Console.ReadKey();
        }
    }
}

上面的程式實現以下的想法:

想像你有2副牌,各8張,編號1~8,一開始先把這2副牌順序地放在16個格子(陣列),然後再洗牌 (位置交換的意思)。

參考作法
1.先將2副牌各1~8編號的牌放在16個位置上
2.從第1張牌開始,與任選一個位置的牌交換 (打亂牌,就像洗牌的意思)

排出來的牌,就是每一張圖的位置。

【程式碼】FlipMatchGame

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        //PicNames這個二維陣列用來建立所有卡片在資源裏的名稱,我用二維陣列,列是"花色",行是數字和j~k
        String[,] PicNames = { 
                             { "ace_of_spades", "_2_of_spades", "_3_of_spades", "_4_of_spades", "_5_of_spades", "_6_of_spades", "_7_of_spades", "_8_of_spades", "_9_of_spades", "_10_of_spades", "jack_of_spades", "queen_of_spades", "king_of_spades"}, 
                             { "ace_of_hearts", "_2_of_hearts", "_3_of_hearts", "_4_of_hearts", "_5_of_hearts", "_6_of_hearts", "_7_of_hearts", "_8_of_hearts", "_9_of_hearts", "_10_of_hearts", "jack_of_hearts", "queen_of_hearts", "king_of_hearts"}, 
                             { "ace_of_diamonds", "_2_of_diamonds", "_3_of_diamonds", "_4_of_diamonds", "_5_of_diamonds", "_6_of_diamonds", "_7_of_diamonds", "_8_of_diamonds", "_9_of_diamonds", "_10_of_diamonds", "jack_of_diamonds", "queen_of_diamonds", "king_of_diamonds"}, 
                             { "ace_of_clubs", "_2_of_clubs", "_3_of_clubs", "_4_of_clubs", "_5_of_clubs", "_6_of_clubs", "_7_of_clubs", "_8_of_clubs", "_9_of_clubs", "_10_of_clubs", "jack_of_clubs", "queen_of_clubs", "king_of_clubs"}
                             };
        String[] Cards = {"","","","","","","","","","","",""};
        Random randomNums;

        PictureBox n1 = null, n2 = null; //分別指向第1張與第2張翻牌
        String s1 = null, s2 = null; //記錄翻牌第1張與第2張的文字,用來比較用
        
        public Form1()
        {
            InitializeComponent();
            randomNums = new Random(); //建立亂數物件
            prepareCards(); //洗牌      
        }

        private void prepareCards() //產生12張卡,其中後6張是跟前面6張一樣,再將其重排
        {
            int i;
            int row, col; //撲克牌組,為2維陣列,用這2個變數來存取此牌組陣列的牌
            bool isRepeat;
            for (i = 0; i <= 5; i++)//只抓前6張牌
            {                
                do
                {
                    isRepeat = false; //此變數用來判讀是否抽出的牌有重覆,預設false…,找到重複的牌之後設為true(繼續抽牌…)
                    //下面二行實現隨機抽一張牌的概念
                    row = randomNums.Next(0, 4); //產生0~3的隨機整數
                    col = randomNums.Next(0, 13); //產生0~12的隨機整數
                    //抽牌後,必須檢查此牌是否跟之前抽出的牌有重覆
                    for (int j = i - 1; j >= 0; j--)//看新抓的牌是否和前面的牌有重複
                    {
                        if (Cards[j].Equals(PicNames[row, col]))
                        {
                            isRepeat = true; break; //若發現有重複的牌,設定isRepeat為true,離開for,讓外層的do-while重複,再隨機抽一張牌…
                        }
                    }
                } while (isRepeat);

                //抽好牌之後,把牌放入Cards陣列中
                Cards[i] = PicNames[row, col]; Cards[i+6] = PicNames[row, col]; //一次二張牌
            }

            for (i = 0; i <= 11; i++) //打亂/重排12張牌
            {
                string temp = Cards[i];
                int a = randomNums.Next(0, 12); //任找一位置來進行牌的交換
                Cards[i] = Cards[a];
                Cards[a] = temp;
            }
        }

        private void pictureBox_Click(object sender, EventArgs e)
        {
            PictureBox pb = (PictureBox)sender;

            String s = pb.Name.Replace("pictureBox", ""); 
            //把元件的名字pictureBox1中的pictureBox去掉,賸下數字的部份,取得1~12的數字字串
            //上面這行的目的是想要知道是那一個PictureBox被點擊了1~12個
            int index = Int32.Parse(s);            
            pb.Image = (Image)Properties.Resources.ResourceManager.GetObject(Cards[index-1]);            

            if (n1 == null) //翻第1張牌的時候
            {
                n1 = pb; pb.Enabled = false; //用n1指向翻出來的牌的pictureBox, 並將該pictureBox設為不作用,以防止再按該pictureBox
                s1 = Cards[index - 1]; //s1字串用來記錄第1張牌的文字
            }
            else //翻第2張牌
            {
                n2 = pb; n2.Enabled = false; //同第1張牌一樣,此部份係處理第2張牌
                s2 = Cards[index - 1];

                if (s1 != s2) //比較翻出來的2張牌,若不一樣,則蓋牌,重新啟動二張卡的作用…
                {
                    System.Threading.Thread.Sleep(1000); //delay1秒,讓玩家可以看出牌被蓋住
                    n1.Image = Properties.Resources.black_joker; //把2張牌再度用鬼牌蓋上
                    n2.Image = n1.Image; //第2張牌也是用鬼牌來蓋上
                    n1.Enabled = true; n2.Enabled = true;//若翻出來的2張牌不一樣,該2張牌蓋上後再設enabled為true
                }
                //n1~n2、s1~s2再設為null,重新進行翻牌判斷
                n1 = null; n2 = null;
                s1 = null; s2 = null;
            }
        }
    }
}

 

【程式設計-C#】打磚塊遊戲 – 處理物件及畫面美工

 

(圖片來源)

OpenGameArt, 遊戲圖案與音效 

1.繪製基本畫面

【程式碼】【專案檔:BrickBreakout – 1

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 BrickBreakout
{
    public partial class Form1 : Form
    {
        PictureBox[,] bricks; //磚塊物件參考變數(二維)
        PictureBox racket; //球拍變數
        private int brick_height = 30; //磚塊高度
        private int brick_space = 5; //磚塊間的空間大小
        private int brick_width; //磚塊寬度,等視窗放到最大後,再計算,12塊磚塊,填滿整個視窗寬邊
        public Form1()
        {
            InitializeComponent();

            this.FormBorderStyle = FormBorderStyle.None; //將視窗的邊框設成"無",使視窗的邊框(連同標題列)消失
            this.TopMost = true; //將視窗設為最上層
            this.Bounds = Screen.PrimaryScreen.Bounds; //將視窗設為全螢幕

            bricks = new PictureBox [6, 12]; //建立二維的磚塊物件參考,用以指向PictureBox,注意,是指向PictureBox物件的參考,不是PictureBox物件本身
            racket = new PictureBox(); //指向一個新建立的PictureBox物件
            racket.Width = 200;  racket.Height = 30; racket.BackColor = Color.DarkGreen; //球拍寬度、高度、顏色
            racket.Left = (this.Bounds.Width - racket.Width) / 2; //球拍水平位置,置中於視窗
            racket.Top = this.Bounds.Height - racket.Height - 10; //球拍垂直位置,置於視窗底部
            this.Controls.Add(racket); //將球拍物件加入Form1的控制項集合

            brick_width = (this.Bounds.Width - 13 * brick_space) / 12; //計算每一排,12個磚塊,每1個磚塊的寬度
            for (int i = 0; i <= 5; i++) //6列,12行的磚塊
            {
                for (int j = 0; j <= 11; j++)
                {
                    bricks[i, j] = new PictureBox(); //產生每一個磚塊PictureBox物件
                    switch (i)
                    {
                        case 0:
                        case 1: bricks[i, j].BackColor = Color.Red; break; //設定每一列磚塊物件的顏色
                        case 2:
                        case 3: bricks[i, j].BackColor = Color.Yellow; break;
                        case 4:
                        case 5: bricks[i, j].BackColor = Color.DarkBlue; break;
                    }
                    bricks[i, j].Height = brick_height; //磚塊的高度
                    bricks[i, j].Width = brick_width; //磚塊的寬度
                    this.Controls.Add(bricks[i, j]); //將磚塊PictureBox物件加入Form1控制項集合
                }
            }

            place_bricsk(); //喚用place_bricsk方法,排列所有的磚塊            
        }
        private void place_bricsk()
        {
            for (int i = 0; i <= 5; i++)
            {
                for (int j = 0; j <= 11; j++)
                {
                    bricks[i, j].Left = brick_space + (brick_width + brick_space) * j;
                    bricks[i, j].Top = brick_space + (brick_height + brick_space) * i;
                }
            }
        }
    }
}

【程式碼 – 20180510版本】【專案檔:打磚塊遊戲

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 打磚塊遊戲
{
    public partial class Form1 : Form
    {
        PictureBox 球拍 = new PictureBox();
        PictureBox[,] 磚塊陣列 = new PictureBox[8, 12];
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            int 畫面寬度 = this.Bounds.Width;
            int 畫面高度 = this.Bounds.Height;
            int 間隔 = 5;

            球拍.Width = 200; 球拍.Height = 30; 球拍.Load("bar.png"); 球拍.SizeMode = PictureBoxSizeMode.StretchImage;

            球拍.Left = (畫面寬度 - 球拍.Width) / 2;
            球拍.Top = ( 畫面高度 - 球拍.Height - 10);
            this.Controls.Add(球拍); //將球拍物件加入表單控制項集合

            //建立6x12個磚塊,並將這些磚塊放入磚塊陣列
            int 磚塊寬度 = (畫面寬度 - 間隔) / 12 - 間隔;
            int 磚塊高度 = 30;
            String[] 磚塊陣列色彩集合 = new String[] {  "brick-blue.png", 
                                                        "brick-blue.png", 
                                                        "brick-green.png", 
                                                        "brick-green.png",
                                                        "brick-orange.png",
                                                        "brick-orange.png",
                                                        "brick-red.png",
                                                        "brick-red.png"};
            for (int i = 0; i <= 7; i++)
            {
                for (int j = 0; j <= 11; j++)
                {
                    PictureBox 磚塊 = new PictureBox();
                    磚塊.Width = 磚塊寬度; 磚塊.Height = 磚塊高度;
                    磚塊.Left = 間隔 + (磚塊寬度 + 間隔) * j;
                    磚塊.Top = 間隔 + (磚塊高度 + 間隔) * i;

                    磚塊.Load(磚塊陣列色彩集合[i]); 磚塊.SizeMode = PictureBoxSizeMode.StretchImage;
              
                    this.Controls.Add(磚塊);
                    磚塊陣列[i, j] = 磚塊;
                }
            }
        }
    }
}

 

 

2.建立與置換美工圖

Google一張我們可以使用的Free圖案,用Photoshop描繪邊緣複製來建立美工圖

 

接著,要示範把底下的球拍置換用美工軟體畫好的圖案,圖片背景必須是去背的,也就是透明背景。

【做法及程式碼】

1.將圖檔加入專案,從方案總管->按右鍵->加入->現有項目->選擇影像檔

並設定美工圖檔的屬性”複製到輸出目錄”的值為”一律複製”。

2.程式碼

racket = new PictureBox(); //指向一個新建立的PictureBox物件	 	 
racket.Load("bar.png"); //載入美工圖檔,bar.png	 	 
racket.SizeMode = PictureBoxSizeMode.AutoSize; //將球拍PictureBox物件的尺寸模式設為AutoSize,使球拍大小自動調整成美工圖案的大小	 	 
racket.Left = (this.Bounds.Width - racket.Width) / 2; //球拍水平位置,置中於視窗	 	 
racket.Top = this.Bounds.Height - racket.Height - 10; //球拍垂直位置,置於視窗底部

3.加上球、及磚塊的圖案

 

方案總管裏加入所有用到的圖案資源:

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 BrickBreakout
{
    public partial class Form1 : Form
    {
        PictureBox[,] bricks; //磚塊物件參考變數(二維)
        PictureBox racket,ball; //球拍與球變數
        private int brick_height = 30; //磚塊高度
        private int brick_space = 3; //磚塊間的空間大小
        private int brick_width; //磚塊寬度,等視窗放到最大後,再計算,12塊磚塊,填滿整個視窗寬邊
        Point OriginCursorPosition;

        public Form1() //建構子,這支程式執行時,以物件方式存在於系統中,此建構子為其物件初始方法
        {
            InitializeComponent();

            this.FormBorderStyle = FormBorderStyle.None; //將視窗的邊框設成"無",使視窗的邊框(連同標題列)消失
            this.TopMost = true; //將視窗設為最上層
            this.Bounds = Screen.PrimaryScreen.Bounds; //將視窗設為全螢幕

            //球拍
            racket = new PictureBox(); //指向一個新建立的PictureBox物件
            racket.Load("bar.png"); //載入美工圖檔,bar.png
            racket.SizeMode = PictureBoxSizeMode.AutoSize; //將球拍PictureBox物件的尺寸模式設為AutoSize,使球拍大小自動調整成美工圖案的大小
            racket.Left = (this.Bounds.Width - racket.Width) / 2; //球拍水平位置,置中於視窗
            racket.Top = this.Bounds.Height - racket.Height - 10; //球拍垂直位置,置於視窗底部
            this.Controls.Add(racket); //將球拍物件加入Form1的控制項集合

            //ball,球
            ball = new PictureBox(); //指向一個新建立的PictureBox物件
            ball.Load("ball.png"); //載入美工圖檔,ball.png
            ball.SizeMode = PictureBoxSizeMode.AutoSize; //將球PictureBox物件的尺寸模式設為AutoSize,使球大小自動調整成美工圖案的大小
            ball.Left = (this.Bounds.Width - ball.Width) / 2; //球水平位置,置中於視窗
            ball.Top = racket.Top - ball.Height; //球垂直位置,置於球拍之上
            this.Controls.Add(ball); //將球物件加入Form1的控制項集合

            //brick, 磚塊,建立8列12行的磚塊牆
            bricks = new PictureBox[8, 12]; //建立二維的磚塊物件參考,用以指向PictureBox,注意,是指向PictureBox物件的參考,不是PictureBox物件本身
            brick_width = (this.Bounds.Width - 13 * brick_space) / 12; //計算每一排,12個磚塊,每1個磚塊的寬度
            for (int i = 0; i <= 7; i++) //8列,12行的磚塊
            {
                for (int j = 0; j <= 11; j++)
                {
                    bricks[i, j] = new PictureBox(); //產生每一個磚塊PictureBox物件
                    
                    switch (i)
                    {
                        case 0:
                        case 1: bricks[i, j].Load("brick-blue.png");break;//設定每一列磚塊物件的顏色
                        case 2:
                        case 3: bricks[i, j].Load("brick-red.png"); break;
                        case 4:
                        case 5: bricks[i, j].Load("brick-green.png"); break;
                        case 6:
                        case 7: bricks[i, j].Load("brick-orange.png"); break;
                    }
                    
                    bricks[i, j].SizeMode = PictureBoxSizeMode.StretchImage; //圖案依PictureBox的大小進行縮放設定
                    bricks[i, j].Height = brick_height; //磚塊的高度
                    bricks[i, j].Width = brick_width; //磚塊的寬度                    
                    this.Controls.Add(bricks[i, j]); //將磚塊PictureBox物件加入Form1控制項集合
                }
            }

            place_bricsk(); //喚用place_bricsk方法,排列所有的磚塊            
        }

        private void place_bricsk()
        {
            for (int i = 0; i <= 7; i++)
            {
                for (int j = 0; j <= 11; j++)
                {
                    bricks[i, j].Left = brick_space + (brick_width + brick_space) * j;
                    bricks[i, j].Top = brick_space + (brick_height + brick_space) * i;
                }
            }
        }
    }
}

 

 

【程式設計-C#】打磚塊遊戲 – 同時播放背景音樂與音效

【程式設計-C#】打磚塊遊戲 – 同時播放背景音樂與音效

【程式設計-C#】打磚塊遊戲 – 同時播放背景音樂與音效

 

設計遊戲所需資源關鍵字:電動遊戲 – Video game, 打磚塊 – Arkanoid, 音效 – sound, 背景 – background, 圖片- picture, 角色 – character, 魔王 – boss

背景音樂下載

打磚塊遊戲設計資源 :

在一個遊戲中,會有背景音樂,然後,遇到一些事件要產生特定的音效,用傳統的方式播放音樂/音效,會只聽到一個聲音…

為了要”同時”播放背景音樂與音效,我們要用二種不同的播放器,否則,當播放一個音效時,背景音樂就會停止:

  1. .Windows內建的WindowsMediaPlayer
  2. Net本身的Windows.Media.SoundPlayer類別

要使用Windows內建的WindowsMediaPlayer,需先加入C:\Windows\System32\wmp.dll到參考中,操作方式如下:

請先把聲音檔加入專案中,並設置”一律複製”:

我們將播放撞擊聲寫成一個方法,方便我們反覆的叫用這個方法來播放適當的聲音:

private void playBom() //播放撞擊音樂方法
{
    var player1 = new WMPLib.WindowsMediaPlayer();
    player1.URL = "collision.wav"; //撞擊聲,我們的聲音檔像圖片一樣加入專案中。
}

然後,在需要播放撞擊聲時,進行上述方法的呼叫:擊中球拍與磚塊

//球拍是否擊中球:
if (ball.Left >= racket.Left && ball.Left <= (racket.Left + racket.Width) && ball.Top >= (racket.Top - ball.Height))
{
    Y_Inc = -Y_Inc;
    playBom();
}

//一一測試每顆磚塊是否被球擊中
for (int i = bricks.GetLength(0) - 1; i >=0 ; i--)
{
    for (int j = bricks.GetLength(1) - 1; j >= 0 ; j--)
    {
        if (bricks[i, j].Visible == true) // 若磚塊是可見的話…,表示磚塊尚未被擊中
        {
            if (ball.Left >= bricks[i, j].Left && ball.Left <= (bricks[i, j].Left + bricks[i, j].Width) && ball.Top <= (bricks[i, j].Top + bricks[i, j].Height))
            {
                Y_Inc = -Y_Inc;
                playBom();
                bricks[i, j].Visible = false; //判定擊中後,球的垂直移動方向改變,並將磚塊的Visible屬性設false,使其看不見
                goto HitBrickExit; //一旦擊中,就不用測試其他的磚塊…,跳離這個測試以節省時間
            }
        }
    }
}
HitBrickExit:

背景音樂以C#的Windows.Media.SoundPlayer類別來播放(放在Form1方法的最後段)

//播放背景音樂  
System.Media.SoundPlayer player = new System.Media.SoundPlayer("POL-cooking-mania-short.wav");
player.PlayLooping();

專案檔下載:BrickBreakout – 3

音樂與音效資源: