两个M5Stack上的纸牌游戏“傻瓜”

本课目的


今天,我们将为两个玩家编写一个网卡游戏。要写什么游戏?让我们编写一个流行的纸牌游戏“傻瓜”,其目的是摆脱所有纸牌。可以此处了解有关规则的更多信息



图片1。


一点理论


— RS-232, , , . "", , . RS-232, M5STACK TTL.


RS-232 "0" -3 -25 , "1" +3 +25 . RS-232 TTL "0" 0 , "1" , 3.3 5 (. 2).



2. RS-232 TTL


M5STACK / R0, R2 (RX) T0, T2 (TX) (. 3), USB . , , 0 1 .



3.


Serial Arduino IDE https://www.arduino.cc/reference/en/language/functions/communication/serial/


ASCII, : https://en.wikipedia.org/wiki/ASCII



  • M5STACK (2 .);
  • USB-C (2 .);
  • .

!


1. —


, . , MS Office Word Paint (. 4).



4. MS Office Word Paint :)


1.2.1 http://forum.m5stack.com/topic/49/lesson-1-2-1-lcd-how-to-create-image-array logo.c, .


extern unsigned char logo[];

2.


, 36 . 6 . 12 . 10 , . , 7. : ( — ; ; ; ) : , , , , . , . (. 5).



5.


define playerAmount 6


#define fullAmount 36
#define playerFieldAmount 10
#define gameFieldAmount 6

struct playCard
{
  int card;
  int suit;
  int color;
  int property = -1; // -2 not avaiable, -1 free, 0 trump, 1 player #1, 2 player #2
  int field; // + player field, - game field
};

String cards[9] = {"6", "7", "8", "9", "10", "J", "Q", "K", "A"};
char suits[4] = {3, 4, 5, 6}; // , , , 
int colors[2] = {0xe8e4, 0x00}; // red, black
playCard deckCards[fullAmount];

3.


. 1. , , (. 5.1):



5.1.


if ((opponentSteps == playerSteps) && (playerSteps == 0))
{
  deckCards[selectedCard].field = -1;
  sync();
}

. 2. , , (. 5.2) , :



5.1.


else if (opponentSteps > playerSteps)
{
  if ((((deckCards[selectedCard].card > deckCards[pfCardId].card) && (deckCards[selectedCard].suit == deckCards[pfCardId].suit)) || ((deckCards[selectedCard].suit == trumpSuit) && (deckCards[pfCardId].suit != trumpSuit))))
  {
    deckCards[selectedCard].field = -opponentSteps;
    sync();
  }
}

. 3. , , :


else if (opponentSteps == playerSteps)
{
  for (int i = 0; i < fullAmount; i++)
  {
    if ((deckCards[selectedCard].card == deckCards[i].card) && (deckCards[i].field < 0) && (deckCards[i].property != -2))
    {
      deckCards[selectedCard].field = -(playerSteps + 1);
      sync();
      break;
    }
  }
}

/. 1. , :


if (opponentSteps == playerSteps) // 
{
    for (int i = 0; i < fullAmount; i++)
    {
        if (deckCards[i].field < 0)
        {
            deckCards[i].property = -2;
        }
    }
}

/. 2. , , :


else if (opponentSteps > playerSteps) //    
{
    for (int i = 0; i < fullAmount; i++)
    {
        if ((deckCards[i].field < 0) && (deckCards[i].property != -2))
        {
            addPlayerCard(playerId, i);
        }
    }
}

4.


M5STACK, .


void drawCard(int x, int y, playCard card) {
    M5.Lcd.fillRoundRect(x, y, 30, 50, 5, 0xffff);
    M5.Lcd.drawRoundRect(x, y, 30, 50, 5, 0x00);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setTextColor(colors[card.color]);
    M5.Lcd.setCursor((x + 3), (y + 6));
    M5.Lcd.print(cards[card.card]);
    M5.Lcd.setTextSize(3);
    M5.Lcd.setCursor((x + 8), (y + 24));
    M5.Lcd.print(suits[card.suit]);
}

void drawEmptyCard(int x, int y) {
  M5.Lcd.fillRect(x, y, 30, 50, 0x2589);
  M5.Lcd.drawRoundRect(x, y, 30, 50, 5, 0x00);
}

Windows: Alt 3 6, .

5.


void drawSelect(playCard card) {
    int n = card.field - 1;
    int x = 10 + (n * 30);
    int y = (yPlayerField - 10);
    drawEmptyCard(x, yPlayerField);
    drawCard(x, y, card);
}

void clearSelect(playCard card) {
    int n = card.field - 1;
    int x = 10 + (n * 30);
    int y = (yPlayerField - 10);
    M5.Lcd.fillRect(x, y, 30, 50, 0x2589);
    drawCard(x, yPlayerField, card);
}

6.


void drawGameTable() {
    M5.Lcd.fillScreen(0x2589); // green table
    drawAllFields();
}

void drawMenu() {
    M5.Lcd.fillRect(0, 0, 320, 20, 0x00); // score bar
    M5.Lcd.fillRect(0, 220, 320, 20, 0x00); // menu bar
    /* menu buttons */
    M5.Lcd.setTextSize(2);
    M5.Lcd.setTextColor(0x7bef);
    M5.Lcd.setCursor(62, 223);
    M5.Lcd.print("G");
    M5.Lcd.setCursor(155, 223);
    M5.Lcd.print("A");
    M5.Lcd.setCursor(247, 223);
    M5.Lcd.print("S");
}

7.


void updateGraphics() {
    drawGameTable();
    drawMenu();
    drawPlayerId();
    drawRest();
    for (int i = 0; i < fullAmount; i++)
    {
        if (deckCards[i].property == playerId)
        {
            if (deckCards[i].field > 0) // if in the hands of
                drawPlayerCard(deckCards[i]); 
            else // if in the playing field
                drawPlPfCard(deckCards[i]); 
        }
        else if (deckCards[i].property == getOpponentId())
        {
            if (deckCards[i].field < 0)
                drawOpPfCard(deckCards[i]); // draw opponent's cards in the playing field
        }
        else if (deckCards[i].property == 0)
        {
            drawTrumpCard(deckCards[i]);
        }
    }
}

(, drawPlayerId()) ;)

8. /



5.3


. , . , true false.


bool serialWriteStr(String str) {
    Serial.print(str);
    Serial.print('\n');
    String input = serialReadStr(); 
    if (input != "")
    {
        if (input[0] == (char)0x04) return true;
    }
    return false;
}

timeout (3000 ) , . .


String serialReadStr() {
    String buf = "";
    long timeout = 3000;
    long previousMillis = millis();
    while (true)
    {
        unsigned long currentMillis = millis();
        if (currentMillis - previousMillis > timeout) break;
        if (Serial.available() > 0)
        {
            char chr = (char)Serial.read();
            if ((chr != (char)0x16) && (chr != (char)0x04) && (buf == "")) // clear trash
            {
                Serial.read();
            }
            else
            {
                if (chr == '\n')
                    break;
                else
                    buf += chr;
            }  
        }
    }   
    if (buf != "")
    {
        Serial.print((char)0x04);
        Serial.print('\n');
    }
    return buf;
}

9.


, , (. 6). , , . (parseString), , ( Split JS).



6.


bool serialRecivePacket() {
    String input = serialReadStr(); 
    if (input.length() > 0)
    {
        if ((char)input[0] == (char)0x16) 
        {
            input[0] = ' ';
            char groupType = ((parseString(0, (char)0x1d, input)).toInt()) + '0';
            String groupData = parseString(1, (char)0x1d, input);
            int groupDataLenmo = (groupData.length() - 1);
            if (groupData[groupDataLenmo] == (char)0x03)  
            {
                groupData[groupDataLenmo] = ' '; 
                if (groupType == (char)0x31) updateReciveDeckCards(groupData); 
                else if (groupType == (char)0x32) playerId = 2; 
                return true;
            }
        }
    return false;
    }
}

String parseString(int idSeparator, char separator, String str) { // like split JS
    String output = "";
    int separatorCout = 0;
    for (int i = 0; i < str.length(); i++)
    {
        if ((char)str[i] == separator)
        {
            separatorCout++;
        }
        else
        {
            if (separatorCout == idSeparator)
        {
            output += (char)str[i];
        }
        else if (separatorCout > idSeparator)
        {
            break;
        }
    }
    return output;
}

parseString:
parseString(1, ':', "cat:Bob,Jack:dog:Martin,Kelvin"); -----> Bob,Jack

parseString(0, ',', "Bob,Jack"); -----> Bob

parseString(1, ',', "Bob,Jack"); -----> Jack


10.


, , , , " !" (. 7). - . , " !" 2.



7.

void handshakePlayerId() {
long tpid = random(10, 1001) * 10;
long previousMillis = millis();
while (!serialRecivePacket())
{
unsigned long currentMillis = millis();
if (currentMillis — previousMillis > tpid) break;
}
while (!serialSendPlayerTId());
}


bool serialSendPlayerTId() {
    String str = "";
    str += (char)0x16; 
    str += (char)0x32; // type "player id selector"
    str += (char)0x1d;
    str += (char)0x03; 
    return serialWriteStr(str);
}

11.


bool serialSendDeckCards() {
    String str = "";
    str += (char)0x16; 
    str += (char)0x31; // type "card transfer flag"
    str += (char)0x1d; 
    for (int i = 0; i < fullAmount; i++)
    {
        str += (char)0x1e; 
        str += deckCards[i].card;
        str += (char)0x1f; 
        str += deckCards[i].suit;
        str += (char)0x1f;
        str += deckCards[i].color;
        str += (char)0x1f;
        str += deckCards[i].property;
        str += (char)0x1f;
        str += deckCards[i].field;
    }
    str += (char)0x03; 
    return serialWriteStr(str);
}

void updateReciveDeckCards(String groupData) {
    for (int i = 0; i < fullAmount; i++)
    {
        /* update new card */
        String record = parseString(i, (char)0x1e, groupData);
        deckCards[i].card = (int8_t)(parseString(0, (char)0x1f, record).toInt());
        deckCards[i].suit = (int8_t)(parseString(1, (char)0x1f, record).toInt());
        deckCards[i].color = (int8_t)(parseString(2, (char)0x1f, record).toInt());
        deckCards[i].property = (int8_t)(parseString(3, (char)0x1f, record).toInt());
        deckCards[i].field = (int8_t)(parseString(4, (char)0x1f, record).toInt());
    }
    getTrumpCard();
    updateGraphics();
    checkWinner();
}

(, getTrumpCard()) ;)

12.


. . loop(). . .


void sync(bool auto_ = false) {
    if (queue != playerId) 
    {
        while (!serialRecivePacket());
        queue = playerId;
    }
    else
    {
        if (!auto_)
        {
          while (!serialSendDeckCards());
          updateGraphics();
          checkWinner();
          queue = getOpponentId();
        }
    }
}

13. ?


whoWin() , -1, .
, , . 10 (playerFieldAmount) , .


int whoWin() {
    int opponentId = getOpponentId();
    int playerAmount_ = getAmount(playerId);
    int opponentAmount = getAmount(opponentId);
    if ((playerAmount_ == 0) || (opponentAmount >= playerFieldAmount)) return playerId;
    if ((opponentAmount == 0) || (playerAmount_ >= playerFieldAmount)) return opponentId;
    return -1; 
}

void checkWinner() {
    int winner = whoWin();
    if (winner != -1) drawWinnerShow(winner);
}

14.


: , beta-, . !

Arduino IDE .


15.


(. 5.1). (. 8). ! (. 8.1).



8.



8.1. !


\


M5Stack


All Articles