A fully interactive Battleship game built with Nuxt 3, Vue 3, TypeScript, and Tailwind CSS. This project demonstrates modern frontend development practices, including type safety, component architecture, testing strategies, and responsive design.
This is a single-player Battleship game where the player attempts to sink all ships on a 10x10 grid by entering coordinates (e.g., A4, J10). The game features:
- Grid-based gameplay with visual feedback for hits, misses, and sunk ships
- Real-time input validation with debounced coordinate entry
- Type-safe architecture using TypeScript interfaces
- Modular composables for game logic separation
- Comprehensive testing with unit and integration tests
- Responsive design with custom CSS grid layouts
- Node.js 18+
- npm or yarn
# Clone the repository
git clone <repository-url>
cd magnolia
# Install dependencies
npm install
# Start development server
npm run dev
# Run tests
npm run test
# Build for production
npm run buildโโโ components/ # Vue components
โ โโโ Gameboard.vue # Game grid visualization
โโโ composables/ # Business logic & state management
โ โโโ useGridHelpers.ts # Core game logic
โโโ pages/ # Nuxt pages
โ โโโ index.vue # Main game interface
โโโ tests/ # Test files
โ โโโ components/ # Component tests
โ โโโ composables/ # Unit tests
โ โโโ pages/ # Integration tests
โโโ typings/ # TypeScript type definitions
โ โโโ grid.d.ts # Grid and cell interfaces
โ โโโ ship.d.ts # Ship-related types
โ โโโ gameResult.d.ts # Game state types
โโโ assets/css/ # Styling and design system
- Framework: Nuxt 3 with Vue 3 Composition API
- Language: TypeScript for type safety
- Styling: Tailwind CSS with custom utility classes
- Testing: Vitest + Vue Test Utils
- Build Tool: Vite (included with Nuxt 3)
- 10x10 Grid: Standard Battleship board with coordinate system (A1-J10)
- Ship Placement: Randomized ship positioning on game start
- 1x Battleship (4 cells)
- 2x Destroyers (3 cells each)
- Input System: Coordinate-based targeting with real-time validation
- Visual Feedback: Color-coded cells for hits, misses, and ship visualization
The project uses comprehensive TypeScript interfaces for type safety:
// Grid system
interface IGrid extends Array<Array<IGridCell>> {}
interface IGridCell {
coordinate: ICoordinate;
hasShip: boolean;
isHit: boolean;
shipId?: string;
}
// Ship management
interface IShip {
id: string;
name: string;
coordinates: IShipCoordinates[];
isSunk: boolean;
shipClass: IShipClass;
}
// Game state
interface IGameResult {
type: "hit" | "miss" | "sunk" | "invalid";
message: string;
class: string;
}Game state is managed through Vue 3's Composition API using a centralized composable:
// useGridHelpers.ts - Core game logic
export const useGridHelpers = () => {
const grid = ref<IGrid>([]);
const ships = ref<IShip[]>([]);
const currentResult = ref<IGameResult | null>(null);
const gameWon = ref<boolean>(false);
// Game logic methods
const initializeGrid = () => {
/* ... */
};
const placeShipsRandomly = () => {
/* ... */
};
const handleFireShot = (coordinate: ICoordinate) => {
/* ... */
};
return {
// State
grid,
ships,
currentResult,
gameWon,
// Methods
initializeGrid,
placeShipsRandomly,
handleFireShot,
};
};Separation of Concerns:
pages/index.vue: UI layout and user interactionscomponents/Gameboard.vue: Grid visualizationcomposables/useGridHelpers.ts: Game logic and state
Props & Events:
<!-- Gameboard Component -->
<Gameboard :grid="grid" :grid-size="GRID_SIZE" />Uses BEMIT as CSS system, using tailwind for utility classes generation:
.c-gameboard {
--cell-dimension: 30px;
display: grid;
grid-template-columns: repeat(10, var(--cell-dimension));
grid-template-rows: repeat(10, var(--cell-dimension));
gap: 1px;
}
.c-gameboard__square {
background-color: #e0e7ff;
}
.c-gameboard__hit {
background-color: #dc2626; /* Red for hits */
}
.c-gameboard__miss {
background-color: #3b82f6; /* Blue for misses */
}The project includes comprehensive testing at multiple levels:
- Grid initialization and validation
- Coordinate parsing and validation
- Ship placement algorithms
- Game logic (hit detection, win conditions)
- Edge cases and error handling
- Component rendering and user interface
- User input handling and validation
- Game state updates and visual feedback
- Victory conditions and messaging
- Grid rendering with different states
- Visual feedback for hits/misses
- Props validation and reactivity