# 興附電研社課
[ToC]
# 第一週
###### tags: `興附電研21th` `C#`
> 本週學習:c++ 基本語法、數據類型、輸入、輸出、變數宣告、儲存類型
---
## 1.程式結構
```cpp
#include <iostream>
using namespace std;
// main() 是程式的進入點
int main()
{
cout << "Hello World" << endl; // 輸出Hello World
return 0;
}
```
* **#include <iostream>** 的功能是告訴編譯器此程式 **==包含 iostream 文件==**。
* **Main()** 函式為 **==程式的進入點==**。
* **using namespace std** 指的是 **==使用 std 這個命名空間==**。
* **cout << "Hello World" << endl** 的功能是 **==輸出「Hello World」==**,並且有 **endl** 的關係所以要換行。
* **return 0** 表示 **==Main()==** 函式的結束。
### Q. APCS 的測驗內容沒有C#,這樣之後會不會很吃虧 ?
A. 其實完全不用害怕呦~ 就我所知,==C++、C#、JAVA、C== 這四種程式語言的語法、編寫風格都很相近的哦 ! 只要精通其中一種程式語言,想再學習其他語言都不是問題~
:::info
:bulb: APCS可以使用的程式語言有 C、C++、Python、Java
:::
> 如果想參加考試檢定的可以參考下圖呦! ( Reference:吳邦一教授 )
> 
## 2.Visual Studio Code ( 簡稱vscode ) 設定
### Step 1: 在桌面上創一個新的資料夾 ( 中英文隨意 )

---
### Step 2: 打開桌面上的 Visual Studio Code

#### 打開後會有下面這個樣子的視窗

#### 再來將鼠標移至上方選單的檔案,拉開之後再點選開啟新的資料夾

#### 接著選擇剛剛創建的資料夾就成功瞜~
---
### Step 3: 安裝 C# 延伸模組
#### 將鼠標移至左方選單,並點有四個格子的那個圖案

#### 點開他後,搜尋欄打==C#==,並安裝 C#、C# Extensions


#### 安裝完後鼠標移到上方選單的終端機,選擇新增終端,接著在終端機打上"dotnet new console",打完按enter

#### 接著鼠標移至左方選單的檔案總管,點下去就可以看到程式碼啦~
>如果沒有看見就點一下左邊列表的 Program.cs
>


>如果還是空的話,就複製下方的程式碼貼上去吧~
```csharp=
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
```
---
### Step 4: 執行第一支程式吧!
#### 在終端機裡面打 "dotnet run",接著等一下就可以看到東西印出來了哦~

>可以拍現動炫耀了ㄎㄎ ( X
:::info
:bulb: 記得在檔案那邊勾選自動儲存,不然就算更改了還是會輸出Hello World!
:::
---
### 再來就開始學基本的輸入輸出還有變數吧~
#### 1. 常見的變數類別 https://ithelp.ithome.com.tw/articles/10213219
#### 2. 基本輸入輸出 https://ithelp.ithome.com.tw/articles/10213373
---
# 第二週 :two:
## 1.程式是怎麼運行的
### **程式執行的簡要概念**
* #### 程式被激活 ---> 從硬碟中讀取==資料 (data)==、==指示 (instructions)==
* #### 程式中的指示會==依照順序被cpu執行==
* #### CPU具有==運算邏輯單元 (ALUS)==
:::info
:bulb: 以人體的部位來比喻的話,CPU就像是大腦
:::
---
### **記憶體階層 (Memory Hierarchy)**

* #### L2以上都在CPU內 -- 暫存器、快取記憶體 (靜態隨機存取記憶體 SRAM)
* #### Main memory -- 動態隨機存取記憶體 (DRAM)
* #### Local secondary storage -- 傳統硬碟 (HDD)、固態硬碟 (SSD)
* #### Remote secondary storage -- 雲端硬碟
---
### **C# 結構 (Structure)**
```csharp=
using System; //使用 System 命名空間
namespace HelloWorld //namespace 稱為 命名空間
{
class Program //有一個 class 叫作 Program
{
// 這個 class 裡面有一個 Main 方法 (method)
static void Main(string[] args)
{
//使用 System (命名空間) 中的 Console (類別) 的 WriteLine (方法)
Console.WriteLine("Hello World!");
// 執行結果 HelloWorld!
}
}
}
```
* #### using System -- 表示讓程式包含 System (命名空間)
* #### 在 HelloWorld (命名空間) 中,有一個 Program (類別),此類別中只有一個 Main (方法)
* #### Main() 方法在 C# 中表示==程式的進入點==
* #### // (雙斜線) 在 C# 中的功能是註解,程式執行的時候會自動忽略過去
* #### Console.WriteLine("HelloWorld!")
> ##### 使用定義於 System (命名空間) 中的 Console (類別),而 WriteLine (方法) 定義於 Console (類別)
* #### C# 文件的後綴詞是 .cs
* #### 一些符號的功能
| 符號 | 功能 |
|:-------:|:-------------------------:|
| **( )** | **通常用於方法 (method)** |
| **{ }** | **劃定範圍** |
| **[ ]** | **用於陣列 (Array)** |
| **//** | **註解** |
| **;** | **表示語句的結束** |
| **" "** | **字串** |
---
### **程式的運行錯誤 (Bug)**
#### 當運行程式的時候,發現答案跟預期的結果不同,大致可分為三種問題
#### 1. CE (Compile Error) -- 表示程式在編譯的時候發生錯誤,通常為語法問題
#### 2. RE (Runtime Error) -- 表示程式在執行的過程中發生錯誤,常見的狀況像是超出陣列大小
#### 3. LE (Logic Error) -- 表示使用者個人的邏輯問題,此問題最難解決
---
### **縮排 (Programming Style)**
#### ==好的縮排可以讓其他人在讓程式更容易閱讀==
##### 1. 沒有縮排
```csharp=
using System;
namespace circle
{class Program{static void Main(string[] args){
Console.WriteLine("HelloWorld!");
} }
}
```
##### 2. 有縮排
```csharp=
using System;
namespace circle
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("HelloWorld!")
}
}
}
```
:::info
**雖然上面兩個程式執行後的結果相同,但是可以很明顯地看到,第二個比第一個來的易讀許多**
:::
---
## 2.資料型態 & 變數
### **Example**:如果以10為半徑,要如何計算出圓面積?
#### ==此時我們可以將此問題拆成三個部分來看==
1. #### Input :要怎麼儲存這筆資料 (將 10 儲存下來)
2. #### Algorithm:要怎麼計算出結果
3. #### Output :結果如何呈現
```csharp=
using System;
namespace circle
{
class Program
{
static void Main(string[] args)
{
//data
int r = 10;
double A;
//algorithms;
A = r * r * 3.14;
//output
Console.WriteLine(A);
}
}
}
```
:::info
:bulb:在這段程式中,我們使用了兩種資料型態:==int== , ==double==
:::
---
### **變數 (Variable)**
#### **概念:**
* ##### 變數就像一個箱子,專門拿來存放東西
* ##### 每一個變數,都必須要有一個型態 (type)
#### **宣告 (Declaration):**
1. ##### 首先我們取一個變數的名稱,假設是 A
2. ##### 接著我們要幫 A 找能夠儲存我們資料的箱子
```csharp
int A ; //變數名稱為 A 且只能儲存 int 類型資料
```
> 此時我們將 A 宣告成一個 int 的型態
#### **記憶體位置:**
##### 你可能會想說:「現在雖然是有箱子沒錯,可是要把箱子放在哪裡呢?」
##### 那當然是記憶體噜~

* ##### 以我們剛剛的 int A 來看,A代表的意義就是箱子的位置 ( 類似箱子上貼有標籤 A )
* ##### 上圖中的 0x000abc01 是==十六進位碼== -- 表示那個箭頭處的位置
* ##### 如果我們此時將整數 10 賦值到 A,則就代表著我們在 0x000abc01 那邊的 int 箱子裡,放了整數 10 進去
* ##### 上圖過程的程式碼如下
```csharp
int A = 10;
```
:::info
C# 中的**等號**表示==將右邊賦值到左邊==,例如 int A = 10,此時 A 的值為 10
:::
#### **命名規定:**
1. ##### 不能以數字開頭
2. ##### 不能是 C# 中的關鍵字,例如:using、class、int、string
3. ##### 名字中間不能以空格隔開
4. ##### 不能有任何的運算符號,例如:+ , - , * , /
| **加法** | **+** |
|:----------:|:-----------------:|
| **減法** | **-** |
| **乘法** | * |
| **除法** | **/** |
| **取餘數** | **%** |
| **X = X ± 1** | **X±±** |
| **開根號** | **Math.Sqrt(值)** |
---
### **資料型態 (Data types)**
##### **在資料型態中主要分為三大類:**
##### ==**原生類型 (Primitive type)、參考類型 (Reference types)、指標類型 (Pointer types)**==
#### **1. 原生類型 (Primitive types)**
##### **(1) 布林值:**
| 類型 | 大小 |
|:-------:|:-------------------------:|
| **bool** | **1 bit** |
##### **(2) 數值:**
###### a. 整數類型
| 類型 | 大小 |
|:---------:|:-----------:|
| **short** | **16 bits** |
| **byte** | **8 bits** |
| **int** | **32 bits** |
| **long** | **64 bits** |
| **char** | **8 bit** |
:::info
**char** 通常都會配合字碼表來處理字元,==本質上還是處理數字==
:::
###### b. 浮點數類型類型
| 類型 | 大小 |
|:----------:|:-----------:|
| **float** | **32 bits** |
| **double** | **64 bits** |
| **decimal**| **128 bits** | |
:::info
**double** 能夠比 **float** 更加精確,但是相對的==運算速度較慢==
:::
:::info
**decimal** 的儲存大小雖然大,但是所含的範圍卻沒有前兩者高,目的是為高精確
:::
#### **2. 參考類型 (Reference types)**
| 類型 | 功能 |
|:----------:|:-----------:|
| **object** | **可以用來裝箱、拆箱** |
| **dynamic** | **可以自動判斷類型** |
| **string**| **處理字串**
:::info
將值轉換成 **object** 類型稱為「**裝箱**」,反之則為「**拆箱**」
:::
#### **2. 指標類型 (Pointer types)**
| 類型 | 功能 |
|:----------:|:-----------:|
| **int*** | **用來儲存位置** |
| **char*** | **用來儲存位置** |
>補充:
>資料型態的轉換 [https://www.runoob.com/csharp/csharp-type-conversion.html](https://)
---
### **==小試身手==**
#### 1. 製作一個 BMI 計算器,輸入「身高」與「公斤」即可獲得 BMI
#### 2. 哈囉 -- 輸入一個字串,輸出 Hello, 字串
>提示:讀取輸入用 Console.ReadLine(),字串的資料類型為 string
---
# 第三週
## 1. 基本輸入、輸出
### **輸出 (Output)**
#### Example:
```csharp=
using System;
namespace input
{
class Program
{
static void Main(string[] args)
{
int num = 5;
// Output
Console.WriteLine("Hello World!"); // 純字串
Console.WriteLine(10); // 數字
Console.WriteLine(num); // 變數名
Console.WriteLine("Hello" + " " + "World!"); // 字串組合
Console.WriteLine("num: " + num); // 字串與變數組合
}
}
}
```
#### 執行結果:

---
### 輸入 (Input)
#### Example:
```csharp=
using System;
namespace output
{
class Program
{
static void Main(string[] args)
{
// input
string str = Console.ReadLine(); // 將輸入的 "字符" 賦值給該變數的儲存空間
Console.WriteLine(str); // 輸出變數
Console.WriteLine(Console.ReadLine()); //直接將輸入的東西打印出來
int num1 = int.Parse(Console.ReadLine()); //處理能力較低
Console.WriteLine(num1);
int num2 = Convert.ToInt32(Console.ReadLine()); //處理能力較高
Console.WriteLine(num2);
}
}
}
```
#### 執行結果:

### 比較 int.Parse() 與 Convert.ToInt32 的差異:
#### 剛剛上面有說到 ==int.Parse() 的處理能力會比 Convert.ToInt32() 的處理能力還來的低==,主要是因為 int.Parse() 接收到 null 時,並不像 Convert.ToInt32() 可以直接轉為 0,而是會以報錯的形式作回應。
#### Example:
```csharp=
using System;
namespace output
{
class Program
{
static void Main(string[] args)
{
// int.Parse()
int num = int.Parse(Console.ReadLine()); //此時輸入 "apple"
}
}
}
```
# 第四週
## 1. Bot基本架構
### (1) bot.py
#### 1. 指令要用 bot.command() 裝飾器
#### 2. 指令的定義下,函式裡面通常會有 ctx 參數
#### 3. async def 的回傳要用 await
```python=
import discord
import json
from discord.ext import commands
with open("settings.json","r",encoding="utf8") as file:
jfile = json.load(file)
intents = discord.Intents.all()
bot = commands.Bot(command_prefix='/',intents=intents)
@bot.event
async def on_ready():
print("開機")
@bot.command()
async def pic(ctx):
await ctx.send(jfile['pic'])
bot.run(jfile['Token'])
```
:::info
:bulb: 使用 discord.py 前,需要先在終端機打上 **pip install discord**
:::
### (2) settings.json
#### 1. json檔就像python的字典一樣,都有 key 對上 value
#### 2. 這裡面的字串只能用==雙引號==
#### 3. 不同資料間需要用逗點隔開
```jsonld=
{
"pic" : "https://th.bing.com/th/id/OIP.7WIYuCOR7fX7p3DUs3wpvgHaHa?w=176&h=180&c=7&r=0&o=5&pid=1.7",
"Token" : "MTA5MTI0ODYyMDM3MzgwMzA0OA.G_s7ND.RDYndlHdt8H86_E6wclkd6mq1LxQu6zC2hp4oE",
"list1" : ["data1","data2"] #利用 Array 方式儲存
}
```
```python=
import json #使用前須先 import
with open("檔案路徑","讀寫模式設定","編碼") as file: #將檔案開啟並以 file 存起來
jfile = json.load(file) #建立一個 jfile 變數,並利用 json.load() 將檔案的內容讀取並儲存
```
## 2. on_message() 功能
### (1) 定義
```python=
@bot.event
async def on_message(message): #小括號裡面的 message 代表機器人收到的訊息資料
await #await 是 async def 的回傳方式
```
### (2) 讀取訊息功能
```python=
@bot.event
async def on_message(message):
if message.context == "ping": #message 代表訊息的資料,message.context 表示從訊息的資料取得內文
await message.channel.send("pong")
```
### (3) 避免洗頻
#### 當讀取的訊息等於傳送的訊息時,機器人會洗頻,所以我們必須==判斷傳送訊息者為誰==
```python=
@bot.event
async def on_message(message):
if message.author == bot.client:
return
```
---
## 3.自訂義指令 bot.command()
### (1) 定義
```python=
@bot.command()
async def command_name(ctx): #ctx 是參考上下文,包含訊息的相關資料
await #await 是 async def 的回傳方式
```
### (2) 傳送訊息
```python=
#command_prefix = '/' --> 指令的前綴為'/'
@bot.command()
async def response(ctx): #ctx 是參考上下文,包含訊息的相關資料
await ctx.send("Ok.") #await 是 async def 的回傳方式
```
:::info
:bulb: 當輸入指令 ==/response== 時,機器人會回復 "Ok."
:::
:::info
:bulb: ==ctx== 代表上下文,儲存該訊息的相關資料
:::
---
[ToC]
- 參考資料
1.https://apcs.csie.ntnu.edu.tw/index.php/info/environment/
2.https://learn.microsoft.com/zh-tw/dotnet/core/tutorials/with-visual-studio-code?pivots=dotnet-6-0
3.https://ithelp.ithome.com.tw/articles/10213373
4.https://ithelp.ithome.com.tw/articles/10213219