【程式設計-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

音樂與音效資源:

 

【程式設計-C#】乒乓遊戲

【程式設計-C#】乒乓遊戲

【程式設計-C#】乒乓遊戲

【重點1】球的移動

【重點2】球拍的移動

【重點3】測定球碰觸邊界

【重點4】測定球拍是否擊中球,沒擊中的話…

 

程式利用計時器(timer1),每隔一段時間執行幾件工作:

1.依據目前游標(Cursor)的位置來移動球拍(racket)

2.將球(ball)的位置(left, top)各加上(speed_left, speed_top),left是水平方向(左右),top是垂直方向(上下)

3.判斷球拍是否擊中球(也就是說ball的left, bottom, top, right是否落於racket的left, bottom, top, right內)

若是的話,改變球往下的方向,變成往上的方向

改變球移動速度,也就是增加speed_left, speed_top,讓球移動的距離增加

得分+1,更新計分版

4.判斷球是否碰到右、左、上邊界,是的話,改變方向,左變右,右變左,上變下

5.若球超出下邊界,遊戲中止,跳出訊息視窗

未來加上幾個特性:加上背景音樂 (參考資料)、背景色變換、隨機變換球移動的速度…

【V 1.1 平滑版】【專案檔下載:PingPong-smooth

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 PingPong
{

    public partial class playground : Form
    {
        int speed_left = 5; //球的水平變換速度
        int speed_top = 5; //球的垂直變換速度
        int point = 0; //得分

        int ball_Left = 50, ball_Top = 50, ball_Width = 48, ball_Height = 48;
        int racket_Left = 0, racket_Top = 0, racket_Width = 150, racket_Height = 20;
        Bitmap bmp = new Bitmap("mushroom.png");
        private SoundPlayer player;

        public playground()
        {
            InitializeComponent();

            player = new SoundPlayer(@"C:\audio_output\2.wav");
            player.PlayLooping(); //背景音樂
            timer1.Enabled = true; //啟動計時器1
            Cursor.Hide(); //將游標隱藏起來
            this.FormBorderStyle = FormBorderStyle.None; //將視窗的邊框設成"無",使視窗的邊框(連同標題列)消失
            this.TopMost = true; //將視窗設為最上層
            this.Bounds = Screen.PrimaryScreen.Bounds; //將視窗設為全螢幕

            racket_Top = this.Bottom - (this.Bottom / 10); //設定球拍的垂直位置
            lblGameOver.Top = (this.Height / 2) - (lblGameOver.Height / 2); //置中遊戲結束的訊息文字
            lblGameOver.Left = (this.Width / 2) - (lblGameOver.Width / 2);
        }

        private void playBom() //播放撞壁時的音樂副程式
        {
            var player1 = new WMPLib.WindowsMediaPlayer();
            player1.URL = @"C:\audio_output\1.wav"; //撞擊聲
        }

        private void timer1_Tick(object sender, EventArgs e) //計時器1的跳動事件
        {
            racket_Left = Cursor.Position.X - (racket_Width / 2); //將球拍的中心位置 設為 游標的水平位置

            ball_Left += speed_left; //移動球-水平
            ball_Top += speed_top; //移動球-垂直

            if ((ball_Top + ball_Height) >= racket_Top && ball_Left >= racket_Left) //判斷球拍是否擊中球
            {
                Random rnd = new Random();

                int r = rnd.Next(1, 10);

                if (speed_top >= 0) speed_top += r; //加速
                else speed_top -= r;

                if (speed_left >= 0) speed_left += r;
                else speed_left -= r;

                speed_top = -speed_top; //改變球的移動方向
                point += 1; //得分+1
                lblPoints.Text = point.ToString();

                playBom();

            }

            if (ball_Left <= this.Left)
            {
                speed_left = -speed_left; //若球的左邊緣在左邊界的左邊,變換水平移動的方向
                playBom();
            }
            if (( ball_Left+ball_Width) >= this.Right)
            {
                speed_left = -speed_left;
                playBom();
            }
            if (ball_Top <= this.Top)
            {
                speed_top = -speed_top; //球超出上邊界…
                playBom();
            }
                if ((ball_Top + ball_Height) >= this.Bottom)  //球出界,遊戲結束
            {
                timer1.Enabled = false; //中止計時器1
                lblGameOver.Visible = true; //顯示出遊戲結束訊息
            }
            Invalidate();
        }

        private void PingPong_KeyDown(object sender, KeyEventArgs e) //當按下按鍵時…
        {
            if (e.KeyCode == Keys.Escape) this.Close(); //按Esc離開遊戲
            if (e.KeyCode == Keys.F1) //重新開始遊戲
            {
                ball_Top = 50;
                ball_Left = 50;
                speed_left = 5;
                speed_top = 5;
                point = 0;
                lblPoints.Text = "0";
                timer1.Enabled = true;
                lblGameOver.Visible = false;
            }

        }

        private void playground_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.FillRectangle(Brushes.BlueViolet, racket_Left, racket_Top, racket_Width, racket_Height);
            e.Graphics.DrawImage(bmp, ball_Left, ball_Top, 64, 64);
        }
    }
}

【V 1.0】【專案檔下載: PingPong

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 PingPong
{
    public partial class PingPong : Form
    {
        public int speed_left = 5; //球的水平變換速度
        public int speed_top = 5; //球的垂直變換速度
        public int point = 0; //得分

        public PingPong()
        {
            InitializeComponent();

            timer1.Enabled = true; //啟動計時器1
            Cursor.Hide(); //將游標隱藏起來
            this.FormBorderStyle = FormBorderStyle.None; //將視窗的邊框設成"無",使視窗的邊框(連同標題列)消失
            this.TopMost = true; //將視窗設為最上層
            this.Bounds = Screen.PrimaryScreen.Bounds; //將視窗設為全螢幕

            racket.Top = playground.Bottom - (playground.Bottom / 10); //設定球拍的垂直位置
            lblGameOver.Top = (playground.Height / 2) - (lblGameOver.Height / 2); //置中遊戲結束的訊息文字
            lblGameOver.Left = (playground.Width / 2) - (lblGameOver.Width / 2);
        }

        private void timer1_Tick(object sender, EventArgs e) //計時器1的跳動事件
        {
            racket.Left = Cursor.Position.X - (racket.Width / 2); //將球拍的中心位置 設為 游標的水平位置
            ball.Left += speed_left; //移動球-水平
            ball.Top += speed_top; //移動球-垂直

            if (ball.Top <= racket.Top && ball.Bottom >= racket.Bottom && ball.Left >= racket.Left && ball.Right <= racket.Right) //判斷球拍是否擊中球
            {
                speed_top += 2; //加速
                speed_left += 2;
                speed_top = -speed_top; //改變球的移動方向
                point += 1; //得分+1
                lblPoints.Text = point.ToString();
            }

            if (ball.Left <= playground.Left) speed_left = -speed_left; //若球的左邊緣在左邊界的左邊,變換水平移動的方向
            if (ball.Right >= playground.Right) speed_left = -speed_left;
            if (ball.Top <= playground.Top) speed_top = -speed_top; //球超出上邊界…
            if (ball.Bottom >= playground.Bottom)  //球出界,遊戲結束
            {
                timer1.Enabled = false; //中止計時器1
                lblGameOver.Visible = true; //顯示出遊戲結束訊息
            }

        }

        private void PingPong_KeyDown(object sender, KeyEventArgs e) //當按下按鍵時…
        {
            if (e.KeyCode == Keys.Escape) this.Close(); //按Esc離開遊戲
            if (e.KeyCode == Keys.F1) //重新開始遊戲
            {
                ball.Top = 50;
                ball.Left = 50;
                speed_left = 5;
                speed_top = 5;
                point = 0;
                lblPoints.Text = "0";
                timer1.Enabled = true;
                lblGameOver.Visible = false;
            }

        }
    }
}

 

 

【Another 乒乓遊戲】

Pingpong-2

【程式設計-C#】開啟CSV資料檔案(.csv)並處理資料

【教學目的】

我們要讀入如下的資料,此資料檔以逗點分隔資料,我們要將資料一行一行讀出來(放在一個字串),並且以逗點方式將資料分開(字串陣列)。

【第一個畫面】未分割資料

【第二個畫面】分割資料

成績檔下載:成績檔

陳X鈴,75,70,75,75
劉X如,75,70,75,75
王X玲,75,70,75,75
黃X如,80,85,90,60
林X君,65,80,95,70
張X惠,65,80,70,65
王X琪,80,70,65,75
余X芬,70,80,50,70
周X誼,80,80,90,65
黃X儀,80,80,90,65
陳X妙,80,80,75,75
黃X蓮,80,80,85,65
顏X芳,80,70,90,65
張X洲,75,80,90,75
王X聰,65,70,75,45
胡X虹,20,80,70,65
~~以下 省略~~

【程式碼】

專案檔下載:openCSV

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 WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            tbResult.Text = "";
            // 建立一個OpenFileDialog物件
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            // 設定OpenFileDialog屬性
            openFileDialog1.Title = "選擇要開啟的CSV檔案";
            openFileDialog1.Filter = "CSV Files (.csv)|*.csv|All Files (*.*)|*.*";
            openFileDialog1.FilterIndex = 1;

            openFileDialog1.Multiselect = true;

            // 喚用ShowDialog方法,打開對話方塊

            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {                
                string theFile = openFileDialog1.FileName; //取得檔名
                Encoding enc = Encoding.GetEncoding("big5"); //設定檔案的編碼
                string[] readText = System.IO.File.ReadAllLines(theFile, enc); //以指定的編碼方式讀取檔案
                foreach (string s in readText)
                {
                    tbResult.Text += s + "\r\n";
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            tbResult.Text = "";
            // 建立一個OpenFileDialog物件
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            // 設定OpenFileDialog屬性
            openFileDialog1.Title = "選擇要開啟的CSV檔案";
            openFileDialog1.Filter = "CSV Files (.csv)|*.csv|All Files (*.*)|*.*";
            openFileDialog1.FilterIndex = 1;

            openFileDialog1.Multiselect = true;

            // 喚用ShowDialog方法,打開對話方塊

            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string theFile = openFileDialog1.FileName; //取得檔名
                Encoding enc = Encoding.GetEncoding("big5"); //設定檔案的編碼
                string[] readText = System.IO.File.ReadAllLines(theFile, enc); //以指定的編碼方式讀取檔案
                foreach (string s in readText)
                {
                    string[] ss = s.Split(','); //將一列的資料,以逗號的方式進行資料切割,並將資料放入一個字串陣列
                    tbResult.Text += ss[0] + "  " + ss[1] + "  " + ss[2] + "  " + ss[3] + "  " + ss[4] + "\r\n";

                    //資料分別在取出的字串陣列裏,姓名->ss[0], 成績1->ss[1], 成績2->ss[2], 成績3->ss[3], 成績4->ss[4]
                }
            }

        }
    }
}

 

【一維字串陣列-字串物件】

 

 

底下的改版程式係將讀出來的資料,轉成浮點數後,放入一個2維的浮點數陣列,然後,將總分加總後,放到最後一個欄位(每列)。

       private void button2_Click(object sender, EventArgs e)
        {
            tbResult.Text = "";
            // 建立一個OpenFileDialog物件
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            // 設定OpenFileDialog屬性
            openFileDialog1.Title = "選擇要開啟的CSV檔案";
            openFileDialog1.Filter = "CSV Files (.csv)|*.csv|All Files (*.*)|*.*";
            openFileDialog1.FilterIndex = 1;

            openFileDialog1.Multiselect = true;

            // 喚用ShowDialog方法,打開對話方塊

            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string theFile = openFileDialog1.FileName; //取得檔名
                Encoding enc = Encoding.GetEncoding("big5"); //設定檔案的編碼
                string[] readText = System.IO.File.ReadAllLines(theFile, enc); //以指定的編碼方式讀取檔案

                string[] name = new string[readText.Length];//宣告一個1維字串陣列,來儲存所有的姓名
                double[][] allData = new double[readText.Length][4]; //宣告一個2維double陣列,用來儲存所有的成績資料,第一維的大小是資料的列數(筆數)
                int line = 0; //表第幾行(第幾列,每一列為一個學生的資料)
                foreach (string s in readText)
                {
                    string[] ss = s.Split(','); //將一列的資料,以逗號的方式進行資料切割,並將資料放入一個字串陣列
                    name[line] = ss[0]; //切出來的字串,第0個元素是姓名
                    allData[line][0] = double.Parse(ss[1]);
                    allData[line][1] = double.Parse(ss[2]);
                    allData[line][2] = double.Parse(ss[3]);
                    allData[line][3] = double.Parse(ss[4]);
                    allData[line][4] = allData[line][0] + allData[line][1] + allData[line][2]+ allData[line][3]; //將每個人的成績加起來放在最後一欄

                    tbResult.Text += name[line] + "  " + allData[line][0] + "  " + allData[line][1] + "  " + allData[line][2] + "  " + allData[line][3] + "  " + allData[line][4] + "\r\n";

                    line++; //進行下一筆資料的處理
                    //資料分別在取出的字串陣列裏,姓名->ss[0], 成績1->ss[1], 成績2->ss[2], 成績3->ss[3], 成績4->ss[4]
                }
            }

        }

 

【程式設計-C#】設計小算盤

【程式設計-C#】設計小算盤

【程式設計-C#】設計小算盤

計算機軟體

 

Windows 7上的小算盤

Windows 10上的小算盤

講解-1:程式設計 20180417 3 計算機程式 共用事件  

講解-2: 程式設計 20180501 1 計算機程式 加減乘除

【程式碼】 

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 Calculator
{
    public partial class Form1 : Form
    {
        int op1, op2;
        char op;
        bool 是否清除輸入方塊 = false;                
        public Form1()
        {
            InitializeComponent();
        }

        private void 數字鍵_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            if (是否清除輸入方塊)
            {
                label1.Text = "0";
                是否清除輸入方塊 = false;
            }


            if (label1.Text == "0") label1.Text = btn.Text;
            else label1.Text += btn.Text;
        }

        private void 加減乘除_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            op = Convert.ToChar(btn.Text);
            op1 = Convert.ToInt32(label1.Text);
            是否清除輸入方塊 = true;

        }

        private void 計算結果_Click(object sender, EventArgs e)
        {
            op2 = Convert.ToInt32(label1.Text);
            switch (op)
            {
                case '+':
                    label1.Text = "" + (op1 + op2);
                    break;
                case '-':
                    label1.Text = "" + (op1 - op2);
                    break;
                case '*':
                    label1.Text = "" + (op1 * op2);
                    break;
                case '/':
                    label1.Text = "" + (op1 / op2);
                    break;
                                                
            }
        }
    }
}

 

提示 –  倒退鍵的處理:

label1.text =  label1.text.Substring( 0, label1.text.Length -2);

 

過河問題:農夫、羊、狼、青菜

過河問題:農夫、羊、狼、青菜

過河問題:農夫、羊、狼、青菜

一名農夫帶著一隻狼、一隻羊和一顆高麗菜渡河,河上只有一艘船,一次只能載農夫和一樣東西到對岸,只有農夫會/能划船,如果農夫沒看著,狼會吃羊,羊會吃菜,農夫要如何成功的將狼、羊、高麗菜帶到另一岸,而不會有損失?

程式畫面

【程式列表】

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 WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        string farmerLocation = "L"; //農夫的位置,一開始在左邊

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            lstBoxL.Enabled = true; L.Text = "西岸(可選取)";
            lstBoxR.Enabled = false; R.Text = "東岸(不可選取)";
        }

        /*
         * 當按了往右邊移動,有三個狀況:
         * 1.若農夫已在右邊,不需要移動,離開
         * 2.只有農夫自己一人過河
         * 3.農夫帶著一物過河,選取的物品從左邊移入右邊(Add),並從左邊移除(Remove)
         * 
         * 2與3共同步驟:
         * 設定農夫位值在右邊
         * 對調左右2個清單方塊的可選取狀態
         */
        private void btn2Right_Click(object sender, EventArgs e) //按下往右移動
        {
            if (farmerLocation == "R") return; //如果農夫已在右邊的話就離開

            if (lstBoxL.SelectedItem != null) //若左邊方塊有選取
            {
                lstBoxR.Items.Add(lstBoxL.SelectedItem); //將左邊方塊的選取項目加到右邊方塊
                lstBoxL.Items.Remove(lstBoxL.SelectedItem); //將左邊方塊選取項目移除掉(移到另一邊的意思)
            }
            lstBoxL.Enabled = false; L.Text = "西岸(不可選取)";
            lstBoxR.Enabled = true; R.Text = "東岸(可選取)";

            btnFarmer.Location = new Point(312, 120); //移動農夫 
            farmerLocation = "R"; //標記農夫的位置在右邊
        }

        private void btn2Left_Click(object sender, EventArgs e)
        {
            if (farmerLocation == "L") return; //如果農夫已在右邊的話就離開

            if (lstBoxR.SelectedItem != null)
            {
                lstBoxL.Items.Add(lstBoxR.SelectedItem);
                lstBoxR.Items.Remove(lstBoxR.SelectedItem);
            }
            lstBoxR.Enabled = false; R.Text = "東岸(不可選取)";
            lstBoxL.Enabled = true; L.Text = "西岸(可選取)";

            btnFarmer.Location = new Point(192, 120);
            farmerLocation = "L";
        }

        private void button1_Click(object sender, EventArgs e)
        {  //取消二邊清單方塊的選取
            lstBoxL.SelectedItem = null;
            lstBoxR.SelectedItem = null;
        }
    }
}

【程式英文】

1.ListBox 清單方塊

2.Item 項目 (清單方塊裏的)

3.Items 項目集合

4.Enabled  啟用的

5.SelectedItem 選取的項目

6.null 未指定/空

7.Location 位置

8.point 點

【遊戲判斷】

1.測試清單方塊裏的項目是否同時出現? 當農夫在另一邊時,此時,遊戲失敗!

a.羊和高麗菜,羊會吃了高麗菜

b.狼和羊,狼會吃了羊

2.若羊、狼、高麗菜同時出現在右邊清單方塊時,此時,遊戲過關!

【程式判斷是否失敗】

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 WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        string farmerLocation = "L"; //農夫的位置,一開始在左邊

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            lstBoxL.Enabled = true; L.Text = "西岸(可選取)";
            lstBoxR.Enabled = false; R.Text = "東岸(不可選取)";
        }

        private void lstBoxL_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private bool isGameFailed()
        {
            bool hasSheep = false, hasWolf = false, hasCab = false;
            if (farmerLocation == "L")
            {
                foreach (object o in lstBoxR.Items)
                {
                    string s = o.ToString();
                    if (s == "羊") hasSheep = true;
                    if (s == "狼") hasWolf = true;
                    if (s == "高麗菜") hasCab = true;
                }

            } else
            {
                foreach (object o in lstBoxL.Items)
                {
                    string s = o.ToString();
                    if (s == "羊") hasSheep = true;
                    if (s == "狼") hasWolf = true;
                    if (s == "高麗菜") hasCab = true;
                }


            }

            bool gameFailed = false;
            if (hasSheep && hasCab) gameFailed = true;
            if (hasSheep && hasWolf) gameFailed = true;
            return gameFailed;
        }

        private void btn2Left_Click(object sender, EventArgs e)
        {
            if (farmerLocation == "L") return; //如果農夫已在右邊的話就離開

            if (lstBoxR.SelectedItem != null)
            {
                lstBoxL.Items.Add(lstBoxR.SelectedItem);
                lstBoxR.Items.Remove(lstBoxR.SelectedItem);
            }
            lstBoxR.Enabled = false; R.Text = "東岸(不可選取)";
            lstBoxL.Enabled = true; L.Text = "西岸(可選取)";

            btnFarmer.Location = new Point(168, 101);
            farmerLocation = "L";

            if (isGameFailed()) MessageBox.Show("You losed!");
        }

        private void btn2Right_Click(object sender, EventArgs e)
        {
            if (farmerLocation == "R") return; //如果農夫已在右邊的話就離開

            if (lstBoxL.SelectedItem != null) //若左邊方塊有選取
            {
                lstBoxR.Items.Add(lstBoxL.SelectedItem); //將左邊方塊的選取項目加到右邊方塊
                lstBoxL.Items.Remove(lstBoxL.SelectedItem); //將左邊方塊選取項目移除掉(移到另一邊的意思)
            }
            lstBoxL.Enabled = false; L.Text = "西岸(不可選取)";
            lstBoxR.Enabled = true; R.Text = "東岸(可選取)";
            
            btnFarmer.Location = new Point(312, 101); //移動農夫 
            farmerLocation = "R"; //標記農夫的位置在右邊

            if (isGameFailed()) MessageBox.Show("You losed!");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //取消二邊清單方塊的選取
            lstBoxL.SelectedItem = null;
            lstBoxR.SelectedItem = null;
        }
    }
}

 

File Selection Manager: Advanced recursive file selection, using pseudo SQL statements

Adding File Selection Manager DLL to your .NET C# project allows you to carry out advanced recursive file selection, using pseudo SQL statements. A time saver for any programming project, this allows you to quickly add features that would otherwise take weeks to program!

來源: File Selection Manager: Advanced recursive file selection, using pseudo SQL statements

mBlok+ Arduino,讓 meArm機械手臂動起來

MeArm是一個扁平設計的機器手臂套件,只需要一支起子和對事物熱情的心即可以完成MeArm的組裝,MeArm能夠帶你進入程式設計、電子、機器人和工程的世界,Lifehacker網站描述MeArm是對初學者一個完美的Arduino專案。

MyArm是我們根據MeArm的開源圖,加上為本地學童精心建造的教學套件,初階版本包括機械手臂、電路板、雙搖桿,進階版本則加上紅外線遙控控制、藍芽與手機控制、無線WiFi物聯網的功能,初階版本在於帶領初學者進入MyArm的世界,透過雙搖桿來控制機械手臂的四顆伺服馬達,可完成手臂的三個維度的運動,以及機械手臂爪子的動作。

紅外線遙控版本,可讓我們用紅外線遙控器控制機械手臂,藉此我們可以學習紅外線遙控的原理與操作,我們也可以用家電的遙控器來做為控制器,甚至透過手機利用一個紅外線發射器,就可以做成一個強大的紅外線遙控器,控制所有家中的電器設備,像是電視、冷氣機等。

藍芽與手機控制版本則是利用智慧型手機內建的藍芽,來連結機械手臂,透過此版本,我們可以學習如何在手機或平板上設計程式。

無線WiFi版本則是因應現今最夯的物聯網科技,此版本可以透過Web對機械手臂進行控制,可實現遠端遙控機械,任何想要學習物聯網科技的不能錯過此一版本。

本教學是我們為了本地學童所建立的完整中文學習資源,希望讓大家夠透過MyArm進入創客的世界。

單一馬達測試

mBlock:(程式下載)

Arduino IDE (程式下載)

/*
馬達的接法Vcc接Arduino板子的Vin,GND接板子GND,訊號線接5、9、10、11,其中之1。
degree: 馬達的旋轉角度(45~135)
PM:1或-1,以用控制degree的值是加上15(角度的變化)還是15。
程式判斷若degree值等於45時,讓PM為1,使得degree累加15
若等於135時,讓PM=-1,使得degree值遞減15
 */

#include <Servo.h>
Servo motor; //定義馬達變數(物件)
void setup() {
  // put your setup code here, to run once:
  motor.attach(9); //設定馬達訊號腳連接至Arduino板子的數位接腳9
}

int pm = 1;
int degree = 45;
void loop() {
  // put your main code here, to run repeatedly:
  motor.write(degree); //讓馬達轉至degree角度
  delay(300); //馬達若以高速方式旋轉會燒毀,必須加上延遲,這邊單位是毫秒,也就是1/1000秒。
  if (degree == 45) {
    pm = 1; 
  } 
  if (degree == 135) {
    pm = -1;
  }  
  degree = degree + (pm * 15); //變化degree,
}

四顆馬達的控制-mBlock參考:

參考資料:

1.Arduino: MeArm 與雙搖桿,http://gsyan888.blogspot.tw/2014/11/arduino-mearm-dual-joystick.html

2.mblock第十一課(伺服馬達)

 

mBlock + Arduino,使用遙桿控制遊戲角色

在這個教學中,我們使用下面的遙桿(可變電阻x2,按鈕開關x1),搖桿提供三個讀值VRx(左右,水平), VRy(上下,垂直), 與SW(按鈕開關)。

我們依照下圖來接線:

Vcc – 5V

GND – GND

VRX – A0 (類比腳位0)

VRY – A1 (類比腳位1)

SW-接數位腳位2

接好之後,輸入底下程式:

在上面的程式後,我們先設定2個變數VRx與VRy,這2個變數分別對應/連接到類比腳位1和0(也就是我們遙桿的VRx與VRy),完成後,按一下旗子,執行程式(記得你必須先進行連接與上傳靭體),此時你會看到熊貓左上角的2個變數值,這個值就是遙桿傳回來的數值。

由上圖可知,VRx的讀值為519,VRy的讀值為520。(每個遙桿的初始讀值不會一樣)

VRx, VRy為類比訊號,讀值從0到1023,由於搖桿平時處於中間位置,讀值應該為1023/2=512或513。

接下來,我們要控制角色熊貓的移動,我們必須先查出移動的範圍,假設水平的活動範圍是從-250~250(大約值),那麼我們的作法就讓讀值減去512,再除以2,舉例來說,若讀值是0,0-512=-512,除以2之後得-256,若讀值是1023,減去512,得511,除以2得255。

我們的程式如下: