← Oyuna dön

İpucu Motorunun Algoritması

Sarı kareyi gösteren motorun iç işleyişi

Yüz Yüze'de ipucu butonuna bastığında bir kare sarıya boyanır. Bu kare, oyun motorunun "şu an oynanabilecek en iyi hamle" olarak hesapladığı seçimdir. Peki motor bu kararı nasıl veriyor? Bu sayfa motorun iç işleyişini açıklar — meraklı oyuncular ve geliştiriciler için.

Tasarım Hedefleri

İpucu motoru üç hedefle tasarlandı:

Bu üç hedef birbiriyle çatışır: doğruluk arttıkça hız azalır, determinizm rastgele simülasyonu zorlaştırır. Çözüm hibrit bir yaklaşımdır.

Genel Mimari

Motor üç katmanlı çalışır:

[1] Aday hamleler bul Mevcut pozisyondan tüm geçerli hamleleri listele. 8 yön: 4 düz (3 kare) + 4 çapraz (2 kare). [2] Her aday için Monte Carlo değerlendirme O hamleyi varsay, kalan oyunu N kez simüle et. Her simülasyon Warnsdorff ile devam eder. Ortalama final skoru kaydet. [3] En yüksek ortalama skoru seç Eşitlikte tie-breaking kuralı uygula. Kazananı sarı kareye işaretle.

Monte Carlo Simülasyonu

Klasik Monte Carlo Tree Search (MCTS) Yüz Yüze için fazla pahalı. Bunun yerine basit bir flat Monte Carlo yaklaşımı kullanılır:

function evaluateMove(move, currentState) { let totalScore = 0; for (let i = 0; i < SIMULATIONS; i++) { const sim = cloneState(currentState); applyMove(sim, move); while (hasValidMoves(sim)) { const next = warnsdorffPick(sim); applyMove(sim, next); } totalScore += sim.placedCount; } return totalScore / SIMULATIONS; }

Yani: hamleyi yap, sonra "Warnsdorff bilgili rastgele oyuncu" oyunu bitirsin, kaç kareye ulaştığına bak. Bunu birkaç kez tekrarla, ortalamasını al.

İki Mod: Hint vs Quick

Motor iki farklı bağlamda çalışır:

Combo sistemi her hamleden sonra "AI ne yapardı?" sorusunu sorar. Eğer kullanıcının yaptığı hamle AI'ın quick mode tahminiyle aynıysa combo sayacı artar. Hızlı bir cevap gerektiği için 30 simülasyon yeterlidir; tam ipucu kalitesinde olmasa da combo amaçları için doğru çalışır.

Warnsdorff Devamı

Simülasyon sırasında "rastgele oyuncu" saf rastgele değil. Her hamlede Warnsdorff kuralı uygulanır:

function warnsdorffPick(state) { const moves = getValidMoves(state); let minDegree = Infinity; let candidates = []; for (const m of moves) { const deg = countValidMovesAfter(state, m); if (deg < minDegree) { minDegree = deg; candidates = [m]; } else if (deg === minDegree) { candidates.push(m); } } return candidates[randomInt(0, candidates.length)]; }

Saf rastgele oyuncu yerine Warnsdorff kullanmak iki etki yaratır: simülasyonların ortalaması daha gerçekçi olur (gerçek bir oyuncu da rastgele değil sezgisel oynar) ve gerekli simülasyon sayısı düşer (varyans azalır).

Seeded PRNG

Determinizm için motor rastgele sayı üreteci olarak Mulberry32 kullanır. Aynı pozisyonda her zaman aynı seed'le başlanır, bu da aynı sonucu garantiler:

function mulberry32(seed) { return function() { seed = (seed + 0x6D2B79F5) | 0; let t = seed; t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; }

Mulberry32 hızlı, basit ve ipucu motoru için yeterli kalitede istatistiksel özelliklere sahip. Kriptografik amaç için yetersiz ama bulmaca simülasyonu için ideal.

Günlük Bulmaca Üretimi

Aynı PRNG günlük bulmacayı üretir. Tohum tarih: YYYYMMDD. Bu, Türkiye saati 00:00'da değişir. Tohum sabit olduğu için dünyada herkes aynı bulmacayı oynar — coğrafi konumdan bağımsız.

const today = new Date(); const seed = today.getFullYear() * 10000 + (today.getMonth() + 1) * 100 + today.getDate(); const rng = mulberry32(seed); const startCell = Math.floor(rng() * 100);

Performans Optimizasyonu

Algoritma birkaç optimizasyon kullanır:

Pratikte 120 simülasyon mobil tarayıcıda 150ms civarı, masaüstünde 50ms altında biter.

Sınırlamalar ve Gelecek

Mevcut motor neredeyse her pozisyonda doğru cevabı verir ama bazı sınırları vardır:

Gelecek versiyonda kalan oyun 12 kareden az olduğunda saf backtracking'e geçilmesi planlanıyor. Bu hibrit, başlangıç-orta oyun simülasyonu + son oyun aramasıyla ipucu kalitesini ispatlanabilir optimum'a yaklaştırabilir.

Kaynak Kodu

Yüz Yüze tek dosyalık vanilla JavaScript uygulamasıdır. Motor ana index.html dosyasının içine inline gömülüdür — IIFE içinde, dış bağımlılık yok. Build adımı yok, derleme yok. Tarayıcıda doğrudan çalışır.

Bu seçim bilinçli: bağımlılıksız bir oyun yıllarca çalışmaya devam eder. NPM paketleri eskimez, framework'ler değişmez, sürüm uyumluluğu sorun olmaz.