An interactive tic-tac-toe game built with React Native, TypeScript and Expo, featuring 8 languages support and intelligent AI.
- ✅ Intuitive and responsive interface
- ✅ Support for 8 languages (i18n)
- ✅ AI with 3 difficulty levels
- ✅ Player vs Player and Player vs AI modes
- ✅ Persistent scoring system
- ✅ Visual highlight of winning cells
- ✅ Automatic win and draw detection
- ✅ Automatic player turn switching
- ✅ Locally saved language preference
- ✅ TypeScript for type safety
- ✅ Modular componentization
- 🇧🇷 Português (pt-BR)
- 🇺🇸 English (en-US)
- 🇪🇸 Español (es-ES)
- 🇫🇷 Français (fr-FR)
- 🇩🇪 Deutsch (de-DE)
- 🇮🇹 Italiano (it-IT)
- 🇯🇵 日本語 (ja-JP)
- 🇨🇳 中文 (zh-CN)
- React Native - Mobile development framework
- TypeScript - Static typing
- Expo - Development platform
- React Hooks - State management
- Context API - Global language management
- AsyncStorage - Preferences persistence
- Minimax Algorithm - Advanced AI for hard mode
jogoDaVelha/
├── components/ # Reusable components
│ ├── Board.tsx # Game board
│ ├── Cell.tsx # Individual cell
│ ├── LanguageSelector.tsx # Language selector
│ └── GameModeSettings.tsx # Mode and difficulty settings
├── contexts/ # React contexts
│ └── LanguageContext.tsx # Language management
├── locales/ # Translation files
│ ├── pt-BR.ts # Portuguese (Brazil)
│ ├── en-US.ts # English
│ ├── es-ES.ts # Spanish
│ ├── fr-FR.ts # French
│ ├── de-DE.ts # German
│ ├── it-IT.ts # Italian
│ ├── ja-JP.ts # Japanese
│ ├── zh-CN.ts # Chinese (Simplified)
│ └── index.ts # Export and configuration
├── types/ # TypeScript type definitions
│ └── index.ts # Game and language types
├── utils/ # Helper functions
│ ├── gameLogic.ts # Game logic
│ └── aiLogic.ts # AI algorithms
├── .github/ # GitHub configurations
│ └── copilot-instructions.md
├── App.tsx # Main component
└── package.json # Project dependencies
- Node.js (v16 or higher)
- npm or yarn
- Expo Go app on your mobile device (optional)
- Clone the repository:
git clone <repository-url>
cd jogoDaVelha- Install dependencies:
npm installnpm startnpm run androidnpm run iosnpm run web- The game starts with player X
- Tap the 👥 icon in the top left corner to switch between modes
- Tap an empty cell to make your move
- Players alternate between X and O
- Tap the mode icon (top left corner)
- Select "Player vs AI"
- Choose the difficulty level:
- 😊 Easy - AI makes random moves (great for beginners)
- 🤔 Medium - AI blocks wins and tries to win (challenging)
- 😈 Hard - AI uses Minimax algorithm (nearly impossible to beat!)
- You always play as X (first)
- AI plays as O
- Tap the 🌐 icon to change language
- Use "New Game" to start a new game
- Use "Reset Scores" to reset the scores
- The first to complete a row, column, or diagonal wins
- If all cells are filled without a winner, it's a draw
Manages the 3x3 board and renders game cells.
Represents an individual board cell with:
- Different visual states for X and O
- Highlight for winning cells
- Disabled after move
Displays the score of both players and draws, translated in the selected language.
Modal for language selection with:
- List of 8 available languages
- Flags for visual identification
- Current language indicator
- Preference persistence
Modal for game configuration with:
- Selection between PvP and PvAI modes
- AI difficulty level choice
- Intuitive interface with emojis
- Visual confirmation of selections
Strategy: Completely random moves
- Randomly chooses from available positions
- Does not consider strategy or blocks
- Ideal for beginners and children
- Player win rate: ~80-90%
// Selects a random available position
export const easyAI = (board: Board): number => {
const availableMoves = board
.map((cell, index) => (cell === null ? index : null))
.filter((index) => index !== null);
return availableMoves[Math.floor(Math.random() * availableMoves.length)];
};Strategy: Defensive and opportunistic play
- Priority 1: Win if there's an opportunity
- Priority 2: Block opponent's imminent victory
- Priority 3: Occupy center if available
- Priority 4: Occupy strategic corners
- Priority 5: Any available position
- Player win rate: ~40-60%
export const mediumAI = (board: Board, aiPlayer: Player): number => {
// 1. Try to win
const winningMove = findWinningMove(board, aiPlayer);
if (winningMove !== -1) return winningMove;
// 2. Block opponent
const blockingMove = findWinningMove(board, opponent);
if (blockingMove !== -1) return blockingMove;
// 3. Center > Corners > Edges
// ...
};Strategy: Minimax Algorithm (Perfect Play)
- Implements the classic Minimax algorithm
- Evaluates all future possibilities
- Always chooses the best possible move
- Impossible to beat (only draw or defeat)
- Adaptive depth for optimization
- Player win rate: ~0-5% (only by AI error or perfect play)
// Minimax: recursively evaluates all possible moves
const minimax = (
board: Board,
depth: number,
isMaximizing: boolean,
aiPlayer: Player,
opponent: Player
): number => {
// Checks for terminal conditions (win, loss, draw)
// Returns score adjusted by depth
// Maximizes for AI, minimizes for opponent
// Returns best move found
};- Smart delay: AI "thinks" for 300ms-800ms for better UX
- Visual indicator: Shows "AI thinking..." during processing
- Interaction blocking: Prevents moves during AI's turn
- Performance optimization: Minimax with depth pruning
- Instant moves: Even in hard mode, response < 1s
The Minimax algorithm is a game theory technique that:
- Simulates all possible moves until the end of the game
- Assigns scores:
- +10 for AI victory (adjusted by depth)
- -10 for opponent victory (adjusted by depth)
- 0 for draw
- Assumes perfect play from both sides
- Chooses the path that maximizes AI's score
Why is it unbeatable?
- Explores ALL ~362,880 game possibilities
- Always chooses the move that leads to the best possible outcome
- In tic-tac-toe, with perfect play, always ends in a draw
The game uses a robust internationalization system based on:
- Context API - Global language management
- AsyncStorage - User preference persistence
- Modular translations - Separate file for each language
- Create a file in
/locales(e.g.,locales/ru-RU.ts):
export default {
title: 'Крестики-нолики',
playerXWins: 'Игрок X выиграл!',
playerOWins: 'Игрок O выиграл!',
draw: 'Ничья!',
playerTurn: 'Ход игрока',
newGame: 'Новая игра',
resetScores: 'Сбросить счет',
draws: 'Ничьи',
language: 'Язык',
selectLanguage: 'Выбрать язык',
};- Import and add in
locales/index.ts:
- Never use hardcoded text - always use translation system
- Use
useLanguage()hook to access translations
import ruRU from './ru-RU';
export const translations = {
// ... other languages
'ru-RU': ruRU,
};
export const AVAILABLE_LANGUAGES = [
// ... other languages
{ code: 'ru-RU', name: 'Русский', flag: '🇷🇺' },
];- Update the type in
types/index.ts:
export type SupportedLanguage = 'pt-BR' | 'en-US' | ... | 'ru-RU';import { useLanguage } from './contexts/LanguageContext';
function MyComponent() {
const { t, language, setLanguage } = useLanguage();
return (
<Text>{t.title}</Text>
);
}checkWinner()- Checks if there's a winnercheckDraw()- Checks if the game ended in a drawcreateEmptyBoard()- Creates a new empty boardtogglePlayer()- Toggles between players
Você pode personalizar cores e estilos editando os arquivos:
- App.tsx - Estilos principais
- components/Cell.tsx - Estilos das células
- components/ScoreBoard.tsx - Estilos do placar
- Componentes funcionais com Hooks
- Nomes de componentes em PascalCase
- Funções auxiliares em camelCase
- Todas as props e estados tipados
- Interfaces para tipos customizados
- ComeCustomization
You can customize colors and styles by editing the files:
- App.tsx - Main styles
- components/Cell.tsx - Cell styles
- components/ScoreBoard.tsx - Scoreboard styles
- Functional components with Hooks
- Component names in PascalCase
- Helper functions in camelCase
- All props and states typed
- Interfaces for custom types
- Comments for documentation
Contributions are welcome! Feel free to:
- Fork the project
- Create a branch for your feature
- Commit your changes
- Push to the branch
- Open a Pull Request
This project is open source and available under the MIT License.
Built with ❤️ using React Native and Expo
**Have fun playing





