本書介紹

這線上電子書整理了 Youtube 頻道「小山的教學平台」的「小山的 C# 教學」影片之中的重點、補充資料以及一些練習題。

本書由頻道主小山本人親自維護,並放在 GitHub 上,經由 GitHub Actions 自動編譯與發佈到 GitHub Page

遷移公告

舊的網站「SLMT's Tutorial Blog」將逐步停止維護,並且 C# 相關的教學內容將會慢慢轉移至這本書中。其他的教學也會建立對應的書籍進行轉移。

課程目錄 (以主題分類)

為了讓各位讀者及觀眾能夠掌握課程大致的架構,以及方便以及學習過基礎的人能夠直接從新的部分切入,因此製作這個目錄以供大家參考。

一、教學簡介 (Tutorial Introduction)

第0課 - 閒聊及影片介紹

二、C# 基礎 (C# Basic)

第1課 - C# 是甚麼?

第2課 - IDE 跟 Hello World

第2.1課 - Visual Studio Community

第3課 - 程式結構與進入點

第4課 - 視窗與按鈕

第5課 - 變數

第6課 - 基本計算

第7課 - 變數宣告意義與型別

第8課 - string 簡介 (僅有 Youtube 影片)

第10課 - if else (僅有 Youtube 影片)

第11課 - for 與 while 迴圈 (僅有 Youtube 影片)

第12課 - 註解與 Debug

第36課 - Constant 常數

第37課 - switch 與 enum

第22課 - Array 陣列

第38課 - Multidimensional Arrarys 多維陣列

三、視窗設計 (Windows Form Design)

第9課 - Label 與 點擊次數記錄程式

第13課 - NumericUpDown

第20課 - TextBox 與 借還錢模擬小程式(上)

第21課 - 借還錢模擬小程式(下)

第39課 - PictureBox

四、物件導向 (Object-Oriented)

1. 物件基礎 (The Basic of Object)

第14課 - 物件導向基礎 Class

第15課 - Class 簡介(續)

第16課 - Value 與 Reference Type

第17課 - Constructor 建構子

第18課 - this 變數

第19課 - static 修飾字

第23課 - Garbage Collection 垃圾回收

2. 封裝性 (Encapsulation)

第24課 - 封裝性 Public vs Private

第25課 - Private 的常見用途

第26課 - Get & Set 存取器

第27課 - 所以到底甚麼是封裝性?

3. 繼承性 (Inheritance)

第28課-繼承性

第29課-繼承性(續)

第31課-Override

第32課-Override vs Method Hiding

第33課-Protected

第34課-Base 關鍵字

第35課-Abstract Class & Abstract Method

4. 專案練習 - 五子棋小遊戲

第40課-五子棋小遊戲(一)-棋盤與棋子

第41課-五子棋小遊戲(二)-動態建立棋子

第42課-五子棋小遊戲(三)-用滑鼠建立棋子

第43課-五子棋小遊戲(四)-判斷交差點的位置

第44課-五子棋小遊戲(五)-正確放置棋子

第45課-五子棋小遊戲(六)-重構與最後準備

第46課-五子棋小遊戲(七)-簡單勝利判斷

5. 多形性 (Polymorphism)

第47課-多型性 (Polymorphism)

第48課-介面 (Interface)

第50課 - 泛型 (Generics) 的初步介紹

五、C# 內建函式庫之使用 (C# Built-in Library)

第30課-亂數 Random

第49課 - 串列 (List)

第 0 課 - 閒聊與影片介紹

本課介紹

本課主要是談關於教學影片的雜事,裡面並沒有任何教學
想直接看教學的人請從下個影片開始看喔!

教學影片

重點提示

  1. 希望我講的話大家都聽得清楚
  2. 有個朋友想學 C#,所以我就乾脆地拍了教學影片
  3. 每個影片長短會盡量控制在 10 分鐘上下
  4. 我們的 C# 教學會使用名為 Visual C# 2010 Express 的 IDE 來開發程式

補充

IDE

IDE 全名為 Integrated Development Environment,中文稱之為「整合開發環境」。簡單來說,IDE 就是一個用來寫程式的程式。裡面整合許多寫程式以及執行程式需要的各種環境。如此一來就可以讓程式設計師專注在撰寫程式碼上面,而不用耗費心思去研究如何編譯(Compile)以及管理程式碼。

相關資訊連結

維基百科 - IDE

http://zh.wikipedia.org/wiki/%E9%9B%86%E6%88%90%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83

第 1 課 - C# 是甚麼?

本課介紹

此課主要在簡介 C# 以及介紹它如何運作

教學影片

重點提示

  1. C# 是由 Microsoft (微軟) 公司推出的程式語言
  2. C# 比較適合在 Windows 下面運行
  3. C# 是物件導向的程式語言
  4. 「物件導向」簡單來說就是「透過建立物件,並且讓這些物件互動,來達成你想完成的目標」
  5. 物件導向有三個原則「封裝(Encapsulation)」、「繼承(Inheritance)」、「多形(Polymorphism)」
  6. C# 必須要配合「.NET Framework」來運行
  7. C# 經過編譯之後,得到的是一種稱為「中間代碼」的東西,而不是組合語言的程式碼。

補充

Microsoft

相信大家都知道世界知名的軟體公司,微軟。這個由比爾蓋茲(Bill Gates)創建的公司,旗下的作業系統,Windows,已經深入到我們周遭的電腦之中。現在大多數的人都使用過他們的產品,而且也變成生活中或不可缺的一部分。

.NET Framework

C# 無法像用 C/C++ 寫的程式,直接在各種環境下執行。C# 經過編譯之後產生的是一種電腦無法直接識別的代碼,因此必須要經過一個程式幫它翻譯。而這個程式就叫做「Common Language Runtime (CLR)」,除了幫忙轉換代碼外,它還會負責管理 C# 程式使用的資源,這對寫程式的人來說是非常方便的。而 CLR 以及 C# 需要用到的其他資料,都被整合在「.NET Framework」這個環境之下。所以「.NET Framework」對 C# 來說是不可或缺的一部份。

編譯(Compile)

這邊的編譯指的是將程式碼轉換成另一種代碼的這個過程。因為我們所看到的程式碼電腦無法直接執行,所以必須轉換成比較方便執行的形式。通常程式碼會在執行之前就先編譯好,以防止在執行的時候浪費時間在編譯上面。

組合語言

程式語言有分很多種,組合語言就是其中一種分類。組合語言的程式碼基本上就是把電腦所看到的機器語言稍微轉換成比較好記的形式而已,所以感覺就像是直接對 CPU(中央處理器) 下指令。但是因為要編寫組合語言必須要很了解 CPU 的執行模式,所以必須要具備許多電腦結構的知識才行。

相關資訊連結

微軟的 C# 與 .NET Framework 簡介

http://msdn.microsoft.com/zh-tw/library/z1zx9t92(v=vs.80).aspx

維基百科對於物件導向的介紹

http://zh.wikipedia.org/wiki/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B

第 2 課 - IDE 跟 Hello World

本課介紹

這次主要在介紹 Visual C# 2010 Express 與製作第一個程式~

注意:因為微軟官方已經不提供 Visual C# Express 了,因此提供了全新的教學來介紹新的 IDE! 詳情請參考「第2.1課-Visual Studio Community」。

教學影片

重點提示

  1. 安裝 Visual C# 2010 Express
  2. Visual C# 2010 Express 剛下載下來有使用期限,必須要註冊才能解除限制
  3. Visual C# 2010 Express 會幫你完成許多工作。例如新增專案時,他會幫你產生一些繁瑣的程式碼。
  4. 撰寫第一個程式「Hello World」
  5. Visual C# 2010 Express 可以在你打某個程式碼的單字時,自動補齊剩下的程式碼
  6. 最好常常按「Ctrl + S」存檔,因為未來是不可預測的
  7. 想要測試程式,按下 IDE 上面的「綠色箭頭」就可以執行了

補充

Visual Studio

許多開發 C++ 或者 C# 的工程師應該都知道 Visual Studio 這個程式。它跟 Visual C# 2010 Express 一樣是開發程式的 IDE。這兩個程式在介面與操作上都極為類似,但是 Visual Studio 卻比 Visual C# 2010 Express 還要強大很多,功能也較為多樣。主要是因為Visual Studio 是「付費軟體」,而 Visual C# 2010 Express 其實可以算是前者的簡化版。

事實上,就連在下開發程式的時候,也是使用 Visual Studio。不過就教學來說,Visual C# 2010 Express 也很夠用了。所以大家可以放心使用。

練習

試著修改 Console.WriteLine 裡面的文字,讓程式顯示自己的名字吧! 像是:「我是 XXX!我超強!」

參考解答:https://github.com/slmt-tutorial-channel/c-sharp-solutions/blob/master/class_1_10/class2.md

第 2.1 課 - Visual Studio Community

本課介紹

本課介紹了 Visual Studio Community
包括介紹各種 Visual Studio 版本的差異
以及安裝時需要注意的事項等等

因為最初教學使用的 Visual C# Express 已經無法取得
因此推薦學生使用這個版本進行練習

教學影片

本課教材

課程投影片:https://github.com/slmt-tutorial-channel/c-sharp-class-materials/blob/master/class-1-10/class-2.1/2.1-slides-vs-community.pdf

重點提示

  1. Visual Studio 是微軟開發的 IDE,有多種版本,一般用戶下載 Community 版即可
  2. Visual Studio Community 有些使用限制如下:
    • 公益使用 (教學、學術、開放原始碼) 不受限制
    • 商用目的在官方公布的公司規模 (2019 年的規定是 250 台電腦內,或營業額一百萬美金以內) 以下,使用不受限制

練習

照著影片下載 Visual Studio Community,寫出第一個程式試試看吧!

相關資訊連結

Visual Studio Community 官方網站

https://visualstudio.microsoft.com/zh-hant/vs/community/

第 3 課 - 程式結構與進入點

本課介紹

這課主要介紹上一課所寫的 HelloWorld 程式碼架構
以及 C# 的 Entry Point(程式進入點)

教學影片

重點提示

  1. 我們可以大致將 C# 程式碼分成兩塊,一塊是含有 using 的區塊,一塊是程式碼的主要部分
    • using 部分主要是在呼叫內建的程式庫
    • 主要區塊就是我們編寫程式邏輯的地方
  2. C# 裡面,用大括號包起來的程式碼算是一個「區塊」。這個區塊屬於括號上面的程式碼所有。
  3. Hello World 的這個程式由裡到外分成三層,namespace、class、method
  4. namespace 可以想成是自己的程式庫,所以在 namespace 內寫程式碼就是在編寫自己的程式庫
  5. class 一般負責 namespace 裡面一部分的工作
  6. method 是在 class 下,負責更細部事務的東西。它有一個明顯的特徵,通常 method 後面都會跟著一個小括號,像是:void Example(int num)
  7. static void main(string[] args) 是特別的 method,所有的 C# 程式都會從這個 method 開始執行。 一般稱之為「進入點(Entry Point)」
  8. Console.WriteLineConsole.ReadKey 也都是 method。前者會在黑色視窗上顯示文字,後者會等待使用者輸入任意字元
  9. 每一行程式碼都必須要加上「;」(分號),代表一行的結束

補充

using System

大家可以看到程式裡面出現了 Console.WriteLine 以及其他 method。那這些 method 到底都寫在哪裡呢?事實上,就是寫在那些名為「System」的程式庫裡。那些程式庫包含了大量可以讓我們寫 C# 更方便的程式碼,以及我們之後會用到的「視窗」也都是寫在名為「System.Windows.Forms」的程式庫內。想要使用這些程式庫,就必須要在程式碼上面打上「using {程式庫名稱}」才行。不過剛開始不太需要注意,因為你的 IDE 都會自動地幫你打理好這些問題。

Console

寫過 C\C++ 程式的人,我想大多數顯示出來的結果都是出現在這個黑色的視窗上對吧?其實我們現在所看到這些視窗、按鈕甚麼的,背後都是由大量的程式碼所建立出來的。而且事實上,這些圖形的畫面是非常耗費資源。早期的程式設計師寫程式,都是在我們看到那個黑底白字的畫面上跑的。而 Console 就是 Windows 下的黑底白字介面。大家可以在「附屬應用程式」>「命令提示字元」那邊開啟 Console 的畫面。

Entry Point

每個程式都會有個獨一無二的「進入點」,也就是作為電腦一開始執行的 method。C\C++ 一般是使用「int main(void)」,win32 的程式是使用「int WINAPI WinMain(...)」,而 C# 就是這個「static void main(string[] args)」。基本上,這個名稱是規定好的,所以不可以隨便更改。如果改成別的名字,電腦就會不知道該從哪裡開始執行。

練習

  1. 試著讓程式顯示多行的文字 例如:

    C# 真好玩
    而且我會寫第一個程式了
    這是第三行的說
    
  2. 接上一題,試著讓程式顯示一行停頓一次。每次停頓時,必須要按下鍵盤按鍵才會繼續。

  3. 根據「相關資訊連結」的「Console 可以使用的 method 清單」,查查看還有甚麼其他 method 可以使用。例如:讓電腦發出 Beep 的一聲。

參考解答:https://github.com/slmt-tutorial-channel/c-sharp-solutions/blob/master/class_1_10/class3.md

相關資訊連結

System 程式庫裡面包含的 Class 清單

http://msdn.microsoft.com/zh-tw/library/system%28v=vs.80%29.aspx

Console 可以使用的 method 清單

http://msdn.microsoft.com/zh-tw/library/system.console_methods%28v=vs.80%29.aspx

第 4 課 - 視窗與按鈕

本課介紹

這課主要在介紹如何製作簡單的視窗程式,並且在視窗上做出按鈕

教學影片

重點提示

  1. 選擇「檔案」>「新增專案」>「Windows Form 應用程式」就可以自動地建立視窗程式
  2. IDE 內的「屬性」視窗可以修改視窗的設定值
    • Ex: Text 是「視窗標題」、BackColor 是「背景顏色」
  3. 想要放入按鈕,只要找到旁邊的「工具箱」視窗,然後把按鈕拖出來就可以了
  4. 想要修改其他物件的屬性,只要點一下那個物件,再去看屬性視窗就可以了
  5. 當我們按下按鈕後,程式會自動執行 private void button1_Click(...) 這個 method 裡面的程式碼
  6. MessageBox.Show() 可以用來顯示對話框,小括號內放的就是要顯示的文字

補充

視窗程式

所謂視窗程式,就是指一般在 windows 內看到這些可以放大縮小的程式。想要建立一個視窗程式需要很複雜的程式碼,例如要利用「C 語言」寫出視窗要做很多不同的設定。像是除了設定視窗的資訊之外,還要進行視窗註冊等等。幸虧 .NET Framework 裡面早就幫你處理好了。這就是為了要讓程式設計師能夠專心在處理其他更重要的事情上面。

Form1.Designer.cs

每當你建立專案的時候,你的 IDE 可是在背後做了很多事情。對於一些有寫程式經驗的人來說,可能會很疑惑到底設定視窗(Ex: 大小、標題...)的程式碼都塞在哪裡?答案是塞在名為「Form1.Designer.cs」這個檔案裏面。注意檔案名稱會隨著視窗名稱改變。每當我們在「屬性」區塊上面做設定,IDE 都會自動地修改「Form1.Designer.cs」裡面的程式碼。

有興趣的話,可以打開那個檔案看看。不過建議不要更動裡面的程式碼,除非你已經很熟悉裡面在做甚麼。

練習

  1. 改改看「屬性」視窗裡面其他設定,看看會造成甚麼影響?
  2. 例如把 MaximizeBoxMinimizeBox 設為 false 看看?
  3. 或者把 Cursor 設為 Hand 然後執行看看?

第 5 課 - 變數

本課介紹

這課主要是在介紹「變數」 包括如何宣告變數、指定數值、以及將值顯示出來等等

教學影片

重點提示

  1. 「變數」主要是在扮演「儲存資料」的腳色
  2. 所有的變數在使用之前,都必須先宣告過一遍
    • 目的在於讓電腦先知道變數的「型別」是甚麼
  3. 想要宣告多個變數,只需要在變數中間用「,」區隔即可
  4. int」代表「整數(Integer)」,例如:-2、10、800000、-9999
  5. =」不是「相等」,而是「指定」
  6. 在使用變數之前,務必先存入某個數值。如果沒有這樣做,電腦不會讓你編譯它
  7. 如果怕自己忘記設定數值,可以在宣告的時候順便指定數值,像是...
    int number = 10;
    
  8. 一般來說,變數的值是可以一直修改的

補充

變數的名稱限制

C# 對於變數的命名有一套限制規則,並不是所有的名稱都可用來當作變數名稱使用。最基本的限制就是,變數不可以使用「關鍵字(Keyword)」作為名稱。那甚麼是關鍵字呢?就是 C# 裡面與程式結構有關的字眼,例如:class、using、namespace.... 基本上就是那些你在 IDE 中看起來有顏色的字。

那另外,其他限制還包括,在同一個 Scope(下面有解釋) 內,不可以使用一樣的變數名稱。變數的第一個字必須是英文、底線等等。詳細可以看看「相關資訊連結」的文章。

那還有一個問題是,可不可以用中文字當作變數名稱呢?可以,但是我強烈建議不要這樣做。主要是因為中文字與一般文字的儲存方式不同,也許會發生不可預期的錯誤。

Scope

變數並不是永久長存的,也不會一直在程式裡面儲存著。每個變數都有它作用的限制範圍,或者也可以說是變數的生存期限。而這個範圍,就稱作「Scope」。今天你在某個地方宣告了變數,但是只要超出了變數的 scope,就無法使用它了。

那要怎麼判別變數的 scope 呢? 很簡單,只要看「大括號 { }」的包起來的區塊就行了。基本上,變數只在大括號包起來的範圍內才有效。而在大括號外面使用變數就會無法呼叫到它。目前只需要知道這樣就好了。

這 個 scope 還提供了一個好處。變數名稱是不可以重複的,不過它有個例外存在。 就是如果你在一個變數的 scope 外宣告了一樣名稱的變數,那就不會互相影響。例如,你在 void button1_Click() 裡面宣告了 num,跟在 void button2_Click() 裡面宣告了 num,這樣就不會互相衝突。

型別 Type

變數在使用之前必須要先宣告型別。這個作用是在於讓電腦知道,它要配給這個變數多少記憶體空間。另外也是要在後面進行一些使用上的判斷,通常可以預防不少語法上的錯誤。

變數的型別有很多種,詳細的種類後面會慢慢介紹。

指定

這課提到「=」代表「指定」,而不是「相等」。真正的「相等」是使用「==」這個符號。這個區分非常重要,因為這是程式設計師常犯的錯誤。在這裡,「指定」代表的意思其實就是把「右邊的值存入左邊的變數」裡的意思。只要這樣記就比較不會出錯。

個人對於變數的命名習慣

我個人對於變數命名有個習慣。如果我的變數名稱是由多個單字拼成的,那我第一個單字的第一個字母會小寫,後面單字的第一個字母會大寫。這不是硬性規定的,但有一部分的趨勢是這樣的。

Ex: 假設某個變數是由「form、background、color」組合而成

formBackgroundColor

練習

  1. 試著在 button1_Click 裡面宣告兩個「名稱相同」的變數,可以發現甚麼問題?
  2. 那如果我分別在 button1_Click 跟 Form1 這兩個 method 中宣告一樣的變數呢?
  3. 那或者我在 button1_Click 裡面跟外面(注意不是在 Form1 的 method 中),宣告名稱一樣的變數呢?

上面這三種情況,為什麼有時候變數可以名稱相同,有時候不行?
(參考補充的 Scope)

參考解答:https://github.com/slmt-tutorial-channel/c-sharp-solutions/blob/master/class_1_10/class5.md

相關資訊連結

變數的內建型別列表

http://msdn.microsoft.com/zh-tw/library/cs7y5x0x%28v=vs.90%29.aspx

第 6 課 - 基本計算

本課介紹

此課主要在教如何進行基本的加減乘除計算
以及複合運算子與遞增預算子的介紹

教學影片

重點提示

  1. +-*/ 分別代表加、減、乘、除的意思
  2. 在 C# 裡面計算數學就只要單純地將數學式列出來就可以了,但是算式務必要在等號的右側,左側則是儲存結果的變數
  3. 除法要是遇到無法整除的情形,它仍會計算到小數點後
  4. 如果你試圖要將小數存入 int (整數) 變數裡面,C# 會自動省略小數點之後,只留下整數的部分存進變數裡面
    • 例如下面程式碼計算結果應為小數的 3.75,但是因為 a 被宣告為整數,所以最後只會存入整數的部分 3
      int a;
      a = 30 / 8;
      
  5. 如果你單純只想算除法的「餘數」的話,可以使用 % 這個符號,相當於數學的 mod 運算
  6. 下面這個式子
    number = number + 8;
    
    可以簡化為
    number += 8;
    
    這個做法可以同樣套用到 -*/% 這些符號上
  7. 如果今天只需要做單純「遞增」或「遞減」的計算,可以使用
    number++;
    number--;   
    
    上面分別代表 number 加一與減一 (注意:只能用於加減一的情況)

補充

計算結果

假設今天你寫了一個四則運算的式子,像是 12 + 30 * 23 - 21 這樣。那他的計算結果會跑到哪裡去呢?事實上,C# 在計算的時候,會依照優先順序把上述的結果一次一次地計算出來。然後再存入「=」左邊的變數裡。

像是 12 + 30 * 23 - 21 (別忘記先乘除後加減的原則) 就會先變成 12 + 690 - 21 ,再轉變成 702 - 21 ,再轉變成 681,最後再存進變數裡。所以其實電腦也沒聰明多少,他們計算的方法跟我們是差不多的。

整數變數

在影片中可以看到,我們把像是 30 / 8 這種除完後會出現小數 3.75 的計算結果硬是存入整數變數中,就會發生小數點後的 .75 不見,只留下 3 的結果。因此如果今天要把小數完整地保留下來,就必須要使用「小數的變數」。關於這點後面的章節會提到。

優先順序

這些計算符號 + - * \ % ,甚至 =++這些符號,都被稱作為「運算子」(Operator)。C# 一看到運算子,就會依照他的計算邏輯把運算子左右兩邊的值抓出來做計算。那麼為了要使結果正確,並且有規則可循。每個運算子都有優先的順序。

像是我們熟悉的「先乘除、後加減」也是 C# 使用運算子的優先順序之一,所以它就會先計算 * / % 的結果,再去計算 + - 的結果。比較少人注意到的是, = 的優先順序是很低的,所以 C# 才會等算式的結果都出來之後才把值存入變數裡。

詳細的優先順序可以參考下面的連結。

相關資訊連結

C# 運算子優先順序和關聯性

https://learn.microsoft.com/zh-tw/dotnet/csharp/language-reference/operators/#operator-precedence

第 7 課 - 變數宣告意義與型別

本課介紹

此課解釋為何變數需要進行宣告,另外進一步地介紹之前提過的 int 型別,並另外介紹 floatdoublebool 型別的變數。

教學影片

重點提示

  1. 宣告變數的意義在於,先告知電腦到底我們要給這個變數多少記憶體空間 (電腦會從型別判斷) 以及它的名稱是甚麼。
  2. 在 C# 裡面,每個 int 的變數可以分配到 32 bits(4 bytes) 的記憶體空間。也就是說,對於每個 int 的變數,電腦會存放 32 個 0 或 1 在記憶體裡面。
  3. int 只能儲存有限大小的數字,而這個範圍是從 2^31 - 1 到 - 2^31,也就是 2,147,483,647 到 - 2,147,483,648 這之間的數字。
  4. 想要儲存小數可以使用 floatdouble,一般會推薦使用 double,因為可以儲存較廣的數字。
  5. C# 預設情況下會將所有數字當成 double 來處理。
  6. 有一種型別 bool 只能儲存 truefalse 兩種資料,這種數值通常用來儲存判斷式的結果。

補充

32 bits 的整數

本課提到 C# 裡面的 int 是使用 32 bits 的空間。但是在 C/C++ 裡面,int 變數使用的空間則跟 CPU 與 Compiler 有關。有時候會是 32-bit ,有時候是 64-bit。而 C# 並沒有這個問題。因為事實上,C# 內建了三種 int 型別,分別為 Int16Int32Int64,代表16、32、64 bits 的整數。當我們打 int 時,程式會自動解析為 Int32 來處理。因此固定都是 32-bit 的整數。

大數 Big Integer

int 能儲存的數字有限,因此當我們需要儲存更大的數字時,可能就不夠用了。從上一段文中可以知道,C# 還有內建的 Int64 這個型別可以使用。但是在密碼學中,進行 RSA 演算法時,因為內含大量的指數 (exponential) 與模數 (mod) 預算,使得 64-bit 的數字也不足以儲存計算結果。這個時候,大數 (Big Integer) 就登場了。

「大數」其實與一般的「整數」無異,不過它使用的記憶體空間會隨著儲存的數字做動態變化。基本上只要你的記憶體夠大,想要儲存多大的數字都不是問題。大數實作方式有很多種,而 Java 跟 C# 都有官方寫好的版本供大家使用。如何實作大數並加以使用也是程式競賽中時常出現的考題呢!

相關資訊連結

變數的內建型別列表

https://learn.microsoft.com/zh-tw/previous-versions/visualstudio/visual-studio-2008/cs7y5x0x(v=vs.90)?redirectedfrom=MSDN

大數 Big Integer 相關資訊

https://learn.microsoft.com/zh-tw/dotnet/api/system.numerics.biginteger?view=net-7.0&redirectedfrom=MSDN

第 8 課 - string 簡介

本課介紹

此課在簡介 string (字串) 是甚麼,以及 string 之間的串接方式。

教學影片

重點提示

  1. string 型別指的是由一連串文字所組成的資料,中文叫做「字串」。
  2. string 與之前提到的 intfloat 這些型別不同,記憶體空間並不是固定的,而是會隨著存放的文字量變化。
  3. 兩個 string 的變數可以透過 + (加法符號),將連個字串連接在一起。
    • 例如:以下例子之中,str3 最後會得到 我是小山 哈哈 這個結果。
      string str1 = "我是小山 ";
      string str2 = " 哈哈 ";
      string str3 = str1 + str2;
      
  4. + 不但可以把兩個字串相接,也可以讓字串與非字串的變數相接起來。
    • 例如:以下例子之中,str2 最後會得到 我是小山 54321 這個結果。
      string str1 = "我是小山 ";
      int number = 54321;
      string str2 = str1 + number;
      
  5. 字串的串接如同一般型別使用 + 的運算,也支援 += 的寫法。
    • 例如:以下例子之中,str1 最後會得到 我是小山 哈哈 這個結果。
      string str1 = "我是小山 ";
      string str2 = " 哈哈 ";
      str1 += str2;
      

補充

字串與非字串相接背後的魔法

本課中提到了字串在與非字串相加的時候,會自動將後者轉換成字串,然後再串接起來。那麼這是基於甚麼樣的原理做到的呢?

事實上,這利用到了 C# 之中的一個重要的設計,Object 型別的存在。

Object 型別是 C# 之中所有類別的基底類別 (類別與基底類別的概念後面課程會介紹),其中它規定每一個 C# 中的型別必須要有 ToString 這個方法。這個方法簡單來說就是要求每一個型別的值或物件,都「必須要可以轉換成字串」。因此我們可以預期所有 C# 中的變數都會有這個方法可以呼叫。這也是為什麼在字串串接時,後者可以不一定要是字串。因為後者就算不是字串,也一定會有 ToString 可以把它轉換成字串。

至於實際上 ToString 是怎麼做到這件事情的,這個就利用到了物件導向的多型性的特性 (也是後面課程會介紹)。多型性讓每一個型別可以自行決定 ToString 該怎麼實作,因此不同的型別可以實作自己的 ToString,以確保自己的型別在轉換成字串時可以用自己想要的方法呈現。

因此當未來大家學會了類別以及 override 之後,就可以實作自己類別的 ToString,確保自己的資料被字串串接時按照自己喜歡的樣子呈現。

相關資訊連結

C# 官方文件 - string 型別的介紹

https://learn.microsoft.com/zh-tw/dotnet/api/system.string?view=net-7.0

第 9 課 - Label 與 點擊次數記錄程式

本課介紹

這課主要是在利用寫一個小型程式來複習前面學到的內容,另外再順便介紹一個新的元件 Label。

教學影片

重點提示

  1. Label 指的是顯示在視窗上的標籤,可以藉由修改 Text 屬性來變更他顯示的文字內容
  2. 變數不可以存在 button1_Click 內,因為每一個變數都有一個「有效期限」。當程式碼執行完 button1_Click 之後,這個變數就會「過期」。如果希望變數一直存在,就必須要放在外面的區塊中。
  3. 修改 Label 的 Name 屬性就可以讓我們透過程式碼取得該元件來操作它的內容。
  4. 每次修改完 times 這個變數之後,記得順便更新 Label 的文字哦~ 不然就會出現沒有同步到的狀況。

練習

  1. (基礎) 試試看再加上另一個按鈕,然後按下去會一次 +2
  2. (進階) 試試看再加上一個遞減按鈕,然後按下去會減少,但最低只能減少到 0 哦!
    • 本題需要 if ... 語法的概念

第 46 課 - 五子棋小遊戲 (七) - 簡單勝利判斷

本課介紹

本課為五子棋系列最後一課
這次的目標就是要寫一個簡單的勝利判斷
來看看怎麼寫吧!

教學影片

重點提示

製作重點

  • 檢查勝利的方式 - 只要檢查最後下的那顆棋子的八個方向是否有五顆棋子連成一直線
  • 在測試程式時,若發生錯誤,可以把滑鼠移到變數上。此時就會顯示該變數的值為多少。
  • 注意在 if 內有多個條件時,若程式發現只要檢查前面的條件就足夠,後面的條件就不會被執行。

製作步驟

  1. Board 內新增一個 private Point 變數,lastPlacedNote,一開始設為 NO_MATCH_NODE
    1. 新增一個 public get 存取器 LastPlacedNote,用來取得 lastPlacedNote
    2. Board 內的 PlaceAPiece 把最後下子的位置存在 lastPlacedNote
  2. Game 內新增一個 private PieceType 變數 winner,一開始設為 PieceType.NONE
    • 新增一個 public get 存取器 Winner,用來取得 winner
  3. Game.PlaceAPiece 內的交換選手前,加入 CheckWinner。代表在交換前會先檢查勝利者。
  4. 實作 GameCheckWinner() (先檢查一個方向)
    1. 先用兩個變數 centerXcenterY 儲存 board.LastPlacedNote 的 X 跟 Y 座標
    2. 加入一個 while 迴圈檢查五顆座標連續的棋子是否顏色相同。檢查棋盤上某個位置的顏色可以用 board.GetPieceType(x, y)
      • 記得在呼叫 board.GetPieceType(x, y) 前,先檢查座標是否有超出棋盤邊界
      • 若發現有一顆顏色不同就提早跳出 (break)
    3. 檢查是否看到五顆棋子,若沒看到代表沒有勝利者
  5. Form1_MouseDown 內檢查 game.Winner
    • 若為 PieceType.BLACK,就用 MessageBox 印出「黑色獲勝」。白色也用類似方式處理。
  6. Game.CheckWinner 內增加兩個 for 迴圈檢查八個方向

練習

  1. 嘗試解決最後棋子下在五顆連線的中間,而不是邊邊時無法判斷勝利的 bug
  2. 嘗試實作重新啟動遊戲的功能
  3. 在有人快勝利時提出警告訊息
  4. 想出一個方法讓白色自動下子 (例如:最簡單的作法,隨便找個讓白色隨機亂下)

參考解答:https://github.com/slmt-tutorial-channel/c-sharp-solutions/blob/master/class_41_50/class46.md