Shrinking the code

I have been teaching myself to code and figured an battleship game would be a all around learning process. So far I have gotten a working code for placing the ships (no error checking yet, just getting the basics laid out). Everything works, but there are a few things I am trying to better and can’t seem to get. One is to shorten the code down. A lot of what is going on is repeating itself. I have tried to put the variable by name into an array and then just call them into a for loop and all I get is a variable type issue. I attempted pointers but that is a tad over my head at this stage. I also tried working out calling the lights by row and column with byte arrays. The issue there was in the rotate feature. You would end up across the board from where you should be. The second issue is the lights flicker while placing the ships on the board. I think this will fix itself with a more concise code. So here is the code any advice would be appreciated.

/* jbruce4390 
battleship game
8x8 matrix with max7219
all buttons are momentary buttons with pull-down resistors  */


#include <LedControl.h>

LedControl s = LedControl(8, 10, 9, 1); //setup matrix

int rot = 5; //rotate button
int enter = 4; //enter button
int enterState = 0; //enter state change
int button_x = 2; // x-axis button
int button_y = 3; // y-axis button
int buttonState_x = 0; //current x-axis state
int buttonState_y = 0; //current y-axis state

int carrierState = 0; // ship rotate state
bool carrierOn = true; // test for rotate button state
int carrier_x = 0; // store x-axis
int carrier_y = 0; // store y-axis

int battleshipState = 0;
bool battleshipOn = true;
int battleship_x = 0;
int battleship_y = 0;

int submarineState = 0;
bool submarineOn = true;
int submarine_x = 0;
int submarine_y = 0;

int cruiserState = 0;
bool cruiserOn = true;
int cruiser_x = 0;
int cruiser_y = 0;

int patrolState = 0; 
bool patrolOn = true; 
int patrol_x = 0; 
int patrol_y = 0; 

int x = 0;
int y = 0;

void setup() {

  s.shutdown(0, false); // turn on matrix
  s.setIntensity(0, 8); // set intensity
  pinMode(2, INPUT); // initiate x-axis button
  pinMode(3, INPUT); // initiate y-axis button
  pinMode(4, INPUT); // initiate enter button
  pinMode(5, INPUT); // initiate rotate button
  
  carrierSet(); // place ships
  battleshipSet();
  cruiserSet();
  submarineSet();
  patrolSet(); 
}

void loop() {  //more to come later
}

void scroll() { // used to move cursor around
  buttonState_x = digitalRead(button_x); // test x-axis
  buttonState_y = digitalRead(button_y); // test y-axis

  if (buttonState_x != LOW || buttonState_y != LOW) { 
    s.clearDisplay(0);
    if (buttonState_x == HIGH) {
      x++;
      buttonState_x = LOW;
    }
    if (buttonState_y == HIGH) {
      y++;
      buttonState_y = LOW;
    }
    s.setLed(0, x, y, true);
    delay(100);
  }
  if (x > 7) { // if the x-axis exceeds matrix size reset
    x = 0;
  }
  if (y > 7) { // if the y=axis exceeds matrix size reset
    y = 0;
  }
}

void carrierSet() {
  x = 0; // clear current x-axis position
  y = 0; // clear current y-axis position
  do {
    scroll(); // move cursor around playing field
    carrier_x = x; //store x-axis
    carrier_y = y; //store y-axis
    s.clearDisplay(0);
    carrier(); //show ship position
    carrierState = digitalRead(rot); // get rotate button state
    delay(100);
    enterState = digitalRead(enter); //test if position has been entered
  } while (enterState == LOW);
  delay(500);
}

void carrier() {
  if (carrierState == HIGH) { // if rotate button is  pressed store state
    carrierOn = !carrierOn;
  }
  if (carrierOn == true) { // set led for x-axis
    for (int i = 0; i < 5; i++) {
      s.setLed(0, carrier_x + i, carrier_y, true);
    }
  }
  else { // set led for y-axis
    for (int i = 0; i < 5; i++) {
      s.setLed(0, carrier_x, carrier_y + i, true);
    }
  }
  delay(50);
}

void battleshipSet() {
  x = 0; 
  y = 0; 
  do {
    scroll(); 
    battleship_x = x; 
    battleship_y = y; 
    s.clearDisplay(0);
    carrier(); 
    battleship(); 
    battleshipState = digitalRead(rot); 
    delay(100);
    enterState = digitalRead(enter); 
  } while (enterState == LOW);
  delay(500);
}

void battleship() {
  if (battleshipState == HIGH) {
    battleshipOn = !battleshipOn;
  }
  if (battleshipOn == true) {
    for (int i = 0; i < 4; i++) {
      s.setLed(0, battleship_x + i, battleship_y, true);
    }
  }
  else {
    for (int i = 0; i < 4; i++) {
      s.setLed(0, battleship_x, battleship_y + i, true);
    }
  }
  delay(50);
}

void cruiserSet() {
  x = 0; 
  y = 0; 
  do {
    scroll(); 
    cruiser_x = x; 
    cruiser_y = y; 
    s.clearDisplay(0);
    carrier(); 
    battleship(); 
    cruiser();
    cruiserState = digitalRead(rot); 
    delay(100);
    enterState = digitalRead(enter); 
  } while (enterState == LOW);
  delay(500);
}

void cruiser() {
  if (cruiserState == HIGH) {
    cruiserOn = !cruiserOn;
  }
  if (cruiserOn == true) {
    for (int i = 0; i < 3; i++) {
      s.setLed(0, cruiser_x + i, cruiser_y, true);
    }
  }
  else {
    for (int i = 0; i < 3; i++) {
      s.setLed(0, cruiser_x, cruiser_y + i, true);
    }
  }
  delay(50);
}

void submarineSet() {
  x = 0; 
  y = 0; 
  do {
    scroll(); 
    submarine_x = x; 
    submarine_y = y; 
    s.clearDisplay(0);
    carrier(); 
    battleship(); 
    cruiser();
    submarine();
    submarineState = digitalRead(rot); 
    delay(100);
    enterState = digitalRead(enter); 
  } while (enterState == LOW);
  delay(500);
}

void submarine() {
  if (submarineState == HIGH) {
    submarineOn = !submarineOn;
  }
  if (submarineOn == true) {
    for (int i = 0; i < 3; i++) {
      s.setLed(0, submarine_x + i, submarine_y, true);
    }
  }
  else {
    for (int i = 0; i < 3; i++) {
      s.setLed(0, submarine_x, submarine_y + i, true);
    }
  }
  delay(50);
}

void patrolSet() {
  x = 0;
  y = 0;
  do {
    scroll(); 
    patrol_x = x; 
    patrol_y = y; 
    patrolState = digitalRead(rot); 
    s.clearDisplay(0);
    carrier();
    battleship();
    cruiser();
    submarine();
    patrol(); 
    delay(100);
    enterState = digitalRead(enter); 
  } while (enterState == LOW);
  delay(500);
}

void patrol() {
  if (patrolState == HIGH) {
    patrolOn = !patrolOn;
  }
  if (patrolOn == true) { 
    s.setLed(0, patrol_x, patrol_y, true);
    s.setLed(0, patrol_x + 1, patrol_y, true);
  }
  else { 
    s.setLed(0, patrol_x, patrol_y, true);
    s.setLed(0, patrol_x, patrol_y + 1, true);
  }
  delay(50);
}

What you can do is a more object oriented type of approach. You can define a struct (not object oriented) or class (object oriented) that acts as a template for your ships.

struct SHIP
{
  int State;
  bool On;
  int x;
  int y;
  int size;
};

SHIP battleship;
SHIP cruiser;
SHIP carrier;
SHIP submarine;

void placeShip(SHIP *ship, int size)
{
	// values just for demo
	ship->State = 0;
	ship->On = true;
	ship->x = 7;
	ship->y = 3;
	ship->size = size;
}

void setup()
{
  placeShip(&battleship, 4);
  placeShip(&carrier, 3);
  placeShip(&cruiser, 2);
  placeShip(&submarine, 1);
}

The code defines a struct and next declares four different (types of) ships. The function placeShip() takes a pointer to one of the declared ships and the size of that ship; it simply demonstrates how to access the different parameters of the ship. The function setup() demonstrates how to call placeShip().
You can also use an array of SHIPs if so desired.

I did not dig deep through your code; everywhere where you currently use one of your ships in the code, you might have to write a function to do something specific (e.g. checkHit(&submarine, posx, posy) to check if a shot did hit the submarine and checkHit(&cruiser, posx, posy) to check if a shot hit a cruiser).

I hope you get the idea.

Appreciate the help. I kind of figured I would need to do something like that. Haven't really done much in that area with much success (always get syntax errors), but I guess there is no better time to learn than now. I'll try to post back with a working sample. In case someone else might be trying the same. Thanks