Показаны различия между двумя версиями страницы.
Следующая версия | Предыдущая версия | ||
products:laboratory_iot_c:exp55 [2024/12/15 17:45] – создано labuser30 | products:laboratory_iot_c:exp55 [2024/12/15 18:04] (текущий) – [Программный код эксперимента] labuser30 | ||
---|---|---|---|
Строка 14: | Строка 14: | ||
==== Программный код эксперимента ==== | ==== Программный код эксперимента ==== | ||
- | < | + | < |
- | from machine import Pin, SPI | + | #include <SPI.h> |
- | from tft import TFT_GREEN | + | #include < |
- | _init() | + | #include " |
- | machine.freq(160000000) | + | |
- | dc = Pin(4, Pin.OUT) | + | #define PIN_CS |
- | cs = Pin(2, Pin.OUT) | + | #define PIN_DC |
- | rst = Pin(5, Pin.OUT) | + | #define PIN_RST |
- | spi = SPI(1, baudrate=40000000, | + | |
- | tft = TFT_GREEN(128, 160, spi, dc, cs, rst, rotate=0) | + | Adafruit_ST7735 |
+ | LittleFS_ImageReader reader; | ||
- | Map = [ | + | bool Map[10][8] = { |
- | | + | {1, |
- | [0, | + | {0, |
- | [1, | + | {1, |
- | [0, | + | {0, |
- | [0, | + | {0, |
- | [1, | + | {1, |
- | [1, | + | {1, |
- | [1, | + | {1, |
- | [1, | + | {1, |
- | [1, | + | {1, |
- | ] | + | }; |
- | Gates = [] | + | struct Pos { |
- | Boxes = [] | + | int x = 0; |
+ | int y = 0; | ||
- | class Box: | + | bool operator == (const Pos &pos) const { |
- | | + | |
- | self.tft | + | } |
- | self.x = x | + | }; |
- | self.y = y | + | |
- | self.picture | + | |
- | | + | |
- | | + | |
- | self.draw() | + | |
- | def draw(self): | + | class Box { |
- | if (self.onGate): | + | |
- | | + | |
- | else: | + | LittleFS_ImageReader |
- | self.tft.draw_bmp(self.x * 16,self.y * 16, self.picture) | + | Pos pos; |
+ | | ||
+ | String picture_on_gate = "/ | ||
+ | bool on_gate = false; | ||
- | def setOnGate(self, state): | + | public: |
- | | + | Box(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, |
+ | tft_ptr = _tft_ptr; | ||
+ | reader_ptr = _reader_ptr; | ||
+ | pos.x = x; | ||
+ | pos.y = y; | ||
+ | } | ||
+ | |||
+ | void draw() { | ||
+ | if (on_gate) reader_ptr-> | ||
+ | else reader_ptr-> | ||
+ | } | ||
+ | |||
+ | void setOnGate(bool | ||
+ | on_gate = state; | ||
+ | } | ||
+ | | ||
+ | bool getOnGate() const { | ||
+ | return on_gate; | ||
+ | } | ||
+ | |||
+ | Pos getPos() const { | ||
+ | return pos; | ||
+ | } | ||
+ | |||
+ | void setPos(Pos _pos) { | ||
+ | pos.x = _pos.x; | ||
+ | pos.y = _pos.y; | ||
+ | draw(); | ||
+ | } | ||
+ | }; | ||
- | def getOnGate(self): | + | class Gate { |
- | | + | private: |
+ | | ||
+ | LittleFS_ImageReader *reader_ptr; | ||
+ | Pos pos; | ||
+ | String picture | ||
- | def getPos(self): | + | public: |
- | | + | Gate(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, |
+ | tft_ptr = _tft_ptr; | ||
+ | reader_ptr = _reader_ptr; | ||
+ | pos.x = x; | ||
+ | pos.y = y; | ||
+ | } | ||
- | | + | |
- | self.x = x | + | reader_ptr-> |
- | self.y = y | + | |
- | | + | |
- | class Gate: | + | Pos getPos() const { |
- | def __init__(self, tft, x, y): | + | |
- | | + | } |
- | | + | }; |
- | | + | |
- | self.picture = ' | + | |
- | self.draw() | + | |
- | def draw(self): | + | class Man { |
- | | + | private: |
+ | | ||
+ | LittleFS_ImageReader | ||
+ | Pos pos; | ||
+ | String | ||
- | def getPos(self): | + | public: |
- | | + | Man(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, |
+ | | ||
+ | tft_ptr = _tft_ptr; | ||
+ | reader_ptr = _reader_ptr; | ||
+ | pos.x = x; | ||
+ | pos.y = y; | ||
+ | } | ||
- | class Man: | + | void draw() const { |
- | def __init__(self, tft, x, y): | + | |
- | | + | } |
- | self.x = x | + | |
- | self.y = y | + | |
- | self.picture = ' | + | |
- | self.draw() | + | |
- | | + | |
- | | + | |
+ | } | ||
- | | + | |
- | | + | |
+ | pos.x = _pos.x; | ||
+ | pos.y = _pos.y; | ||
+ | draw(); | ||
+ | } | ||
+ | }; | ||
- | def setPos(self, x, y): | + | class Button { |
- | | + | private: |
- | | + | int pin; |
- | | + | bool pressState; |
- | | + | bool oldState; |
+ | |||
+ | public: | ||
+ | Button(int _pin, bool _pressState) { | ||
+ | pin = _pin; | ||
+ | setPinMode(); | ||
+ | | ||
+ | oldState = not _pressState; | ||
+ | } | ||
+ | |||
+ | bool onPress() { | ||
+ | bool state = digitalRead(pin); | ||
+ | if (state != oldState){ | ||
+ | | ||
+ | | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
- | class Button: | + | void setPinMode() const { |
- | def __init__(self, p, pressSate): | + | |
- | self.pin = Pin(p, Pin.IN) | + | |
- | self.pressSate = pressSate | + | }; |
- | self.oldState = 0 | + | |
- | + | ||
- | def onPress(self): | + | |
- | state = self.pin.value() | + | |
- | if state != self.oldState: | + | |
- | self.oldState = state | + | |
- | if state == self.pressSate: | + | |
- | return True | + | |
- | return False | + | |
- | tft.initr(tft.BGR) # tft.initr(tft.RGB) #Если вместо синего цвета отображается красный, а вместо красного синий | + | const int boxes_number = 3; |
- | tft.clear(tft.COLOR_BLACK) | + | Box boxes[boxes_number] = { |
+ | {&tft, & | ||
+ | {&tft, & | ||
+ | | ||
+ | }; | ||
- | x = 0 | + | const int gates_number |
- | y = 0 | + | Gate gates[gates_number] |
+ | {&tft, & | ||
+ | {&tft, & | ||
+ | {&tft, & | ||
+ | }; | ||
- | for row in Map: | + | Man man(&tft, &reader, 5, 6); |
- | for col in row: | + | |
- | if col: | + | |
- | tft.draw_bmp(x * 16, y * 16,' | + | |
- | x+=1 | + | |
- | x=0 | + | |
- | y+=1 | + | |
- | Boxes.append(Box(tft, 3,4)) | + | Button btn_up(16, HIGH); |
- | Boxes.append(Box(tft, 4,6)) | + | Button btn_down(15, HIGH); |
- | Boxes.append(Box(tft, 2,7)) | + | Button btn_left(12, HIGH); |
+ | Button btn_right(0, LOW); | ||
- | Gates.append(Gate(tft, 6,3)) | + | bool canMove(Pos pos) { |
- | Gates.append(Gate(tft, 6,4)) | + | if (Map[pos.y][pos.x]) return false; |
- | Gates.append(Gate(tft, 6,5)) | + | else return true; |
+ | } | ||
+ | |||
+ | int feelBox(Pos pos) { | ||
+ | for (int i = 0; i < boxes_number; | ||
+ | if (boxes[i].getPos() == pos) return i; | ||
+ | } | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | bool boxOnGate(Pos pos) { | ||
+ | for (int i = 0; i < gates_number; | ||
+ | if (gates[i].getPos() == pos) return true; | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
- | man = Man(tft, 5, 6) | + | void setup() { |
+ | Serial.begin(9600); | ||
+ | Serial.println(); | ||
+ | Serial.println(" | ||
+ | LittleFS.begin(); | ||
+ | | ||
+ | tft.setRotation(2); | ||
+ | tft.fillScreen(ST77XX_BLACK); | ||
- | btnUp = Button(16, 1) | + | for (int y = 0; y < 10; y++) { |
- | btnDown | + | for (int x = 0; x < 10; x++) { |
- | btnLeft = Button(12, 1) | + | |
- | btnRight = Button(0, 0) | + | } |
+ | } | ||
- | def canMove(x,y): | + | for (int i = 0; i < boxes_number; |
- | | + | |
- | return False | + | } |
- | else: | + | |
- | | + | |
- | def feelBox(x,y): | + | for (int i = 0; i < gates_number; |
- | | + | |
- | if B.getPos() == (x,y): | + | } |
- | return B | + | |
- | return False | + | man.draw(); |
- | def boxFeelGate(x, | + | btn_left.setPinMode(); |
- | for G in Gates: | + | } |
- | if G.getPos() == (x,y): | + | |
- | return True | + | |
- | | + | |
- | while True: | + | void loop() { |
- | | + | Pos man_pos |
- | | + | Pos new_pos |
+ | Pos new_pos_next = {-1, -1}; | ||
- | | + | |
- | | + | |
- | | + | |
+ | } | ||
- | | + | |
- | | + | |
- | | + | |
+ | } | ||
- | | + | |
- | | + | |
- | | + | |
+ | } | ||
- | | + | |
- | | + | |
- | | + | |
+ | } | ||
- | if newPos != (-1,-1): | + | Pos not_pos |
- | B = feelBox(newPos[0], | + | |
- | if B and canMove(newPosNext[0], | + | |
- | if boxFeelGate(newPosNext[0], | + | |
- | B.setOnGate(True) | + | |
- | else: | + | |
- | B.setOnGate(False) | + | |
- | B.setPos(newPosNext[0], | + | |
- | man.setPos(newPos[0], | + | |
- | if not B and canMove(newPos[0], | + | |
- | man.setPos(newPos[0], | + | |
- | for G in Gates: | + | if (!(new_pos == not_pos)) { |
- | | + | int box = feelBox(new_pos); |
- | if not (feelBox(gPos[0], gPos[1])) and gPos != man.getPos(): | + | if (box >= 0 && canMove(new_pos_next)) { |
- | G.draw() | + | if (boxOnGate(new_pos_next)) boxes[box].setOnGate(true); |
+ | else boxes[box].setOnGate(false); | ||
- | win = 1 | + | boxes[box].setPos(new_pos_next); |
- | for B in Boxes: | + | man.setPos(new_pos); |
- | if (not B.getOnGate()): | + | } |
- | win = 0 | + | |
- | break | + | if (box == -1 && canMove(new_pos)) man.setPos(new_pos); |
- | + | ||
- | if (win): | + | for (int i = 0; i < gates_number; |
- | tft.draw_bmp(0, 16, 'win.bmp') | + | if (feelBox(gates[i].getPos()) == -1 and !(man.getPos() == gates[i].getPos())) { |
- | raise SystemExit | + | |
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | bool win = true; | ||
+ | |||
+ | | ||
+ | { | ||
+ | if (!boxes[i].getOnGate()){ | ||
+ | win = false; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | | ||
+ | } | ||
</ | </ | ||
Строка 220: | Строка 306: | ||
'' | '' | ||
- | < | + | < |
- | def canMove(x,y): | + | bool canMove(Pos pos) { |
- | if (Map[y][x]): | + | if (Map[pos.y][pos.x]) return |
- | | + | else return |
- | else: | + | } |
- | | + | |
</ | </ | ||
- | Функция '' | + | Функция '' |
- | < | + | |
- | def feelBox(x,y): | + | < |
- | for B in Boxes: | + | int feelBox(Pos pos) { |
- | if B.getPos() == (x,y): | + | for (int i = 0; i < boxes_number; |
- | return | + | if (boxes[i].getPos() == pos) return i; |
- | | + | } |
+ | | ||
+ | } | ||
</ | </ | ||
- | Функция '' | + | Функция '' |
- | < | + | |
- | def boxFeelGate(x,y): | + | < |
- | for G in Gates: | + | bool boxOnGate(Pos pos) { |
- | if G.getPos() == (x,y): | + | for (int i = 0; i < gates_number; |
- | | + | if (gates[i].getPos() == pos) return |
- | return | + | } |
+ | | ||
+ | } | ||
</ | </ | ||
Строка 249: | Строка 338: | ||
Если нажатие было и новая координата определена, | Если нажатие было и новая координата определена, | ||
- | < | + | < |
- | | + | |
</ | </ | ||
- | Если ящик есть, значит мы должны двигаться вместе с ящиком. Но для этого нужно проверить может ли передвинуться ящик (нет ли стены перед ящиком). | + | Если ящик есть |
- | <code python[enable_line_numbers=" | + | <code python[enable_line_numbers=" |
- | if B and canMove(newPosNext[0], | + | if (box >= 0 && |
</ | </ | ||
- | Если все в порядке и ящик может передвинуться, | + | Если все в порядке и ящик может передвинуться, |
После чего передвигаем ящик и кладовщика в новую координату. | После чего передвигаем ящик и кладовщика в новую координату. | ||
Строка 265: | Строка 354: | ||
Далее идет вспомогательная логика. В частности мы перерисовываем цели, если на них нет ящика или кладовщика. Это нужно, чтобы после прохождения ящика или кладовщика по цели они прорисовывались заново, | Далее идет вспомогательная логика. В частности мы перерисовываем цели, если на них нет ящика или кладовщика. Это нужно, чтобы после прохождения ящика или кладовщика по цели они прорисовывались заново, | ||
- | < | + | < |
- | for G in Gates: | + | for (int i = 0; i < gates_number; |
- | gPos = G.getPos() | + | if (feelBox(gates[i].getPos()) == -1 and !(man.getPos() |
- | if not (feelBox(gPos[0], gPos[1])) and gPos != man.getPos(): | + | |
- | G.draw() | + | } |
+ | } | ||
</ | </ | ||
- | Далее идет проверка условия выигрыша. Игра считается выигранной когда все ящики установлены на свои цели. Для этого мы проверяем условие нахождения ящика на цели для каждого ящика. Если у всех ящиков соблюдается данное условие, | + | Далее идет проверка условия выигрыша. Игра считается выигранной когда все ящики установлены на свои цели. Для этого мы проверяем условие нахождения ящика на цели для каждого ящика. Если у всех ящиков соблюдается данное условие, |
- | < | + | < |
- | win = 1 | + | |
- | for B in Boxes: | + | |
- | if (not B.getOnGate()): | + | |
- | win = 0 | + | { |
- | break | + | |
- | + | win = false; | |
- | if (win): | + | break; |
- | tft.draw_bmp(0, 16, 'win.bmp') | + | } |
- | raise SystemExit | + | } |
+ | |||
+ | | ||
</ | </ | ||