---
# System prepended metadata

title: 程式挑戰啦～～
tags: [創客社]

---

# 程式挑戰啦～～

###### tags: `創客社`

填入 ==\\\*Your Code Here*\\== 中的程式，依挖空程度分為三種難度：
- 「一塊蛋糕啦」
- 「有點難」
- 「乾這是要我重新打喔」

複製貼上各自難度的Code~有問題盡量問！！解不出來也不用氣餒，就直接看解答～

-----> [解答！！！！](https://github.com/william0503tw/TFTGameConsole_Piano/blob/main/piano.ino) <-----


#### 難度敘述：
 - 「一塊蛋糕啦」 :
 
    - 只需大概懂程式，挖掉像顏色、基本語法、class中的基本參數以及搭配滿滿的Hint，上下觀察即可看出解答
    - **適用者**：快樂生活，且被期中周荼毒的可憐學子，深有同感，服用此可增加信心，延長益壽
    - 難度: :star: :star:

    
    
 - 「有點難」: 
     - 難上加難啦～，挖掉蠻多的，也沒Hint參考，但憑藉理解code原理可以打出解答
    - **適用者**：想測試最近所學者，以及對遊戲機特性的人，那他很適合你，但跟「一塊蛋糕啦」有點難度落差
    - 難度: :star: :star: :star2: :star2: 


 - 「乾這是要我重新打喔」:
     - 好啦，基本上都不見了，但架構還存在40％
     - **適用者**: 夜晚難眠者，服用此配方後，一覺到天亮，為此，難度直接開到頂，直接把code挖到他老媽都認不出(建議搭配上次社課講義
     - 難度: :star2: :star2: :star2: :star2: :star2: :star2: :star2: 


==把你選擇難度的code貼在IDE中開改吧～==

---

## 難度「一塊蛋糕啦」
```cpp=
#include "config.h"
#include <math.h>

// Declare object tft(display) and ts(touch screen)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
XPT2046_Touchscreen ts(TS_CS);

// parameters for screen calibration
float xCalC = 0.0, yCalC = 0.0;
float xCalM = 0.0, yCalM = 0.0;

// Piano has White note and black note
// And below is the dimensions of them (pixel)
const int8_t BlackNoteHeight = 120 ;
const int8_t BlackNoteWidth = 30 ;
const uint16_t WhiteNoteHeight = 240 ;
const int8_t WhiteNoteWidth = 40 ;

// Declare "BaseFreq" for calculate output frequency
float BaseFreq = 261.6 ; //C4

class ScreenPoint {
    public:
        int16_t x;
        int16_t y;

        //Constructor take (x,y) as parameters
        ScreenPoint(int16_t xIn, int16_t yIn){
            /*
            //////////Your Code Here////////////
            Hint: Copy "xIn" into x, and copy "yIn" into y
            */
        }
};

ScreenPoint getScreenCoords(TS_Point p) {
    int16_t xCoord = round((p.x * xCalM) + xCalC);
    int16_t yCoord = round((p.y * yCalM) + yCalC);

    if(xCoord < 0)
        xCoord = 0;
    if(xCoord >= tft.width())
        xCoord = tft.width() - 1;
    if(yCoord < 0)
        yCoord = 0;
    if(yCoord >= tft.height())
        yCoord = tft.height() - 1;

    return(/*//Your Code Here////*/);
    //Hint: return type : ScreenPoint using its Constructor
}

void calibrateTouchScreen(){
    TS_Point p;
    int16_t x1,y1,x2,y2;

    tft.fillScreen(ILI9341_BLACK);

    while(ts.touched());
    tft.drawFastHLine(10,20,20,ILI9341_WHITE);
    tft.drawFastVLine(20,10,20,ILI9341_WHITE);

    while(!ts.touched());
    p = ts.getPoint();
    x1 = p.x;
    y1 = p.y;
    tft.drawFastHLine(10,20,20,ILI9341_BLACK);
    tft.drawFastVLine(20,10,20,ILI9341_BLACK);
    delay(500);

    while(ts.touched());
    tft.drawFastHLine(tft.width() - 30,tft.height() - 20,20,/*//////Your Code Here//////*/);
    tft.drawFastVLine(tft.width() - 20,tft.height() - 30,20,/*//////Your Code Here//////*/);

    while(!ts.touched());
    p = ts.getPoint();
    x2 = p.x;
    y2 = p.y;
    tft.drawFastHLine(tft.width() - 30,tft.height() - 20,20,/*//////Your Code Here//////*/);
    tft.drawFastVLine(tft.width() - 20,tft.height() - 30,20,/*//////Your Code Here//////*/);

    int16_t xDist = tft.width() - 40;
    int16_t yDist = tft.height() - 40;

    xCalM = (float)xDist / (float)(x2 - x1);
    xCalC = 20.0 - ((float)x1 * xCalM);

    yCalM = (float)yDist / (float)(y2 - y1);
    yCalC = 20.0 - ((float)y1 * yCalM);
}


void drawPiano(){

    tft.fillScreen(/*//////Your Code Here//////*/);

    int count = 0 ;
    bool t = 0 ;

    String note[9] = {"C","D","E","F","G","A","B","C"};

    tft.setTextSize(2);
    tft.setTextColor(ILI9341_BLACK);

    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        tft.drawFastVLine(i,0,tft.height(),/*//////Your Code Here//////*/);
        tft.setCursor(i + 15,210);
        //Print String "note" declare above
        tft.print(/*//////Your Code Here//////*/);
    }

    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        if(count == 2 && !t){
            count = 0 ;
            t = 1 ;
            continue;
        }else if(count == 3){
            count = 0;
            t = 0 ;
            continue;
        }
        tft.fillRect(i + 25 ,/*///Your Code Here////*/ , BlackNoteWidth , BlackNoteHeight ,/*///Your Code Here///*/);
        count++;
    }
}

frequency
void playNote(ScreenPoint p,int8_t shift){

    bool isBlackPlayed = 0 ;

    // Black Notes
    bool t = 0 ;
    int count = 0 ; //For avoiding white notes
    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        if(count == 2 && !t){
                count = 0 ;
                t = 1 ;
                continue;
            }else if(count == 3){
                count = 0;
                t = 0 ;
                continue;
        }
        if(p.x > i + 25 && p.x < i + 25 + BlackNoteWidth && p.y > 0 && p.y < BlackNoteHeight){
            tone(/*//////Your Code Here//////*/,getPianoFreq('B',i / 40 , shift),100);
            isBlackPlayed = 1 ;
        }
        count++ ;
    }
    //White Notes
    //Enter the loop if the black notes aren't touched
    if(!isBlackPlayed){
        for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
            if(p.x > i && p.x < i + WhiteNoteWidth && p.y > 0 && p.y < WhiteNoteHeight){
                tone(/*//////Your Code Here//////*/,getPianoFreq('W',i / 40 , shift),100);
            }
        }
    }
}

float getPianoFreq(char n,int p,int8_t shift){
    if(n == 'B'){
        /*//////Your Code Here//////*/(p){
            case 0: p = 41 + shift;    break;
            case 1: p = 43 + shift;    break;
            case 3: p = 46 + shift;    break;
            case 4: p = 48 + shift;    break;
            case 5: p = 50 + shift;    break;
            case 7: p = 53 + shift;    break;
        }
        return pow(pow(2,0.0833333),p-49) * 440.0 ;
    }else if(n == 'W'){
        /*//////Your C Here//////*/(p){
            case 0: p = 40 + shift;    break;
            case 1: p = 42 + shift;    break;
            case 2: p = 44 + shift;    break;
            case 3: p = 45 + shift;    break;
            case 4: p = 47 + shift;    break;
            case 5: p = 49 + shift;    break;
            case 6: p = 51 + shift;    break;
            case 7: p = 52 + shift;    break;
        }
        return pow(pow(2,0.0833333),p-49) * 440.0 ;
    }
}

void printLevel(int shift){
    tft.fillRect(2,2,22,22,/*//////Your Code Here//////*/);
    tft.setCursor(4,4);
    tft.setTextColor(/*//////Your Code Here//////*/);
    tft.setTextSize(2);
    tft.print(shift);
}


int8_t shift = 0 ;
int level = 4 ;

void setup()
{
    Serial.begin(BUADRATE);

    //Avoid confronation between touchscreen and tft display
    pinMode(TS_CS, OUTPUT);
    digitalWrite(TS_CS, HIGH);
    pinMode(TFT_CS, OUTPUT);
    digitalWrite(TFT_CS, HIGH);

    //pinMode
    pinMode(buzzer, OUTPUT);
    //Button pinMode
    pinMode(UP,/*//////Your Code Here//////*/);
    pinMode(DOWN,/*//////Your Code Here//////*/);
    pinMode(RIGHT,/*//////Your Code Here//////*/);
    pinMode(LEFT,INPUT_PULLU);

    //tft display and touch screen initialization
    tft.begin();
    tft.setRotation(ROTATION);
    tft.fillScreen(ILI9341_BLACK);
    ts.begin();
    ts.setRotation(ROTATION);

    //touchscreen's calibration
    calibrateTouchScreen();

    //500 ms delay for safety (optional)
    delay(500);

    //draw the piano
    drawPiano();

    //print level
    printLevel(level);
}

void loop()
{
    //If I did not touch the screen, the program would stuck in while loop.
    while(!ts.touched()){
        if(digitalRead(RIGHT) == 0){
            shift += 12 ;
            level += 1 ;
            printLevel(level);
        }else if(digitalRead(LEFT) == 0){
            shift -= 12 ;
            level -= 1 ;
            printLevel(level);
        };
        delay(300);
    };

    ScreenPoint sp = getScreenCoords(ts.getPoint());
    playNote(sp,shift);
}
```


## 難度「有點難」
```cpp=
#include "config.h"
#include <math.h>

// Declare object tft(display) and ts(touch screen)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
XPT2046_Touchscreen ts(TS_CS);

// parameters for screen calibration
float xCalC = 0.0, yCalC = 0.0;
float xCalM = 0.0, yCalM = 0.0;

const int8_t BlackNoteHeight = 120 ;
const int8_t BlackNoteWidth = 30 ;
const uint16_t WhiteNoteHeight = 240 ;
const int8_t WhiteNoteWidth = 40 ;

float BaseFreq = 261.6 ; //C4

class ScreenPoint {
    public:
        int16_t x;
        int16_t y;

        ScreenPoint(int16_t xIn, int16_t yIn){
            /*//////Your Code Here//////*/
        };
};

ScreenPoint getScreenCoords(TS_Point p) {
    int16_t xCoord = round((p.x * xCalM) + xCalC);
    int16_t yCoord = round((p.y * yCalM) + yCalC);

    if(xCoord < 0)
        xCoord = 0;
    if(xCoord >= tft.width())
        xCoord = tft.width() - 1;
    if(yCoord < 0)
        yCoord = 0;
    if(yCoord >= tft.height())
        yCoord = tft.height() - 1;

    return(/*//Your Code Here////*/);
    //Hint: return type : ScreenPoint using its Constructor
}

void calibrateTouchScreen(){
    TS_Point p;
    int16_t x1,y1,x2,y2;

    tft.fillScreen(ILI9341_BLACK);

    while(ts.touched());
    tft.drawFastHLine(10,20,20,/*//Your Code Here////*/);
    tft.drawFastVLine(20,10,20,/*//Your Code Here////*/);

    while(!ts.touched());
    p = ts.getPoint();
    x1 = p.x;
    y1 = p.y;
    tft.drawFastHLine(10,20,20,/*//Your Code Here////*/);
    tft.drawFastVLine(20,10,20,/*//Your Code Here////*/);
    delay(500);

    while(ts.touched());
    tft.drawFastHLine(tft.width() - 30,tft.height() - 20,20,/*//////Your Code Here//////*/);
    tft.drawFastVLine(tft.width() - 20,tft.height() - 30,20,/*//////Your Code Here//////*/);

    while(!ts.touched());
    p = ts.getPoint();
    x2 = p.x;
    y2 = p.y;
    tft.drawFastHLine(tft.width() - 30,tft.height() - 20,20,/*//////Your Code Here//////*/);
    tft.drawFastVLine(tft.width() - 20,tft.height() - 30,20,/*//////Your Code Here//////*/);

    int16_t xDist = tft.width() - 40;
    int16_t yDist = tft.height() - 40;

    xCalM = (float)xDist / (float)(x2 - x1);
    xCalC = 20.0 - ((float)x1 * xCalM);

    yCalM = (float)yDist / (float)(y2 - y1);
    yCalC = 20.0 - ((float)y1 * yCalM);
}


void drawPiano(){

    tft.fillScreen(/*//////Your Code Here//////*/);

    int count = 0 ;
    bool t = 0 ;

    String note[9] = {"C","D","E","F","G","A","B","C"};

    tft.setTextSize(2);
    tft.setTextColor(ILI9341_BLACK);

    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        tft.drawFastVLine(i,0 , /*//Your Code Here////*/ , /*//////Your Code Here//////*/);
        tft.setCursor(i + 15,210);
        //Print String "note" declare above
        tft.print(/*//////Your Code Here//////*/);
    }

    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        if(count == 2 && !t){
            count = 0 ;
            t = 1 ;
            continue;
        }else if(count == 3){
            count = 0;
            t = 0 ;
            continue;
        }
        tft.fillRect(i + 25 ,/*///Your Code Here////*/ , BlackNoteWidth , BlackNoteHeight ,/*///Your Code Here///*/);
        count++;
    }
}


void playNote(ScreenPoint p,int8_t shift){
    bool isBlackPlayed = 0 ;

    // Black Notes
    bool t = 0 ;
    int count = 0 ; //For avoiding white notes
    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        if(count == 2 && !t){
                count = 0 ;
                t = 1 ;
                continue;
            }else if(count == 3){
                count = 0;
                t = 0 ;
                continue;
        }
        if(p.x > i + 25 && p.x < i + 25 + BlackNoteWidth && p.y > 0 && p.y < BlackNoteHeight){
            tone(/*//////Your Code Here//////*/,getPianoFreq('B',/*//Your Code Here////*/, shift),100);
            isBlackPlayed = 1 ;
        }
        count++ ;
    }
    //White Notes
    //Enter the loop if the black notes aren't touched
    if(!isBlackPlayed){
        for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
            if(p.x > i && p.x < i + WhiteNoteWidth && p.y > 0 && p.y < WhiteNoteHeight){
                tone(/*//////Your Code Here//////*/,getPianoFreq('W',i, shift),100);
            }
        }
    }
}

float getPianoFreq(char n,int p,int8_t shift){
    if(n == 'B'){
        /*//////Your Code Here//////*/(p){
            case 0: p = 41 + shift;    break;
            case 1: p = 43 + shift;    break;
            case 3: p = 46 + shift;    break;
            case 4: p = 48 + shift;    break;
            case 5: p = 50 + shift;    break;
            case 7: p = 53 + shift;    break;
        }
        return pow(pow(2,0.0833333),p-49) * 440.0 ;
    }else if(n == 'W'){
        /*//////Your C Here//////*/(p){
            case 0: p = 40 + shift;    break;
            case 1: p = 42 + shift;    break;
            case 2: p = 44 + shift;    break;
            case 3: p = 45 + shift;    break;
            case 4: p = 47 + shift;    break;
            case 5: p = 49 + shift;    break;
            case 6: p = 51 + shift;    break;
            case 7: p = 52 + shift;    break;
        }
        /*//Your Code Here////*/ pow(pow(2,0.0833333),p-49) * 440.0 ;
    }
}

void printLevel(int shift){
    tft.fillRect(2,2,22,22,/*//////Your Code Here//////*/);
    tft.setCursor(4,4);
    tft.setTextColor(/*//////Your Code Here//////*/);
    tft.setTextSize(2);
    tft.print(shift);
}


int8_t shift = 0 ;
int level = 4 ;

void setup()
{
    Serial.begin(BUADRATE);

    //Avoid confronation between touchscreen and tft display
    pinMode(TS_CS, OUTPUT);
    digitalWrite(TS_CS, /*//Your Code Here////*/);
    pinMode(TFT_CS, OUTPUT);
    digitalWrite(TFT_CS, /*//Your Code Here////*/);

    //pinMode
    pinMode(buzzer, OUTPUT);
    //Button pinMode
    pinMode(UP,/*//////Your Code Here//////*/);
    pinMode(DOWN,/*//////Your Code Here//////*/);
    pinMode(RIGHT,/*//////Your Code Here//////*/);
    pinMode(LEFT,INPUT_PULLU);

    //tft display and touch screen initialization
    tft.begin();
    tft.setRotation(ROTATION);
    tft.fillScreen(ILI9341_BLACK);
    ts.begin();
    ts.setRotation(ROTATION);

    //touchscreen's calibration
    calibrateTouchScreen();

    //500 ms delay for safety (optional)
    delay(500);

    //draw the piano
    drawPiano();

    //print level
    printLevel(level);
}

void loop()
{
    //If I did not touch the screen, the program would stuck in while loop.
    while(/*//////Your Code Here//////*/){
        if(/*//////Your Code Here//////*/){
            //Right Button
            shift += 12 ;
            level += 1 ;
            printLevel(level);
        }else if(/*//////Your Code Here//////*/){
            //Left Button
            shift -= 12 ;
            level -= 1 ;
            printLevel(level);
        };
        delay(300);
    };

    ScreenPoint sp = getScreenCoords(ts.getPoint());
    playNote(sp,shift);
}

```



## 難度「乾這是要我重新打喔」
```cpp=
#include "config.h"
#include <math.h>

// Declare object tft(display) and ts(touch screen)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
XPT2046_Touchscreen ts(TS_CS);

// parameters for screen calibration
float xCalC = 0.0, yCalC = 0.0;
float xCalM = 0.0, yCalM = 0.0;

const int8_t BlackNoteHeight = 120 ;
const int8_t BlackNoteWidth = 30 ;
const uint16_t WhiteNoteHeight = 240 ;
const int8_t WhiteNoteWidth = 40 ;

float BaseFreq = 261.6 ; //C4

class ScreenPoint {
    public:
        int16_t x;
        int16_t y;

        ScreenPoint(int16_t xIn, int16_t yIn){
            /*//////Your Code Here//////*/
        };
};

ScreenPoint getScreenCoords(TS_Point p) {
    //Transfer into calibrated coordinate
    /*//////Your Code Here//////*/

    if(xCoord < 0)
        xCoord = 0;
    if(xCoord >= tft.width())
        xCoord = tft.width() - 1;
    if(yCoord < 0)
        yCoord = 0;
    if(yCoord >= tft.height())
        yCoord = tft.height() - 1;

    return(/*//Your Code Here////*/);
    //Hint: return type : ScreenPoint using its Constructor
}

void calibrateTouchScreen(){
    /*//////Your Code Here//////*/
    //加油
}


void drawPiano(){

    tft.fillScreen(/*//////Your Code Here//////*/);

    int count = 0 ;
    bool t = 0 ;

    String note[9] = {"C","D","E","F","G","A","B","C"};

    tft.setTextSize(2);
    tft.setTextColor(ILI9341_BLACK);

    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        tft.drawFastVLine(i,0 , /*//Your Code Here////*/ , /*//////Your Code Here//////*/);
        tft.setCursor(i + 15,210);
        //Print String "note" declare above
        tft.print(/*//////Your Code Here//////*/);
    }

    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        if(/*//////Your Code Here//////*/){
            count = 0 ;
            t = 1 ;
            continue;
        }else if(/*//////Your Code Here//////*/){
            count = 0;
            t = 0 ;
            continue;
        }
        tft.fillRect(i + 25 ,/*///Your Code Here////*/ , BlackNoteWidth , BlackNoteHeight ,/*///Your Code Here///*/);
        count++;
    }
}


void playNote(ScreenPoint p,int8_t shift){
    bool isBlackPlayed = /*//////Your Code Here//////*/ ;

    // Black Notes
    bool t = 0 ;
    int count = 0 ; //For avoiding white notes
    for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
        if(/*//////Your Code Here//////*/){
                count = 0 ;
                t = 1 ;
                continue;
            }else if(/*//////Your Code Here//////*/){
                count = 0;
                t = 0 ;
                continue;
        }
        if(p.x > i + 25 && p.x < i + 25 + BlackNoteWidth && p.y > 0 && p.y < BlackNoteHeight){
            tone(/*//////Your Code Here//////*/,getPianoFreq('B',/*//Your Code Here////*/, shift),100);
            isBlackPlayed = 1 ;
        }
        count++ ;
    }
    //White Notes
    //Enter the loop if the black notes aren't touched
    if(!isBlackPlayed){
        for(int i = 0 ; i <= tft.width() ; i += tft.width() / 8){
            if(/*//////Your Code Here//////*/){
                tone(/*//////Your Code Here//////*/,getPianoFreq('W',i, shift),100);
            }
        }
    }
}

float getPianoFreq(char n,int p,int8_t shift){
    if(/*//////Your Code Here//////*/){
        /*//////Your Code Here//////*/(p){
            case 0: p = 41 + shift;    break;
            case 1: p = 43 + shift;    break;
            case 3: p = 46 + shift;    break;
            case 4: p = 48 + shift;    break;
            case 5: p = 50 + shift;    break;
            case 7: p = 53 + shift;    break;
        }
        return pow(pow(2,0.0833333),p-49) * 440.0 ;
    }else if(/*//////Your Code Here//////*/){
        /*//////Your Code Here//////*/(p){
            case 0: p = 40 + shift;    break;
            case 1: p = 42 + shift;    break;
            case 2: p = 44 + shift;    break;
            case 3: p = 45 + shift;    break;
            case 4: p = 47 + shift;    break;
            case 5: p = 49 + shift;    break;
            case 6: p = 51 + shift;    break;
            case 7: p = 52 + shift;    break;
        }
        /*//Your Code Here////*/ pow(pow(2,0.0833333),p-49) * 440.0 ;
    }
}

void printLevel(int shift){
    tft.fillRect(2,2,22,22,/*//////Your Code Here//////*/);
    tft.setCursor(4,4);
    tft.setTextColor(/*//////Your Code Here//////*/);
    tft.setTextSize(2);
    tft.print(shift);
}


int8_t shift = 0 ;
int level = 4 ;

void setup()
{
    Serial.begin(BUADRATE);

    //Avoid confronation between touchscreen and tft display
    pinMode(TS_CS, OUTPUT);
    digitalWrite(TS_CS, /*//Your Code Here////*/);
    pinMode(TFT_CS, OUTPUT);
    digitalWrite(TFT_CS, /*//Your Code Here////*/);

    //pinMode
    pinMode(buzzer, OUTPUT);
    //Button pinMode
    pinMode(UP,/*//////Your Code Here//////*/);
    pinMode(DOWN,/*//////Your Code Here//////*/);
    pinMode(RIGHT,/*//////Your Code Here//////*/);
    pinMode(LEFT,INPUT_PULLU);

    //tft display and touch screen initialization
    tft.begin();
    tft.setRotation(ROTATION);
    tft.fillScreen(ILI9341_BLACK);
    ts.begin();
    ts.setRotation(ROTATION);

    //touchscreen's calibration
    calibrateTouchScreen();

    //500 ms delay for safety (optional)
    delay(500);

    //draw the piano
    drawPiano();

    //print level
    printLevel(level);
}

void loop()
{
    //If I did not touch the screen, the program would stuck in while loop.
    while(/*//////Your Code Here//////*/){
        if(/*//////Your Code Here//////*/){
            //Right Button
            shift += 12 ;
            level += 1 ;
            printLevel(level);
        }else if(/*//////Your Code Here//////*/){
            //Left Button
            shift -= 12 ;
            level -= 1 ;
            printLevel(level);
        };
        delay(300);
    };

    ScreenPoint sp = getScreenCoords(ts.getPoint());
    playNote(sp,shift);
}

```