2-player X/O. Positions 1–9, detects wins/draws.
# Tic-Tac-Toe - NumWorks # Created by Alvar Laigna - https://alvarlaigna.com # Arrows:move OK:place Back:quit from kandinsky import fill_rect as F,draw_string as D from ion import keydown as K from time import sleep as Z from random import choice SW,SH=320,222 BK=(0,)*3;WH=(255,)*3 BL=(50,110,230);GR=(60,60,60) XC=(230,70,70);OC=(70,180,230) WC=(0,220,100);DG=(100,)*3 CS=56;PAD=4 OX=(SW-CS*3)//2;OY=(SH-CS*3)//2+6 okv=1 if K(4)or K(52) else 0 def okd(): return K(4)or K(52) def okp(): global okv d=okd() if d and not okv: okv=1 return True if not d:okv=0 return False def wup(): while okd():Z(0.02) Z(0.12) def title(): F(0,0,SW,SH,BK) D("TIC-TAC-TOE",80,18,(0,200,200),BK) # Draw mini board for i in range(1,3): F(OX+i*CS-1,OY-30,2,CS*3-30,(40,)*3) F(OX,OY+i*CS-1-30,CS*3,2,(40,)*3) dx(1,0,OY-30);do(2,0,OY-30) dx(0,1,OY-30);do(1,1,OY-30) do(0,2,OY-30);dx(2,2,OY-30) dx(1,2,OY-30) sel=1 opts=["vs Friend","vs CPU"] while True: for i in range(2): y=132+i*28 if i==sel: F(80,y-2,160,22,BL) D("> "+opts[i],85,y,WH,BL) else: F(80,y-2,160,22,BK) D(" "+opts[i],85,y,(120,)*3,BK) D("Up/Down + OK",90,200,(80,)*3,BK) while True: if K(17):return 0 if K(1)or K(2):sel=1-sel;Z(0.15);break if okp():wup();return sel+1 Z(0.04) def dx(c,r,oy=None): if oy is None:oy=OY x,y=OX+c*CS+10,oy+r*CS+10 s=CS-20 for i in range(s): F(x+i,y+i,3,3,XC) F(x+s-i-1,y+i,3,3,XC) def do(c,r,oy=None): if oy is None:oy=OY cx2,cy2=OX+c*CS+CS//2,oy+r*CS+CS//2 rd=CS//2-10 for a in range(-rd,rd+1): for b in range(-rd,rd+1): d=a*a+b*b if(rd-3)**2<=d<=rd*rd: F(cx2+a,cy2+b,1,1,OC) def board(): F(0,0,SW,SH,BK) D("TIC-TAC-TOE",90,2,(80,)*3,BK) for i in range(1,3): F(OX+i*CS-1,OY,2,CS*3,GR) F(OX,OY+i*CS-1,CS*3,2,GR) def cell(c,r,bg): F(OX+c*CS+1,OY+r*CS+1,CS-2,CS-2,bg) def cursor(c,r): x,y=OX+c*CS,OY+r*CS # Blue corners for ox,oy,dw,dh in((0,0,12,3),(0,0,3,12), (CS-12,0,12,3),(CS-3,0,3,12), (0,CS-3,12,3),(0,CS-12,3,12), (CS-12,CS-3,12,3),(CS-3,CS-12,3,12)): F(x+ox,y+oy,dw,dh,BL) def clear_cursor(c,r): x,y=OX+c*CS,OY+r*CS for ox,oy,dw,dh in((0,0,12,3),(0,0,3,12), (CS-12,0,12,3),(CS-3,0,3,12), (0,CS-3,12,3),(0,CS-12,3,12), (CS-12,CS-3,12,3),(CS-3,CS-12,3,12)): F(x+ox,y+oy,dw,dh,BK) # Redraw grid lines if needed if c>0:F(OX+c*CS-1,OY+r*CS,2,CS,GR) if r>0:F(OX+c*CS,OY+r*CS-1,CS,2,GR) def check(b,p): wins=[(0,1,2),(3,4,5),(6,7,8), (0,3,6),(1,4,7),(2,5,8), (0,4,8),(2,4,6)] for w in wins: if b[w[0]]==b[w[1]]==b[w[2]]==p: return w return None def ai_move(b,me,op): # Win if possible for i in range(9): if b[i]==0: b[i]=me if check(b,me):b[i]=0;return i b[i]=0 # Block opponent win for i in range(9): if b[i]==0: b[i]=op if check(b,op):b[i]=0;return i b[i]=0 # Center if b[4]==0:return 4 # Corners cn=[i for i in(0,2,6,8)if b[i]==0] if cn:return choice(cn) # Edges ed=[i for i in(1,3,5,7)if b[i]==0] if ed:return choice(ed) return -1 def hline(w): for i in w: c,r=i%3,i//3 cell(c,r,BK) F(OX+c*CS+4,OY+r*CS+4,CS-8,CS-8,(20,50,20)) def game(mode): while True: b=[0]*9 pl=1;cx,cy=1,1 vs_cpu=mode==2 board() cursor(cx,cy) msg="" while True: if K(17):return mv=False oc,or2=cx,cy if K(0)and cx>0:cx-=1;mv=True elif K(3)and cx<2:cx+=1;mv=True elif K(1)and cy>0:cy-=1;mv=True elif K(2)and cy<2:cy+=1;mv=True elif okp(): idx=cy*3+cx if b[idx]==0: b[idx]=pl cell(cx,cy,BK) if pl==1:dx(cx,cy) else:do(cx,cy) w=check(b,pl) if w: hline(w) for i in w: c2,r2=i%3,i//3 if b[i]==1:dx(c2,r2) else:do(c2,r2) Z(0.3) nm="X"if pl==1 else"O" msg=nm+" wins!" mc=XC if pl==1 else OC break if all(v!=0 for v in b): msg="Draw!";mc=DG;break pl=2 if pl==1 else 1 if vs_cpu and pl==2: Z(0.3) ai=ai_move(b,2,1) if ai>=0: b[ai]=2 ac,ar=ai%3,ai//3 cell(ac,ar,BK) do(ac,ar) w=check(b,2) if w: hline(w) for i in w: c2,r2=i%3,i//3 if b[i]==1:dx(c2,r2) else:do(c2,r2) Z(0.3) msg="O wins!";mc=OC;break if all(v!=0 for v in b): msg="Draw!";mc=DG;break pl=1 cursor(cx,cy) Z(0.18) if mv: clear_cursor(oc,or2) idx2=or2*3+oc if b[idx2]==1:dx(oc,or2) elif b[idx2]==2:do(oc,or2) cursor(cx,cy) Z(0.12) Z(0.03) # Result F(60,SH-24,200,22,BK) D(msg,SW//2-len(msg)*5,SH-22,mc,BK) D("OK=again",SW//2-40,SH-10,(80,)*3,BK) while True: if K(17):return if okp():wup();break Z(0.05) m=title() if m:game(m)