// Battleships Arduino
// 2 Player Game
//
// June 6, 2022
#include <LiquidCrystal.h>
#include <LedControl.h>
// Debug mode ------
const bool DEBUG = true;
// Player [1] Dot Matrix Displays
#define P0DIN 52
#define P0CS 50
#define P0CLK 48
// Player [1] Controls
// Joystick
#define P0_V_PIN A0
#define P0_H_PIN A1
#define P0_S_PIN 46
// Buttons
#define P0_B_ONE 44
#define P0_B_TWO 42
// Player [2] Dot Matrix Displays
#define P1DIN 53
#define P1CS 51
#define P1CLK 49
// Player [2] Controls
// Joystick
#define P1_V_PIN A2
#define P1_H_PIN A3
#define P1_S_PIN 47
// Buttons
#define P1_B_ONE 45
#define P1_B_TWO 43
// 16x2 LCD Pins
#define LCD_RS 13
#define LCD_E 12
#define LCD_D4 11
#define LCD_D3 10
#define LCD_D2 9
#define LCD_D1 8
class PLAYER
{
public:
int selectedShip[2] = {0, 0}; // ship #, rotation of ship
int opponentBoard[8][8]; // 0=empty, 2=miss, 3=hit
int tempBoard[8][8];
int Board[8][8]; // 0=empty, 1=ship, 2=miss, 3=hit
private:
double health;
};
const int SHIPS[4][5][4] =
{
{ // Ship 0, 2x1:
{1,0,0,0}, // #---
{1,0,0,0}, // #---
{0,0,0,0}, // ----
{0,0,0,0}, // ----
{2,1,2,1} // ID (height, width, count, solid)
},
{ // Ship 1, 3x1:
{1,0,0,0}, // #---
{1,0,0,0}, // #---
{1,0,0,0}, // #---
{0,0,0,0}, // ----
{3,1,3,1} // ID (height, width, count, solid)
},
{ // Ship 2, 4x1:
{1,0,0,0}, // #---
{1,0,0,0}, // #---
{1,0,0,0}, // #---
{1,0,0,0}, // #---
{4,1,4,1} // ID (height, width, count, solid)
},
{ // Ship 3, 3x2:
{1,0,0,0}, // #---
{1,1,0,0}, // ##--
{0,1,0,0}, // -#--
{0,0,0,0}, // ----
{3,2,4,0} // ID (height, width, count, solid)
},
};
const byte boat[8] = {
B00100,
B01100,
B11100,
B01100,
B00100,
B11111,
B01110,
};
const byte arrowRight[8] = {
B00100,
B00110,
B11111,
B11111,
B11111,
B00110,
B00100,
};
// Global Variables
const int SIZE = 8;
const int maxX = SIZE - 1;
const int maxY = SIZE - 1;
int TURN = 0;
int PHASE = 0;
int X0 = 0;
int Y0 = 0;
int X1 = 0;
int Y1 = 0;
PLAYER player[2];
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D3, LCD_D2, LCD_D1);
LedControl P0HLCD = LedControl(P0DIN, P0CLK, P0CS, 0);
LedControl P0ALCD = LedControl(P0DIN, P0CLK, P0CS, 1);
LedControl P1HLCD = LedControl(P1DIN, P1CLK, P1CS, 0);
LedControl P1ALCD = LedControl(P1DIN, P1CLK, P1CS, 1);
// Functions
void selection(int H, int V, int& X, int& Y, int p);
void update_display(int X, int Y, int p, int ship);
void draw_display(int p);
void battleships(int current_player, int turn);
void setup()
{
lcd.createChar(0, arrowRight);
lcd.createChar(1, boat);
lcd.begin(16, 2);
lcd.print(" Battleships ");
lcd.write(byte(1));
lcd.setCursor(0,1);
lcd.print("Conquer the sea!");
delay(1750);
lcd.clear();
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
player[0].opponentBoard[i][j] = 0;
player[0].Board[i][j] = 0;
player[0].tempBoard[i][j] = 0;
player[1].opponentBoard[i][j] = 0;
player[1].Board[i][j] = 0;
player[1].tempBoard[i][j] = 0;
}
}
if (DEBUG == true)
{
Serial.begin(9600);
Serial.println("[!] DEBUG MODE: ON");
}
pinMode(P0_V_PIN, INPUT);
pinMode(P0_H_PIN, INPUT);
pinMode(P0_S_PIN, INPUT_PULLUP);
pinMode(P0_B_ONE, INPUT_PULLUP);
pinMode(P0_B_TWO, INPUT_PULLUP);
pinMode(P1_V_PIN, INPUT);
pinMode(P1_H_PIN, INPUT);
pinMode(P1_S_PIN, INPUT_PULLUP);
pinMode(P0_B_ONE, INPUT_PULLUP);
pinMode(P0_B_TWO, INPUT_PULLUP);
P0HLCD.shutdown(0, false);
P0ALCD.shutdown(0, false);
P1HLCD.shutdown(0, false);
P1ALCD.shutdown(0, false);
P0HLCD.setIntensity(0,8);
}
// -------------------------
void loop()
{
int H0 = map(analogRead(P0_H_PIN), 0, 1023, -1, 1);
int V0 = map(analogRead(P0_V_PIN), 0, 1023, -1, 1);
int H1 = map(analogRead(P1_H_PIN), 0, 1023, -1, 1);
int V1 = map(analogRead(P1_V_PIN), 0, 1023, -1, 1);
if (PHASE >= 0)
{
selection(H0, V0, X0, Y0, 0);
selection(H1, V1, X1, Y1, 1);
if (PHASE == 0)
{
lcd.print("P1");
lcd.setCursor(14,0);
lcd.print("P2");
}
lcd.setCursor(0,1);
lcd.print(s0);
lcd.write(byte(0));
lcd.print(X0);
lcd.print(",");
lcd.print(Y0);
lcd.setCursor(11,1);
lcd.print(s1);
lcd.write(byte(0));
lcd.print(X1);
lcd.print(",");
lcd.print(Y1);
PHASE++;
}
//delay(500);
}
// -------------------------
void selection(int H, int V, int& X, int& Y, int p)
{
char vertString[10];
char horzString[10];
sprintf(vertString,"V %i, P %i\n", V, p);
sprintf(horzString,"H %i, P %i\n", H, p);
if (p != 1)
{
if (V < 0) {
Serial.print(vertString);
Y = min(Y + 1, maxY);
}
else if (V > 0) {
Serial.print(vertString);
Y = max(Y - 1, 0);
}
if (H > 0) {
Serial.print(horzString);
X = min(X + 1, maxX);
}
else if (H < 0) {
Serial.print(horzString);
X = max(X - 1, 0);
}
if (digitalRead(P0_S_PIN) == LOW)
{
Serial.println("Ship rotated!");
if (player[p].selectedShip[1] == 0)
{
player[p].selectedShip[1]++; // rotate ship
}
else
{
player[p].selectedShip[1] = 0;
}
}
if (player[p].selectedShip[1] == 0)
{
for (int i = 0; i < SHIPS[player[p].selectedShip[0]][4][0]; i++)
{
for (int j = 0; j < SHIPS[player[p].selectedShip[0]][4][1]; j++)
{
if (SHIPS[player[p.selectedShip[0]][i][j]])
{
if (X + i <= 7player[p].tempBoard[X + i][Y + y] != 0)
{
return;
}
}
}
}
}
}
}
// void update_display(int X, int Y, int p, int s)
// {
// for (int i = 0; i < SHIPS[s][0][1]; i++)
// {
// for (int j = 0; j < SHIPS[s][0][2]; j++)
// {
// if (SHIPS[s][i][j] == 1)
// {
// player[p].tempBoard[X + j][Y + i] = 1;
// }
// }
// }
// Serial.print("\n");
// }
// void draw_display(int p)
// {
// for (int i = 0; i < maxY; i++)
// {
// for (int j = 0; j < maxX; j++)
// {
// if (player[p].tempBoard[i][j] != 0)
// {
// switch (p)
// {
// case 0: P0HLCD.setLed(0, Y, X, true); break;
// case 1: P1HLCD.setLed(0, Y, X, true); break;
// }
// }
// }
// }
// }
// TODO: Change to 8x8 array
// if (p == 0)
// {
// if (digitalRead(P0_S_PIN) == LOW) {
// P0HLCD.clearDisplay(0);
// }
// P0HLCD.setLed(0, Y, X, true);
// }
// else
// {
// if (digitalRead(P1_S_PIN) == LOW) {
// P0HLCD.clearDisplay(0);
// }
// P1HLCD.setLed(0, Y, X, true);
// }