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.
Yorumlarınızı ve iyileştirmelerinizi bekliyorum.
Kod:
$ErrorActionPreference = "Stop"
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# -------------------- SKOR TABLOSU & KATEGORİ TANIMLARI --------------------
$script:Categories = [ordered]@{
"Upper1" = "1'ler"
"Upper2" = "2'ler"
"Upper3" = "3'ler"
"Upper4" = "4'ler"
"Upper5" = "5'ler"
"Upper6" = "6'lar"
"3oak" = "3 Aynı (3-of-a-kind)"
"4oak" = "4 Aynı (4-of-a-kind)"
"FH" = "Full House (25 Puan)"
"SS" = "Küçük Kent (Small Straight - 30 Puan)"
"LS" = "Büyük Kent (Large Straight - 40 Puan)"
"Y" = "Yahtzee (50 Puan)"
"Chance" = "Şans (Toplam)"
}
function New-Scorecard {
$sc = [ordered]@{}
foreach ($k in $script:Categories.Keys) { $sc[$k] = $null }
return $sc
}
function Get-OpenCategories($scorecard) {
return @($scorecard.Keys | Where-Object { $scorecard[$_] -eq $null })
}
# -------------------- 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-AllCategories([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, [string[]]$openCategories) {
$allScores = Score-AllCategories $dice
$best = -1; $name = ""
foreach ($k in $openCategories) {
if ($allScores[$k] -gt $best) {
$best = $allScores[$k]
$name = $k
}
}
# Açık kategorilerin hepsi 0 veriyorsa ilk açık kategoriyi öner
if ($best -lt 0 -and $openCategories.Count -gt 0) {
$name = $openCategories[0]
$best = 0
}
return @{ Score = $best; Category = $name; All = $allScores }
}
# -------------------- 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, [string[]]$openCategories) {
$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 $openCategories
$total += $b.Score
}
return $total / $rerolls.Count
}
function Find-BestKeep([int[]]$dice, [int]$rollsLeft, [string[]]$openCategories) {
$bestEV = -1.0; $bestMask = 0; $bestKept = @()
if ($rollsLeft -eq 1) {
for ($mask=0; $mask -lt 32; $mask++) {
$ev = Evaluate-Keep1 $dice $mask $openCategories
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) {
$best1 = Find-BestKeep $dice 1 $openCategories
$bestEV = $best1.EV + 2.5; $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 $openCategories
$ev = $ev1 + 3.0
if ($ev -gt $bestEV) {
$bestEV = $ev; $bestMask = $mask; $bestKept = $keptList
}
}
}
return @{
EV = $bestEV
Mask = $bestMask
Kept = $bestKept
FreeCount = 5 - $bestKept.Count
}
}
# -------------------- ARAYÜZ VE GÖRÜNTÜLEME --------------------
function Show-Dashboard($scorecard, $turnNum) {
Clear-Host
Write-Host "==================================================" -ForegroundColor Cyan
Write-Host " YAHTZEE OPTİMİZE TUR & EV ASİSTANI v4.0 " -ForegroundColor Cyan
Write-Host " TUR: $turnNum / 13 " -ForegroundColor Yellow
Write-Host "==================================================" -ForegroundColor Cyan
Write-Host "`n--- GÜNCEL SKOR TABLOSU ---" -ForegroundColor Yellow
$upperSum = 0
for ($f=1; $f -le 6; $f++) {
$k = "Upper$f"
$val = if ($scorecard[$k] -eq $null) { "[AÇIK]" } else { $scorecard[$k] }
$col = if ($scorecard[$k] -eq $null) { "DarkGray" } else { "Green" }
if ($scorecard[$k] -ne $null) { $upperSum += $scorecard[$k] }
Write-Host " $($script:Categories[$k]): $val" -ForegroundColor $col
}
$bonus = if ($upperSum -ge 63) { 35 } else { 0 }
Write-Host " Upper Toplamı: $upperSum / 63 (Bonus: +$bonus)" -ForegroundColor Yellow
Write-Host "-------------------------------------------"
$totalScore = $bonus
foreach ($k in $scorecard.Keys) {
if ($scorecard[$k] -ne $null) { $totalScore += $scorecard[$k] }
if (-not $k.StartsWith("Upper")) {
$val = if ($scorecard[$k] -eq $null) { "[AÇIK]" } else { $scorecard[$k] }
$col = if ($scorecard[$k] -eq $null) { "DarkGray" } else { "Green" }
Write-Host " $($script:Categories[$k]): $val" -ForegroundColor $col
}
}
Write-Host "-------------------------------------------"
Write-Host " GENEL TOPLAM PUAN: $totalScore" -ForegroundColor Magenta
Write-Host "==================================================`n"
}
# -------------------- ANA OYUN AKIŞ DÖNGÜSÜ --------------------
$scorecard = New-Scorecard
$turn = 1
while ($turn -le 13) {
$openCats = Get-OpenCategories $scorecard
if ($openCats.Count -eq 0) { break }
Show-Dashboard $scorecard $turn
Write-Host "--- $turn. TUR BAŞLIYOR ---" -ForegroundColor Yellow
# 1. ATIŞ
$input1 = Read-Host "[1. ATIŞ] 5 zarı boşlukla girin (Örn: 2 3 3 4 5) veya çıkış '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
Write-Host "Gelen Zarlar: $($dice1 -join ' ')" -ForegroundColor Cyan
$res2 = Find-BestKeep $dice1 2 $openCats
Write-Host "`n--- 1. ATIŞ SONRASI STRATEJİ ---" -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 5 zarı girin (Tuttuklarınız + Yeni Atılanlar) veya Pas geçip Sonlandır 'p'"
if ($input2 -eq "q") { break }
$finalDice = $dice1
if ($input2 -ne "p") {
$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
$finalDice = $dice2
Write-Host "Gelen Zarlar: $($dice2 -join ' ')" -ForegroundColor Cyan
$res1 = Find-BestKeep $dice2 1 $openCats
Write-Host "`n--- 2. ATIŞ SONRASI STRATEJİ (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 veya Pas geç 'p'"
if ($input3 -eq "q") { break }
if ($input3 -ne "p") {
$dice3 = $input3 -split '\s+' | Where-Object { $_ -ne "" } | ForEach-Object { [int]$_ }
if ($dice3.Count -eq 5) { $finalDice = $dice3 | Sort-Object }
}
}
# TUR SONU DEĞERLENDİRME VE KATEGORİ SEÇİMİ
$allScores = Score-AllCategories $finalDice
$bestRecommendation = Best-Score $finalDice $openCats
Write-Host "`n==================================================" -ForegroundColor Cyan
Write-Host " TUR SONU - KATEGORİ SEÇİMİ " -ForegroundColor Cyan
Write-Host "==================================================" -ForegroundColor Cyan
Write-Host "Final Zarları: $($finalDice -join ' ')" -ForegroundColor Cyan
Write-Host "Önerilen Kategori : $($script:Categories[$bestRecommendation.Category]) ($($bestRecommendation.Score) Puan)" -ForegroundColor Green
Write-Host "`nKullanılabilir (Açık) Kategorilerdeki Puan Durumu:" -ForegroundColor Yellow
$catMap = @{}
$i = 1
foreach ($cat in $openCats) {
$scoreVal = $allScores[$cat]
$color = if ($scoreVal -gt 0) { "Green" } else { "DarkGray" }
Write-Host " [$i] $($script:Categories[$cat]) : $scoreVal Puan" -ForegroundColor $color
$catMap[$i] = $cat
$i++
}
# Kullanıcıdan kategori doldurmasını isteme
while ($true) {
$choice = Read-Host "`nPuanı kaydetmek istediğiniz kategori numarasını seçin (1-$($openCats.Count)) [Öneri için Enter'a basın]"
if ([string]::IsNullOrWhiteSpace($choice)) {
$selectedCat = $bestRecommendation.Category
$scoreToApply = $bestRecommendation.Score
break
}
if ($choice -match '^\d+$' -and [int]$choice -ge 1 -and [int]$choice -le $openCats.Count) {
$selectedCat = $catMap[[int]$choice]
$scoreToApply = $allScores[$selectedCat]
break
}
Write-Host "Geçersiz seçim!" -ForegroundColor Red
}
$scorecard[$selectedCat] = $scoreToApply
Write-Host "`n-> '$($script:Categories[$selectedCat])' kategorisine $scoreToApply puan yazıldı." -ForegroundColor Cyan
Start-Sleep 2
$turn++
}
Show-Dashboard $scorecard 13
Write-Host "Oyun Bitti! Toplam Skor Hesaplandı." -ForegroundColor Green
Son düzenleme: