[ boyan3001 @ 27.06.2012. 15:25 ] @
Pravim neki Yamb u C#, za svoj grosh i ucenje. Programiranje znam, ali nisam profesionalac i nisam radio nikad ozbiljnije poslove i projekte. U realizaciji Yamba za sad nisam nasao ni na kakvu specijalnu prepreku, ali sam se zapitao da li neke stvari radim racionalno, odnosno onako kako bi profesionalni programer pristupio. Dilema mi se javila kod algoritma za prepoznavanje dobijene Ful kombinacije.
Dakle od 6 bacenih kockica (za sad mi kockice baca obican pseudo-random generator na osnovu nekog prostog seed-a, tipa datum i vreme), ful cine 3 iste plus 2 iste kockice. E sad, dok za druge kombinacije nije bilo problem napisati kratku logiku, kod Fula je stvar malo drugacija. Ja sam pristpio nekom prilicno ociglednom (da ne kazem seljackom) logikom, gde se proverava da li su prva tri elementa ista, pa ako jesu, da li su i naredna dva ista. Medjutim, ovde se stvar komplikuje za pisanje, kad se uzme u obzir da je u igri 6, a Ful cine 5 kockica. Te kombinacije mogu pasti u nekoliko razlicitih oblika, tipa 111223, 112223, 113222, 311122... itd.
Ja sam pisanju pristupio vezivajuci if/else if nizove, ali to rezultuje izuzetno nezgrapnim kodom i za pisanje i za pracenje. Algoritam uprosceno receno izgleda ovako nekako:
Ako su prvi i drugi element isti i ako su drugi i treci isti, ispitaj da li su cetvrti i peti isti i to onda znaci Ful.
Ako nisu, da li su drugi i treci isti i da li je treci i cetvrti isti, ako jeste da li su i peti i sesti isti, ako jesu, to je onda Ful.
itd...
Nadam se da ste me skapirali?

Dakle, moje pitanje je, kako bi ovo eventualno moglo da se napise na elegantniji i efikasniji nacin (ili bar jedan od ova dva da se postigne)?

E da... sve ovo podrazumeva da su elementi prethodno sortirani.
[ Mihajlo Cvetanović @ 27.06.2012. 15:40 ] @
Ideš kroz niz brojeva i brojiš iste brojeve. Imaš sa strane jedan niz čiji su elementu brojači, a indeks elementa je broj istih brojeva. Recimo da se taj niz zove GroupCounter. Kad brojiš iste brojeve inkrementiraš neki privremeni brojač ThisGroupCount. Kad naletiš na broj koji je različit od ong što trenutno brojiš onda inkrementiraš jedan od elemenata u GrupiCounter, konkretno GroupCounter[ThisGroupCount]++, i zatim postavljaš ThisGroupCount = 1, jer si naleteo na prvi broj nove grupe. Kad dođeš do kraja niza, to jest šeste kockice pravi se da si naleteo na novu grupu, da bi uračunao i tu poslednju.

Kada imaš ful? Onda kada je GroupCounter[2] >= 1 && GroupCounter[3] >= 1.

Dva para? GroupCounter[2] >= 2
Kare? GroupCounter[4] >= 1
[ mmix @ 27.06.2012. 15:47 ] @
alternativno,
Mozes da grupises dobitke po broju i onda da sortiras po broju pogodaka (npr 113333 dobijes 4x"3" i 2x"1") nek je niz dobiataka s

jamb - s[0] >= 5
kare - s[0] >= 4
full - s[0] >= 3 && s[1] >=2

itd.
[ boyan3001 @ 27.06.2012. 16:21 ] @
Hvala, ukapirao sam obe ideje i rade ono sto treba. Ali ima tu jos jedna kvaka, zaboravio sam da je napomenem. Posto je Yamb u pitanju, po identifikaciji kombinacije, potrebno je i sabrati poene za nju, sto znaci da moram znati i od kojih vrednosti je nastala Ful kombinacija, jer broj bodova je zbir kockica koje su dale Ful, plus bonus od 30 bodova. A ovde (ako sam vas dobro skapirao na kraju), ne znam koji su brojevi dali Ful, znam samo da ista postoji u datoj kombinacji.

Ja sam mehaniku igre ovako zamislio. Kad igrac dobije kombinaciju, koju zeli da upise u tabelu, klikne samo na zeljeno polje u tabeli, nakon cega igra proverava i identifikuje kombinacju, kako se uklapa u to polje. Ako se ne uklapa nikako, upisace nulu, ako se uklapa, mora da sabere kockice, doda odgovarajuce bonuse i upise u polje tabele.
[ Mihajlo Cvetanović @ 27.06.2012. 17:24 ] @
Ja sam već zaboravio koje sve kombinacije idu jamb, pa sam lupio ono "dva para". Ako ne postoji kombinacija u kojoj nam trebaju dve grupe sa istim brojem članova onda onaj niz GroupCounter ne mora da bude brojač, nego maksimalna vrednost. Umesto da se zove GroupCounter mogli bi da je nazovemo štajaznam, GroupValue, i da se postavlja sa GroupValue[ThisGroupCount] = max(GroupValue[ThisGroupCount], ThisGroupValue), gde je ThisGroupValue vrednost te grupe čiji je broj članova ThisGroupCount. Svako ispitivanje je onda ispitivanje da li je različito od nule, pa ako jeste onda računaš ukupnu vrednost.

Za ful bi recimo broj poena bio 30 + GroupValue[3]*3 + GroupValue[2]*2.
[ boyan3001 @ 27.06.2012. 18:18 ] @
Da, skontao sam, to je to, hvala ;)
Za ostale kombinacije nije tesko napraviti daleko jednostavnije ispitivanje. Kombinacije su sledece:
Kenta - niz po redu, od 1 do 5 ili od 2 do 6. Sortira se dobijena kombinacija i trazi da li postoji vise od dve iste kockice, ako ne postoji, to je Kenta;
Triling - tri iste. Prosto sortiranje od najvece ka najmanjoj. Ako su prve tri iste, to je to;
Ful - tri iste, plus dve iste;
Kare/Poker - 4 iste, ista prica kao sa Trilingom;
Yamb - 5 istih, kao i Kare i Triling.

Stvar je u tome da sam program tako pisao da svako polje razlicitog tipa (Yamb, Kare, Ful...) ima svoj algoritam koji ispituje samo svoj domen i ako dobije pozitivnu identifikaciju, upisuje sta treba. Cini mi se da je ovo jednostavnije, jer se poziva samo ono sto treba, zavisno od toga na koje je polje igrac kliknuo. Nema potrebe da igra skonta da u kombinacji postoji i Yamb i Kare i Triling, ako igrac ionako upisuje samo Yamb.
[ Nedeljko @ 27.06.2012. 19:14 ] @
Triling ti ne valja. Ako tako radiš i poker i jamb, ne valjaju ni oni.
[ boyan3001 @ 27.06.2012. 19:47 ] @
Pogresno sam napisao. Traze se iste u nizu, a ne prve u nizu, moja greska.
[ Srđan Pavlović @ 28.06.2012. 14:27 ] @
Kad se vec igras, mogao si skinuti Android SDK (pises u Javi),
pa napraviti taj jamb da mozemo da ga igramo na smartfonovima

http://developer.android.com/guide/components/fundamentals.html
[ Shadowed @ 28.06.2012. 14:30 ] @
Covek rece da radi u C#
Ali da, mogao si da uzmes WinPhone SDK i...
[ Srđan Pavlović @ 28.06.2012. 14:56 ] @
Naravno, mislio sam ako zna Javu, uglavnom ko zna C, zna i Javu... bar toliko da se napise program za jamb :)
[ boyan3001 @ 28.06.2012. 15:24 ] @
Ova ideja Yamba na kompu je u stvari rekreacija one jedne prastare domace verzije, koja je kruzila netom pre 10tak i vise godina, od nekog GD Softa iz Kragujevca valjda. Zvala se Yamb98. Ja imam jos uvek taj .exe i radi bez problema na Win7-ici, bez potrebe za modovima kompatibilnosti. Ali za danasnje vreme izgleda strasno skrnavo, najvise zbog upotrebe posebnih YU fontova, koji danas daju neke pogresne karaktere.
Takodje, ta verzija je sa mogucnostima bila relativno jednostavna. Ja sam imao ideju da omogucim izbor razlicitih kolona za igru, mogucnost cuvanja rezultata i liste kombinacija, zarad analize, kao mozda i neke statisticke alatke, hot-seat i mrezni multiplayer za single ili okrsaje u parovima... itd. Uglavnom, da pokrije sve varijacije i modove igranja u novom modernom ruhu. Razmisljao sam i o tome, da bi ovakav tip igre vrhunski legao na mobilne uredjaje.
Moje primarno programersko znanje je peceno na C/C++, pa tek onda na C# i nesto malko Javi. No znam, da su koncepti C# i Jave relativno slicni, te da nije neki problem prilagoditi se. Meni je Java nesto oduvek bila malo mrska, pa sam je nekako izbegavao, ali kontam da se bez Jave danas ne moze, tako da bi mi u jednom trenutku neka Java gimnastika kroz ovaj Yamb dobro dosla svakako. Kad osposobim ovu Windows .NET verziju, okacicu je ovde svakako ;)
[ Srđan Pavlović @ 28.06.2012. 15:39 ] @
https://play.google.com/store/...LDEsImNvbS52aXNjb2RlLnlhbWIiXQ

Ovako nesto :)
[ boyan3001 @ 28.06.2012. 16:11 ] @
Tako nesto, samo jos bolje =)
Sad vidim da u toj verziji tu postoji kombinacija 2 para, a nema trilinga. Ono malo sto sam istrazivao pre nego sto sam poceo ovo da radim, nisam video jos verziju koja nudi mogucnost da se sama igra konfigurise u smislu polja koja ucestvuju u igri, kao i kolona sa razlicitim pravilima popunjavanja (najava, dojava, iz sredine, ka sredini, maksimumi... itd, svasta sam video dosad) ili ekstra bonusima, kao npr, ako padne kompletna kenta, od 1 do 6, dobija se bonus od +10 ili ako padne npr Yamb od svih 6 kockica. Ideja je da se sve te varijacije implementiraju kao konfigurabilne opcije, znaci neki ultimate Yamb koji ce moci svako da igra kako je naucio i najvise mu godi ;)
[ Srđan Pavlović @ 28.06.2012. 16:24 ] @
Da, tako nešto bi bilo odlično :)

Ja najvolim da igram onaj jamb sa 10 kolona, ima blokčić da se kupi na trafikama...
[ boyan3001 @ 28.06.2012. 17:22 ] @
Cek da vidim da se prebrojimo:

1. Opadajuca - popunjava se redom odozgo na dole;
2. Rastuca - redom odozdo na gore;
3. Slobodna - slobodna;
4. Iz sredine - od polja maksimum i minimum, na gore, odnosno dole;
5. Ka sredini - od prvog i poslednjeg polja (ovde moze da postoji opciono ogranicenje da ne moze da se predje sredina, ako jedan niz stigne pre do iste);
6. Najava - najava odredjenog polja;
7. Dojava - naredni protivnik mora da ponovi najavu koja je odigrana prethodno;
8. Slobodna najava - najava kolone, ali su sva slobodna polja u igri za upis (vidjenu u pomenutom Yambu98 i nigde vise, malo mi deluje bezveze);
9. Rucno - upis je moguce samo, ako su izrucene sve kockice. Opciono ogranicenje samo na prvu ruku ili bilo koju, pod uslovm da su sve kockice bacene;
10. Maksimum - upisuje se maksimum iz svake kategorije (reda). Opciono upisivanje samo ako je apsolutni maksimum, odnosno sledi nula usled nedostatka istog;
11. Poslednja - ili "Last Man Standing / Ko prezivi pricace" kako je ja jos zovem :D, popunjava se redom, tek kad se sve ostale popune do kraja. Ovo je za prave kockare varijanta.

To je ono sto je meni poznato. Ako neko zna jos neku nek napise, da je uvrstimo... ili ako ima prosto dobru ideju, da prosirimo jos.
[ Nedeljko @ 28.06.2012. 21:45 ] @
off topic

Meni se kod jamba ne sviđa to što igrač ne utiče na igru protivnika. Ladno mogu da se zatvore svako u svoju sobu i da na kraju uporede rezultate.
[ Srđan Pavlović @ 28.06.2012. 23:15 ] @
Hehe, pa nije baš skroz tačno to. Prvo, ima faktor nerviranja
protivnika dok igra (pa upisuje rezultate na losija mesta), a drugo,
ima psiholoski faktor kada igras bolje ili losije pored nekoga ko vodi ili gubi...
a naravno i onaj faktor socijalizacije, kada je zovnes na yamb, kafu, i tako to
[ mmix @ 29.06.2012. 00:34 ] @
kontra najava?
[ mmix @ 29.06.2012. 02:59 ] @
Kad se vec radi u c# onda da malo zacinimo

Code (csharp):

var dobitak = new int[] { 3, 2, 5, 5, 3, 5 };
var bacanje = 2;


 var defs = new[] { new { ime = "Jamb", mindef = new[] { 5 }, bonus = 50 },
        new { ime = "Kare", mindef = new[] { 4 }, bonus = 40 },
        new { ime = "Ful", mindef = new[] { 3, 2 }, bonus = 30 },
        new { ime = "Triling", mindef = new[] { 3 }, bonus = 20 } };

 var target = from cifra in Enumerable.Range(1, 6).Reverse()
      join dob in dobitak on cifra equals dob into grupaPogodaka
      select new {cifra, brojPogodaka = grupaPogodaka.Count() };

 var capital = from def in defs
               let grupe = target.OrderByDescending(x => x.brojPogodaka).ThenByDescending(x => x.cifra)
       let mix = def.mindef.Zip(grupe, (minpon, redni) => new { minpon, redni })
       let active = mix.All(e => e.minpon <= e.redni.brojPogodaka)
       let skor = active ? def.bonus + mix.Sum(e => e.minpon * e.redni.cifra) : 0
       select new { def.ime, active, skor };

 var kentatest = target.SkipWhile(e => e.brojPogodaka == 0).TakeWhile(e =>e.brojPogodaka > 0);
 var kenta = new { ime = "Kenta", active = kentatest.Count() >= 5, skor = kentatest.Count() >= 5 ? 76 - bacanje * 10 : 0 };
 var max = new { ime = "Max", active = true, skor = dobitak.OrderByDescending(x => x).Take(5).Sum() };
 var min = new { ime = "Min", active = true, skor = dobitak.OrderBy(x => x).Take(5).Sum() };

 var regular = from pog in target
                   select new { ime = pog.cifra.ToString(), active = true, skor = pog.cifra * pog.brojPogodaka };


 var rezultat = capital.Union(new[] { kenta, max, min }).Union(regular);
 


Izlaz:
Code:

ime       active    skor
-------------------------
Jamb      False     0
Kare      False     0
Ful       True      51
Triling   True      35
Kenta     False     0
Max       True      21
Min       True      18
6         True      0
5         True      15
4         True      0
3         True      6
2         True      2
1         True      0

[ Nedeljko @ 29.06.2012. 09:06 ] @
Ako sam do sada mislio da znam nešto o C#-u, sada definitivno vidim da ne znam ništa. Što je najgore, ovaj kod se kompajlira. Bi li mogao samo još da dodaš kod za ispis, pa da se igram sa kodom?
[ dejanet @ 29.06.2012. 09:21 ] @
^ C# Lambda sintaksa, mislim..

Najablize tome Groovy Closures..
[ Shadowed @ 29.06.2012. 10:34 ] @
Moracu ja da probam tako.. Da programiram sa plaze
[ boyan3001 @ 29.06.2012. 11:18 ] @
@Nedeljkov off
Mislim da je Srdjan u pravu sto se tice psihologije igre u dvoje ili vise. Slicno je kao i u pokeru, ni tu nemas neku realnu kontrolu nad kartama, samo minimalnu i vise simbolicnu i cela igra je igra psihologije. Ovde u Yambu dodje tako, ali je psihologija vise zabavna, nego pod ozbiljnom tenzijom. Mada opet, sve zavisi ko kako shvata pobedu i gubitak

@mmix
Kontra najava? Mislis, obavezno igranje onoga sto je prethodi igrac odigrao u svojoj najavi? Ako je to to, to sam pobrojao pod imenom dojava (tako sam ja bar sretao naziv, mada mislim da sam cuo i ovu drugu verziju).
A kod je vrh, jedva sam ga desifrovao kako radi, mada nisam siguran da sam sve dobro razumeo, da budemo posteni Meni je takav pristup vrlo stran, kao nekom ko je naucio programiranje na C/C++, moj kod je daleko klasicnijeg oblika.
Ali, ako je sa plaze kao sto kaze Shadowed, onda kapiram zasto je tako hi'
[ Nedeljko @ 29.06.2012. 11:57 ] @
Pa, nije u pokeru tako, jer se u pokeru igra sa jednim špilom karata, a ne sa po jednim za svakog igrača i postoji tajnost, pa blefiranje sa ulozima. Itekako ti utičeš na drugog. Zato mi se jamb ne sviđa.
[ Mihajlo Cvetanović @ 29.06.2012. 12:10 ] @
Mogli bi da napravimo nekakav poker-jamb. Prvo se bacaju sve kockice, a onda sledi licitacija poenima. Onaj ko uzme ruku nastavlja sa bacanjem i upisuje sebi poene umanjene za ono što je licitirao.

Mada, ovo nije toliko poker, koliko neke kartaške igre u kojima ima ta licitacija.
[ mmix @ 29.06.2012. 12:43 ] @
Pa dobro, Yamb je skoro cista igra na srecu, poker se u vecini jurisdikcija tretira kao game of skill.

Citat:
Nedeljko: Ako sam do sada mislio da znam nešto o C#-u, sada definitivno vidim da ne znam ništa. Što je najgore, ovaj kod se kompajlira. Bi li mogao samo još da dodaš kod za ispis, pa da se igram sa kodom?


To je LINQ (Language Integrated Query), labmda je samo deo te price kojim se upravlja LINQom.

npr
Code (csharp):
var samoparni = niz.Where(x => x % 2 == 0);

u zagradama je lambda ostalo je linq, u ovom primeru petlja ide kroz niz, za svaki element izvrzsava lambdu (gde element lokalno dobije ime x) i u izlaz pusta samo one kojima je uslov true, tj gde lambda vrati true. Itd. c# ti isto dopusta da za dobar deo LINQ operacija koristis query notaciju, tako da gornju operaciju mozes da napises i kao
Code (csharp):
var samoparni = from x in niz
                where x % 2 == 0
                select x;

ima tu jos caka, npr linq radi i sa kompleksnim tipovima (svi koji podrzavaju IEnumerable) elementi mogu da budu kompleksni, nizovi cak mogu da budu potpuno dinamicki generisani (npr Enumerable.Range koji koristim generise niz integera od 1 do 6 dinamicki on the fly)

Getting Started with LINQ in C#
101 LINQ Samples

u osnovi fency for/next procesiranje

E da, ako hoces da se igras sa LINQom, najbolje je da skines LINQPad (www.linqpad.net). U rezimu C# statements koristis .Dump() ekstenziju da vidis rezultat.
[ Shadowed @ 29.06.2012. 12:55 ] @
Jedino sto mi se ne svidja je sto je izmesan query i direktno koriscenje funkcija, mada bi mozda bilo necitljivije da je korisceno samo jedno.
[ mmix @ 29.06.2012. 13:07 ] @
Citat:
Shadowed: Jedino sto mi se ne svidja je sto je izmesan query i direktno koriscenje funkcija, mada bi mozda bilo necitljivije da je korisceno samo jedno.


Pa namerno sam ovako stavio posto je decko nov, da se ne obeshrabri kenta mini i max su najveci prblem zbog Take i na kraju problem je sto query notacija nema union.

A sto se tice plaze,... eeeeeee


[ mmix @ 29.06.2012. 14:39 ] @
nedeljko evo ti nesto sto ces prepoznati lakse, dinamicki generisan fib niz i onda iz njega izvuceni elementi deljivi sa 3.

Code (csharp):

void Main()
{
     var f = from x in Fib()
               where x % 3 == 0
               select x;
     f.Dump();
}

public static IEnumerable<ulong> Fib()
{
     ulong prethodni = 0, trenutni = 1, sledeci = 1;
     while (true)    
     {
          yield return sledeci;
          try
          {
               sledeci = checked(prethodni + trenutni);        
          }
          catch (OverflowException) { yield break; }
          prethodni = trenutni;        
          trenutni = sledeci;    
     }
}

[ Nedeljko @ 29.06.2012. 16:14 ] @
Ma, razumem sve u 0x10.

Ta tvoja funkcija niti ima indeks kao argument, niti ubacuje elemente u neki kontejner. Ma, znam ja, brojke ne lažu... ali ipak...