TiFpuzzle2

TiFpuzzle

A fun and interactive puzzle game for iPhone and iPad

Features

How to Play

  1. Launch: App starts with a 3x3 puzzle grid at the top and scattered pieces at the bottom
  2. Load photo (optional):
    • Tap the camera icon to take a photo directly with your device camera
    • Or tap “Load photo” button to choose any image from your photo library
  3. Switch difficulty: Tap the title (e.g., “TiFpuzzle 3x3”) to toggle between 3x3 and 4x4 modes
  4. Drag pieces: Drag puzzle pieces from the bottom area to their correct positions in the top grid
  5. Snap to grid: When a piece is dropped close to its correct position, it automatically snaps into place
  6. Complete puzzle: Solve all pieces to see the completion message
  7. Unlock Auto Solve: Tap the grid corners in this order to reveal the Auto Solve button:
    • Upper-left corner → Lower-left corner → Lower-right corner → Upper-right corner
    • (Tap same sequence again to hide the button)
  8. Auto Solve: Press the green “Auto Solve” button to watch the puzzle solve itself
  9. Speed up: During auto-solve, tap the title to accelerate animation from 1.2s to 0.3s per piece
  10. Stop: Press the red “Stop Auto Solve” button to pause automatic solving
  11. Play Again: After completion, press “Play Again” to shuffle and start over

Requirements

Setup

  1. Clone the repository https://github.com/TiFcode/TiFpuzzle2
  2. Add your puzzle image to Assets.xcassets with the name “puzzle”
  3. Open TiFpuzzle2.xcodeproj in Xcode
  4. Build and run on simulator or device

Technical Details

Design Pattern: MVVM (Model-View-ViewModel)

The app follows a strict separation of concerns:

┌─────────────────────────────────────────┐
│ Models/                                  │
│ - PuzzlePiece.swift (Data model)        │
└─────────────────────────────────────────┘
                   ↓
┌─────────────────────────────────────────┐
│ ViewModels/                              │
│ - PuzzleViewModel.swift (Business logic) │
└─────────────────────────────────────────┘
                   ↓
┌─────────────────────────────────────────┐
│ Views/                                   │
│ - ContentView.swift (Coordinator)        │
│ - MenuBarView.swift                      │
│ - PuzzleGridView.swift                   │
│ - WorkingAreaView.swift                  │
│ - PuzzlePieceView.swift                  │
│ - ImagePicker.swift                      │
└─────────────────────────────────────────┘
                   ↓
┌─────────────────────────────────────────┐
│ Constants.swift (Configuration)          │
└─────────────────────────────────────────┘

Application Structure

TiFpuzzle is built using SwiftUI with a clean, zone-based layout that separates different functional areas:

Zone-Based Layout

The UI is divided into three main zones:

  1. Menu Bar (Top)
    • Camera button
    • Photo picker button
    • Title (tap to toggle grid size)
    • Auto-solve button (conditional)
    • Help/Privacy buttons
  2. Upper Zone - Puzzle Grid Area
    • Fixed-size grid where pieces snap into correct positions
    • Tap detection for secret sequence
    • White background with shadow
  3. Lower Zone - Working Area
    • Randomly scattered puzzle pieces (initial placement)
    • All pieces are draggable within boundaries
    • Pieces can be dragged up to the grid and dropped
    • Boundary enforcement (top: menu bar, bottom: 1cm margin)

Details For Each Zone

Upper Zone - Puzzle Grid Area

Lower Zone - Working Area

Menu Bar

Core Components

PuzzlePiece Model

struct PuzzlePiece: Identifiable {
    let id: Int              // Unique identifier
    let row: Int             // Correct row position (0-based)
    let col: Int             // Correct column position (0-based)
    var position: CGPoint    // Current position in working area
    var rotation: Double     // Rotation angle (always 0 in current version)
    var isPlaced: Bool       // Whether piece is in correct grid position
    var zIndex: Double       // Layering order for overlapping pieces
}

PuzzlePieceView

ImagePicker (UIViewControllerRepresentable)

State Management

The app uses SwiftUI’s @State property wrappers for reactive state:

Puzzle State:

Animation State:

Geometry Tracking:

Secret Feature State:

Image Selection State:

Coordinate Space Management

The app uses three coordinate systems:

  1. Global Coordinates - Absolute screen positions tracked via GeometryReader.frame(in: .global)
  2. Grid Coordinates - Relative positions within the upper grid zone
  3. Lower Area Coordinates - Relative positions within the lower working zone

Drop Detection Flow:

  1. Drag gesture provides location in lower area coordinates
  2. Convert to global: globalY = localY + lowerAreaFrame.minY
  3. Convert to grid: gridY = globalY - gridFrame.minY
  4. Calculate target cell: targetRow = Int(gridY / cellSize)
  5. Check correctness: targetRow == piece.row && targetCol == piece.col
  6. Calculate snap distance from cell center
  7. If distance ≤ 60 points, snap piece into place

Boundary Enforcement

Drag Constraints:

Initialization & Shuffle:

Secret Features

Auto Solve Unlock Sequence:

Animation Speed Control:

Orientation Handling

Technical Details

Privacy

For information about how this app handles your data, please see our Privacy Policy.

License

The source code of the project “TiFpuzzle” located at https://github.com/TiFcode/TiFpuzzle2 is licensed under the Apache License 2.0 - see the https://tifcode.github.io/TiFpuzzle2/LICENSE.html file for details.

Attribution Requirements

If you use this code in your project, you MUST:

See the NOTICE.html file for complete attribution requirements.