From 673e4900e93767b8bb3241b89c13424ff6fbf547 Mon Sep 17 00:00:00 2001 From: Vasil Zlatanov Date: Mon, 8 May 2017 00:40:40 +0100 Subject: Implement 2048 game prototype --- src/2048.cpp | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/2048.h | 17 ++++++ src/main.cpp | 54 ++++++++++++------ 3 files changed, 232 insertions(+), 17 deletions(-) create mode 100644 src/2048.cpp create mode 100644 src/2048.h diff --git a/src/2048.cpp b/src/2048.cpp new file mode 100644 index 0000000..13afd1f --- /dev/null +++ b/src/2048.cpp @@ -0,0 +1,178 @@ +/* + Date: 2 Feb 2016 + Author: Vasil Zlatanov +*/ + +#include "2048.h" +#include +#include //needed for random +#include // needed to for "random" seed + +void init(int board[SIZE][SIZE]) +{ + int x, y; + // Load start config + for (x = 0; x < SIZE; x++) { + for (y = 0; y < SIZE; y++) { + board[x][y] = 0; + } + } + board[SIZE - 1][SIZE - 1] = 1; +} + +int move(int direction, int board[SIZE][SIZE]){ + int done; + switch(direction) { + case 3 : + done = slideLeft(board); + break; + case 2 : + done = slideDown(board); + break; + case 1 : + done = slideUp(board); + break; + case 0 : + done = slideRight(board); + break; + default : + done = 0; + } + return done; +} + +int slideLeft(int board[SIZE][SIZE]) +{ + int done; + rotate(board); + done = slideUp(board); + rotate(board); + rotate(board); + rotate(board); + return done; +} + +int slideRight(int board[SIZE][SIZE]) +{ + int done; + rotate(board); + rotate(board); + rotate(board); + done = slideUp(board); + rotate(board); + return done; +} + +int slideUp(int board[SIZE][SIZE]) +{ + int done = 0; + int x; + for (x = 0; x < SIZE; x++) { + done |= push(board[x]); + } + return done; +} + +int slideDown(int board[SIZE][SIZE]) +{ + int done; + rotate(board); + rotate(board); + done = slideUp(board); + rotate(board); + rotate(board); + return done; +} + +int push(int array[SIZE]) +{ + int x, n, stop = 0, done = 0; + for (x = 1; x < SIZE; x++) { + if (array[x] != 0) { // make sure there is something in box + done = 2; // don't exit loop until we determine if there is a move + for (n = x - 1; done == 2; n--) { + if (array[n] != 0) { // if box has number in it + if (array[n] == array[x]) { // same so merge + array[n]++; // increase by power of two + stop = n + 1; // avoid double merge such as 2 2 0 4 + array[x] = 0; + done = 1; + } else { // not the same so move just below + if (n + 1 != x) { + array[n + 1] = array[x]; + array[x] = 0; + done = 1; + } else { + done = 0; // we can't slide any further + } + } + } else { + if (n == stop) { + array[stop] = array[x]; + array[x] = 0; + done = 1; + } + } + } + } + } + return done; +} + +void rotate(int board[SIZE][SIZE]) +{ + int x, y, n = SIZE, temp; + for (x = 0; x < n / 2; x++) { + for (y = x; y < n - x - 1; y++) { + temp = board[x][y]; + board[x][y] = board[y][n - x - 1]; + board[y][n - x - 1] = board[n - x - 1][n - y - 1]; + board[n - x - 1][n - y - 1] = board[n - y - 1][x]; + board[n - y - 1][x] = temp; + } + } +} + +int gameover(int board[SIZE][SIZE]) +{ + int x, y; + int nofree = 1; + for (x = 0; x < SIZE - 1; x++) { + for (y = 0; y < SIZE - 1; y++) { + if (board[x][y] == 0) { + nofree = 0; // means we have a free square + } + } + } + + if (nofree) { + // Check if there is any moves horizontaly or vertically; + for (x = 0; x < SIZE - 1; x++) { + for (y = 0; y < SIZE - 1; y++) { + if ((board[x][y] == board[x][y + 1]) || + (board[x][y] == board[x + 1][y])) { + return 0; + } + } + } + } + return nofree; +} + +void add2(int board[SIZE][SIZE]) +{ + int x, y, r, pos = 0, free[SIZE * SIZE][2]; + for (x = 0; x < SIZE; x++) { + for (y = 0; y < SIZE; y++) { + if (board[x][y] == 0) { + free[pos][0] = x; + free[pos][1] = y; + pos++; + } + } + } + if (free > 0) { + r = rand() % pos; + board[free[r][0]][free[r][1]] = 1; + } +} diff --git a/src/2048.h b/src/2048.h new file mode 100644 index 0000000..9b19f64 --- /dev/null +++ b/src/2048.h @@ -0,0 +1,17 @@ +#define SIZE 4 + +int move(int direction, int board[SIZE][SIZE]); + +void init(int board[SIZE][SIZE]); + +void add2(int board[SIZE][SIZE]); + +void rotate(int board[SIZE][SIZE]); + +int slideLeft(int board[SIZE][SIZE]); +int slideRight(int board[SIZE][SIZE]); +int slideUp(int board[SIZE][SIZE]); +int slideDown(int board[SIZE][SIZE]); +int gameover(int board[SIZE][SIZE]); + +int push(int array[SIZE]); diff --git a/src/main.cpp b/src/main.cpp index 19f280d..229ef25 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ #include "mbed.h" +#include "2048.h" #include "spi_init.h" #include "counter.h" #include "Adafruit_SSD1306.h" @@ -7,15 +8,14 @@ #define SW_PERIOD 20000 // 20ms void tout(void); -void pwm_invert(void); +void draw(int board[4][4]); // Onboard LED -DigitalOut out_wave(LED1); PinName switch_pin[] = { SW_PINS }; Counter *switch_position[4]; Ticker timer; -Ticker pwm; +//Ticker pwm; volatile uint16_t switch_count[4] = { 0, 0, 0, 0 }; volatile uint16_t switch_pressed[4] = { 0, 0, 0, 0 }; @@ -31,6 +31,10 @@ Adafruit_SSD1306_Spi oled(gSpi, D_DC_PIN, D_RST_PIN, D_CS_PIN, 64, 128); int main(void) { + int done = 0; + int board[4][4]; + init(board); + oled.setRotation(2); wait(0.5); @@ -43,30 +47,30 @@ int main(void) timer.attach_us(&tout, SW_PERIOD); oled.clearDisplay(); - oled.printf("%ux%u Group Ay08-04\r\n", oled.width(), oled.height()); + oled.printf("%ux%u Group Ay08-04\n", oled.width(), oled.height()); + + draw(board); for (;;) { if (update) { update = 0; + done = 0; oled.setTextCursor(0, 0); //Write the latest switch osciallor count for (int i = 3; i >= 0; --i) { - current_f[i] += (switch_pressed[i] && !last_pressed[i]); - if (current_f[i] > 9) - current_f[i] = 0; - oled.printf("\nS:%u C:%05u N:%u", switch_pressed[i], switch_count[i], current_f[i]); + if (switch_pressed[i] && !last_pressed[i]) + done = move(i, board); } - uint16_t frequency = 1000*current_f[3] + 100*current_f[2] + 10*current_f[1] + current_f[0]; - - oled.printf("\nF:%u ", frequency); + if(done){ + add2(board); + draw(board); + } - if (frequency < 25) - pwm.attach_ms(&pwm_invert, 500/frequency); - else - pwm.attach_us(&pwm_invert, 500000/frequency); + if(gameover(board)) + oled.printf("\nGame Over!"); //Copy the display buffer to the display oled.display(); @@ -95,6 +99,22 @@ void tout(void) update = 1; } -void pwm_invert(void){ - out_wave = !out_wave; +void draw(int board[SIZE][SIZE]) +{ + int x, y; + int value; + for (y = 0; y < SIZE; y++) { + for (x = 0; x < SIZE; x++) { + if (board[x][y] != 0) { + value = 2; + for (int i = 1; i < board[x][y]; ++i) { + value = value * 2; + } + } else { + value = 0; + } + oled.printf("%d\t", value); + } + oled.printf("\n"); + } } -- cgit v1.2.3