diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5d97d44
--- /dev/null
+++ b/README.md
@@ -0,0 +1,95 @@
+# Scrabble Game - HTML5 Interactive Multiplayer
+
+An interactive multiplayer HTML5 implementation of the classic Scrabble word game.
+
+## Project Structure
+
+```
+scrabble-game/
+├── index.html # Main game page
+├── css/
+│ └── styles.css # Game styling and responsive design
+├── js/
+│ └── game.js # Core game logic and initialization
+└── README.md # Project documentation
+```
+
+## Features (Planned)
+
+- Interactive game board
+- Multiplayer support (up to 4 players)
+- Word validation
+- Score calculation
+- Responsive design for mobile and desktop
+- Turn-based gameplay
+- Tile management system
+
+## Getting Started
+
+1. Open `index.html` in a modern web browser
+2. The game will initialize automatically
+3. Check the browser console for initialization confirmation
+
+## Development Status
+
+### ✅ Completed
+- Basic HTML5 project structure
+- Responsive CSS styling
+- JavaScript game object framework
+- Mobile-friendly design
+
+### 🚧 In Progress
+- Game board rendering
+- Tile system implementation
+- Player management
+
+### 📋 Planned
+- Multiplayer functionality
+- Dictionary integration
+- Score tracking
+- Game state persistence
+- Sound effects
+- Animations
+
+## Technical Stack
+
+- **HTML5** - Semantic markup and game structure
+- **CSS3** - Styling with responsive design
+- **Vanilla JavaScript (ES6)** - Game logic without external dependencies
+
+## Browser Compatibility
+
+- Chrome (latest)
+- Firefox (latest)
+- Safari (latest)
+- Edge (latest)
+- Mobile browsers (iOS Safari, Chrome Mobile)
+
+## Game Configuration
+
+The game configuration can be modified in `js/game.js`:
+
+```javascript
+config: {
+ boardSize: 15,
+ maxPlayers: 4,
+ tilesPerPlayer: 7
+}
+```
+
+## Future Enhancements
+
+- Online multiplayer via WebSockets
+- AI opponent
+- Tournament mode
+- Statistics tracking
+- Custom word lists
+- Theme customization
+
+## Contributing
+
+This project is part of the TEST-104 initiative to build an interactive multiplayer HTML5 game of Scrabble.
+
+## License
+
+This project is for educational purposes as part of the development workflow testing.
\ No newline at end of file
diff --git a/css/styles.css b/css/styles.css
new file mode 100644
index 0000000..17161d8
--- /dev/null
+++ b/css/styles.css
@@ -0,0 +1,524 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ line-height: 1.6;
+ color: #333;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ min-height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 20px;
+}
+
+.container {
+ background: white;
+ border-radius: 20px;
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
+ padding: 40px;
+ max-width: 900px;
+ width: 100%;
+ animation: fadeIn 0.5s ease-in;
+}
+
+header {
+ text-align: center;
+ margin-bottom: 30px;
+}
+
+.game-title {
+ font-size: 3rem;
+ color: #5a67d8;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
+ font-weight: 700;
+ letter-spacing: 2px;
+}
+
+.welcome-section {
+ text-align: center;
+ margin-bottom: 40px;
+}
+
+.welcome-message {
+ font-size: 1.2rem;
+ color: #4a5568;
+ max-width: 600px;
+ margin: 0 auto;
+}
+
+.game-container {
+ min-height: 400px;
+ background: transparent;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 20px;
+}
+
+:root {
+ --square-regular: #F5E6D3;
+ --square-tw: #DC143C;
+ --square-dw: #FFB6C1;
+ --square-tl: #00008B;
+ --square-dl: #87CEEB;
+ --square-center: #FFD700;
+ --board-border: #8B4513;
+ --square-border: #D2B48C;
+}
+
+.board-wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ background: white;
+ padding: 10px;
+ border-radius: 10px;
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
+}
+
+.board-with-labels {
+ display: flex;
+ align-items: center;
+}
+
+.board-grid {
+ display: grid;
+ grid-template-columns: repeat(15, 1fr);
+ grid-template-rows: repeat(15, 1fr);
+ gap: 1px;
+ background: var(--square-border);
+ border: 3px solid var(--board-border);
+ padding: 1px;
+ aspect-ratio: 1;
+ width: min(600px, calc(100vw - 120px));
+ height: min(600px, calc(100vw - 120px));
+}
+
+.board-square {
+ background: var(--square-regular);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ position: relative;
+ aspect-ratio: 1;
+}
+
+.board-square:hover {
+ transform: scale(1.05);
+ z-index: 10;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
+}
+
+.board-square.triple-word {
+ background: var(--square-tw);
+}
+
+.board-square.double-word {
+ background: var(--square-dw);
+}
+
+.board-square.triple-letter {
+ background: var(--square-tl);
+}
+
+.board-square.double-letter {
+ background: var(--square-dl);
+}
+
+.board-square.center {
+ background: var(--square-center);
+}
+
+.square-label {
+ font-size: 0.7em;
+ font-weight: bold;
+ text-align: center;
+ pointer-events: none;
+}
+
+.board-square.triple-word .square-label,
+.board-square.triple-letter .square-label {
+ color: white;
+}
+
+.board-square.double-word .square-label {
+ color: #8B0000;
+}
+
+.board-square.double-letter .square-label {
+ color: #00008B;
+}
+
+.board-square.center .square-label {
+ font-size: 1.2em;
+ color: #8B4513;
+}
+
+.coordinate-labels {
+ display: flex;
+ font-weight: bold;
+ color: #5a67d8;
+ font-size: 0.9rem;
+}
+
+.coordinate-labels.top,
+.coordinate-labels.bottom {
+ flex-direction: row;
+ width: 100%;
+ justify-content: center;
+ margin: 5px 0;
+}
+
+.coordinate-labels.left,
+.coordinate-labels.right {
+ flex-direction: column;
+ height: min(600px, calc(100vw - 120px));
+ justify-content: space-around;
+ margin: 0 10px;
+}
+
+.coordinate-label {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: calc(min(600px, calc(100vw - 120px)) / 15);
+ height: calc(min(600px, calc(100vw - 120px)) / 15);
+}
+
+.coordinate-labels.left .coordinate-label,
+.coordinate-labels.right .coordinate-label {
+ width: auto;
+ height: calc(min(600px, calc(100vw - 120px)) / 15);
+}
+
+.label-spacer {
+ width: 13px;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@media (max-width: 768px) {
+ .game-title {
+ font-size: 2rem;
+ }
+
+ .container {
+ padding: 30px 20px;
+ max-width: 100%;
+ }
+
+ .welcome-message {
+ font-size: 1rem;
+ }
+
+ .game-container {
+ min-height: 300px;
+ padding: 10px;
+ }
+
+ .board-grid {
+ width: min(500px, calc(100vw - 80px));
+ height: min(500px, calc(100vw - 80px));
+ }
+
+ .coordinate-labels.left,
+ .coordinate-labels.right {
+ height: min(500px, calc(100vw - 80px));
+ }
+
+ .coordinate-label {
+ width: calc(min(500px, calc(100vw - 80px)) / 15);
+ height: calc(min(500px, calc(100vw - 80px)) / 15);
+ font-size: 0.75rem;
+ }
+
+ .coordinate-labels.left .coordinate-label,
+ .coordinate-labels.right .coordinate-label {
+ height: calc(min(500px, calc(100vw - 80px)) / 15);
+ }
+
+ .square-label {
+ font-size: 0.6em;
+ }
+}
+
+.tile-rack-container {
+ margin-top: 30px;
+ background: white;
+ border-radius: 15px;
+ padding: 20px;
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
+}
+
+.tile-rack-wrapper {
+ text-align: center;
+}
+
+.rack-title {
+ color: #5a67d8;
+ margin-bottom: 15px;
+ font-size: 1.2rem;
+}
+
+.tile-rack {
+ display: flex;
+ justify-content: center;
+ gap: 10px;
+ min-height: 70px;
+ background: linear-gradient(135deg, #8B7355 0%, #6B5D54 100%);
+ border-radius: 10px;
+ padding: 15px;
+ box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.2);
+ margin-bottom: 20px;
+}
+
+.tile-slot {
+ width: 55px;
+ height: 55px;
+ background: rgba(255, 255, 255, 0.1);
+ border: 2px dashed rgba(255, 255, 255, 0.3);
+ border-radius: 5px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.tile {
+ width: 50px;
+ height: 50px;
+ background: #FFF8DC;
+ border: 2px solid #D2B48C;
+ border-radius: 5px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ cursor: grab;
+ font-weight: bold;
+ font-size: 24px;
+ color: #2C3E50;
+ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.2),
+ 0 1px 2px rgba(0, 0, 0, 0.1);
+ transition: transform 0.2s, box-shadow 0.2s;
+ user-select: none;
+}
+
+.tile:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3),
+ 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.tile.dragging {
+ opacity: 0.5;
+ cursor: grabbing;
+ transform: scale(1.1);
+ z-index: 1000;
+}
+
+.tile.dragging-active {
+ opacity: 0.7;
+ cursor: grabbing;
+ transform: scale(1.05);
+}
+
+.tile-letter {
+ font-size: 24px;
+ font-weight: bold;
+ text-align: center;
+}
+
+.tile-points {
+ position: absolute;
+ bottom: 2px;
+ right: 4px;
+ font-size: 10px;
+ font-weight: bold;
+ color: #5C4033;
+}
+
+.tile.blank .tile-letter {
+ color: transparent;
+}
+
+.tile.blank .tile-points {
+ display: none;
+}
+
+.board-square.occupied {
+ background-color: #E8DCC0;
+}
+
+.board-square.valid-drop {
+ background-color: #90EE90 !important;
+ animation: pulse 0.5s ease-in-out infinite;
+}
+
+.board-square.invalid-drop {
+ background-color: #FFB6C1 !important;
+}
+
+@keyframes pulse {
+ 0% {
+ transform: scale(1);
+ }
+ 50% {
+ transform: scale(1.05);
+ }
+ 100% {
+ transform: scale(1);
+ }
+}
+
+.game-controls {
+ display: flex;
+ justify-content: center;
+ gap: 15px;
+}
+
+.game-btn {
+ padding: 10px 20px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ border: none;
+ border-radius: 8px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: transform 0.2s, box-shadow 0.2s;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+.game-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
+}
+
+.game-btn:active {
+ transform: translateY(0);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.game-btn:disabled {
+ background: #CBD5E0;
+ cursor: not-allowed;
+ transform: none;
+}
+
+.board-square .tile {
+ width: 90%;
+ height: 90%;
+ margin: auto;
+}
+
+@media (max-width: 480px) {
+ .game-title {
+ font-size: 1.5rem;
+ letter-spacing: 1px;
+ }
+
+ .container {
+ padding: 20px 10px;
+ border-radius: 10px;
+ }
+
+ .welcome-message {
+ font-size: 0.9rem;
+ }
+
+ .game-container {
+ min-height: 250px;
+ padding: 5px;
+ }
+
+ .board-wrapper {
+ padding: 5px;
+ }
+
+ .board-grid {
+ width: calc(100vw - 60px);
+ height: calc(100vw - 60px);
+ max-width: 400px;
+ max-height: 400px;
+ }
+
+ .coordinate-labels.left,
+ .coordinate-labels.right {
+ height: calc(100vw - 60px);
+ max-height: 400px;
+ margin: 0 5px;
+ }
+
+ .coordinate-label {
+ width: calc((100vw - 60px) / 15);
+ height: calc((100vw - 60px) / 15);
+ max-width: calc(400px / 15);
+ max-height: calc(400px / 15);
+ font-size: 0.65rem;
+ }
+
+ .coordinate-labels.left .coordinate-label,
+ .coordinate-labels.right .coordinate-label {
+ width: auto;
+ height: calc((100vw - 60px) / 15);
+ max-height: calc(400px / 15);
+ }
+
+ .square-label {
+ font-size: 0.5em;
+ }
+
+ .board-square.center .square-label {
+ font-size: 0.9em;
+ }
+
+ .tile-rack {
+ gap: 5px;
+ padding: 10px;
+ }
+
+ .tile-slot {
+ width: 40px;
+ height: 40px;
+ }
+
+ .tile {
+ width: 36px;
+ height: 36px;
+ font-size: 18px;
+ }
+
+ .tile-letter {
+ font-size: 18px;
+ }
+
+ .tile-points {
+ font-size: 8px;
+ }
+
+ .game-controls {
+ flex-direction: column;
+ gap: 10px;
+ }
+
+ .game-btn {
+ font-size: 0.9rem;
+ padding: 8px 16px;
+ }
+}
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..e362a63
--- /dev/null
+++ b/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+ Scrabble Game
+
+
+
+
+
+
+
+
+ Welcome to Scrabble! Get ready to challenge your vocabulary and strategic thinking skills.
+
+
+
+
+
+
Game board will appear here
+
+
+
+
+
Your Tiles
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/js/game.js b/js/game.js
new file mode 100644
index 0000000..e1d8a6f
--- /dev/null
+++ b/js/game.js
@@ -0,0 +1,625 @@
+'use strict';
+
+const ScrabbleGame = {
+ config: {
+ boardSize: 15,
+ tilePoints: {
+ A: 1, B: 3, C: 3, D: 2, E: 1, F: 4, G: 2, H: 4,
+ I: 1, J: 8, K: 5, L: 1, M: 3, N: 1, O: 1, P: 3,
+ Q: 10, R: 1, S: 1, T: 1, U: 1, V: 4, W: 4, X: 8,
+ Y: 4, Z: 10, BLANK: 0
+ },
+ tileDistribution: {
+ A: 9, B: 2, C: 2, D: 4, E: 12, F: 2, G: 3, H: 2,
+ I: 9, J: 1, K: 1, L: 4, M: 2, N: 6, O: 8, P: 2,
+ Q: 1, R: 6, S: 4, T: 6, U: 4, V: 2, W: 2, X: 1,
+ Y: 2, Z: 1, BLANK: 2
+ },
+ maxPlayers: 4,
+ tilesPerPlayer: 7,
+ specialSquares: {
+ tripleWord: [
+ [0, 0], [0, 7], [0, 14],
+ [7, 0], [7, 14],
+ [14, 0], [14, 7], [14, 14]
+ ],
+ doubleWord: [
+ [1, 1], [2, 2], [3, 3], [4, 4],
+ [1, 13], [2, 12], [3, 11], [4, 10],
+ [13, 1], [12, 2], [11, 3], [10, 4],
+ [13, 13], [12, 12], [11, 11], [10, 10],
+ [7, 7]
+ ],
+ tripleLetter: [
+ [1, 5], [1, 9],
+ [5, 1], [5, 5], [5, 9], [5, 13],
+ [9, 1], [9, 5], [9, 9], [9, 13],
+ [13, 5], [13, 9]
+ ],
+ doubleLetter: [
+ [0, 3], [0, 11],
+ [2, 6], [2, 8],
+ [3, 0], [3, 7], [3, 14],
+ [6, 2], [6, 6], [6, 8], [6, 12],
+ [7, 3], [7, 11],
+ [8, 2], [8, 6], [8, 8], [8, 12],
+ [11, 0], [11, 7], [11, 14],
+ [12, 6], [12, 8],
+ [14, 3], [14, 11]
+ ],
+ center: [[7, 7]]
+ }
+ },
+
+ state: {
+ isInitialized: false,
+ currentPlayer: null,
+ players: [],
+ board: [],
+ tileBag: [],
+ playerRack: [],
+ tiles: {},
+ score: {},
+ draggedTile: null,
+ tileIdCounter: 0
+ },
+
+ init() {
+ console.log('Scrabble game initialized');
+
+ this.state.isInitialized = true;
+ this.createBoard();
+ this.initializeTileBag();
+ this.createTileRack();
+ this.setupEventListeners();
+ this.drawInitialTiles();
+ },
+
+ initializeTileBag() {
+ this.state.tileBag = [];
+ this.state.tiles = {};
+
+ for (const [letter, count] of Object.entries(this.config.tileDistribution)) {
+ for (let i = 0; i < count; i++) {
+ const tileId = `tile-${this.state.tileIdCounter++}`;
+ const tile = {
+ id: tileId,
+ letter: letter,
+ points: this.config.tilePoints[letter],
+ location: 'bag'
+ };
+ this.state.tileBag.push(tile);
+ this.state.tiles[tileId] = tile;
+ }
+ }
+
+ this.shuffleTileBag();
+ console.log(`Tile bag initialized with ${this.state.tileBag.length} tiles`);
+ },
+
+ shuffleTileBag() {
+ for (let i = this.state.tileBag.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [this.state.tileBag[i], this.state.tileBag[j]] =
+ [this.state.tileBag[j], this.state.tileBag[i]];
+ }
+ },
+
+ createTileRack() {
+ const rackElement = document.getElementById('tile-rack');
+ if (!rackElement) return;
+
+ rackElement.innerHTML = '';
+ for (let i = 0; i < this.config.tilesPerPlayer; i++) {
+ const slot = document.createElement('div');
+ slot.className = 'tile-slot';
+ slot.dataset.slotIndex = i;
+ rackElement.appendChild(slot);
+ }
+
+ this.state.playerRack = new Array(this.config.tilesPerPlayer).fill(null);
+ },
+
+ drawInitialTiles() {
+ const tilesToDraw = Math.min(this.config.tilesPerPlayer, this.state.tileBag.length);
+ for (let i = 0; i < tilesToDraw; i++) {
+ this.drawTileToRack(i);
+ }
+ },
+
+ drawTileToRack(slotIndex) {
+ if (this.state.tileBag.length === 0) {
+ console.log('No more tiles in bag');
+ return null;
+ }
+
+ if (this.state.playerRack[slotIndex] !== null) {
+ return null;
+ }
+
+ const tile = this.state.tileBag.pop();
+ tile.location = 'rack';
+ tile.rackIndex = slotIndex;
+ this.state.playerRack[slotIndex] = tile;
+
+ const tileElement = this.createTileElement(tile);
+ const slot = document.querySelector(`.tile-slot[data-slot-index="${slotIndex}"]`);
+ if (slot) {
+ slot.appendChild(tileElement);
+ }
+
+ return tile;
+ },
+
+ createTileElement(tile) {
+ const tileDiv = document.createElement('div');
+ tileDiv.className = 'tile';
+ tileDiv.id = tile.id;
+ tileDiv.draggable = true;
+
+ if (tile.letter === 'BLANK') {
+ tileDiv.classList.add('blank');
+ }
+
+ const letterSpan = document.createElement('span');
+ letterSpan.className = 'tile-letter';
+ letterSpan.textContent = tile.letter === 'BLANK' ? '' : tile.letter;
+
+ const pointsSpan = document.createElement('span');
+ pointsSpan.className = 'tile-points';
+ pointsSpan.textContent = tile.points;
+
+ tileDiv.appendChild(letterSpan);
+ tileDiv.appendChild(pointsSpan);
+
+ this.setupTileDragEvents(tileDiv, tile);
+
+ return tileDiv;
+ },
+
+ setupTileDragEvents(tileElement, tile) {
+ tileElement.addEventListener('dragstart', (e) => {
+ this.handleDragStart(e, tile);
+ });
+
+ tileElement.addEventListener('dragend', (e) => {
+ this.handleDragEnd(e, tile);
+ });
+
+ tileElement.addEventListener('touchstart', (e) => {
+ this.handleTouchStart(e, tile);
+ }, { passive: false });
+
+ tileElement.addEventListener('touchmove', (e) => {
+ this.handleTouchMove(e, tile);
+ }, { passive: false });
+
+ tileElement.addEventListener('touchend', (e) => {
+ this.handleTouchEnd(e, tile);
+ }, { passive: false });
+ },
+
+ handleDragStart(e, tile) {
+ this.state.draggedTile = tile;
+ e.target.classList.add('dragging');
+ e.dataTransfer.effectAllowed = 'move';
+ e.dataTransfer.setData('text/plain', tile.id);
+
+ console.log(`Started dragging tile: ${tile.letter} (${tile.points} points)`);
+ },
+
+ handleDragEnd(e, tile) {
+ e.target.classList.remove('dragging');
+ this.state.draggedTile = null;
+
+ document.querySelectorAll('.valid-drop, .invalid-drop').forEach(el => {
+ el.classList.remove('valid-drop', 'invalid-drop');
+ });
+ },
+
+ handleTouchStart(e, tile) {
+ e.preventDefault();
+ this.state.draggedTile = tile;
+ const touch = e.touches[0];
+
+ const tileElement = e.target.closest('.tile');
+ tileElement.classList.add('dragging-active');
+
+ tileElement.style.position = 'fixed';
+ tileElement.style.zIndex = '1000';
+ tileElement.style.left = `${touch.clientX - 25}px`;
+ tileElement.style.top = `${touch.clientY - 25}px`;
+ },
+
+ handleTouchMove(e, tile) {
+ e.preventDefault();
+ const touch = e.touches[0];
+ const tileElement = e.target.closest('.tile');
+
+ if (tileElement) {
+ tileElement.style.left = `${touch.clientX - 25}px`;
+ tileElement.style.top = `${touch.clientY - 25}px`;
+
+ const elementBelow = document.elementFromPoint(touch.clientX, touch.clientY);
+ if (elementBelow && elementBelow.classList.contains('board-square')) {
+ this.highlightDropTarget(elementBelow);
+ }
+ }
+ },
+
+ handleTouchEnd(e, tile) {
+ e.preventDefault();
+ const tileElement = e.target.closest('.tile');
+ const touch = e.changedTouches[0];
+
+ tileElement.classList.remove('dragging-active');
+ tileElement.style.position = '';
+ tileElement.style.zIndex = '';
+ tileElement.style.left = '';
+ tileElement.style.top = '';
+
+ const elementBelow = document.elementFromPoint(touch.clientX, touch.clientY);
+
+ if (elementBelow) {
+ if (elementBelow.classList.contains('board-square')) {
+ this.handleTileDrop(elementBelow, tile);
+ } else if (elementBelow.classList.contains('tile-slot')) {
+ this.returnTileToRack(tile, elementBelow);
+ }
+ }
+
+ this.state.draggedTile = null;
+ document.querySelectorAll('.valid-drop, .invalid-drop').forEach(el => {
+ el.classList.remove('valid-drop', 'invalid-drop');
+ });
+ },
+
+ highlightDropTarget(square) {
+ document.querySelectorAll('.valid-drop, .invalid-drop').forEach(el => {
+ el.classList.remove('valid-drop', 'invalid-drop');
+ });
+
+ const row = parseInt(square.dataset.row);
+ const col = parseInt(square.dataset.col);
+
+ if (this.canPlaceTile(row, col)) {
+ square.classList.add('valid-drop');
+ } else {
+ square.classList.add('invalid-drop');
+ }
+ },
+
+ canPlaceTile(row, col) {
+ return this.state.board[row][col].tile === null;
+ },
+
+ placeTileOnBoard(tile, row, col) {
+ if (!this.canPlaceTile(row, col)) {
+ return false;
+ }
+
+ if (tile.location === 'rack') {
+ this.state.playerRack[tile.rackIndex] = null;
+ delete tile.rackIndex;
+ } else if (tile.location === 'board') {
+ this.state.board[tile.boardRow][tile.boardCol].tile = null;
+ }
+
+ this.state.board[row][col].tile = tile;
+ tile.location = 'board';
+ tile.boardRow = row;
+ tile.boardCol = col;
+
+ const square = document.querySelector(`.board-square[data-row="${row}"][data-col="${col}"]`);
+ const tileElement = document.getElementById(tile.id);
+
+ if (square && tileElement) {
+ square.appendChild(tileElement);
+ square.classList.add('occupied');
+ }
+
+ console.log(`Placed ${tile.letter} at ${this.getCoordinateString(row, col)}`);
+ return true;
+ },
+
+ returnTileToRack(tile, slot) {
+ const slotIndex = parseInt(slot.dataset.slotIndex);
+
+ if (this.state.playerRack[slotIndex] !== null) {
+ return false;
+ }
+
+ if (tile.location === 'board') {
+ const square = document.querySelector(
+ `.board-square[data-row="${tile.boardRow}"][data-col="${tile.boardCol}"]`
+ );
+ if (square) {
+ square.classList.remove('occupied');
+ }
+ this.state.board[tile.boardRow][tile.boardCol].tile = null;
+ delete tile.boardRow;
+ delete tile.boardCol;
+ } else if (tile.location === 'rack' && tile.rackIndex !== slotIndex) {
+ this.state.playerRack[tile.rackIndex] = null;
+ }
+
+ tile.location = 'rack';
+ tile.rackIndex = slotIndex;
+ this.state.playerRack[slotIndex] = tile;
+
+ const tileElement = document.getElementById(tile.id);
+ if (slot && tileElement) {
+ slot.appendChild(tileElement);
+ }
+
+ return true;
+ },
+
+ handleTileDrop(square, tile) {
+ const row = parseInt(square.dataset.row);
+ const col = parseInt(square.dataset.col);
+
+ this.placeTileOnBoard(tile, row, col);
+ },
+
+ getTileAtPosition(row, col) {
+ if (row < 0 || row >= this.config.boardSize ||
+ col < 0 || col >= this.config.boardSize) {
+ return null;
+ }
+ return this.state.board[row][col].tile;
+ },
+
+ shuffleRackTiles() {
+ const rackTiles = this.state.playerRack.filter(tile => tile !== null);
+ const emptySlots = [];
+
+ for (let i = 0; i < this.config.tilesPerPlayer; i++) {
+ if (this.state.playerRack[i] === null) {
+ emptySlots.push(i);
+ }
+ this.state.playerRack[i] = null;
+ }
+
+ for (let i = rackTiles.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [rackTiles[i], rackTiles[j]] = [rackTiles[j], rackTiles[i]];
+ }
+
+ const availableSlots = [...Array(this.config.tilesPerPlayer).keys()];
+ rackTiles.forEach((tile, index) => {
+ const slotIndex = availableSlots[index];
+ this.state.playerRack[slotIndex] = tile;
+ tile.rackIndex = slotIndex;
+
+ const tileElement = document.getElementById(tile.id);
+ const slot = document.querySelector(`.tile-slot[data-slot-index="${slotIndex}"]`);
+ if (tileElement && slot) {
+ slot.appendChild(tileElement);
+ }
+ });
+
+ console.log('Rack tiles shuffled');
+ },
+
+ refillRack() {
+ let tilesDrawn = 0;
+ for (let i = 0; i < this.config.tilesPerPlayer; i++) {
+ if (this.state.playerRack[i] === null && this.state.tileBag.length > 0) {
+ this.drawTileToRack(i);
+ tilesDrawn++;
+ }
+ }
+ console.log(`Drew ${tilesDrawn} new tiles. ${this.state.tileBag.length} tiles remaining in bag.`);
+ },
+
+ setupEventListeners() {
+ const squares = document.querySelectorAll('.board-square');
+ squares.forEach(square => {
+ square.addEventListener('click', (e) => {
+ const row = parseInt(e.target.dataset.row);
+ const col = parseInt(e.target.dataset.col);
+ const coords = this.getCoordinateString(row, col);
+ console.log(`Square clicked: ${coords} (row: ${row}, col: ${col})`);
+ });
+
+ square.addEventListener('dragover', (e) => {
+ e.preventDefault();
+ if (this.state.draggedTile) {
+ this.highlightDropTarget(square);
+ }
+ });
+
+ square.addEventListener('drop', (e) => {
+ e.preventDefault();
+ if (this.state.draggedTile) {
+ this.handleTileDrop(square, this.state.draggedTile);
+ }
+ });
+
+ square.addEventListener('dragleave', (e) => {
+ square.classList.remove('valid-drop', 'invalid-drop');
+ });
+ });
+
+ const rackSlots = document.querySelectorAll('.tile-slot');
+ rackSlots.forEach(slot => {
+ slot.addEventListener('dragover', (e) => {
+ e.preventDefault();
+ });
+
+ slot.addEventListener('drop', (e) => {
+ e.preventDefault();
+ if (this.state.draggedTile) {
+ this.returnTileToRack(this.state.draggedTile, slot);
+ }
+ });
+ });
+
+ const drawBtn = document.getElementById('draw-tiles-btn');
+ if (drawBtn) {
+ drawBtn.addEventListener('click', () => {
+ this.refillRack();
+ });
+ }
+
+ const shuffleBtn = document.getElementById('shuffle-tiles-btn');
+ if (shuffleBtn) {
+ shuffleBtn.addEventListener('click', () => {
+ this.shuffleRackTiles();
+ });
+ }
+ },
+
+ getCoordinateString(row, col) {
+ const colLetter = String.fromCharCode(65 + col);
+ const rowNumber = row + 1;
+ return `${colLetter}${rowNumber}`;
+ },
+
+ getSquareType(row, col) {
+ const { specialSquares } = this.config;
+
+ if (row === 7 && col === 7) {
+ return 'center';
+ }
+
+ for (const [r, c] of specialSquares.tripleWord) {
+ if (r === row && c === col) return 'triple-word';
+ }
+
+ for (const [r, c] of specialSquares.doubleWord) {
+ if (r === row && c === col) return 'double-word';
+ }
+
+ for (const [r, c] of specialSquares.tripleLetter) {
+ if (r === row && c === col) return 'triple-letter';
+ }
+
+ for (const [r, c] of specialSquares.doubleLetter) {
+ if (r === row && c === col) return 'double-letter';
+ }
+
+ return 'regular';
+ },
+
+ getSquareLabel(type) {
+ const labels = {
+ 'triple-word': '3W',
+ 'double-word': '2W',
+ 'triple-letter': '3L',
+ 'double-letter': '2L',
+ 'center': '★',
+ 'regular': ''
+ };
+ return labels[type] || '';
+ },
+
+ createBoard() {
+ const gameContainer = document.getElementById('game-container');
+ if (!gameContainer) return;
+
+ gameContainer.innerHTML = '';
+
+ const boardWrapper = document.createElement('div');
+ boardWrapper.className = 'board-wrapper';
+
+ const boardGrid = document.createElement('div');
+ boardGrid.className = 'board-grid';
+ boardGrid.id = 'scrabble-board';
+
+ this.addCoordinateLabels(boardWrapper, 'top');
+
+ const boardWithSideLabels = document.createElement('div');
+ boardWithSideLabels.className = 'board-with-labels';
+
+ this.addCoordinateLabels(boardWithSideLabels, 'left');
+ boardWithSideLabels.appendChild(boardGrid);
+ this.addCoordinateLabels(boardWithSideLabels, 'right');
+
+ boardWrapper.appendChild(boardWithSideLabels);
+ this.addCoordinateLabels(boardWrapper, 'bottom');
+
+ this.state.board = [];
+ for (let row = 0; row < this.config.boardSize; row++) {
+ this.state.board[row] = [];
+ for (let col = 0; col < this.config.boardSize; col++) {
+ const square = document.createElement('div');
+ square.className = 'board-square';
+ square.dataset.row = row;
+ square.dataset.col = col;
+
+ const squareType = this.getSquareType(row, col);
+ square.classList.add(squareType);
+
+ const label = this.getSquareLabel(squareType);
+ if (label) {
+ const labelSpan = document.createElement('span');
+ labelSpan.className = 'square-label';
+ labelSpan.textContent = label;
+ square.appendChild(labelSpan);
+ }
+
+ boardGrid.appendChild(square);
+ this.state.board[row][col] = {
+ tile: null,
+ type: squareType
+ };
+ }
+ }
+
+ gameContainer.appendChild(boardWrapper);
+ console.log('15x15 Scrabble board created successfully');
+ },
+
+ addCoordinateLabels(container, position) {
+ const labelContainer = document.createElement('div');
+ labelContainer.className = `coordinate-labels ${position}`;
+
+ if (position === 'top' || position === 'bottom') {
+ labelContainer.innerHTML = '';
+ for (let i = 0; i < this.config.boardSize; i++) {
+ const label = document.createElement('div');
+ label.className = 'coordinate-label';
+ label.textContent = String.fromCharCode(65 + i);
+ labelContainer.appendChild(label);
+ }
+ labelContainer.innerHTML += '';
+ } else {
+ for (let i = 0; i < this.config.boardSize; i++) {
+ const label = document.createElement('div');
+ label.className = 'coordinate-label';
+ label.textContent = i + 1;
+ labelContainer.appendChild(label);
+ }
+ }
+
+ container.appendChild(labelContainer);
+ },
+
+ startGame() {
+ console.log('Start game method ready for implementation');
+ },
+
+ endTurn() {
+ console.log('End turn method ready for implementation');
+ },
+
+ calculateScore(word) {
+ console.log('Score calculation method ready for implementation');
+ return 0;
+ },
+
+ validateWord(word) {
+ console.log('Word validation method ready for implementation');
+ return false;
+ }
+};
+
+document.addEventListener('DOMContentLoaded', () => {
+ console.log('DOM Content Loaded - Initializing Scrabble Game');
+
+ ScrabbleGame.init();
+
+ window.ScrabbleGame = ScrabbleGame;
+});
\ No newline at end of file