来自:https://www.hackster.io/abhijaysaini/mi ... ame-86c95d
这是hackster上一个在microbit上编写的贪吃蛇游戏,使用了Mbed(C++)进行编程,作者目前没有提供源码,只有HEX文件。希望有兴趣的网友可以移植到makecode或micropython上。
microbit的贪吃蛇游戏
- shaoziyang
- 帖子: 3956
- 注册时间: 2019年 10月 21日 13:48
Re: microbit的贪吃蛇游戏
main.cpp
FixedStack.cpp
FixedStack.h
代码: 全选
#include "MicroBit.h"
#include "FixedStack.h"
MicroBit uBit;
bool FINISHED; // True if player WINS the game
enum DIRECTION {LEFT, RIGHT, UP, DOWN}; // Game Controls
const uint8_t WIDTH = 5; // WIDTH of the LED matrix
const uint8_t HEIGHT = 5; // HEIGHT of the LED matrix
const uint8_t SNAKE_BRIGHTNESS = 25; // Snake's brightness on the screen
const uint8_t FRUIT_BRIGHTNESS = 255; // Fruit's brightness on the screen
class RandomPixel {
public:
uint8_t X; // x-coordinate of the fruit
uint8_t Y; // y-coordinate of the fruit
RandomPixel();
void refresh(); // Refresh the X and Y coordinates of the fruit to a random, unoccupied position
void display(MicroBitImage m, uint8_t brightness); // Display the fruit on the LED Matrix
} Fruit;
class Snake {
public:
signed char X; // x-coordinate of the Head of the Snake
signed char Y; // y-coordinate of the Head of the Snake
uint8_t score; // Current score of the game
DIRECTION direction; // Current heading of the Snake
FixedStack* body; // Snake's body implemented using the FixedStack data structure
bool setDirection; // The player is allowed to set the Snake's direction only once per movement of the Snake
Snake();
bool offScreen(); // Returns true if the Snake goes outside the 5x5 LED Matrix
void move(); // Increment the Snake's position in the direction it's headed
void display(MicroBitImage m, uint8_t brightness); // Display the Snake's body on the LED Matrix
bool occupied(uint8_t x, uint8_t y); // Returns true if the Snake's body is currently occupying the specified coordinates
bool selfDestruct(); // Returns true if the Snake runs into itself
} SnakeBody;
/*
Snake function definitions
*****************************************
*/
Snake::Snake() {
X = uBit.random(WIDTH-2);
Y = uBit.random(HEIGHT);
score = 1;
setDirection = true;
direction = RIGHT;
body = new FixedStack(1);
body->push(new Node(X, Y));
}
bool Snake::offScreen() {
if (X < 0 || X > (WIDTH-1) || Y < 0 || Y > (HEIGHT-1))
return true;
return false;
}
void Snake::move() {
switch (direction) {
case UP: Y--;
break;
case DOWN: Y++;
break;
case LEFT: X--;
break;
case RIGHT: X++;
break;
}
if (X == (Fruit.X) && Y == (Fruit.Y)) {
body->incrementMaxSize(new Node(X, Y));
score++;
if (score == 25) FINISHED = true;
else Fruit.refresh();
}else delete body->push(new Node(X, Y));
setDirection = true;
}
void Snake::display(MicroBitImage m, uint8_t brightness) {
Node* itr = body->peek();
while (itr) {
m.setPixelValue(itr->x_cord, itr->y_cord, brightness);
itr = itr->next;
}
}
bool Snake::occupied(uint8_t x, uint8_t y) {
Node* itr = this->body->peek();
while (itr) {
if (itr->x_cord == x && itr->y_cord == y)
return true;
itr = itr->next;
}
return false;
}
bool Snake::selfDestruct() {
if (this->body->size() >= 5) {
Node* itr = this->body->peek()->next->next->next->next;
while (itr) {
if (itr->x_cord == this->body->peek()->x_cord && itr->y_cord == this->body->peek()->y_cord) {
return true;
}
itr = itr->next;
}
}
return false;
}
/*
*****************************************
*/
/*
RandomPixel function definitions
*****************************************
*/
RandomPixel::RandomPixel() {
uBit.init();
(this->X) = uBit.random(2)+3;
(this->Y) = uBit.random(HEIGHT);
}
void RandomPixel::refresh() {
do {
(this->X) = uBit.random(WIDTH);
(this->Y) = uBit.random(HEIGHT);
} while(SnakeBody.occupied(this->X, this->Y));
}
void RandomPixel::display(MicroBitImage m, uint8_t brightness) {
m.setPixelValue(X, Y, brightness);
}
/*
*****************************************
*/
/*
User Events
*****************************************
*/
void onButtonA(MicroBitEvent e) {
if (SnakeBody.setDirection) {
switch (SnakeBody.direction) {
case UP: SnakeBody.direction = LEFT;
break;
case DOWN: SnakeBody.direction = RIGHT;
break;
case LEFT: SnakeBody.direction = DOWN;
break;
case RIGHT: SnakeBody.direction = UP;
break;
}
SnakeBody.setDirection = false;
}
}
void onButtonB(MicroBitEvent e) {
if (SnakeBody.setDirection) {
switch (SnakeBody.direction) {
case UP: SnakeBody.direction = RIGHT;
break;
case DOWN: SnakeBody.direction = LEFT;
break;
case LEFT: SnakeBody.direction = UP;
break;
case RIGHT: SnakeBody.direction = DOWN;
break;
}
SnakeBody.setDirection = false;
}
}
/*
*****************************************
*/
int main() {
uBit.init();
FINISHED = false;
uBit.display.setDisplayMode(DISPLAY_MODE_GREYSCALE);
uBit.display.setBrightness(100);
uBit.display.print("SNAKE", 500);
uBit.display.print(3);
uBit.sleep(800);
uBit.display.print(2);
uBit.sleep(800);
uBit.display.print(1);
uBit.sleep(800);
const uint8_t game[] = {
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
};
MicroBitImage map(WIDTH, HEIGHT, game);
uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, onButtonA);
uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, onButtonB);
map.setPixelValue(SnakeBody.X, SnakeBody.Y, SNAKE_BRIGHTNESS);
map.setPixelValue(Fruit.X, Fruit.Y, FRUIT_BRIGHTNESS);
uBit.display.print(map);
uBit.sleep(1000);
while (1) {
map.clear();
SnakeBody.move();
if (SnakeBody.offScreen() || SnakeBody.selfDestruct() || FINISHED)
break;
SnakeBody.display(map, SNAKE_BRIGHTNESS);
Fruit.display(map, FRUIT_BRIGHTNESS);
uBit.display.print(map);
uBit.sleep(750);
}
uBit.display.clear();
/*
Game over Animations
*/
if (FINISHED) {
MicroBitImage fill("255,255,255,255,255\n255,255,255,255,255\n255,255,255,255,255\n255,255,255,255,255\n255,255,255,255,255\n");
uBit.display.print(fill);
MicroBitImage f1("0,0,0,0,0\n0,0,0,0,0\n0,0,255,0,0\n0,0,0,0,0\n0,0,0,0,0\n");
MicroBitImage f2("0,0,0,0,0\n0,255,255,255,0\n0,255,0,255,0\n0,255,255,255,0\n0,0,0,0,0\n");
MicroBitImage f3("255,255,255,255,255\n255,0,0,0,255\n255,0,0,0,255\n255,0,0,0,255\n255,255,255,255,255\n");
uBit.sleep(1000);
while (1) {
uBit.display.clear();
uBit.display.print(f2);
uBit.sleep(500);
uBit.display.print(f1);
uBit.sleep(500);
uBit.display.clear();
uBit.sleep(500);
uBit.display.print(f1);
uBit.sleep(500);
uBit.display.print(f2);
uBit.sleep(500);
uBit.display.print(f3);
uBit.sleep(500);
}
}else{
uBit.display.scroll("GAME OVER", 100);
uBit.display.scroll("SCORE:", 100);
while (1) {
uBit.display.print(SnakeBody.score);
uBit.sleep(1000);
}
}
}
代码: 全选
#include <cstdio>
#include "FixedStack.h"
FixedStack::FixedStack(int max) {
this->head = NULL;
this->max_size = max;
this->stack_size = 0;
}
int FixedStack::size() { return this->stack_size; }
bool FixedStack::isEmpty() {
if (this->head)
return false;
return true;
}
Node* FixedStack::peek() {
return this->head;
}
Node* FixedStack::push(Node* node) {
if (!isEmpty()) {
Node* temp = this->head;
this->head = node;
node->next = temp;
if (stack_size < max_size) {
this->stack_size++;
return NULL;
}else{
temp = this->head;
while (temp->next->next) {
temp = temp->next;
}
Node* tr = temp->next;
temp->next = NULL;
return tr;
}
}else {
node->next = NULL;
this->head = node;
this->stack_size++;
return NULL;
}
}
void FixedStack::incrementMaxSize(Node* node) {
node->next = this->head;
this->head = node;
this->max_size++;
this->stack_size++;
}
代码: 全选
#ifndef FSTK
#define FSTK
/*
Definition: The Node class stores data for exactly ONE pixel
Specifically, the X and Y coordinates of the pixel
Usage: A collection of Nodes creates the "Snake" body
(stored inside the FixedStack Data Structure)
*/
class Node {
public:
uint8_t x_cord; // x-coordinate of the pixel
uint8_t y_cord; // y-coordinate of the pixel
Node* next; // (Internal) Pointer to the next Node
// Initializing the data fields
Node(uint8_t x, uint8_t y) {
this->next = NULL;
this->x_cord = x;
this->y_cord = y;
}
};
/*
Definition: The FixedStack is derived from the Stack (Last In First Out or LIFO) Data Structure
The FixedStack has a Fixed Max Size, meaning that items at the bottom of the stack will be removed as additional items are pushed onto the stack
The Max Size can be incremented, but cannot be reduced
Usage: The Snake class (defined in the "main.cpp" file) uses a FixedStack to contruct the "body" of the "Snake"
*/
class FixedStack {
private:
int max_size; // Max Size of the FixedStack
int stack_size; // Current size of the FixedStack (Excludes NULL elements)
Node* head; // Head of the FixedStack
public:
FixedStack(int size); // Initialize the FixedStack with a max size
int size(); // Returns the current size of the FixedStack
bool isEmpty(); // Returns true if the FixedStack is empty
Node* peek(); //Rreturns the head Node of the FixedStack
Node* push(Node* node); // Push a Node onto the FixedStack. Returns the last Node if overflows and NULL otherwise.
void incrementMaxSize(Node* node); // Increase the max size of the FixedStack by 1 and push a new Node onto the FixedStack
};
#endif
-
- 随机主题
- 回复总数
- 阅读次数
- 最新文章
-
- 1回复总数
- 3835 阅读次数
- 最新文章 由 shaoziyang
2019年 11月 29日 12:45
-
- 1回复总数
- 3471 阅读次数
- 最新文章 由 shaoziyang
2019年 11月 29日 12:52
-
- 1回复总数
- 4692 阅读次数
- 最新文章 由 shaoziyang
2019年 11月 29日 12:59