Naval Clash Game With 16x16 NeoPixel Matrix WS1812B - Random Ships Arrangement

PaulRB, thank you for this advice. Actually I know that, but use only when I am not sure what value may come with a shortened condition so that to check that something came at all (I mean when several different values may come with it and I don't know which one it was) . It's rather a professional way of dealing with that. I am not a professional yet. What is more, it may end up with a mistake as well, so I prefer to be precise most of the time.

P.S. I have updated the code. Now it works properly and it's possible to choose a random field with a joystick, just in case if it still matters. You can find it below:

#include <Adafruit_NeoPixel.h>
#include <Vector.h>
#include <limits.h>

#define PIN    4
#define RGB    4      
#define SIZE   16
#define SHIP   10
#define MOVE   512
#define SLEEP  0
#define SPEED  0

#define XJ1  A0
#define YJ1  A1
#define SW1  A2

Adafruit_NeoPixel pixels(SIZE * SIZE, PIN);

struct Color {

    int r;
    int g;
    int b;

};

struct Coord {

    int x;
    int y;
    
    Color c;

};

struct Deck {

    int qty;
    int slot;

};

bool error                 = false;
bool selected              = false;

Coord c;

Coord storage_v[2 * SHIP] = {};
Vector<Coord> v(storage_v, 2 * SHIP);

String direction[SHIP] = {"HOR", "VER", "HOR", "VER", "HOR", "VER",  "HOR", "VER", "HOR", "VER"};
Deck   decks[SHIP]     = {{4, 0}, {3, 0}, {3, 0}, {2, 0}, {2, 0}, {2, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}};
Color  colors[RGB]     = {{UCHAR_MAX, UCHAR_MAX / 2, 0}, {0, UCHAR_MAX, 0}, {UCHAR_MAX , 0, 0}, {UCHAR_MAX / 2, 0, UCHAR_MAX}};

void setup() {

    Serial.begin(9600);
    pixels.begin();

    //Link joystick
    pinMode(XJ1, INPUT);
    pinMode(YJ1, INPUT);
    pinMode(SW1, INPUT);
    //Link joystick

    pixels.setBrightness(5);

    //Clear vectors initialized with zeroes
    v.clear();
    //Clear vectors initialized with zeroes

    //Shuffle decks and colors (primarily for the random set)
    ShuffleColors(decks,  SHIP);
    ShuffleColors(colors, RGB);
    //Shuffle decks and colors (primarily for the random set)


}

//Shuffle decks and their colors (template function)
template<class T>
void ShuffleColors(T arr[], int limit) {
    
    for (int i = 0; i < limit; i++) {

        int n    = random(0, limit);

        auto temp = arr[n];
        arr[n]    = arr[i];
        arr[i]    = temp;

    }

}
//Shuffle decks and their colors (template function) 

//Clear game field (for random set only)
void ClearGameField() {

    for (int i = 0; i < v.size(); i++) {

        pixels.setPixelColor(XY(v[i].y, v[i].x), pixels.Color(0, 0, 0));                               
        pixels.show();

    }

}
//Clear game field (for random set only)

//Check if the ship is not beyond the grid (for random set only)
bool CheckFieldShipBoundary(int x, int y, int decks, String dir, String name) {

    if ((x >= 1 && x <= SIZE) && (y >= 1 && y <= SIZE)) {

        if (dir == "HOR") {

            if (decks - 1 <= SIZE - y) {

                return true;

            } 

            return false;

        } else if (dir == "VER") {

            if (decks - 1 <= SIZE - x) {

                return true;

            } 

            return false;

        }

    }

    return false;

}
//Check if the ship is not beyond the grid (for random set only)

//Check if the ship has got enough space around (for random set only)
bool CheckShipObstacleAround(int x, int y, int decks, String dir, String name) {

    if (dir == "HOR") {

        if ((y - 2 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 2, x - 2)) != 0) ||
            (y - 2 >= 0 && x - 1 >= 0         && pixels.getPixelColor(XY(y - 2, x - 1)) != 0) ||
            (y - 2 >= 0 && x >= 0 && x < SIZE && pixels.getPixelColor(XY(y - 2, x))     != 0)) {

            return false;

        }

        for (int i = 0; i < decks; i++) {

            int cx = x - 1;
            int cy = y - 1 + i;

            if ((cy >= 0 && cy < SIZE && cx - 1 >= 0   && pixels.getPixelColor(XY(cy, cx - 1)) != 0) ||
                (cy >= 0 && cy < SIZE && cx + 1 < SIZE && pixels.getPixelColor(XY(cy, cx + 1)) != 0)) {

                return false;

            }
            
        }

        if ((y + decks - 1 >= 0 && y + decks - 1 < SIZE && x - 2 >= 0         && pixels.getPixelColor(XY(y + decks - 1, x - 2)) != 0) ||
            (y + decks - 1 >= 0 && y + decks - 1 < SIZE && x - 1 >= 0         && pixels.getPixelColor(XY(y + decks - 1, x - 1)) != 0) ||
            (y + decks - 1 >= 0 && y + decks - 1 < SIZE && x >= 0 && x < SIZE && pixels.getPixelColor(XY(y + decks - 1, x))     != 0)) {

            return false;

        }

        return true; 

    } else if (dir == "VER") {

        if ((y - 2 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 2, x - 2)) != 0) ||
            (y - 1 >= 0 && x - 2 >= 0         && pixels.getPixelColor(XY(y - 1, x - 2)) != 0) ||
            (y >= 0 && y < SIZE && x - 2 >= 0 && pixels.getPixelColor(XY(y, x - 2))     != 0)) {

            return false;

        }

        for (int i = 0; i < decks; i++) {

            int cx = x - 1 + i;
            int cy = y - 1;

            if ((cy - 1 >= 0   && cx >= 0 && cx < SIZE && pixels.getPixelColor(XY(cy - 1, cx)) != 0) ||
                (cy + 1 < SIZE && cx >= 0 && cx < SIZE && pixels.getPixelColor(XY(cy + 1, cx)) != 0)) {

                return false;

            } 

        }

        if ((y - 2 >= 0 && x + decks - 1 >= 0 && x + decks - 1 < SIZE         && pixels.getPixelColor(XY(y - 2, x + decks - 1)) != 0) ||
            (y - 1 >= 0 && x + decks - 1 >= 0 && x + decks - 1 < SIZE         && pixels.getPixelColor(XY(y - 1, x + decks - 1)) != 0) ||
            (y >= 0 && y < SIZE && x + decks - 1 >= 0 && x + decks - 1 < SIZE && pixels.getPixelColor(XY(y,     x + decks - 1)) != 0)) {

            return false;

        }

        return true; 

    }

}
//Check if the ship has got enough space around (for random set only)

//Check if one ship does not overlap another (for random set only)
void ResetShipAfterOverlap(int i, int cx, int cy, String name) {

    for (int j = 0; j < v.size(); j++) {

        if ((v[j].x == cx) && (v[j].y == cy)) {

            Serial.println("OVERLAPPED " + name + "!");
            delay(SLEEP);
            int index = i;

            for (int i = 0; i < index; i++) {

                pixels.setPixelColor(XY(v.back().y, v.back().x), pixels.Color(0, 0, 0));                               
                pixels.show();
                v.pop_back();

            }

            error = true;
            break;

        }

    }

}
//Check if one ship does not overlap another (for random set only)

//Check random ship RGB color (the same number of decks) (for random set only) 
void SetShipRGBColor(int x, int y, int decks, String dir, String name) {

    c.x = x;
    c.y = y;

    for (int i = 0; i < RGB; i++) {

        if (decks == RGB - i) {

            c.c.r = colors[decks-1].r;
            c.c.g = colors[decks-1].g;
            c.c.b = colors[decks-1].b;

        }

    }

    v.push_back(c);

    pixels.setPixelColor(XY(c.y, c.x), pixels.Color(c.c.r, c.c.g, c.c.b));                               
    pixels.show();

}
//Check random ship RGB color (the same number of decks) (for random set only)

//Set a random ship position (for random set only)
void SetHomeShipPosition(int x, int y, int decks, String dir, String name) {

    error = false;

    if ((CheckFieldShipBoundary(x, y, decks, dir, name) == true) && (CheckShipObstacleAround(x, y, decks, dir, name) == true)) {

        if (dir == "HOR") {

            for (int i = 0; i < decks; i++) {

                int cx = x - 1;
                int cy = y - 1 + i;
                
                ResetShipAfterOverlap(i, cx, cy, name);

                if (error == true) {

                    break;

                }

                SetShipRGBColor(cx, cy, decks, dir, name);

            }
            
            if (error == false) {

                Serial.println("OK " + name + "!");
                delay(SLEEP);

            }

        } else if (dir == "VER") {

            for (int i = 0; i < decks; i++) {

                int cx = x - 1 + i;
                int cy = y - 1;

                ResetShipAfterOverlap(i, cx, cy, name);

                if (error == true) {

                    break;

                }

                SetShipRGBColor(cx, cy, decks, dir, name);

            }

            if (error == false) {

                Serial.println("OK " + name + "!");
                delay(SLEEP);

            }

        }

    } else {

        if (CheckFieldShipBoundary(x, y, decks, dir, name) == false) {
         
            error = true;
            Serial.println("NOT ENOUGH SPACE " + name + "!");
            delay(SLEEP);

        } else if (CheckShipObstacleAround(x, y, decks, dir, name) == false) {

            error = true;
            Serial.println("TOO NEARBY " + name + "!");
            delay(SLEEP);

        }

    }

}
//Set a random ship position (for random set only)

//Player joystick control
void PlayerJoystickControl() {

    int x = analogRead(A1);
    int y = analogRead(A0);

    if (x == 2 * MOVE - 1 && y == MOVE) { //LEFT

        GenerateRandomShipSet();
        //delay(SPEED);
        Serial.println("LEFT");
        selected = false;

    } else if (x == 0 && y == MOVE) { //RIGHT

        GenerateRandomShipSet();
        //delay(SPEED);
        Serial.println("RIGHT");
        selected = false;
        
    } else if (y == 2 * MOVE - 1 && x == MOVE) { //DOWN

        GenerateRandomShipSet();
        //delay(SPEED);
        Serial.println("DOWN");
        selected = false;

    } else if (y == 0 && x == MOVE) { //UP

        GenerateRandomShipSet();
        //delay(SPEED);
        Serial.println("UP");
        selected = false;

    }

}
//Player joystick control

//Generate a random multi-colored field with ships (according to the Naval Clash game rules)
void GenerateRandomShipSet() {

    if (selected == false) {

        ClearGameField();
        v.clear();

        for (int i = 0; i < SHIP; i++) {

            randomSeed(micros() + analogRead(A0) + analogRead(A1));

            SetHomeShipPosition(random(1, SIZE + 1), random(1, SIZE + 1), decks[i].qty, direction[random(0, SIZE)], String(i + 1));
            if (error == true) {
                
                //if (i >= 0) {
                
                    i--;
                    Serial.print("INDEX => ");
                    Serial.println(i);

                //}

            }

        }

        ShuffleColors(decks,  SHIP);
        ShuffleColors(colors, RGB);

        selected = true;

    }

}
//Generate a random multi-colored field with ships (according to the Naval Clash game rules)

void loop() { 

    PlayerJoystickControl();

}

int XY(int x, int y) { 

    if (y % 2 == 0) {

        return y * SIZE + x;

    } else {

        return ((y + 1) * SIZE - 1) - x;

    }

}