Kanasta
Online

Karetní hra · Sólo projekt
Kanasta Online: dvě zelené karty rubem nahoru se zlatým diamantovým vzorem.

Kanasta Online je digitální verze klasické týmové karetní hry pro 4 hráče. Nápad vznikl na horách, když jsme zapomněli vzít fyzické karty a mě napadlo zkusit ji předělat do online podoby. Žádný login, jen kód místnosti, minimum kroků než se rozjede hra.

Postavila jsem backend, frontend i UI. Náročná část není render karet, ale kompletní pravidla kanasty napsaná od nuly: slohy, divoké karty, zamrzlý balík, minimum bodů pro první slohu závislé na skóre týmu, canasty, validace ukončení kola.

Role Sólo vývojářka
Typ Karetní hra · WIP
Období Od března 2026
Technologie
Node.js Express 4.18 Socket.io 4.7 Vanilla JavaScript Vanilla CSS (Grid) HTML In-memory state

Backend v Node.js + Express + Socket.io drží celý herní stav v paměti a v reálném čase ho posílá připojeným hráčům. Klient je vanilla JS bez frameworku.

Server posílá privátní stav pro každého hráče, ne globální broadcast. Soupeři vidí jen počet karet v ruce a vyložené slohy, ne konkrétní karty. Herní stav je authoritative na serveru, takže hráč nemůže cheatovat lokální manipulací s DOM.

Frontend bez frameworku, CSS Grid layout.

  • Rozložení stolu: spoluhráč naproti, soupeři po stranách (rotace o 90°), moje ruka dole. Hráč okamžitě vidí, kdo je v jeho týmu.
  • Sestavovač sloh: multi-select karty, sestav víc sloh před submitem, pošli všechno naráz.
  • Živé status badges: KANASTA a ČISTÁ KANASTA na dokončených slohách, ZAMRZLÝ na balíku, dynamický „Minimum bodů první slohy" podle aktuálního skóre týmu.
  • Inline validation: pokus o invalid tah (málo karet, přebytek divokých) ukáže error zprávu přímo v UI, ne v alert popupu.
Rozehraná partie 2v2 (Tým A vs Tým B): dvě slohy označené KANASTA (žluté badge), dobírací balík uprostřed s odhazovacím balíkem vedle, akční lišta dole s možnostmi tahu.

Čtyři kritické body, které mi u kanasty daly nejvíc zabrat, a které by se daly použít i v jiných real-time herních systémech.

1. Zamrzlý balík a vícekrokové vykládání

Problém: Kanasta povolí vzít celý odhazovací balík, pokud z něj umíš vyložit slohu s pomocí vrchní karty. Když je balík zamrzlý, hráč musí mít v ruce 2 přirozené karty stejné hodnoty jako vrchní karta. A pak z převzatého balíku často skládá víc sloh najednou.

Řešení: takeDiscardPileWithMelds() přijme víc sloh naráz a všechny ověří před tím, než něco změní. Kontroluje, že má hráč karty v ruce, každá sloha je legální, sedí požadavek zamrzlého balíku a první sloha týmu má dost bodů. Buď projdou všechny kontroly, nebo se nic nezmění.

2. Minimum bodů pro první slohu podle týmového skóre

Problém: Bodový práh pro první slohu závisí na aktuálním skóre týmu: záporné skóre → 15 b., do 1 500 → 50 b., do 3 000 → 90 b., do 5 000 → 120 b., nad 5 000 → 150 b. Nelze mít fixní hodnotu.

Řešení: Práh se počítá pokaždé znovu z aktuálního skóre týmu. Volá se všude, kde tým může vyložit první slohu, i při každé aktualizaci UI pro hráče.

3. Privátní stav pro každého hráče přes Socket.io

Problém: Server posílá plný stav, ale klient nemá vidět ruce soupeřů.

Řešení: getStateForPlayer(playerId) projde stav před každým odesláním klientovi a zamaskuje cizí ruce, místo karet posílá jen jejich počet.

4. Validace ukončení kola a bodování

Problém: Hráč může ukončit kolo jen pokud jeho tým má alespoň jednu kanastu. Bodování musí spočítat body za slohy, odečíst penalizaci za karty v ruce, přičíst bonusy za červené trojky a kanasty, a rozhodnout o konci hry při 10 000.

Řešení: calculateRoundScores(goOutTeam) v jednom průchodu spočítá body pro oba týmy naráz. Klíčová nuance: pokud tým nemá kanastu, jeho slohy se počítají jako záporné body (a bonus 800 za všechny 4 červené trojky se stane penalizací -800). Tým skončí kolo v mínusu i s kartami na stole. Až pak porovnání s 10 000 a rozhodnutí o konci hry nebo pokračování dalším kolem.

Prototyp zatím běží lokálně, ale funguje kompletní 2v2 hra s pravidly kanasty (108 karet, 16 socket eventů, hra do 10 000 bodů) včetně rejoinu po výpadku spojení.

Chybí do plné verze: grafika (karty i UI jsou zatím minimalistické), doladění pravidel v edge cases, oprava zbývajících bugů.