# MicroPython按鈕控制

micro:bit有兩個可程式化按鈕，讓我們可以和micro:bit進行互動，這兩個按鈕在設計小遊戲的時候非常好用。那麼，如果使用MicroPython，要如何去偵測這個按鈕呢？答案是is\_pressed()這個函數，而按鈕A是button\_a，按鈕B則是button\_b，以下是一個簡單的運用按鈕改變圖案的例子：

```python
from microbit import *

display.show(Image.HEART)
while True:
    if button_a.is_pressed():
        display.show(Image.HAPPY)
    elif button_b.is_pressed():
        display.show(Image.SAD)

```

上面這個程式在一開始執行的時候會顯示愛心圖案，如果按下去A按鈕就會變成笑臉，按下去B按鈕則變成哭臉。之後就只能在笑臉和哭臉之間做變化，因為在無窮迴圈中只有這兩種選擇。

假設我們想要讓使用者在同時按下A和B按鈕（也就是積木中的A+B按下事件）就恢復成愛心圖案的話，也許你會想到以下此種方式：

{% hint style="danger" %}
請注意，以下的程式是錯誤的！
{% endhint %}

```python
from microbit import *

display.show(Image.HEART)
while True:
    if button_a.is_pressed():
        display.show(Image.HAPPY)
    elif button_b.is_pressed():
        display.show(Image.SAD)
    elif button_a.is_pressed() and button_b.is_pressed():
        display.show(Image.HEART)
```

上面這個程式的邏輯是，如果A按鈕被按下去就顯示笑臉，否則如果B按鈕被按下去的話就顯示哭臉，否則如果A按鈕被按下去而且B按鈕也被按下去的話，就會顯示愛心圖案。

邏輯上看起來沒問題，但其實存在一個嚴重的瑕疵，那就是第9行的條件其實同時包含了第5行和第7行的條件，意思是說，任一個按鈕被按下去時，一定會先滿足第5行或是第7行的條件，如此第9行的那個條件根本就沒有機會被執行到。

改正的方法是，把第9行的條件移到最前面去，先檢查是否兩個按鈕同時被按下，如果有就換成愛心圖案，如果沒有的話，再分別檢查A和B按鈕有沒有其中一個被按下去。修正後的程式如下：

{% hint style="warning" %}
請注意，底下的程式仍然有一些問題喔
{% endhint %}

```python
from microbit import *

display.show(Image.HEART)
while True:
    if button_a.is_pressed() and button_b.is_pressed():
        display.show(Image.HEART)
    elif button_a.is_pressed():
        display.show(Image.HAPPY)
    elif button_b.is_pressed():
        display.show(Image.SAD)
```

同學們可以執行上述的程式看看問題在哪裡！

發現了嗎？A按鈕和B按鈕都沒問題，但是當A和B同時按下時的那一瞬間是可以切換成愛心的，可是當手一鬆開按鈕的時候就會發現，圖案馬上又恢復成笑臉或哭臉了，端看你的那一隻手指放得比較慢一些。

造成這個問題的原因在於A和B按鈕同時放開的時候，其中一個按鈕會放得慢一些，而由於程式運行的速度很快，很快地又回到按鈕的判斷，此時很快地又判斷到其中一個按鈕被按下去，因此立刻又被切換成該按鈕的符號了。為了解決這個問題，在換成愛心圖案之後讓程式暫停個一秒鐘，使得們的手指來得及同時鬆開按鈕，就不會有問題了。完成後的程式如下所示：

```python
from microbit import *

display.show(Image.HEART)
while True:
    if button_a.is_pressed() and button_b.is_pressed():
        display.show(Image.HEART)
        sleep(1000)
    elif button_a.is_pressed():
        display.show(Image.HAPPY)
    elif button_b.is_pressed():
        display.show(Image.SAD)
```

以下這個程式執行之後，平時它會以顯示愛心的符號，當按下A按鈕時，則會顯示笑臉，在按下B按鈕後，則會顯示哭臉。然而有一個要讓同學們比較的地方是，在程式中，每顯示一個圖案都會暫停5秒鐘，在這段期間內，程式是沒有在運作的，如果你在這段暫停時間內按下按鈕的話，這個按下去的動作會被忽略掉，這也是為什麼下面這個程式在執行的時候，你會覺得按鈕好像不太靈敏的樣子，有時候可以換圖案，有時候又不行：

```python
from microbit import *

while True:
    if button_a.is_pressed():
        display.show(Image.HAPPY)
        sleep(5000)
    elif button_b.is_pressed():
        display.show(Image.SAD)
        sleep(5000)
    else:
        display.show(Image.HEART)
        sleep(5000)
```

為了避免上述的問題發生，當然把sleep的時間減少是一個方法，但是，最好的方法是把is\_pressed()改成was\_pressed()，這個函數不是回傳偵測的當時按鈕被按下去的情形，而是檢查在前一次偵測到這一次的偵測期間按鈕是否曾經被按下過，只要按過就會回傳True，如此就可以改善前一個程式所遇到的問題了。

```python
from microbit import *

while True:
    if button_a.was_pressed():
        display.show(Image.HAPPY)
        sleep(5000)
    elif button_b.was_pressed():
        display.show(Image.SAD)
        sleep(5000)
    else:
        display.show(Image.HEART)
        sleep(5000)
```

除了is\_pressed()以及was\_pressed()這兩個函數之外，還有一個函數get\_presses()是用來紀錄從上一次呼叫檢查按鈕的函數到現在，某一個按鈕總共被按了幾次。以下的程式例執行的時候會開始倒數10秒，時間到之後會顯示在這期間，按鈕A總共被按了幾次：

```python
from microbit import *

for i in range(9, -1, -1):
    display.show(i)
    sleep(1000)
display.show(Image.HEART)
sleep(1000)
number = button_a.get_presses()
display.show(number)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nkust.gitbook.io/micro-bit/micropython-an-kong-zhi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
