advanced-games-library
Version:
Advanced Gaming Library for React Native - Four Complete Games with iOS Compatibility Fixes
478 lines (426 loc) • 12.7 kB
JavaScript
/**
* SimplePuzzleGameComponent - JavaScript Fallback Version
* A React Native component for the sliding puzzle game
*
* @version 1.0.0
* @author Games Studio
*/
import React from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
Alert,
SafeAreaView,
StatusBar,
Dimensions,
} from 'react-native';
const { width: screenWidth } = Dimensions.get('window');
// Fallback SimplePuzzleGameComponent
const SimplePuzzleGameComponent = ({
gridSize = 3,
difficulty = 'easy',
onGameComplete,
onGameStart,
onMove,
showMenu = true,
autoStart = false,
title = '🧩 Puzzle Game',
subtitle = 'Welcome to the exciting puzzle game!',
showStats = true,
enableHints = true,
enableReset = true,
theme = {
primaryColor: '#3498db',
secondaryColor: '#2ecc71',
backgroundColor: '#f8f9fa',
textColor: '#2c3e50'
}
}) => {
const [currentScreen, setCurrentScreen] = React.useState(showMenu ? 'menu' : 'game');
const [gameState, setGameState] = React.useState({
tiles: [],
moves: 0,
time: 0,
score: 0,
isComplete: false,
startTime: null
});
const [isLoading, setIsLoading] = React.useState(false);
// Helper functions
const formatTime = (seconds) => {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins}:${secs.toString().padStart(2, '0')}`;
};
const formatScore = (score) => {
return score.toLocaleString();
};
const createInitialTiles = (size) => {
const tiles = [];
const totalTiles = size * size;
for (let i = 0; i < totalTiles - 1; i++) {
tiles.push({
id: `tile-${i}`,
value: i + 1,
position: { row: Math.floor(i / size), col: i % size },
correctPosition: { row: Math.floor(i / size), col: i % size },
isEmpty: false
});
}
// Add empty tile
tiles.push({
id: 'empty',
value: '',
position: { row: size - 1, col: size - 1 },
correctPosition: { row: size - 1, col: size - 1 },
isEmpty: true
});
return tiles;
};
const shuffleTiles = (tiles) => {
const shuffled = [...tiles];
const emptyTile = shuffled.find(tile => tile.isEmpty);
let moves = 100;
while (moves > 0) {
const neighbors = getNeighbors(emptyTile.position, gridSize);
const randomNeighbor = neighbors[Math.floor(Math.random() * neighbors.length)];
swapTiles(shuffled, emptyTile.position, randomNeighbor);
moves--;
}
return shuffled;
};
const getNeighbors = (position, size) => {
const neighbors = [];
const { row, col } = position;
if (row > 0) neighbors.push({ row: row - 1, col });
if (row < size - 1) neighbors.push({ row: row + 1, col });
if (col > 0) neighbors.push({ row, col: col - 1 });
if (col < size - 1) neighbors.push({ row, col: col + 1 });
return neighbors;
};
const swapTiles = (tiles, pos1, pos2) => {
const tile1 = tiles.find(t => t.position.row === pos1.row && t.position.col === pos1.col);
const tile2 = tiles.find(t => t.position.row === pos2.row && t.position.col === pos2.col);
if (tile1 && tile2) {
const tempPos = { ...tile1.position };
tile1.position = { ...tile2.position };
tile2.position = tempPos;
}
};
const startNewGame = (size = gridSize) => {
setIsLoading(true);
setTimeout(() => {
const tiles = createInitialTiles(size);
const shuffledTiles = shuffleTiles(tiles);
setGameState({
tiles: shuffledTiles,
moves: 0,
time: 0,
score: 0,
isComplete: false,
startTime: Date.now()
});
setCurrentScreen('game');
setIsLoading(false);
onGameStart?.();
}, 500);
};
const moveTile = (position) => {
if (gameState.isComplete) return false;
const emptyTile = gameState.tiles.find(tile => tile.isEmpty);
const neighbors = getNeighbors(emptyTile.position, gridSize);
const canMove = neighbors.some(n => n.row === position.row && n.col === position.col);
if (canMove) {
const newTiles = [...gameState.tiles];
swapTiles(newTiles, emptyTile.position, position);
const newMoves = gameState.moves + 1;
const newScore = Math.max(0, 1000 - newMoves * 10);
const newGameState = {
...gameState,
tiles: newTiles,
moves: newMoves,
score: newScore,
time: Date.now() - gameState.startTime
};
setGameState(newGameState);
onMove?.({ position, moves: newMoves });
if (isPuzzleSolved(newTiles)) {
const finalState = {
...newGameState,
isComplete: true
};
setGameState(finalState);
onGameComplete?.(finalState);
}
return true;
}
return false;
};
const isPuzzleSolved = (tiles) => {
return tiles.every(tile =>
tile.position.row === tile.correctPosition.row &&
tile.position.col === tile.correctPosition.col
);
};
const resetGame = () => {
startNewGame(gridSize);
};
const renderTile = (tile, index) => {
if (tile.isEmpty) {
return (
<View
key={tile.id}
style={[
styles.tile,
styles.emptyTile,
{
width: (screenWidth - 80) / gridSize,
height: (screenWidth - 80) / gridSize,
}
]}
/>
);
}
return (
<TouchableOpacity
key={tile.id}
style={[
styles.tile,
{
width: (screenWidth - 80) / gridSize,
height: (screenWidth - 80) / gridSize,
backgroundColor: theme.primaryColor,
}
]}
onPress={() => moveTile(tile.position)}
activeOpacity={0.7}
>
<Text style={[styles.tileText, { color: 'white' }]}>
{tile.value}
</Text>
</TouchableOpacity>
);
};
const renderPuzzleBoard = () => {
const boardSize = gridSize;
const rows = [];
for (let row = 0; row < boardSize; row++) {
const rowTiles = [];
for (let col = 0; col < boardSize; col++) {
const tile = gameState.tiles.find(t =>
t.position.row === row && t.position.col === col
);
if (tile) {
rowTiles.push(renderTile(tile, row * boardSize + col));
}
}
rows.push(
<View key={row} style={styles.row}>
{rowTiles}
</View>
);
}
return <View style={styles.board}>{rows}</View>;
};
const renderMenuScreen = () => (
<SafeAreaView style={[styles.container, { backgroundColor: theme.backgroundColor }]}>
<StatusBar barStyle="dark-content" backgroundColor={theme.backgroundColor} />
<View style={styles.menuContent}>
<Text style={[styles.title, { color: theme.textColor }]}>{title}</Text>
<Text style={[styles.subtitle, { color: theme.textColor }]}>{subtitle}</Text>
<View style={styles.menuButtons}>
<TouchableOpacity
style={[styles.menuButton, { backgroundColor: theme.primaryColor }]}
onPress={() => startNewGame(3)}
>
<Text style={styles.menuButtonText}>3x3 Grid</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.menuButton, { backgroundColor: theme.primaryColor }]}
onPress={() => startNewGame(4)}
>
<Text style={styles.menuButtonText}>4x4 Grid</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.menuButton, { backgroundColor: theme.primaryColor }]}
onPress={() => startNewGame(5)}
>
<Text style={styles.menuButtonText}>5x5 Grid</Text>
</TouchableOpacity>
</View>
</View>
</SafeAreaView>
);
const renderGameScreen = () => (
<SafeAreaView style={[styles.container, { backgroundColor: theme.backgroundColor }]}>
<StatusBar barStyle="dark-content" backgroundColor={theme.backgroundColor} />
<View style={styles.gameHeader}>
<Text style={[styles.gameTitle, { color: theme.textColor }]}>Puzzle Game</Text>
{showStats && (
<View style={styles.stats}>
<Text style={[styles.statText, { color: theme.textColor }]}>
Moves: {gameState.moves}
</Text>
<Text style={[styles.statText, { color: theme.textColor }]}>
Time: {formatTime(Math.floor(gameState.time / 1000))}
</Text>
<Text style={[styles.statText, { color: theme.textColor }]}>
Score: {formatScore(gameState.score)}
</Text>
</View>
)}
</View>
<View style={styles.gameContent}>
{renderPuzzleBoard()}
</View>
<View style={styles.gameControls}>
{enableReset && (
<TouchableOpacity
style={[styles.controlButton, { backgroundColor: theme.secondaryColor }]}
onPress={resetGame}
>
<Text style={styles.controlButtonText}>Reset</Text>
</TouchableOpacity>
)}
{showMenu && (
<TouchableOpacity
style={[styles.controlButton, { backgroundColor: theme.primaryColor }]}
onPress={() => setCurrentScreen('menu')}
>
<Text style={styles.controlButtonText}>Menu</Text>
</TouchableOpacity>
)}
</View>
</SafeAreaView>
);
if (isLoading) {
return (
<SafeAreaView style={[styles.container, { backgroundColor: theme.backgroundColor }]}>
<View style={styles.loadingContainer}>
<Text style={[styles.loadingText, { color: theme.textColor }]}>Loading...</Text>
</View>
</SafeAreaView>
);
}
return currentScreen === 'menu' ? renderMenuScreen() : renderGameScreen();
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
menuContent: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
title: {
fontSize: 32,
fontWeight: 'bold',
marginBottom: 10,
textAlign: 'center',
},
subtitle: {
fontSize: 16,
textAlign: 'center',
marginBottom: 40,
},
menuButtons: {
width: '100%',
maxWidth: 300,
},
menuButton: {
padding: 15,
borderRadius: 10,
marginBottom: 15,
alignItems: 'center',
},
menuButtonText: {
color: 'white',
fontSize: 18,
fontWeight: 'bold',
},
gameHeader: {
padding: 20,
alignItems: 'center',
},
gameTitle: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 10,
},
stats: {
flexDirection: 'row',
justifyContent: 'space-around',
width: '100%',
},
statText: {
fontSize: 14,
fontWeight: 'bold',
},
gameContent: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
board: {
borderWidth: 2,
borderColor: '#ddd',
borderRadius: 10,
padding: 10,
backgroundColor: 'white',
},
row: {
flexDirection: 'row',
},
tile: {
justifyContent: 'center',
alignItems: 'center',
margin: 2,
borderRadius: 8,
elevation: 3,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
},
emptyTile: {
backgroundColor: 'transparent',
elevation: 0,
shadowOpacity: 0,
},
tileText: {
fontSize: 18,
fontWeight: 'bold',
},
gameControls: {
flexDirection: 'row',
justifyContent: 'space-around',
padding: 20,
},
controlButton: {
padding: 15,
borderRadius: 10,
minWidth: 100,
alignItems: 'center',
},
controlButtonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
fontSize: 18,
fontWeight: 'bold',
},
});
export { SimplePuzzleGameComponent };
export default SimplePuzzleGameComponent;