From 17b832064c7649dacfbe7d3e4c24b26700622a3d Mon Sep 17 00:00:00 2001 From: Rh17S15 Date: Mon, 22 Sep 2025 19:43:52 +0200 Subject: [PATCH] Split tictactoe into different files, classes, and functions to comply with MVC --- MVC/__pycache__/minimax.cpython-310.pyc | Bin 0 -> 2382 bytes MVC/__pycache__/model.cpython-310.pyc | Bin 0 -> 1845 bytes MVC/__pycache__/playerhandler.cpython-310.pyc | Bin 0 -> 587 bytes MVC/__pycache__/printer.cpython-310.pyc | Bin 0 -> 3407 bytes MVC/__pycache__/savestate.cpython-310.pyc | Bin 0 -> 319 bytes MVC/__pycache__/tictactoe.cpython-310.pyc | Bin 0 -> 3239 bytes MVC/main.py | 3 + MVC/minimax.py | 69 ++++++++++ MVC/model.py | 59 ++++++++ MVC/playerhandler.py | 16 +++ MVC/printer.py | 84 ++++++++++++ MVC/tictactoe.py | 126 ++++++++++++++++++ 12 files changed, 357 insertions(+) create mode 100644 MVC/__pycache__/minimax.cpython-310.pyc create mode 100644 MVC/__pycache__/model.cpython-310.pyc create mode 100644 MVC/__pycache__/playerhandler.cpython-310.pyc create mode 100644 MVC/__pycache__/printer.cpython-310.pyc create mode 100644 MVC/__pycache__/savestate.cpython-310.pyc create mode 100644 MVC/__pycache__/tictactoe.cpython-310.pyc create mode 100644 MVC/main.py create mode 100644 MVC/minimax.py create mode 100644 MVC/model.py create mode 100644 MVC/playerhandler.py create mode 100644 MVC/printer.py create mode 100644 MVC/tictactoe.py diff --git a/MVC/__pycache__/minimax.cpython-310.pyc b/MVC/__pycache__/minimax.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9901c13dd2a814ceb88ca5e6833f89533ca54077 GIT binary patch literal 2382 zcmZ`*TWcFf6rRg!wYvEhHNh&^)&Pz{>H)V$6@dQTJ$~$K?L>5Zramb`VA3G@M9wQnC&t_w@J-72S2jqpq%{}3?4v> zZi8^iE)@hL1Un|XTySAPZ-^XZFjfAE7kItaGbabW*;fI@f`$ukF)_Oa z_9HW~l0ut}@`KMH-%!sG$bDsIP)|%z0L+slFUr{eLfTYR#KQ61N?})}ICo;65=x-Y zC#6$5DvLq_4OU+ki>su~;WYAs42k?*EP-yq2<#xi2WM-`TW9PXj+saUM2$yJo4yytPT1==@tH-q z+uLM;E?pdcFnJ5>nfs<6IxRnHu1{mG+z`e}6g5i~oPF2n+CO=L%C-Hl6-#_Yash%6-3e;L1;IXTK%0(fxE} zX-GsYe(y%H9XX+NRYB{$@JClJ;|f+VYc8EDxxIdTU^}kwN2-)A#@4QHp)20Hyous% z5P4`(6T||wsBzh<%%D|PrAxF*Z_+X?!?*}Nda&p0pQXwjYOx|+0cp?`ez^F?u{v0z z*@v`)O;gP+C{HLfIw>@!3+?9-K5_$!42o@{LCF~q0!4RsV&PLug2ng|B}hp$i?}ZK z(OfK048(p7vA~WPi(H(}(Z_F{Zy#Srpbb5e1-=;#SIQ$S3ET=CE!gR_Ppt;q<4_qWd6@ zkix1+VQF1q_Px>-`XXJv1NS{B4$@y%rU`3HmLXg&f&hjxJxxtgzZ85Vs<7E{1NT{9 zHot^ngrMyCJ#zSAR`8dU00fdTNfsip;wAhIK%$&d1#kI&Ehq2bUhNJ6s RIh3`TLO1beDoX^k@*ha$_u2pe literal 0 HcmV?d00001 diff --git a/MVC/__pycache__/model.cpython-310.pyc b/MVC/__pycache__/model.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d6aeeded680c396a418fbe8f93737c2c60b0079 GIT binary patch literal 1845 zcmZux&2HO95Z+lXe9)FuYb(o3mwpOjSP7hvwNDVOxoa8cKV9xCeF`J zTK#;WTBGD5Yd!1s^E_)k)p<`RgF!m%wVqy<{e1ZUl+qW&-ofL?t>j&ydIriY{R z!}DS5$&Zg(1Bw$FHbESx!?cWJ0#}4+JXk#Sf5%Nr$kAd`m(VX7`2t@{%tz=<94#hd z2ot2>j7=~hdu*RgfcgilR*}NnuPJ+)1QmI@ft`V03|tz2lqHu+e{I6K6LG5e{v4eWi$?NmegzYlf^XOxQ{=qb6(uVD%~ed zSYZp)hTGP+@C5s3IzEZGanfN~30G9Y-KFK*XpE2H{Dd@bl3TZ0u%-AF?kk9#kcY5K zg5lzg5aXQ{(b$dA7X5vO$w0-ismC}cFEaAOIR5z}$*L6#L{ok1J7nG`Lv^A*CPP`& zB(N1kw#4Z7ph<%C78F6i1OyP&f=1xd6AHT?`Nq$SBdX%f(zr`!*fOR=-gbit9#pWu OBW>8y4Q%o5^8WyE<$uut literal 0 HcmV?d00001 diff --git a/MVC/__pycache__/playerhandler.cpython-310.pyc b/MVC/__pycache__/playerhandler.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f704828c1a78e887b74348b59c9a483b805089e0 GIT binary patch literal 587 zcmY+ByH3L}6o&0w+E7}C4onOTEE&=WW`rtL0(GENDnckivZ6R7QJo7;GZY~)&^O=( zSQvOEue=2l=Oit($NInc`0^je&U?KMf%ts=;O~@>Z%npBhhzvU`+zIL38yR2o8}R& z&4{fBFuoHSWJ6GS0tksmIq@`3Jso6#Oi+t!Twf8d%_(>osy7w>GL*5OaS_T%04Mni z?4#!hR2~61eIX3011Z;m8aIGCC*WmHZWX;(^yU(5+eK}As=DhA3u0exva=@B{KTfp zC`0l1MdTh7_<3;SJPqB#uY@}b;yf4bROXTN(=^E$!+jaS+6Ff( O>%2L_MeTsE(JKyClO+#Cf0%Ads=1_B&1Sk+8Xw?F$5T{6uiim_xuGh(#IQDhz zOM2GjDZC)TUjRtF@-O+7r#$xoQ6a%MYdiOY2JmTTXLo1!W@f*c*|5>5Y4|?+?icaR zoTmLogUQdp;5J&c2=bXGG{L?_JJokJp+C@?hJ*R3PsivsTI7Sc+Ab5?t}d9+ztwgP zVF(kwDN3S@z9cHbLSGhDQA1x5bE1yk5)CnrzA7$>1@tv>SuCQT6EBD>=U*9^> zV{N1h^FWu^L@8*1FN1$sRDue43;gS%8Zc4A?|CQ8pBS+g8zVN-m$i|xteujql6>64 zKkG0t8#ROmrR$w!j`MZS`3Bl%%4$uP8g3xYpsAL!^)s?1WgBN?N6I#zF`jBoGcEPW z*0dz;VBbv*-wjeDiX~Re$o2QqvbX2CzDU_ODLeR8lUK0)*~4}(JapTAd*HVpIK43R z+uJhSm-gYI7wosUhjA|q##62w1pEB{{dQmOul1$B=6P%VgSCU8{l&w(m{iVg^@nLq z@#+sr&1fE^&KB7^+I2S1%s-RG{BBxfQHMdS_=qP{>6)I_LFk%J83X3vCcTr~{wf?u zzV98m0e8Ys3NNr@H{!N*x$R5W7DFC7&YHi^U67mM>xlsmVL;lb9cdM=tjw{>X)2xnujzz=yV? z)oRHlNXlg*bSD!klx>eBm3A*-DVZ<+K3kZAHECEvQ?TY>$X_D>ds!34bqyTAN8G8A z`_Swp^*i^KYJ$fhKO>h*3Js-FQ&)aTtB>3$?veqs`c-U?ro{``64C#2mRuUEsMZ|1 z|Kh8Fp{8{F2}~7QBIFQo(h>&3$ox?gC5$eO^ni^FjLJWk5RB}^93e1cLsV#Vq{&x< zQfvx~5b>BzoO5&PoVU-D zxjY&Gxwr=}=nrCU^CR2$1P=y>kD$Qn`r2l54C5FuzN27#fi6S7iVKSgKusi)$pCqd zF3nPEsO+KsJ2ia|se^#8BBWW#kWlF>XKbYPoas6}TNb0uY&1tED!6o?q!WW-T0LKx z1yU_Lj{tKGe;U03qBGOrto+x4p)*U@f7jTeak^OE&e8+QkY-cBQw=Ryz`QvQsp&Lc^zS|-XsmQ!mz#>*qUXuESr6L zC*YwkaMO`}gn&bG;60lX2GZMJI0%r#?u7&*eryLZ>Fxk$UNAsji9hD6!*jyM40Lvtwu!@gN*yR-vfHcZPkJLoed8{!@>!87ttl;0Qz>T!Oy=|xqzp=lsNZwK zd_a5&{AGc_7ZqHI)k(Hy{7oRuYDW}vBu;4WhlnqJIPhaHgYd_EqrJI>Dnn^5OBz+; zR91bRI5M?Jt%$k)Y%EmN71-W;kW+QjV!B~56G31yQy(YTTyDzR$)b6FN4x)dN6>lp zj{c9a|8{ZJ{8nu59$Bq!?DEWwp^BMUEI#7TA7*c1kX0~Q7N`Y+YJrK$fG1d98A_DV z^IBH!NRA!jG%a7lFuB^~$DZ$V#FLDXvF#zsZ&q=eW>)qI6Y>U;RU$JbxS@7N`OeQE zp$gqwEV)`3GbQm4gU+${1bcxp29(wDa#TGG)X9W=ehKr0$R*61`8UIPB z(Cv29S{D^W41D72-R|Ro?Pn{J>Vv#au^4 vnI|b?s1QeVrlncTs#=EnE#-Z~GU}$1>ol3_pLbAdeVA$d5uK<&vZ((J+0r0| literal 0 HcmV?d00001 diff --git a/MVC/__pycache__/savestate.cpython-310.pyc b/MVC/__pycache__/savestate.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f8d9b1670f86abaaa6155541c3469c53b6c41c47 GIT binary patch literal 319 zcmd1j<>g`kg22uNDYJm|V-N=!umL#^KwPW_B+?mD7#1-CNk%Zqgv4eBvRR`TQdoi+ zG+8xSZ!!A+VyyYas8GZN)K|m|Bs5vSf~ZFgQ+_dO7qNhZSwRGdrO66bf>4ZLVVAna z7~!YMc#EYtu`G2ZLlFnaAQ15@LO&xvH&wqNu{1|NI5{IfKSw{HC_lX@F*i3eFI_*N zvLquv4v?;GZ<4>G;DB(Wq_ub}c4hfQvN RN@-529V5`5Vvx7g7yv8iNXh^J literal 0 HcmV?d00001 diff --git a/MVC/__pycache__/tictactoe.cpython-310.pyc b/MVC/__pycache__/tictactoe.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ae6d0731c14141b9a1ee71f0a1ae0dfa5fce5f9 GIT binary patch literal 3239 zcmaJ@&2JmW6`z@1E|)9n!?NlmP71h4k(OvBIjPYGfn&I};~)nMZsi66QG?j-tfi%v zyX5T3u^bYJp#X7i`4d(-1TfHZZ)wqgV{&XSI=4WA9P0kw%u=Lcr6lIfn>X`5X7;`L zO}@AoF#P`UStb87q9f)L-r>x6OFS^3?PS-KL+jULf=r&C6b-j0) z6w>*GN#{^>o04y{j(ZF{Y%3x<{}UKoM=P#^#Ks5gbJ*sv%VCpuJ!=h?T-o@9b$#i{ zCi<52Wea^^JOsLRH;KwHD)V?N;xIS;5l?<@pcTIaDOtsj*qHTLDJsWsqI9c<;oQ=z znuhZvL*#s`##Pi(;o4ffS-W-Pe>E?E{o9F4~9hL8>Z~!|yn|BV%-8`F#Vzr;` zTzc=l&7s;^AF6acN!EvZ>wDSe?e}kNmeW(%7#?W9*FykhueU^-_dxzFeBm{R`kQ=w>J2>4~J^fud^t87j5uEPhxT zhYQ3RVeg@y8ysi{?o4r7vIrCERgg8b;yTC*UqK!Hl(+e7+~eLe;jN-~pZQ|Nxx@tz zoE0wqb8*Qx)fR9cD{Tw-E8rh3&FYUf5xFor{m}_iqt8&hh%Z^<3NHB*c8JP2bZ)YH zA5GjRZ0w>+kO?)1nsK3my!lxzab}XSfc)p2Np~BW_;*(&}~>1XufwAc4<$iSa9Eet%H+@pHP5jo-tm-;qD^v4-vlvuArpocOM+KKZYssf_QV z>5hL;^Q-4HzcQZxHosr8i*@E+I`N=uO~h0C)W+x6r+l8J`OR~h-x#0YTA!u(l-=hB z==_q|FMr5y;`<-+&$$Yuzs+O|@Dyy>0$)L<98(G@z&TTtrl)Rm$|Rcp66d-6;nh>tI`N3YGY|D?P(uBJJzk>c9MiIQ3+OXom3 zj#?*v14KJvnsyqduodk{T_o}{k;_Dkf7+!9Lj45X+i1m`AZy|Z3ROJ2B2H89*%ik% z^6%42!sV`bbpDKxPn|I#CRObXa@EF7Dp`$lcy1U}G|vrn*WBfJcuY8O3>A&)dLero z9M##jx$|ApknTj3z?PB_Q1qMl`U188%EUQCx?=IJ-yGK!XprXCSV-?TY$8U#9{mD* z^8&2G%O51+v)^lFe6(7lX@H0b%Lt7kNeJ!t7P93Ui*~aBTnlp}%&@9W5sv<7c*0@7 zPl)LE2}Aw za0(kvk_~lG48tgn^8Ku|`Sm(krzh+8AVRx?Fv&i^L~#?uHE*o|Xy8*50eATY{MTsw zvG{M>A-VXsSR;HeYs^|`e7m|pXwnw*I6=lc3-qYV!a>~Y>7WPjlKUy~?Ot!RAEtK3 zoTEJi!en!Tir#<*#7se`-_p=j%8VGCqn88WeL= best_score: + best_score = score + best_move = j, k + elif not is_maximizing and score < best_score: + best_score = score + best_move = j, k + + if best_score == 0 and best_move == (0, 0): # is None: + empty_cells = [(j, k) for j in range(0, len(current_field), 2) for k in range(0, len(current_field), 2) if + current_field[j][k] == " "] + random.seed() + random_move = random.choice(empty_cells) + return 0, random_move[0], random_move[1] + else: + if best_move is None: + return 0, -1, -1 # No available moves + else: + # print('The next best move is:', best_move, "score: ", best_score) + return best_score, best_move[1], best_move[0] + + def check_win(self, ifield, player1_char, player2_char): + # nothing 0, 0; draw 1, 1; win player1 1, 0; win player2 0, 1 + for j in range(0, len(ifield), 2): + if ifield[j][0] == ifield[j][2] == ifield[j][4] == player1_char: + return 1, 0 + elif ifield[j][0] == ifield[j][2] == ifield[j][4] == player2_char: + return 0, 1 + elif ifield[0][j] == ifield[2][j] == ifield[4][j] == player1_char: + return 1, 0 + elif ifield[0][j] == ifield[2][j] == ifield[4][j] == player2_char: + return 0, 1 + + if ifield[0][0] == ifield[2][2] == ifield[4][4] == player1_char: + return 1, 0 + elif ifield[0][0] == ifield[2][2] == ifield[4][4] == player2_char: + return 0, 1 + elif ifield[0][4] == ifield[2][2] == ifield[4][0] == player1_char: + return 1, 0 + elif ifield[0][4] == ifield[2][2] == ifield[4][0] == player2_char: + return 0, 1 + elif all(ifield[j][k] != " " for j in range(len(ifield)) for k in range(len(ifield))): + return 1, 1 + else: + return 0, 0 diff --git a/MVC/model.py b/MVC/model.py new file mode 100644 index 0000000..c9b6a3c --- /dev/null +++ b/MVC/model.py @@ -0,0 +1,59 @@ +import os.path +if os.path.isfile("./savestate.py"): + from savestate import save + +class Model: + field = None + def __init__(self): + self.field = [[" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "]] + + + + def do_move(self, x, y, player1, player1_char, player2_char): + self.field[y*2][x*2] = (player1_char if player1 else player2_char) + # printer() + # win = check_win(field) + # if win == (0, 0): + # savetosavestate + """player1 = not player1 + turn() controller""" + '''elif win == (1, 1): + elif win == (1, 0): + elif win == (0, 1): + ''' + + def loadsavestate(self): + if os.path.isfile('./savestate.py'): + from savestate import save + self.field = save + + def checksavestate(self): + if os.path.isfile('./savestate.py'): + return True + return False + + def savetosavestate(self): + f = open("savestate.py", "w") + f.write("save = " + repr(self.field)) + f.close() + + def deletesavestate(self): + os.remove("savestate.py") + + + def check_move(self, x, y, verbose): + + x = int(x * 2) + y = int(y * 2) + if not self.field[y][x] == " ": + if verbose: + # self.printer.occupied() + return False + else: + return True + # else: + # do_move(x, y) diff --git a/MVC/playerhandler.py b/MVC/playerhandler.py new file mode 100644 index 0000000..2440468 --- /dev/null +++ b/MVC/playerhandler.py @@ -0,0 +1,16 @@ +class Playerhandler: + + player1 = None # bool that states which player is currently playing + player1_char = None + player2_char = None + ai = None + + + def __init__(self): + self.player1 = True # bool that states which player is currently playing + self.player1_char = "X" + self.player2_char = "O" + self.ai = False + ''' + def getPlayer(self): + return''' \ No newline at end of file diff --git a/MVC/printer.py b/MVC/printer.py new file mode 100644 index 0000000..54e1c33 --- /dev/null +++ b/MVC/printer.py @@ -0,0 +1,84 @@ +# Das hier ist die View + +class Printer: + def printfield(self, ifield): # function that prints the field + print(" 0 1 2", end="\n") + for j in range(0, len(ifield)): + print("0" if j == 0 else "1" if j == 2 else "2" if j == 4 else " ", end=" ") + for k in range(0, len(ifield)): + print(str(ifield[j][k]), end=" ") + print("\n", end="") + + + def occupied(self): + print("Your given coordinates are already occupied. \nPlease Try again.\n") + + def aicalc(self): + print("Next move is being calculated...") + + def aimoved(self, best_move): + print("AI moved to ", best_move[1] // 2, best_move[2] // 2) + + def playermove(self, player1, player1_char, player2_char): + while True: + + + next_move_x = int(input( + f"Player {1 if player1 else 2} ({player1_char if player1 else player2_char}), please choose the x (" + f"horizontal) coordinates of your next move: ")) + if next_move_x in list(range(3)): + break + else: + print("Please be sure to input a valid number (0-2). \nPlease try Again.") + + while True: + next_move_y = int(input( + f"Player {1 if player1 else 2} ({player1_char if player1 else player2_char}), please choose the y (" + f"vertical) coordinates of your next move: ")) + if next_move_y in list(range(3)): + break + else: + print("Please be sure to input a valid number (0-2). \nPlease try Again.") + + next_move = (next_move_x, next_move_y) + return next_move + + def welcomemessage(self): + print("Welcome to Kat&Paul's TicTacToe:") + + def checksavestate(self): + return input("An older savestate has been found. Do you want to continue it? (y/n): ") + + def invalidsavestate(self): + return input("That was not a valid input. Type y/n if you want to continue or not: ") + + def checkai(self): + inp = input("Do you want to play against AI or local multiplayer? 1/2: ") + + + while True: + if inp == "1": + return 1 + break + elif inp == "2": + return 2 + break + return 3 + + def invalidai(self): + return input("That was not a valid input. Type 1/2 if you want to play against AI or local multiplayer: ") + + def startsplaying(self, player1, player1_char, player2_char): + print(f"Player {1 if player1 else 2} ({player1_char if player1 else player2_char}) will start playing.") + + + def endmessage(self,i, j, ai): + if i == 1 and j == 1: + print("Its a draw.") + if i == 1 and j == 0: + print("Player 1 won.") + if i == 0 and j == 1 and ai: + print("AI won.") + if i == 0 and j == 1 and not ai: + print("Player 2 won.") + diff --git a/MVC/tictactoe.py b/MVC/tictactoe.py new file mode 100644 index 0000000..541d365 --- /dev/null +++ b/MVC/tictactoe.py @@ -0,0 +1,126 @@ +import os.path +import random +import printer +import playerhandler +import model +import minimax + + +class Tictactoe: + printer = None + playerhandler = None + minimax = None + model = None + def __init__(self): + self.printer = printer.Printer() + self.playerhandler = playerhandler.Playerhandler() + self.minimax = minimax.Minimax() + self.model = model.Model() + + def turn(self): # function that checks whose turn it is and where they can place their symbol + self.printer.printfield(self.model.field) + if self.playerhandler.ai and not self.playerhandler.player1: + self.printer.aicalc() + best_move = self.minimax.minimax(self.model.field, not self.playerhandler.player1, self.playerhandler.player1_char, self.playerhandler.player2_char) + self.printer.aimoved(best_move) + self.model.do_move(best_move[1]//2, best_move[2]//2, self.playerhandler.player1, self.playerhandler.player1_char, + self.playerhandler.player2_char) + # self.printer.printfield(self.model.field) + + + else: + while True: + nextmove = self.printer.playermove(self.playerhandler.player1, self.playerhandler.player1_char, + self.playerhandler.player2_char) + next_move_x, next_move_y = nextmove + # return self.model.check_move(next_move_x, next_move_y, True) + + if self.model.check_move(next_move_x, next_move_y, True): + self.model.do_move(next_move_x, next_move_y, self.playerhandler.player1, self.playerhandler.player1_char, self.playerhandler.player2_char) + break + # self.playerhandler.player1 = not self.playerhandler.player1 + else: + self.printer.occupied() + self.printer.printfield(self.model.field) + + win = self.check_win(self.model.field, self.playerhandler.player1_char, self.playerhandler.player2_char) + if win == (0, 0): + self.model.savetosavestate() + self.playerhandler.player1 = not self.playerhandler.player1 + self.turn() + elif win == (1, 1): + self.model.deletesavestate() + elif win == (1, 0): + self.model.deletesavestate() + elif win == (0, 1): + self.model.deletesavestate() + self.printer.endmessage(win[0], win[1], self.playerhandler.ai) + self.turn() + + + def check_win(self, ifield, player1_char, player2_char): + # nothing 0, 0; draw 1, 1; win player1 1, 0; win player2 0, 1 + for j in range(0, len(ifield), 2): + if ifield[j][0] == ifield[j][2] == ifield[j][4] == player1_char: + return 1, 0 + elif ifield[j][0] == ifield[j][2] == ifield[j][4] == player2_char: + return 0, 1 + elif ifield[0][j] == ifield[2][j] == ifield[4][j] == player1_char: + return 1, 0 + elif ifield[0][j] == ifield[2][j] == ifield[4][j] == player2_char: + return 0, 1 + + if ifield[0][0] == ifield[2][2] == ifield[4][4] == player1_char: + return 1, 0 + elif ifield[0][0] == ifield[2][2] == ifield[4][4] == player2_char: + return 0, 1 + elif ifield[0][4] == ifield[2][2] == ifield[4][0] == player1_char: + return 1, 0 + elif ifield[0][4] == ifield[2][2] == ifield[4][0] == player2_char: + return 0, 1 + elif all(ifield[j][k] != " " for j in range(len(ifield)) for k in range(len(ifield))): + return 1, 1 + else: + return 0, 0 + + # verbose = True + + def main(self): + inp = None + self.printer.welcomemessage() + if self.model.checksavestate(): + inp = self.printer.checksavestate() + while True: + if inp == "n": + break + + if inp == "y": + self.model.loadsavestate()# self.tictactoe.checksavestateplayer() + spacecount = 0 + for j in range(0, len(self.model.field)): + for k in range(0, len(self.model.field)): + if self.model.field[j][k] == " ": + spacecount += 1 + if spacecount % 2 == 0: + self.playerhandler.player1 = False + break + # self.printer.checkai() + + + # inp = self.printer.invalidsavestate() + + # inp = self.printer.checkai() + while True: + checkai = self.printer.checkai() + if checkai == 1: + self.playerhandler.ai = True + break + elif checkai == 2: + break + elif checkai == 3: + self.printer.invalidai() + + # printer.printfield(self.model.field) + self.printer.startsplaying(self.playerhandler.player1, self.playerhandler.player1_char, + self.playerhandler.player2_char) + self.turn()