From 22891ae2b6fd6737f5e6d91c83a0d1461f48f8ac Mon Sep 17 00:00:00 2001 From: kara-mosr Date: Wed, 14 Jan 2026 11:23:18 +0100 Subject: [PATCH] Algo Victoire + Console Player + Main + Javadoc --- .../fr/iut_fbleau/GameAPI/AbstractBoard.class | Bin 0 -> 2065 bytes .../fr/iut_fbleau/GameAPI/AbstractGame.class | Bin 0 -> 2148 bytes .../GameAPI/AbstractGamePlayer.class | Bin 0 -> 431 bytes build/fr/iut_fbleau/GameAPI/AbstractPly.class | Bin 0 -> 417 bytes build/fr/iut_fbleau/GameAPI/IBoard.class | Bin 0 -> 636 bytes build/fr/iut_fbleau/GameAPI/Player.class | Bin 0 -> 894 bytes build/fr/iut_fbleau/GameAPI/Result.class | Bin 0 -> 938 bytes build/fr/iut_fbleau/HexGame/HexBoard.class | Bin 0 -> 5569 bytes build/fr/iut_fbleau/HexGame/HexMain$1.class | Bin 0 -> 431 bytes build/fr/iut_fbleau/HexGame/HexMain.class | Bin 0 -> 2125 bytes build/fr/iut_fbleau/HexGame/HexPly.class | Bin 0 -> 1189 bytes .../HexGame/HumanConsolePlayer.class | Bin 0 -> 2871 bytes javaAPI/fr/iut_fbleau/HexGame/HexBoard.java | 232 ++++++++++++++---- javaAPI/fr/iut_fbleau/HexGame/HexMain.java | 34 +++ .../HexGame/HumanConsolePlayer.java | 68 +++++ 15 files changed, 280 insertions(+), 54 deletions(-) create mode 100644 build/fr/iut_fbleau/GameAPI/AbstractBoard.class create mode 100644 build/fr/iut_fbleau/GameAPI/AbstractGame.class create mode 100644 build/fr/iut_fbleau/GameAPI/AbstractGamePlayer.class create mode 100644 build/fr/iut_fbleau/GameAPI/AbstractPly.class create mode 100644 build/fr/iut_fbleau/GameAPI/IBoard.class create mode 100644 build/fr/iut_fbleau/GameAPI/Player.class create mode 100644 build/fr/iut_fbleau/GameAPI/Result.class create mode 100644 build/fr/iut_fbleau/HexGame/HexBoard.class create mode 100644 build/fr/iut_fbleau/HexGame/HexMain$1.class create mode 100644 build/fr/iut_fbleau/HexGame/HexMain.class create mode 100644 build/fr/iut_fbleau/HexGame/HexPly.class create mode 100644 build/fr/iut_fbleau/HexGame/HumanConsolePlayer.class create mode 100644 javaAPI/fr/iut_fbleau/HexGame/HexMain.java create mode 100644 javaAPI/fr/iut_fbleau/HexGame/HumanConsolePlayer.java diff --git a/build/fr/iut_fbleau/GameAPI/AbstractBoard.class b/build/fr/iut_fbleau/GameAPI/AbstractBoard.class new file mode 100644 index 0000000000000000000000000000000000000000..7c1f157be56955f4e8a179a64cd2165f76336470 GIT binary patch literal 2065 zcmX^0Z`VEs1_pD6a4rTR1`AFGK?X|@Va3T{&0qr}Y`Gci802o1MXjk%2e4w5TXGuOuKRu`;!YkwMNUtw=w! zv?M+)DJM0tRNp-@H`Ot~Qy(I4&B(x>ky%`lUsTD+An22oSeB??T9TQg?~+C@1=3SXoKfRn0jH7BFlS`o$}9$@3jZ=tdSTYkjACTqOiwKd zN-ZwUDPd&5Z309EC=F#6`=q8P<}fl47Xnd?3>=vysYQt;`9+KjVj7xA5$_2Vw`OFp z#wtNvG%_-6D*Xlw!@uz!jWdT9lmXmI+F0 zLa+z`%j$tL3J-%6g8~nO2!kjOgBXK2JA*F|gCB_F&mhXq5WvF_$PmQC5X=z5$e@Tl z55mk0$f@LE2xSQ2VNhaF=3$Tr8LPse%E+JqvImkO{qloLlQUd%Qgc)DN?a?FQwvHm z^Ya)Pj_^72bEGV{_Ek`wb3 zl2R2wA(WR2@=zEfgED@{f&+k&K>%T|e^ORzatR}Y40er>0L3W{NrsFJ>;XQGk*-08 zaF!7x13%ajM1jP}z>%1e;+9!dT*Am8ssTwgV827$04^`MA$bd`N(7dMkd-kqa2BMd zWCsK`OPjFfeUmU|Gh%tF?)Nbt?nYat1D~O$;ns z8JIw(G9j6&&cMZ>!63q*%^=O7!=T8(z`(-5B*MnP0!ma+bJf9KVPN3a+QPuBy_12B zi2-B`#Bp2)1L6~6@ lgE+%va7^$pFnO>u@cv=oVrSrBVPr62Fa?L788{i40|1ph=obJ0 literal 0 HcmV?d00001 diff --git a/build/fr/iut_fbleau/GameAPI/AbstractGame.class b/build/fr/iut_fbleau/GameAPI/AbstractGame.class new file mode 100644 index 0000000000000000000000000000000000000000..b2e2856db54a5c1037204cc0fe9793be89367c05 GIT binary patch literal 2148 zcmX^0Z`VEs1_pD6L@ov)231Z5K?XGtq0Y^q$e;ltG`SeG7_`|LbU++kE(Uf6JrGMD zL>RC$7;-TfF&GPh%-~|+VXy!RTe34)u`^gRGVmmq78RxDl{n=m7NsyU$oZrd>1URf z#HS_Yq$ZZ?yC>$RItF;^dxGVy85y{86AJ=z5-U@SiWwP%eXv890M8)AJHbN{dn%8DcS2*x;}NVyZO`S;wT}lA^@q5|D$SD($Qp8Q5$x^D;~9 z7#U17aA<_O9Mc`vnqiC#EYA5Usf-N#KACx`ex2NbbjR}&0GYt1M|2G*2(aCoZW zasaXopdd$z&ft=w%)E3)2KKVVoYGYPG_bYcfW#G85FOTB4B-qBj0|d!;8$Q&$ShV! zR7lFn&rhjTNX|%2EYVZ&Q~-sLLTP~>BZGKuVs@%?eqM57NqA;ShI4*iaY&)fRTa6GcPZ-$T=smxHz?#kzoe1ZBR2HdC4O&FC{0nSOucd8Yv+` z>_8Sl(HK%$kcun`RUVCG0+!SXHNrVDCnq?wB-NUoA%T%W6~lkn+{VZthhH6wB7-0U zs1{>lU;-6f3=9lRpt6gBkwF~HmSA9FU}TVFkYZqBkY-?DFlJz4U}j)o;MdyDz^J9Y zm4Qi1XDb8qMg|53Mg|!M1_mJp76t|e6$TatRR&H5H3mKgb*NFY42%qN4Dt+&V1srt zFoRWQXl-F&+R4De$S{i`RBHL4c8A1K2wt7pgIEGB7Y0 zFz_%KGAJ+@F=#OuGZ-+KGT1VhF?capFhnz0GQ=@hGbk`HFbFfSF#KciWM^P!XHaBk tQ2N0j0P?>w*f14_7zPFgE(S)1D26zOXa-3J69xtb4hBXBQwBx`GXUZmRVe@f literal 0 HcmV?d00001 diff --git a/build/fr/iut_fbleau/GameAPI/AbstractGamePlayer.class b/build/fr/iut_fbleau/GameAPI/AbstractGamePlayer.class new file mode 100644 index 0000000000000000000000000000000000000000..deaa1ac26125b3ea82cfa337f9854d3f1a7464d0 GIT binary patch literal 431 zcmX^0Z`VEs1_pBm5iSN627XQkW(EOv20?ZPAw~w~OvhYC205R!BK^$LlK8ZwoYcfp zefPxNRL1~M{eYar%G4rjMg}&U%)HDJJ4OaY4g5+q!x$M@obyvs85#I}GV@aXN^_G^ zi$W5Ua#9%?c+xY=QX}(Ai+uCTQW+VXahc`ml%H6XVy%h8D#xValA^@ql7O5_YeojH z;QZ2}3ut*cmt&7#TPj7#Oq|m>8HC7#O&; vwlgqlX>Vm<+6Y$7#lXP8$H2_Mz#z!L!XU)J$so+a$iU6O1D53lo5KeH11f0p literal 0 HcmV?d00001 diff --git a/build/fr/iut_fbleau/GameAPI/AbstractPly.class b/build/fr/iut_fbleau/GameAPI/AbstractPly.class new file mode 100644 index 0000000000000000000000000000000000000000..79018e631267e0837a60499a408777bc9cb0294f GIT binary patch literal 417 zcmX^0Z`VEs1_pBm5iSN627XQkW(EOv20?ZPAw~wato+i{(jrC%IiIv5{mjym__U;) z)WlMK_r%;(#{f_LfSkn2)FNv}1~!|_yv!0iMg~O<{7N;$7#Ucc^HWk88TfrN^HTjv zbCXhwLK2g5QW+UI(^E?zMlv!eXlUX$iIIUTIKQ+gIn^x_q*uT(sko#lF}Wllr&2E~ zu`H2?ft^8^hk=!WjgdhSyYrE>Ffs^$H0kFg=B4ZVCuOB3moPFgYiNeCC^9fJurM$% zFfuTK3}awmU}9ioU}xZ9U}WHAU|`T<}|L(?ZKu`E%)v?Mb} z-xDfs&B(wRoSB}NSW;S)%E(}iRgn!5w%J)TGO(uP2jo-|>%1^V2KLfCs1{}o%`ip= zj^f0$ROkGHN_^qr>6D*Xlw!@uz~Y>rlFG=y?~|FA>Q|bZlv)&$n3R*s$iNkxUs{x$ z>Xr%Oa6{DVf&9+MAcH-YAZi#H1VF0va}x8?_5G8wQj<&A7#SEDm>58SgN2cSnSq6Y zfrXKQm4OXRvommjX-)<%FwM=t!@$VE%fP_E#K6bG$iUAa02UWy5Mp3pU}O+x5Mf|s m5M^LskYWIt%)r2;wE-+6#=yY9#=ywHz~IZk$RG|jK>`3QqM||o literal 0 HcmV?d00001 diff --git a/build/fr/iut_fbleau/GameAPI/Player.class b/build/fr/iut_fbleau/GameAPI/Player.class new file mode 100644 index 0000000000000000000000000000000000000000..6be1739d62f257aa093333e7149132b118672f47 GIT binary patch literal 894 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 literal 0 HcmV?d00001 diff --git a/build/fr/iut_fbleau/HexGame/HexMain$1.class b/build/fr/iut_fbleau/HexGame/HexMain$1.class new file mode 100644 index 0000000000000000000000000000000000000000..f572f6f0f079918c8f965725c3893adc083f71b0 GIT binary patch literal 431 zcmX^0Z`VEs1_pBmQ7#5%20nHMes%^yMg}&U%)HDJJ4OZ*4WG0k{mjym__U;))WlMK z_r%;(#{f@#PpACEq7-YNti-ZJ{nC=m9DUck(p=xf0&C4MMg|t={FGEi27aH+yi~u^ z+@#c^ki?{%R7M7_;QZ2}2qOc(YhH3resN}Ax^HSpMt%xA zgAfmcFoOsq1BYK~afwHMaS0Ct3j-@7gFLF6JW?w_&eDe(r((#+z~h;hms;eUlUQ7w zTFl6xgsK6g8srJbq~emI#N-kXpOHZpRS}x0j0`NfiJ5tf3}PD55MSpc=B4WgmlS2@ zrCV!;F(@!FF)%ZL03!nf$ej#~3~USx4Dt-jU~zUWZJq55j2jsk7#JDY85kJY7(fc8 o7+4rM7#J9s7&sZYz#6$3co=xWBHRoD3=9lh42%p+AafZQ0BMwF3;+NC literal 0 HcmV?d00001 diff --git a/build/fr/iut_fbleau/HexGame/HexMain.class b/build/fr/iut_fbleau/HexGame/HexMain.class new file mode 100644 index 0000000000000000000000000000000000000000..10e072e70290b0436cff1ba2801aab91e3d7e30f GIT binary patch literal 2125 zcmX^0Z`VEs1_pD6GA;&b1`RF-O$IG?25oi*9WDkI23>XrJx&IF1_LezHU>j>1|xO` zV=e|x1`|#OE(TL}1~V=OUIufJhy_T*lAXbdi$RdVnv21P!4{;^j*G#b!GVjxk-=Gona9W=rV;Ivl~|UjpOcuEt{+@dl$n=q4bsRP zT#}fa?VDHtR?p7h&B(wNoL^d$oa&Yd($C|OTH%|RnWqQR&B(y*ms(unn+md^n1?}@ zL5`ilhljzJ!H4uc#cgDhUl7#Re>fdr0B|D>$cMTfVc@c;ec&mE+{QwWH3Xv9+YgXA=cE)H5IHB7#SJF za}%>uo%8dO6HCG~OEN$iup}|Bq!`Uos13;R0~JE^5>ynF-dK}!@{3d18S+7StB8?7 z1spWs=+4Y5%g;`QmVyx5-4c^a@{20j8A=!#*nINyvr7vY8D=1R9I6SDZ#@$8QgTv@ zRUj&%F%LEy>H?(TLD3jeS&)iFIday;62ed;oD*|$f-_4}t=Sn$85vYDJcP|{j0|%4 z)iEeCNHIt=fB+K%BdADcU}TVIU|^7CU}RuqU|?X?+RnhZk%57MkwJlhfq@My$j!jX zpva&ERr-~Ije(tkfuT!)-9~F4%R&Y|EoP$~3`{o58CZOGGq6NTZ)afj-Oa!jxru>& zI|GN`ZU)XsA+GHV+*T}-ESng3b~ErsZerlk-Oj+bje$QLBqjh66M%{BW)O_jk!0D< zAY{cV$-0d}*otivgNV*H2GLCnB9d%77{qolh%+#3W026@#vr+ofsuieL4ZM+fti5` z>~1RtJ_ZH`J_cq6ez1%PgD`_EgD8UrgBXJ`gE)gbg9Jk~gA_wLgET`PgDgWSgB(LE zg91Y*gCc`60|SE~1Ji#7VFo641{FpIMs@~f1_l-eRR#tICI&SIbp{ZRkwK6_hJk@W jh=GYg5EP&c3=9Pf#SDcEk_^ra3=A9$j0`Rej0~;-Qh_z_ literal 0 HcmV?d00001 diff --git a/build/fr/iut_fbleau/HexGame/HexPly.class b/build/fr/iut_fbleau/HexGame/HexPly.class new file mode 100644 index 0000000000000000000000000000000000000000..51bf46d6f2297899ccf99fc72bdb9f2a1141fa11 GIT binary patch literal 1189 zcmX^0Z`VEs1_pBmb1nuB260XXb_NL$A<4zS&LG9bAk82n#K6Fyz|Nq^&Y;A|z+9AH z&d9*%$;iN*oS(zUz-E(~msw)R$e^s@lUAgkSy~dGmXwp4SgP-yn49Vt;He*wlUSKr zWbNsx8OF%K;+&t7%E-X)lbM(5SDKrYS`?C)l#|NHz?Pm`5(F}uSwqtk!gU6j&ry;e zTvC*om(Iu_qM_-Nl~|UjpOcuEt`8BlW@O+B&Mz%WPIb!!8N=<7S`m;_sRvTW!@$F! z%)`LRz{SJB4I)$+RM{ESco@_fG#D8KobvNaic5+T3w%>cGV)W3`PmpWIT*Bf7_=F5 z7#U!vD0rHPN#CS#qMO0~!9LTSZNgxxGO9FB#85tA_ga{}+IMY*0AOXb4prE0N zKL{Ba1VH{m_CF&7ds$*mX{vu3BZHa-QtE(To&Jw^sOh*zo$z|mvN zsH0GnUk;*@^K)z&YZ)2Da}%>uo%8dO6HCG~OER4E^NLFn^Gb>t88nbBg2scVCl;&N z8T3KHY0Su=f^c|dURi#2Dm4Be=DQ^(m*f{!vNM=6GO+pN=VzA|Ff#CX=H;apIp-u6 z7pE38GR#1>6lw+}<~$PfQgTv@RUjIzkpcngHY5=gjUklVs>)RNiCz@#O+m4SI90|Nsi13y?FNS=>@m4Tmui$Q>a zpFxm;kwE}Vf=rNQU}RuqU|?X?+QPuJ2Cj__EGWXj$RLDODKolK2?j<6VFr)}kg2*1 z%wPjVwYD*^?0^`qwS|Fs7Xupu!v-{4WEq$lM8TdFV=!W1VBlh4WH4YbVK8KnWRPWG PVBlb2WRPQEWRM2{10*6e literal 0 HcmV?d00001 diff --git a/build/fr/iut_fbleau/HexGame/HumanConsolePlayer.class b/build/fr/iut_fbleau/HexGame/HumanConsolePlayer.class new file mode 100644 index 0000000000000000000000000000000000000000..ab4c1f67dd53a6f560378542daacdd06fec12149 GIT binary patch literal 2871 zcmX^0Z`VEs1_pD6say=|3}&1RY7FM=3>NGRmK+RLTnsD>)|?DB47OYhb`19148{x& zTnvT`jzSC!46YzCH!cQu1`m*!CkKNUi1y}S@L^~0K~{@~57c7{wIhAf6`c7_}thFpd`9)^5|0v?7! zh9X7=0jK=@5|IB2d{av@@>7cW*%*pB7)p2;N*T&{7|Izk*cmE#7%Ca6co?b~su&qq z3QIFfco=FJY8e?=QY$h`7#ZX-+!^%PtyQgaJ(Qmqt>6-?L}T6h>* z8QK^bWN-$1Ku#qnyxMsfIv6?`8N8hHOA8b-b8-%^Oi#>F&`3@!PF2WHPA)AtyfRfm zUm+vEs92#OC$S_ou~b1{AvdwKEHSef8X1~;3PFcgrWO|`R;E_z@i26OOymQbn4XxP zmzYr9mgOU6& zl!6i)D09J*H;4~Osf-K)h!_nnDay=CXJinLhGai*a)bz4V+1D143L?S9L30>h%3uM zEV2e=Ur`NAgF)iRZm29SNzG+sV9qZsVPp`6sL#yT4=BpaD+w+sN=?kQW@HcsI~rA( zk%7Gcq$nqkkpaab|D>$cgtpa7(WKdGmD9SHaNY2mERIpND zWDw6y%uaRA&r41$3C}Fa0F@;riFqZ(Xcj`FLKD+MMg~@}-x(PM!65_6YOrFLk%1#G zwW0)6WHK^{XkgXNQc{$e%g7**T3DKxQ|y_ZmtU0XoLHQS7LqUrL@_e3r>B+#XI7;$ zGB9gsdNMK?xPsDb6-t^_uu_0}Q$fQ(!NwNE(@D7eR}ouL<0zD;CgPyt5{*qxbqW%=2u`VenH zqTVerxg@`+lAU2PBLkaHetvdo0V4yCC#dRl&PgmTPAz6+n1SpSs2Pyb+#@kBB`395 z1)>pJfr71q*nup9qA{ehAQf2>svJ3>v7~gU5zdJ@Il-AFsn+ZaQy3XkG5m+kZHx?Z z_|-8eGN>`AGcYhPG6*qfFlaI`FfcJNGH5YqGcYpfFfcG^GcYkQGcYi4YiVz1VARst z%D}V{tX!9Yfq@S!CCI?aAjH7MAk4tXpvRyO(a3m+ft7)Sfq~(@_CW^bSq!|p8CW8P zShq8}Mg}a?BFVyRw1Yv`j8&3_1Rappel des conditions de victoire + *
    + *
  • {@link Player#PLAYER1} gagne s'il existe un chemin de pions connectés + * reliant le bord gauche au bord droit.
  • + *
  • {@link Player#PLAYER2} gagne s'il existe un chemin de pions connectés + * reliant le bord haut au bord bas.
  • + *
+ * + *

Idée de l'algorithme de détection de victoire

+ * On modélise le plateau comme un graphe : + *
    + *
  • Chaque case est un sommet
  • + *
  • Deux cases sont connectées si elles sont voisines sur la grille hexagonale (6 voisins)
  • + *
+ * + * Pour tester la victoire d'un joueur, on lance un parcours (DFS/BFS) : + *
    + *
  1. On part de toutes les cases du bord de départ qui contiennent un pion du joueur.
  2. + *
  3. On explore tous les pions du joueur connectés à ces cases.
  4. + *
  5. Si on atteint le bord opposé, il existe un chemin : le joueur gagne.
  6. + *
+ * + * Complexité : O(N²) au pire (on visite chaque case au plus une fois). */ public class HexBoard extends AbstractBoard { + /** Taille du plateau : size x size. */ private final int size; - private Player[][] cells; - private Deque historyLocal; + /** + * Grille des cases. + * Une case vaut : + *
    + *
  • null : case vide
  • + *
  • PLAYER1 : pion du joueur 1
  • + *
  • PLAYER2 : pion du joueur 2
  • + *
+ */ + private final Player[][] cells; + + /** + * Offsets des 6 voisins d'une case dans une grille hexagonale. + * + * Pour une case (r,c), les voisins potentiels sont : + * (r-1,c), (r+1,c), (r,c-1), (r,c+1), (r-1,c+1), (r+1,c-1). + */ private static final int[][] NEIGHBORS = { - {-1, 0}, {+1, 0}, - { 0, -1}, { 0, +1}, - {-1, +1}, {+1, -1} + {-1, 0}, {+1, 0}, + { 0, -1}, { 0, +1}, + {-1, +1}, {+1, -1} }; + /** Crée un plateau vide avec {@link Player#PLAYER1} qui commence. */ public HexBoard(int size) { - super(); - this.size = size; - this.cells = new Player[size][size]; - this.historyLocal = new ArrayDeque<>(); - this.currentPlayer = Player.PLAYER1; + this(size, Player.PLAYER1); } + /** + * Constructeur interne, utile pour {@link #safeCopy()}. + * @param size taille du plateau + * @param current joueur courant + */ + private HexBoard(int size, Player current) { + super(current, new ArrayDeque<>()); + if (size <= 0) throw new IllegalArgumentException("size must be > 0"); + this.size = size; + this.cells = new Player[size][size]; + } + + /** @return la taille du plateau. */ + public int getSize() { + return size; + } + + /** + * Vérifie si (r,c) est dans le plateau. + * @param r ligne (0..size-1) + * @param c colonne (0..size-1) + */ private boolean inBounds(int r, int c) { return r >= 0 && r < size && c >= 0 && c < size; } + /** @return le contenu d'une case (null si vide). */ private Player getCell(int r, int c) { return cells[r][c]; } + /** Modifie une case (utilisé par doPly/undoPly). */ private void setCell(int r, int c, Player p) { cells[r][c] = p; } + /** + * Teste la victoire de PLAYER1 (gauche -> droite). + * + *

Détails de l'algorithme

+ *
    + *
  1. On initialise une structure "visited" pour ne pas revisiter les cases.
  2. + *
  3. On met dans une pile toutes les cases du bord gauche (colonne 0) + * qui contiennent un pion PLAYER1.
  4. + *
  5. On effectue un DFS : + *
      + *
    • on dépile une case
    • + *
    • si elle est sur la colonne size-1 : on a touché le bord droit -> victoire
    • + *
    • sinon, on empile tous ses voisins qui sont des pions PLAYER1 et pas encore visités
    • + *
    + *
  6. + *
+ * + * @return true si PLAYER1 a un chemin gauche->droite, false sinon + */ private boolean hasPlayer1Won() { boolean[][] visited = new boolean[size][size]; Deque stack = new ArrayDeque<>(); + + // 1) points de départ : bord gauche for (int r = 0; r < size; r++) { if (getCell(r, 0) == Player.PLAYER1) { visited[r][0] = true; stack.push(new int[]{r, 0}); } } + + // 2) DFS while (!stack.isEmpty()) { int[] cur = stack.pop(); - int cr = cur[0]; - int cc = cur[1]; + int cr = cur[0], cc = cur[1]; + + // condition d'arrivée : bord droit if (cc == size - 1) return true; + + // explore les 6 voisins for (int[] d : NEIGHBORS) { int nr = cr + d[0], nc = cc + d[1]; - if (inBounds(nr, nc) && !visited[nr][nc] && getCell(nr, nc) == Player.PLAYER1) { + if (inBounds(nr, nc) + && !visited[nr][nc] + && getCell(nr, nc) == Player.PLAYER1) { visited[nr][nc] = true; stack.push(new int[]{nr, nc}); } @@ -66,23 +157,42 @@ public class HexBoard extends AbstractBoard { return false; } + /** + * Teste la victoire de PLAYER2 (haut -> bas). + * + * Même principe que {@link #hasPlayer1Won()} mais : + *
    + *
  • Départ : bord haut (ligne 0)
  • + *
  • Arrivée : bord bas (ligne size-1)
  • + *
+ * + * @return true si PLAYER2 a un chemin haut->bas, false sinon + */ private boolean hasPlayer2Won() { boolean[][] visited = new boolean[size][size]; Deque stack = new ArrayDeque<>(); + + // points de départ : bord haut for (int c = 0; c < size; c++) { if (getCell(0, c) == Player.PLAYER2) { visited[0][c] = true; stack.push(new int[]{0, c}); } } + + // DFS while (!stack.isEmpty()) { int[] cur = stack.pop(); - int cr = cur[0]; - int cc = cur[1]; + int cr = cur[0], cc = cur[1]; + + // condition d'arrivée : bord bas if (cr == size - 1) return true; + for (int[] d : NEIGHBORS) { int nr = cr + d[0], nc = cc + d[1]; - if (inBounds(nr, nc) && !visited[nr][nc] && getCell(nr, nc) == Player.PLAYER2) { + if (inBounds(nr, nc) + && !visited[nr][nc] + && getCell(nr, nc) == Player.PLAYER2) { visited[nr][nc] = true; stack.push(new int[]{nr, nc}); } @@ -98,18 +208,50 @@ public class HexBoard extends AbstractBoard { int r = hp.getRow(), c = hp.getCol(); return inBounds(r, c) && getCell(r, c) == null - && hp.getPlayer() == this.getCurrentPlayer(); + && hp.getPlayer() == getCurrentPlayer(); + } + + /** + * Teste si un coup est immédiatement gagnant. + * + * On joue le coup, on teste la victoire, puis on annule le coup. + * Cela permet d'évaluer un coup sans modifier définitivement l'état du plateau. + * + * @param move coup à tester + * @return true si après ce coup le joueur a gagné, false sinon + */ + public boolean isWinningMove(AbstractPly move) { + if (!isLegal(move)) return false; + Player p = move.getPlayer(); + + doPly(move); + boolean winNow = (p == Player.PLAYER1) ? hasPlayer1Won() : hasPlayer2Won(); + undoPly(); + + return winNow; } @Override public void doPly(AbstractPly move) { - if (!(move instanceof HexPly)) + if (!(move instanceof HexPly)) { throw new IllegalArgumentException("Coup invalide: " + move); + } + if (!isLegal(move)) { + throw new IllegalStateException("Coup illégal: " + move); + } + HexPly hp = (HexPly) move; - if (!isLegal(hp)) - throw new IllegalStateException("Coup illégal: " + hp); setCell(hp.getRow(), hp.getCol(), hp.getPlayer()); - historyLocal.push(hp); + addPlyToHistory(move); + setNextPlayer(); + } + + @Override + public void undoPly() { + AbstractPly last = removePlyFromHistory(); + HexPly hp = (HexPly) last; + + setCell(hp.getRow(), hp.getCol(), null); setNextPlayer(); } @@ -120,46 +262,32 @@ public class HexBoard extends AbstractBoard { @Override public Result getResult() { - if (hasPlayer1Won()) return Result.WIN; - if (hasPlayer2Won()) return Result.LOSS; - return Result.DRAW; + if (!isGameOver()) return null; + if (hasPlayer1Won()) return Result.WIN; // du point de vue PLAYER1 + return Result.LOSS; } @Override - public Iterator getPlies() { - Player me = this.getCurrentPlayer(); + public Iterator iterator() { + Player me = getCurrentPlayer(); List moves = new ArrayList<>(); + for (int r = 0; r < size; r++) { for (int c = 0; c < size; c++) { - if (getCell(r, c) == null) moves.add(new HexPly(me, r, c)); + if (getCell(r, c) == null) { + moves.add(new HexPly(me, r, c)); + } } } return moves.iterator(); } - @Override - public Iterator getHistory() { - return historyLocal.iterator(); - } - - @Override - public void undoLastPly() { - if (historyLocal.isEmpty()) return; - HexPly last = (HexPly) historyLocal.pop(); - setCell(last.getRow(), last.getCol(), null); - this.currentPlayer = last.getPlayer(); - } - @Override public IBoard safeCopy() { - HexBoard copy = new HexBoard(this.size); - copy.currentPlayer = this.currentPlayer; + HexBoard copy = new HexBoard(this.size, this.getCurrentPlayer()); for (int r = 0; r < size; r++) { - for (int c = 0; c < size; c++) { - copy.cells[r][c] = this.cells[r][c]; - } + System.arraycopy(this.cells[r], 0, copy.cells[r], 0, size); } - copy.historyLocal = new ArrayDeque<>(this.historyLocal); return copy; } @@ -180,8 +308,4 @@ public class HexBoard extends AbstractBoard { sb.append("Current player: ").append(getCurrentPlayer()).append("\n"); return sb.toString(); } - - public int getSize() { - return size; - } } diff --git a/javaAPI/fr/iut_fbleau/HexGame/HexMain.java b/javaAPI/fr/iut_fbleau/HexGame/HexMain.java new file mode 100644 index 0000000..e9d3885 --- /dev/null +++ b/javaAPI/fr/iut_fbleau/HexGame/HexMain.java @@ -0,0 +1,34 @@ +package fr.iut_fbleau.HexGame; + +import fr.iut_fbleau.GameAPI.*; + +import java.util.EnumMap; +import java.util.Scanner; + +/** + * Lancement d'une partie de Hex en console. + */ +public class HexMain { + + public static void main(String[] args) { + int size = 7; + if (args.length >= 1) { + try { size = Integer.parseInt(args[0]); } catch (NumberFormatException ignored) {} + } + + HexBoard board = new HexBoard(size); + + Scanner sc = new Scanner(System.in); + EnumMap players = new EnumMap<>(Player.class); + players.put(Player.PLAYER1, new HumanConsolePlayer(Player.PLAYER1, sc)); + players.put(Player.PLAYER2, new HumanConsolePlayer(Player.PLAYER2, sc)); + + AbstractGame game = new AbstractGame(board, players) {}; + Result res = game.run(); + + System.out.println(board); + System.out.println("Résultat (du point de vue de PLAYER1) : " + res); + + sc.close(); + } +} diff --git a/javaAPI/fr/iut_fbleau/HexGame/HumanConsolePlayer.java b/javaAPI/fr/iut_fbleau/HexGame/HumanConsolePlayer.java new file mode 100644 index 0000000..63068fc --- /dev/null +++ b/javaAPI/fr/iut_fbleau/HexGame/HumanConsolePlayer.java @@ -0,0 +1,68 @@ +package fr.iut_fbleau.HexGame; + +import fr.iut_fbleau.GameAPI.*; + +import java.util.Scanner; + +/** + * Joueur humain en console. + * + * Format attendu : "row col" (indices à partir de 0). + */ +public class HumanConsolePlayer extends AbstractGamePlayer { + + private final Scanner in; + + public HumanConsolePlayer(Player me, Scanner in) { + super(me); + this.in = in; + } + + @Override + public AbstractPly giveYourMove(IBoard board) { + if (!(board instanceof HexBoard)) { + throw new IllegalArgumentException("Ce joueur attend un HexBoard."); + } + HexBoard hb = (HexBoard) board; + + while (true) { + System.out.println(hb); + System.out.print("Joueur " + board.getCurrentPlayer() + " - entrez un coup (row col) : "); + + String line = in.nextLine().trim(); + if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) { + throw new IllegalStateException("Partie interrompue par l'utilisateur."); + } + if (line.equalsIgnoreCase("help")) { + System.out.println("Entrez deux entiers : row col (0 <= row,col < " + hb.getSize() + ")"); + System.out.println("Commandes: help, quit"); + continue; + } + + String[] parts = line.split("\\s+"); + if (parts.length != 2) { + System.out.println("Format invalide. Exemple: 3 4"); + continue; + } + + try { + int r = Integer.parseInt(parts[0]); + int c = Integer.parseInt(parts[1]); + HexPly ply = new HexPly(board.getCurrentPlayer(), r, c); + + if (!hb.isLegal(ply)) { + System.out.println("Coup illégal (case occupée / hors plateau / mauvais joueur). Réessayez."); + continue; + } + + if (hb.isWinningMove(ply)) { + System.out.println("Coup gagnant !"); + } + + return ply; + } catch (NumberFormatException e) { + System.out.println("Veuillez entrer deux entiers."); + } + } + } +}