Katılım
17 Aralık 2023
Mesajlar
7.699
Makaleler
2
Çözümler
35
Beğeniler
6.649
Yer
Denizli
PowerShell ile çalışıyor. Yahtzee adlı oyun için yaptırttım. Bayağı iyi ve hızlı çalışıyor.
Yorumlarınızı ve iyileştirmelerinizi bekliyorum.
Kod:
$ErrorActionPreference = "Stop"
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

# -------------------- SKOR VE ANALİZ FONKSİYONLARI --------------------
function Get-Counts([int[]]$dice) {
    $c = @(0,0,0,0,0,0,0)
    foreach ($d in $dice) { if ($d -ge 1 -and $d -le 6) { $c[$d]++ } }
    return $c
}

function Score-Categories([int[]]$dice) {
    $counts = Get-Counts $dice
    $sum = ($dice | Measure-Object -Sum).Sum
    $scores = @{}

    # Upper 1-6
    for ($f=1; $f -le 6; $f++) { $scores["Upper$f"] = $f * $counts[$f] }

    # 3 & 4 of a Kind
    $has3 = ($counts | Where-Object { $_ -ge 3 }).Count -gt 0
    $has4 = ($counts | Where-Object { $_ -ge 4 }).Count -gt 0
    $scores["3oak"] = if ($has3) { $sum } else { 0 }
    $scores["4oak"] = if ($has4) { $sum } else { 0 }

    # Full House & Yahtzee
    $yahtzee = $false; $has3exact = $false; $has2exact = $false
    for ($i=1; $i -le 6; $i++) {
        if ($counts[$i] -eq 5) { $yahtzee = $true }
        if ($counts[$i] -eq 3) { $has3exact = $true }
        if ($counts[$i] -eq 2) { $has2exact = $true }
    }
    $scores["FH"] = if ($yahtzee -or ($has3exact -and $has2exact)) { 25 } else { 0 }
    $scores["Y"]  = if ($yahtzee) { 50 } else { 0 }

    # Straights
    $unique = $dice | Sort-Object -Unique
    $set = @{}
    foreach ($u in $unique) { $set[$u] = $true }
    $large = ($set.ContainsKey(1) -and $set.ContainsKey(2) -and $set.ContainsKey(3) -and $set.ContainsKey(4) -and $set.ContainsKey(5)) -or
             ($set.ContainsKey(2) -and $set.ContainsKey(3) -and $set.ContainsKey(4) -and $set.ContainsKey(5) -and $set.ContainsKey(6))
    $small = $false
    foreach ($seq in @(@(1,2,3,4),@(2,3,4,5),@(3,4,5,6))) {
        $ok = $true
        foreach ($n in $seq) { if (-not $set.ContainsKey($n)) { $ok = $false; break } }
        if ($ok) { $small = $true; break }
    }
    $scores["SS"]     = if ($small) { 30 } else { 0 }
    $scores["LS"]     = if ($large) { 40 } else { 0 }
    $scores["Chance"] = $sum

    return $scores
}

function Best-Score([int[]]$dice) {
    $s = Score-Categories $dice
    $best = 0; $name = ""
    foreach ($k in $s.Keys) {
        if ($s[$k] -gt $best) { $best = $s[$k]; $name = $k }
    }
    return @{ Score = $best; Category = $name; All = $s }
}

# -------------------- EV (BEKLENEN DEĞER) MOTORU --------------------
function Generate-Rerolls([int[]]$kept, [int]$freeCount) {
    if ($freeCount -eq 0) { return ,@($kept) }
    $results = New-Object System.Collections.Generic.List[object]
    $max = [int][Math]::Pow(6, $freeCount)
    for ($i=0; $i -lt $max; $i++) {
        $newDice = New-Object int[] 5
        $idx = 0
        foreach ($k in $kept) { $newDice[$idx++] = $k }
        $n = $i
        for ($f=0; $f -lt $freeCount; $f++) {
            $newDice[$idx++] = ($n % 6) + 1
            $n = [Math]::Floor($n / 6)
        }
        $results.Add($newDice)
    }
    return $results
}

function Evaluate-Keep1([int[]]$dice, [int]$mask) {
    $kept = @(); $freeCount = 0
    for ($i=0; $i -lt 5; $i++) {
        if (($mask -band (1 -shl $i)) -ne 0) { $kept += $dice[$i] } else { $freeCount++ }
    }
    $rerolls = Generate-Rerolls $kept $freeCount
    if ($rerolls.Count -eq 0) { return 0.0 }
    $total = 0.0
    foreach ($r in $rerolls) {
        $b = Best-Score $r
        $total += $b.Score
    }
    return $total / $rerolls.Count
}

function Find-BestKeep([int[]]$dice, [int]$rollsLeft) {
    $bestEV = -1.0; $bestMask = 0; $bestKept = @()

    if ($rollsLeft -eq 1) {
        for ($mask=0; $mask -lt 32; $mask++) {
            $ev = Evaluate-Keep1 $dice $mask
            if ($ev -gt $bestEV) {
                $bestEV = $ev; $bestMask = $mask
                $bestKept = @()
                for ($i=0; $i -lt 5; $i++) {
                    if (($mask -band (1 -shl $i)) -ne 0) { $bestKept += $dice[$i] }
                }
            }
        }
    } elseif ($rollsLeft -eq 2) {
        # 2 atış hakkı kalmışsa hızlı yaklaşım ve 1-roll optimizasyonu hibrit kullanılır
        $best1 = Find-BestKeep $dice 1
        $bestEV = $best1.EV + 3.0; $bestMask = $best1.Mask; $bestKept = $best1.Kept

        $counts = Get-Counts $dice
        $maxC = ($counts | Measure-Object -Maximum).Maximum
        $target = 1
        for ($f=1; $f -le 6; $f++) { if ($counts[$f] -eq $maxC) { $target = $f; break } }

        for ($mask=0; $mask -lt 32; $mask++) {
            $keepsTarget = $true; $keptList = @(); $free = 0
            for ($i=0; $i -lt 5; $i++) {
                if (($mask -band (1 -shl $i)) -ne 0) {
                    $keptList += $dice[$i]
                    if ($dice[$i] -ne $target) { $keepsTarget = $false }
                } else { $free++ }
            }
            if (-not $keepsTarget -and $maxC -ge 2) { continue }
            $ev1 = Evaluate-Keep1 $dice $mask
            $ev = $ev1 + 3.5
            if ($ev -gt $bestEV) {
                $bestEV = $ev; $bestMask = $mask; $bestKept = $keptList
            }
        }
    }

    return @{
        EV = $bestEV
        Mask = $bestMask
        Kept = $bestKept
        FreeCount = 5 - $bestKept.Count
    }
}

# -------------------- ANA OYUN AKIŞ DÖNGÜSÜ --------------------
function Show-Header {
    Clear-Host
    Write-Host "==================================================" -ForegroundColor Cyan
    Write-Host "     YAHTZEE OPTİMİZE TUR & EV ASİSTANI v3.0      " -ForegroundColor Cyan
    Write-Host "==================================================" -ForegroundColor Cyan
}

while ($true) {
    Show-Header
    Write-Host "Yeni Bir Tur Başlıyor..." -ForegroundColor Yellow
   
    # 1. ATIŞ
    $input1 = Read-Host "`n[1. ATIŞ] 5 zarı boşlukla girin (Örn: 2 3 3 4 5) ya da çıkış için 'q'"
    if ($input1 -eq "q") { break }
   
    $dice1 = $input1 -split '\s+' | Where-Object { $_ -ne "" } | ForEach-Object { [int]$_ }
    if ($dice1.Count -ne 5) { Write-Host "Hata: Tam 5 zar girmelisiniz!" -ForegroundColor Red; Start-Sleep 2; continue }
    $dice1 = $dice1 | Sort-Object

    $b1 = Best-Score $dice1
    if ($b1.Score -eq 50) {
        Write-Host "MÜKEMMEL! Doğrudan YAHTZEE (50 Puan) yakaladınız!" -ForegroundColor Magenta
        Read-Host "Devam etmek için Enter'a basın..."; continue
    }

    Write-Host "Gelen Zarlar: $($dice1 -join ' ')" -ForegroundColor Cyan
    $res2 = Find-BestKeep $dice1 2
    Write-Host "`n--- 1. ATIŞ SONRASI EV STRATEJİSİ ---" -ForegroundColor Green
    if ($res2.Kept.Count -eq 0) {
        Write-Host "-> Tavsiye: Hiçbirini tutmayın, hepsini yeniden atın." -ForegroundColor Yellow
    } else {
        Write-Host "-> Tutulması Gerekenler: $($res2.Kept -join ' ')" -ForegroundColor Yellow
        Write-Host "-> Yeniden Atılacak Zar Sayısı: $($res2.FreeCount)" -ForegroundColor Yellow
    }
    Write-Host "-> Tahmini Beklenen Puan (EV): $([string]::Format('{0:N2}', $res2.EV))" -ForegroundColor Cyan

    # 2. ATIŞ
    $input2 = Read-Host "`n[2. ATIŞ] Yeni gelen 5 zarı girin (Tuttuklarınız + Yeni Atılanlar)"
    if ($input2 -eq "q") { break }
   
    $dice2 = $input2 -split '\s+' | Where-Object { $_ -ne "" } | ForEach-Object { [int]$_ }
    if ($dice2.Count -ne 5) { Write-Host "Hata: Tam 5 zar girmelisiniz!" -ForegroundColor Red; Start-Sleep 2; continue }
    $dice2 = $dice2 | Sort-Object

    $b2 = Best-Score $dice2
    if ($b2.Score -eq 50) {
        Write-Host "MÜKEMMEL! Yahtzee yakalandı!" -ForegroundColor Magenta
        Read-Host "Devam etmek için Enter'a basın..."; continue
    }

    Write-Host "Gelen Zarlar: $($dice2 -join ' ')" -ForegroundColor Cyan
    $res1 = Find-BestKeep $dice2 1
    Write-Host "`n--- 2. ATIŞ SONRASI EV STRATEJİSİ (Son Hak) ---" -ForegroundColor Green
    if ($res1.Kept.Count -eq 0) {
        Write-Host "-> Tavsiye: Hepsini yeniden at." -ForegroundColor Yellow
    } else {
        Write-Host "-> Son Atışta Tutulacaklar: $($res1.Kept -join ' ')" -ForegroundColor Yellow
        Write-Host "-> Yeniden Atılacak Zar Sayısı: $($res1.FreeCount)" -ForegroundColor Yellow
    }
    Write-Host "-> Tahmini Beklenen Puan (EV): $([string]::Format('{0:N2}', $res1.EV))" -ForegroundColor Cyan

    # 3. ATIŞ (SON)
    $input3 = Read-Host "`n[3. ATIŞ - SON] Final 5 zarını girin"
    if ($input3 -eq "q") { break }
   
    $dice3 = $input3 -split '\s+' | Where-Object { $_ -ne "" } | ForEach-Object { [int]$_ }
    if ($dice3.Count -ne 5) { Write-Host "Hata: Tam 5 zar girmelisiniz!" -ForegroundColor Red; Start-Sleep 2; continue }
    $dice3 = $dice3 | Sort-Object

    $finalRes = Best-Score $dice3
    Write-Host "`n==================================================" -ForegroundColor Cyan
    Write-Host "          FİNAL TURU - EN İYİ SKOR ÖNERİSİ        " -ForegroundColor Cyan
    Write-Host "==================================================" -ForegroundColor Cyan
    Write-Host "Son Zarlar: $($dice3 -join ' ')" -ForegroundColor Cyan
    Write-Host "Önerilen Kategori : $($finalRes.Category)" -ForegroundColor Green
    Write-Host "Alınacak Puan     : $($finalRes.Score)" -ForegroundColor Green

    Write-Host "`nTüm Alternatif Skorlar:" -ForegroundColor Yellow
    foreach ($k in $finalRes.All.Keys) {
        if ($finalRes.All[$k] -gt 0) {
            Write-Host " - $k : $($finalRes.All[$k]) puan"
        }
    }
    Write-Host "==================================================" -ForegroundColor Cyan
   
    $cont = Read-Host "`nYeni bir tur için Enter'a basın ya da çıkmak için 'q'"
    if ($cont -eq "q") { break }
}
Write-Host "Program kapatıldı." -ForegroundColor DarkGray