網誌

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

 

 

CSS 教學 從 HTML + CSS開始

本文主要參考: http://www.w3.org/Style/Examples/011/firstcss.en.html

這個簡短的教學提供給那些想要學習CSS,卻從來沒有使用過CSS樣式的學習者,這個教學沒有太多的CSS介紹,僅僅介紹如何建立一個HTML文件加上一個CSS樣式文件,以及學習如何讓它們整合在一起。

在這個教學之後,你可以進一步地找一些教學及資料,給未來的網頁加上更多的HTML和CSS文件。

在未來,你可以使用專用的HTML 或 CSS 編輯器,幫助你設計複雜的網站。

在完成這個學習的最後,你將會製作出如下的一個HTML文件:

這個網頁只是為了學習網頁的建立與樣式的設定,不是一個完整有設計感的網頁,要多看一些好的設計,找一些富有設計感的模版來學習建置網頁。
【第一步:撰寫HTML】

在這個教學,我們只使用最簡單的文字編輯工具,例如,在Windows裡的Notepad (記事本),在Mac上的TextEdit ,或是在KDE裏的KEdit。我們的目的是要了解網頁背後的運作基礎與原理,一旦建立了相關概念,就可以進階到更高級的工具,如Style Master,Dreamweaver或GoLive。

目前,學習你的第一個CSS樣式時,不要因為使用太多的進階功能而分心。

第一步打開你的文字編輯器,在一個空的窗口開始,輸入以下的內容:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>我的第一個樣式頁面</title>
</head>
<body>
  <!-- 目錄 -->
  <ul class="navbar">
    <li><a href="index.html">首頁</a>
    <li><a href="musings.html">我思我在</a>
    <li><a href="town.html">我的家鄉</a>
    <li><a href="links.html">連接</a>
  </ul>
  <!-- 主要內容 -->
  <h1>我的第一個樣式頁面</h1>
  <p>歡迎來到我的樣式頁面!
  <p>這個網頁沒有圖片, 不過至少有CSS樣式、有超連結, 只是沒有所有的網頁元素…
  <p>這個網頁應該有更多的HTML元素,只是現在,我不知道要給你們什麼…
  <address>
    弘光科技大學 資訊管理系 <br>
    臺中市臺灣大道1段100號
  </address>
</body>
</html>

你直接從複製(copy)上面的內容,並以貼上(paste)的方式,將資料填入編輯器中:

儲存時,請以文字的方式進行存檔(整個教學完成後會有數個檔案):

注意一:當你使用記事本儲存檔案時,若最後的副檔名是txt,請將其去掉,網頁檔案的副檔名為htm或html。

注意二:在開始進行這個學習時,請在目錄建一個目錄用來儲存所有的檔案,以我為例,我在D槽中建了一個myWebPage目錄。

上面HTML文件的第一行宣告HTML的類型(DOCTYPE 意思是文件類型)。在這個案例中,它是HTML 4.01 版本。

在<和>裡的單詞叫標籤,像你看能到的,這文件包含<html> 和 </html> 標籤,表示一個html文件的開始與結束。

<head> 和</head>為html文件的檔頭定義標籤,目前,它包含了這個html文件的標題,之後我們會在這裡加上CSS樣式設定。

<body>是文件文本,原則上,<!– 和–>為html文件的註解。

<ul>標籤是“無序列表”,意謂沒有編號的列表。 <li> 是“列表項目”。

<p> 是“文字段落”。

<a> 是超連結。

注意:HTML不難,不過就是一組標籤的定義,同學可以在網路找到許多的html教學,例:HTML 簡介與應用

注意,本案例並沒下“li”和“p”結束元素,在HTML裡(但不是在XHTML 裡),允許忽略</li>和</p>標籤,只是為了使得文本稍微容易閱讀一點,你可以加上它們,如果你喜歡的話。

現在從檔案選單裡將這個html文件儲存為index.html,先不要關掉記事本編輯器,我們還會需要它。

接下來,我們使用瀏覽器裡打開“index.html”文件。

目前頁面看起來非常單調,沒有任何的設計元素……

【第二步:為網頁加些色彩】

我們從內嵌在HTML 文件裡的樣式開始,之後,我們會把CSS樣式 放進獨立的文件裡,獨立的css文件是一個比較好的作法,對比於混合CSS的HTML文件,它讓相同的樣式使用起來更簡單,你只需要編寫樣式一遍,就可以讓所有的HTML文件來使用CSS樣式。

CSS樣式是透過添加一個<style>元素在HTML文件的表頭中,加入下面的五行來定義<body>區塊的前景與背景顏色。

<!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01//EN”>
<html>
<head>
  <title>我的第一個樣式頁面</title>
  <style type="text/css">
    body {
      color: purple;
      background-color: #d8da3d }
   </style>
</head>

第一行說的是,這是一個樣式表,並且它是用CSS (“text/css”)編寫的。第二行說的是,我們為“body” 元素添加了樣式。第三行設定了文本的顏色是紫色,接下来一行設定了背景是一種帶綠的黃色。

注意:CSS樣式的撰寫規則如下,每條規則有三個部分:

  1. 選擇器(在案例裡:“body”),告訴瀏覽器HTML文件的哪個部分受規則影響了;
  2. 屬性(在示案裡:’color”和’background-color’都是屬性),規定了佈局的什麼方面被設置了;
  3. (’purple’和’#d8da3d’ )給出了樣式屬性的值。

兩個屬性的設置,可以分別獨立撰寫:

body { color: purple }
body { background-color: #d8da3d }

 

現在儲存文件,回到瀏覽器,按下“更新”鍵,觀察網頁變化情形,網頁應該有了色彩。除了頂端的連接列表,網頁文件應該是帶有泛綠的黃色背景的紫色文件。

注意:在CSS裡顏色有多種方法來規定。此案例展示了它們的兩種方法:色彩名稱(“purple” )和色彩十六進制編碼(“#d8da3d” )。色彩的名稱大約有140種,而十六進制代碼有超過16,000,000種顏色。我們可以到底下網頁去取得顏色名稱與編碼

【第三步:指定字型】

另外一件容易做的事情是為頁面多種元素的字體製造一些區別,可以透過body來設定文本的字體,而且透過h1 來設定標題1的字體,底下的案例,是中文字體的設定,字體可以使用列表的方式,瀏覽器會視平台可用的字體,由左到右來選定可以套用的字體。

也就是說,由於不能確定你的讀者電腦上用的是什麼字體,我們添加字體的替代方案:如果沒有Georgia,Times New Roman 或Times 也可以,如果所有的都不行,瀏覽器會使用任何襯線字體,如果沒有Helvetica字體,瀏覽器會選取在形狀上是很相似的Geneva,Arial 和sunSans-Regular,如果沒有這些字體,瀏覽器會選擇任何其它無襯線的字體。

參考:

在文件裏加上底下關於字體的CSS設定:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>My first styled page</title>
  <style type="text/css">
    body {
      font-family: 'cwTeXHei', 'Noto Sans TC', Arial, "文泉驛正黑", "WenQuanYi Zen Hei", "儷黑 Pro", "LiHei Pro", "微軟正黑體", "Microsoft JhengHei", sans-serif;
      color: purple;
      background-color: #d8da3d }
    h1 {
      font-family: 'cwTeXHei', 'Noto Sans TC', Arial, "文泉驛正黑", "WenQuanYi Zen Hei", "儷黑 Pro", "LiHei Pro", "微軟正黑體", "Microsoft JhengHei", sans-serif;}
  </style>
</head>

<body>
以下略

再次儲存文件,並在瀏覽器按“更新”,現在網頁的字體已經擺脫不好看的細明體了。


【第四步:加上一個導覽列】
在HTML 頁面頂部的列表是為了建立一個導覽選單。許多網站有些目錄分類在頂部或是在頁面的邊上,我們把它放在左邊。

導覽選單已經定義在HTML 頁面裡,就是一開始在頂部的<ul>列表,目前連結尚未完整,我們的“網站”到現在為止只有一個頁面,之後我們要把所有連結對應的網頁加上來。

我們要把列表移到左邊去,然後把其它的內文稍微右移,來調整整個網頁的空間,我們要使用的CSS屬性’padding-left’(移動文本主體)和’position’、’left ‘和’top’(移動選單)。

還有其它的方法來做到這一點,例如:“column”或“layout” 。

參考:

在這個編輯器窗口,在HTML文件裡添加以下的行:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>My first styled page</title>
  <style type="text/css">
    body {
      padding-left: 11em;
      font-family: 'cwTeXHei', 'Noto Sans TC', Arial, "文泉驛正黑", "WenQuanYi Zen Hei", "儷黑 Pro", "LiHei Pro", "微軟正黑體", "Microsoft JhengHei", sans-serif;
      color: purple;
      background-color: #d8da3d }
    ul.navbar {
      position: absolute;
      top: 2em;
      left: 1em;
      width: 9em }
    h1 {
      font-family: 'cwTeXHei', 'Noto Sans TC', Arial, "文泉驛正黑", "WenQuanYi Zen Hei", "儷黑 Pro", "LiHei Pro", "微軟正黑體", "Microsoft JhengHei", sans-serif;}
  </style>
</head>
<body>

以下略

如果你再次保存文件,在瀏覽器裡刷新它,你現在就可以得到主要文本左邊的鏈接列表了。已經看起來更加有意思了,是不是?


主要本文被移到了右邊,現在鏈接列表在它的左邊,而不是在頂部了。

注意:’position: absolute’說明ul 元素的定位獨立於或早或晚在文件中出現的任何文本,而”left’和’top’標明了在什麼位置。在這個情況中,從視窗頂部起2em,左邊起1em。

‘2em’表示2倍當前字體的大小。例如,如果選單用一個12點的字體顯示,那麼2em就是24點。 em在CSS裡是非常有用的一個單位,因為它能自動適應讀者可能使用的字體。許多瀏覽器有一個加大或是減少字體大小的選單:你可以試一試,看看當字體加大了選單如何在大小方面加大,如果我們換做使用一個像素大小,情況就不會是這樣了。

【第五步:設計超連結樣式】

導覽選單依然看起來只像個列表,而不像選單。讓我們給它添加一些樣式。我們會移除列表項目符號,再把項目移到左邊,項目符號的位置。我們還會給每個項目它們自己的白色背景和黑色框框。(為什麼?沒有特殊的原因,只是因為我們能夠這樣做。)

我們也沒有說明鏈接的顏色應該是什麼,所以,讓我們也加上:藍色顯示用戶沒有看過的鏈接,紫色顯示已經訪問過的鏈接:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>My first styled page</title>
  <style type="text/css">
    body {
      padding-left: 11em;
      font-family: 'cwTeXHei', 'Noto Sans TC', Arial, "文泉驛正黑", "WenQuanYi Zen Hei", "儷黑 Pro", "LiHei Pro", "微軟正黑體", "Microsoft JhengHei", sans-serif;
      color: purple;
      background-color: #d8da3d }
    h1 {
      font-family: 'cwTeXHei', 'Noto Sans TC', Arial, "文泉驛正黑", "WenQuanYi Zen Hei", "儷黑 Pro", "LiHei Pro", "微軟正黑體", "Microsoft JhengHei", sans-serif;}
    ul.navbar {
      list-style-type: none;
      padding: 0;
      margin: 0;
      position: absolute;
      top: 2em;
      left: 1em;
      width: 9em }
    ul.navbar li {
      background: white;
      margin: 0.5em 0;
      padding: 0.3em;
      border-right: 1em solid black }   
    ul.navbar a {
      text-decoration: none }
      a:link {
      color: blue }
      a:visited {
      color: purple }
  </style>
</head>
<body>

以下略

注意:按慣例來說,瀏覽器用下標線和顏色來顯示超鏈接。通常,使用類似我們在這裡規定的顏色:藍色顯示你還沒有訪問過的鏈接頁面(或是很久之前訪問過的),紫色顯示你已經看過的。

在HTML 裡,超鏈接是用<a>元素創建的,所以要規定顏色,我們需要添加“a”的樣式規則。為了區分已經訪問過的和沒有訪問過的鏈接,CSS提供了兩個“假類”(:link 和:visited) 。它們稱為“假類 pseudo-classes”以區別那些類別的屬性,在我們的案例裡,指定ul的類別屬性:class= “navbar”

【第六步:加上一個水平線】

接下來添加的樣式是用來把文本跟底端簽名分開的一個水平線規則。我們會使用’border-top’在<address>元素上面來添加一條線:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>My first styled page</title>
  <style type="text/css">
    body {
      padding-left: 11em;
      font-family: 'cwTeXHei', 'Noto Sans TC', Arial, "文泉驛正黑", "WenQuanYi Zen Hei", "儷黑 Pro", "LiHei Pro", "微軟正黑體", "Microsoft JhengHei", sans-serif; 
      color: purple;
      background-color: #d8da3d }
    ul.navbar {
      list-style-type: none;
      padding: 0;
      margin: 0;
      position: absolute;
      top: 2em;
      left: 1em;
      width: 9em }
    h1 {
      font-family: 'cwTeXHei', 'Noto Sans TC', Arial, "文泉驛正黑", "WenQuanYi Zen Hei", "儷黑 Pro", "LiHei Pro", "微軟正黑體", "Microsoft JhengHei", sans-serif;}
      ul.navbar li {
      background: white;
      margin: 0.5em 0;
      padding: 0.3em;
      border-right: 1em solid black }
    ul.navbar a {
      text-decoration: none }
      a:link {
      color: blue }
      a:visited {
      color: purple }
    address {
      margin-top: 1em;
      padding-top: 1em;
      border-top: thin dotted }
  </style>
</head>

<body>

以下略

現在我們的樣式完成了。接下來,讓我們看看如何把樣式表放進單獨的文件裡,如此以來其它的頁面能分享同樣的樣式。


【第七步:將樣式設定放在另一個獨立的檔案】

我們現在有一個嵌入樣式CSS的HTML 文件,只是如果我們的網站發展了,我們肯定會要許多頁面分享相同的樣式,有一個比複製樣式表到每個頁面更好的辦法:我們把樣式放進單獨的文件,使用所有的頁面都可以參考它。

要製作樣式表文件,我們需要建立另一個空的文件,從HTML 文件中複製在<style>元素裡的內容,記得不要複製<style>和</style>這2個標籤,它們屬於HTML ,不屬於CSS。在新的記事本應該有完整的樣式:

文件必須確保與index.html文件在同一個目錄裡,上面的樣式檔案儲存為“mystyle.css”。

現在回到編輯indexl.html的HTML記事本視窗,移除從<style>標籤開始到包括</style>標籤的所有內容,再用<link>元素替換它,如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>我的第一個樣式頁面</title>
  <link rel="stylesheet" href="mystyle.css">
</head>
以下略

這會告訴瀏覽器在目錄中找到叫“mystyle.css”的樣式表。

【第八步:產生所有的連結檔案】
接下來,請產生底下三個網頁,好讓導覽連結能夠正確地切換到各個網頁:

  • musings.html
  • town.html
  • links.html

【第九步:將網頁檔案放在網站空間】

目前,我們所有的作業都是在自己的電腦上,所以瀏覽器是以file:///方式來打開網頁檔案,而不是以http://的型式,要讓所有的人可以從網際網路上來存取你的網站,你必須要有一個可以在網際網路上任意存取的網站空間,並把所有網頁的檔案上傳到網站:

  1. 自行架站,在家或在學校或在機關或在…
  2. 我的學生可以由我提供網站空間。
  3. 免費的虛擬主機 (virtual host),比較容易,可參考各家提出的方式,將網站上傳到申請的免費虛擬空間。
  4. 虛擬伺服器 (virtual private server)
  5. google 雲端主機

【HTML/CSS產生器】

在這個教學之後,你可以利用在網路上的HTML/CSS產生器工具來是快速產生需要HTML/CSS碼,try it now!

【參考資料】

PLC sources

【PLC Standards]

【Documents】

【Listing of Open Source Ladder editors】

Ladder Logic Simulator

【HAL】

【Production Editors】

【CNC】

【plc peripheral】

 

【PLC-based Motion/Motor Controller】

PLC-based vs. proprietary robotic controls

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