From 353163005704843ac96f8875a85efb6bcb0ea367 Mon Sep 17 00:00:00 2001 From: l21211714 <tom.larguier@etu.univ-amu.fr> Date: Fri, 8 Dec 2023 17:18:18 +0100 Subject: [PATCH] Ce con sait pas faire de git --- __pycache__/puissance4.cpython-310.pyc | Bin 0 -> 3232 bytes __pycache__/test_puissance4.cpython-310.pyc | Bin 0 -> 1963 bytes puissance4.py | 140 ++++++++++++++++++++ test_puissance4.py | 51 +++++++ 4 files changed, 191 insertions(+) create mode 100644 __pycache__/puissance4.cpython-310.pyc create mode 100644 __pycache__/test_puissance4.cpython-310.pyc create mode 100644 puissance4.py create mode 100644 test_puissance4.py diff --git a/__pycache__/puissance4.cpython-310.pyc b/__pycache__/puissance4.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b1015cf425bb15d7419ab92b9e42e8f458fbe8b6 GIT binary patch literal 3232 zcmd1j<>g{vU|^VUQJnfifPvvLh=Yuo7#J8F7#J9e!x$JCQW#Pga~Pr+Q<zeiTNt94 zQdm-0TNt94Q`l12TNt8PQaDmLTNt8PQ@B#NTNt9)Qg~8$TNt9)Q}|N&TNt7^QaMuu zvYCoBQ#qO$7#UI+gTYu+@FmDbzhn@Jj9C~M7@R?N^D!_mlrUs5rZAQ;r7-m}1v6+e z`)M-0WMg1pc*)Mdz_60>7HdjLWkISY^DU;lf?KRrsYUt4x0o~YN>(xyaWXJKh_4`@ zI9tVp7N-^!$CTvf<|M{=hK9rho5lo|Cgx<89A2rAn3J9#6B3{hP?}j>oS2uKs$ddR z0Ariz6;$5hNiIrFEJ=+|%1<mxVFtMm6i9rGMcfPw49Sd0J^)FA+z9qW5d#B54TB3q ztVu0n2}24v5PO*z8EP0^7-E%bnQE9)ShAUlBuf}lSW_5Nm_c%dJT*)yY}rgjDkTgl z>?oof*-S-xB@8K?2+<M-P_ULTq;NGeGBOl0r7#3DXmb1gVywBvpvicPIW;e(2;{sf zW(5U>mrz!O!b_0ztC$u16{=*kb#--dVNJ$ctOZ4xc_o_6w^+fRzr|dXUw(@@IX?#x z#zmm?bc-9T5E4Y75Ga;nU|`^2<YDAs<Y453Vjf1O1~x`6MwV|yqM)DyxdRq@AT~Vy z4M1s+v4)X_ftewjv4|^$DVwoKERTtiA&;wuA%(eyF@;frA&p6rA%!`cDVQOJC73~z z)vt&j6!D-)0DIdF>_|<fA|a5l2#A2E42Y`*GmGQP5_2+B;&bwo6H7Al^Mqm1Yrs?_ z267|FG?*Jf?gM!a9KE2V1&vmwW@Z<LSn*os8ipE>+nAwl14XZF4HL4c4JaQl1Tz$} zfg_96?<FfJP5=M@|3Ad_pjZN>?xMuJ^i)k2gxhbi733sVrWO@}oCx+Aga8LWS4vTS zL3}}GYI3SL$Ok+O3=9H{B8&ozY>Z6*SpFBufcydqW2}C;#|X-ADU8jaq-k8sRKk$L z1ZL|%{lo+c>l(&vrXn-2Z<tb;#lhi^BF2J6j1^go5#)QeV1`1jLKaX02ipO$j}^?u zv@Z{2AIP>Egc~4YEaD6pVyviQaQmDJZ9s7aw!;$aKZt!s82(#>un%M_+}{v!u$?K$ z{)C8w?M*@U>l(P-RfQ#RyR9I0r!X}$xiG|H+Ws11y97fGY6wHbS-|4RwnM~O!Q#la zzlPhsvv5-iM=*mXr{7CZ@+|_T0Z2*{03|$7@(w8ik#0qj3=9mg6ekVJE#NGJExGZO zXXfQ)=B3By=9i_)f)bn;0|NsO6Az;RlL#XSaxgJ9F#Y7=!Y(4g2!b#*e2fB2Aie}6 zM1+O2NFF`8f(m^Q24}rV;Ob!kV-2W+VrXST6bB12#B3N!pz<}0;6T@^WrFJiC#hQI z8s-}26sBxuNrqaM6y_4<8kS~835HtM5{3mVB@9`tHLN9UDJ;EAH7sdN3mI$KYS@rX zuwf{afo5h%z=E<cB%DDZuE|~mDl=}eq~&B56oHDxTg*ABdAGQe^YfAuOH%U^OHzwK zUMu1Ng+DtY$47A{=jX&{=B1=oL~($aDTyVCQG$8-dGVm?E<QCUH8(Y{q&SK*uQV4d zR2;>gms%c=rF`ZqN-aw*DozE-mFDL8fZ`040JIo|m;@Mk7<m{a7=;*Feitc&LLOE~ zfM}58K`sM_d<eLpXlAHoNMWpHOkt{Js$nc%QNxtNl+9EmR>D}r0IG>fm{ORV8EcvI zI7^sISh83bu%$4iuq<Q(iB*-?FfU+FVO_{r<eS1&!T}2T6oytNNrq-vac`Q!md#k? z3oh=(P*v2jlyKHC)UY%&F*1~JrLfnq%w|a8n9B^ZHO~X2wwbY(wT3l?Gn=U>ri2Sp zGp2CYGUi#9aMv)@ur@OlO)TL7v1*u_nHd>McxxDHn3|c2s^PBZO5v$tn$3{H3o#e0 zn<a&>hDm~<mZ^kg0bdP63V$~9LdK#ANO}Z7Zh)vQ;Ytw%@xmGMcv%=q_$wEKvLo2V zLLl)-hCIe{h8o5qPEfi5VNGE_H*n&qiuKAbO)V`_FjUZp(9}^#&dAR!&MYoYtx_n> zOI1kD&&kirOI6S?)HT;p&^1&j$S*BYC@jq^DM>BTQ7D26Wafb*yGS7?5w68hQ^88% zB`79uF&2Syd=-Z?)VNYmOGW{r>+s4{y&?$)28Jr(fW)Gb%v6QUypq(SqWs)~(p0^W zDt4#?OF<QnLZU)?VtU@;m5N1jpb`U=^sBgh6HAga6!J=Q6iYQgO**J8nR(#4HdRl- z8R4tL3l#G5OUqIdOZ7@~85kH`^Gb>iuLM~NQyi9BnwgW6TBT5&m|2`zq)?itke8pE zRFtZaLScaDX$pYbaNyR+E!NDug3^*(%*7=|kQ~cal$e*2pL>fPL}%ue+~O)ONh~TU zF3&8<0B2TkW+@T`c^uSM09Uf$qU#oOVouI2uCT<M(p1-?qWmIFHgL9%;!ID>O^wel zOD&3GDJd<=i{dIRPA!TD+Z@FQ%Ht*Z@zAVV1TKEjS}dHPMnF8sln783c4J^*U}Izf zK_*a3i;Gc+iHS*%QGk()QHYU)iGzuQ5!B-1VdP@s0JjD>nE1ddSs0lbIG9)(Kv|#Z zKhM1)T?Ph*TO9H6xrv#1@$s5mw^;K^a|<fLL4gP*aH9y}QAh~DwB~_47Y}Kcpt+mF oCO1E&G$+*#ltPL@p~b<#!NkGL!OOwI!N#G_!NZ}=#mMp>0F0Zr`Tzg` literal 0 HcmV?d00001 diff --git a/__pycache__/test_puissance4.cpython-310.pyc b/__pycache__/test_puissance4.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68241a7089fc93ded2a8e6c79ab4c72b6010ec30 GIT binary patch literal 1963 zcmd1j<>g{vU|`r|S)3}u#=!6x#6iX^3=9ko3=9m#VGIlmDGVu$ISf${nlXwgg&~D0 zhdGxeiY1pdiZz!liY=EtianPjii45Cogsxeg{6fdg(a0Ci?f+IiYt{ng*BV0NHdjT z0nb7PMurr|U@+EXdkM19Pm}c)PjXReVo7RzQhs7l$}Pdn;`p+}oXnK?oc!d(lFa<P zTU;qc`33O>nW@RCxA=-u%TkMqQ{$8Kb4qjbZt;|7=H+GPrN`&ym!&3yj6}vvFprop zFfgPtL@}l?L@}i>rZBZIL@`608pV>rn!?t?5XG9pp2E?>5XF|lnZnh=5XGLt9n7G~ zbBiw|wYVgpG_$xkF)umQB$*M(0+9Kjz;Xr!mKFm8LkUAOLoH(s!ve+{#w?~3#)V9b z3^fc3m}?kQn6jA`uq<R)$jHc$!Vt`$$?T`e^pcH%f#D@P0|P@5$XHF*B9Mu<xD$(u zQ;SMm3riDoZm||;Bo?IJ;(~~U6qTmlVouD-S;=&Zr8qSw?G`II+*UFa2{JG+e061D zU~smI2`x@7Dvl}1&&^4U@eB=#2{w%hEKSVGEIGVVAu%UCKPDtV0q!RSlbDj!;*$6R zxF_`rDsKsb#gO9$<k(^m!N$nPD8^W&fEqG-7#c9biWTHK%&;n9s$ooFY-R$54Jfq0 zd?pAV8dfhs;q#J%fq_Aj1sq64JfKixW?*1|1(#c5PH}1xA4nJ!6yWeE5&|g@1G@|( zVR3_80`ZRkqX=V_DmMRM=)&+6JOQY|6F><g$U`ZN&CKBF2YHW4k^zz&pdKm`0r`dL zB`8QBk<SeA7s$9GQ2xZ~6@IW+5E()M;Rha&ALOw40ihhl@u0v1Sr1OVpd128y(OTy zV02-K<)~$X#6$`c$Rma9;J9G{rDfE(0XrG&A7}z*ElSKwPb~tAgX0Ml%9_kY{GiAI zIr$c2JS2X=F$In!NP0ug&Y~c{fufv^k%y5F<U6b>4p|F^|2SbOt_B=A3mDTGQWzJ3 zNG34J3?`A;AQ85OjJ1qlzq2$mF*1}eAn60iGo(OBWPKnuNFNh8lo%GU)G*dCEd-}& zaFnz9X|jVO8b1M5^b%AM;8Y1!1WrRZ6&1;WQW)zkro4hE*2JQs#L6O2Y=bjS6gOBP zJ{45NAV*9Te`-ZRYH~?xN_<gjacNEodNc`x6Ci3SEDee%6$S<d7DhH?_=}5^g$Y$e zjI&A!TM|Vz&`*=&7Ds%1USe))eEco0`1suXl+qj!n<qXV<Yb6UkuWGdiGv795Fra9 z6hH(xSs@5e0xJR)v!DPd2Bk<21`b9JRuJT21IvKy%T3J8i;vgjjp8WH%PawTG>SE^ zG`FC#NS=X#A&Lu8Kti%AC<8$fImp~1P$Iv@0rH)5VsR?i)FMSt`NIM-7%3pZ4g<OA d7KaVQXLg|Ctr%2xfgC2oD8$5}%fra>9{_i^v2p+a literal 0 HcmV?d00001 diff --git a/puissance4.py b/puissance4.py new file mode 100644 index 0000000..c0600bb --- /dev/null +++ b/puissance4.py @@ -0,0 +1,140 @@ +import numpy as np + +def create_board(): + return np.zeros((6, 7), dtype=int) + +def print_board(board): + for row in board: + print("|", end="") + for col in row: + if col == 0: + print(" ", end="|") + elif col == 1: + print(" X ", end="|") + elif col == 2: + print(" O ", end="|") + print() + print("+---" * 7) + +def is_valid_location(board, col): + return board[0, col - 1] == 0 if 1 <= col <= 7 else False + +def drop_piece(board, col, player): + for row in range(5, -1, -1): + if board[row, col - 1] == 0: + board[row, col - 1] = player + break + +def winning_move(board, player): + for col in range(4): + for row in range(6): + if ( + board[row, col] == player + and board[row, col + 1] == player + and board[row, col + 2] == player + and board[row, col + 3] == player + ): + return True + + for col in range(7): + for row in range(3): + if ( + board[row, col] == player + and board[row + 1, col] == player + and board[row + 2, col] == player + and board[row + 3, col] == player + ): + return True + + for col in range(4): + for row in range(3): + if ( + board[row, col] == player + and board[row + 1, col + 1] == player + and board[row + 2, col + 2] == player + and board[row + 3, col + 3] == player + ): + return True + + for col in range(4): + for row in range(3, 6): + if ( + board[row, col] == player + and board[row - 1, col + 1] == player + and board[row - 2, col + 2] == player + and board[row - 3, col + 3] == player + ): + return True + + return False + +def reverse_column(board, col, turn): + board[:, col - 1] = np.flip(board[:, col - 1]) + + for col_index in range(col - 1, col): + col_data = board[:, col_index] + non_zero_elements = col_data[col_data != 0] + num_zeros = 6 - len(non_zero_elements) + new_col = np.concatenate((np.zeros(num_zeros, dtype=int), non_zero_elements)) + board[:, col_index] = new_col + + return 3 - turn + + +def play_game(): + board = create_board() + game_over = False + turn = 1 + + while not game_over: + print_board(board) + + if turn == 1: + user_input = input("Joueur 1 (X), choisissez une colonne (1-7, -1 pour quitter, r1 pour inverser verticalement la colonne 1) : ") + else: + print("Tour de l'IA :") + col_input = str(np.random.randint(1, 8)) + + if np.random.rand() < 0.2: + available_cols = [col for col in range(1, 8) if board[5, col - 1] != 0] + if available_cols: + col_to_reverse = np.random.choice(available_cols) + turn = reverse_column(board, col_to_reverse, turn) + print(f"Colonne {col_to_reverse} inversée (IA).") + continue + + user_input = col_input + + try: + if user_input.startswith("r") and 1 <= int(user_input[1:]) <= 7: + col_to_reverse = int(user_input[1:]) + turn = reverse_column(board, col_to_reverse, turn) + print(f"Colonne {col_to_reverse} inversée.") + else: + col = int(user_input) + + if col == -1: + print("Partie interrompue.") + game_over = True + elif is_valid_location(board, col): + drop_piece(board, col, turn) + + if winning_move(board, turn): + print_board(board) + print(f"Joueur {turn} a gagné!") + game_over = True + else: + turn = 3 - turn + + if np.all(board != 0): + print_board(board) + print("Match nul!") + game_over = True + else: + print("Colonne invalide. Choisissez à nouveau.") + except ValueError: + print("Entrée invalide. Veuillez saisir un nombre de colonne (1-7, -1 pour quitter, r1 pour inverser la colonne 1).") + + +if __name__ == "__main__": + play_game() diff --git a/test_puissance4.py b/test_puissance4.py new file mode 100644 index 0000000..dfc534b --- /dev/null +++ b/test_puissance4.py @@ -0,0 +1,51 @@ +import unittest +import numpy as np +from puissance4 import create_board, is_valid_location, drop_piece, reverse_column, winning_move + +class TestPuissance4(unittest.TestCase): + def test_create_board(self): + board = create_board() + self.assertEqual(board.shape, (6, 7)) + self.assertTrue((board == 0).all()) + + def test_is_valid_location(self): + board = create_board() + self.assertTrue(is_valid_location(board, 1)) + self.assertFalse(is_valid_location(board, 8)) + + def test_drop_piece(self): + board = create_board() + drop_piece(board, 1, 1) + self.assertEqual(board[5, 0], 1) + + def test_winning_move(self): + board = create_board() + for _ in range(4): + drop_piece(board, 1, 1) + self.assertTrue(winning_move(board, 1)) + + def test_reverse_column(self): + board = np.array([ + [0, 0, 0, 0, 0, 0, 0], + [0, 2, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0], + [0, 2, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0] + ]) + + reverse_column(board, 2) + + expected_result = np.array([ + [0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0], + [0, 2, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0], + [0, 2, 0, 0, 0, 0, 0] + ]) + + self.assertTrue(np.array_equal(board, expected_result)) + +if __name__ == '__main__': + unittest.main() -- GitLab