hi all i've just finished my first excursion into artificial intelligence with a game less trivial than tictactoe, and here it is in case anybody can offer criticism/suggestions/etc
peace stm ############################### #) connectfour - python 3.6.1 ############################### from tkinter import * from random import choice class infinity: def __init__(self,signum): self.signum = signum def __repr__(self): return '+oo' if self.signum > 0 else '-oo' def __lt__(self,other): return False if self.signum > 0 else True def __le__(self,other): return False if self.signum > 0 else True def __gt__(self,other): return True if self.signum > 0 else False def __ge__(self,other): return True if self.signum > 0 else False def __eq__(self,other): return isinstance(other,infinity) and self.signum == other.signum ex, oh, blank = 'red black white' .split() startboard = {(i,j):blank for i in range(6) for j in range(7)} def getlines(board): horizontal = [[(i, j+k) for k in range(4)] for i in range(6) for j in range(7)] vertical = [[(i+k, j) for k in range(4)] for i in range(6) for j in range(7)] positive = [[(i+k, j+k) for k in range(4)] for i in range(6) for j in range(7)] negative = [[(i+k, j-k) for k in range(4)] for i in range(6) for j in range(7)] linear = horizontal + vertical + positive + negative lines = [line for line in linear if all(i in range(6) and j in range(7) for (i,j) in line)] return [[board[square] for square in line] for line in lines] def getwinner(board): lines = getlines(board) return ex if [ex]*4 in lines else oh if [oh]*4 in lines else None def getmover(board): boardvalues = list(board.values()) return ex if boardvalues.count(ex)==boardvalues.count(oh) else oh def getoptimum(mover): return max if mover == ex else min def getaccessibles(board): return [j for j in range(7) if board[0,j] == blank] def getvalue(winner,accessibles): return infinity(+1) if winner == ex else infinity(-1) if winner == oh else 0 if not accessibles else None def makemove(board,column,mover): board = board.copy() empties = [row for row in range(6) if board[row,column] == blank] if not empties: return board board[max(empties),column] = mover return board def takemoveback(board,column): board = board.copy() occupied = [row for row in range(6) if board[row,column] != blank] if not occupied: return board board[min(occupied),column] = blank return board def guessvalue(board): lines = getlines(board) exs = [line for line in lines if line.count(ex)==3 and line.count(oh)==0] ohs = [line for line in lines if line.count(oh)==3 and line.count(ex)==0] return len(exs)-len(ohs) def heuristicvalue(board,depth): winner = getwinner(board) accessibles = getaccessibles(board) value = getvalue(winner,accessibles) if value != None: return value if depth == 0: return guessvalue(board) mover = getmover(board) optimum = getoptimum(mover) children = [makemove(board,column,mover) for column in accessibles] return optimum(heuristicvalue(child,depth-1) for child in children) def getmoves(board,depth): accessibles = getaccessibles(board) if not accessibles: return [] mover = getmover(board) optimum = getoptimum(mover) children = [makemove(board,column,mover) for column in accessibles] values = [heuristicvalue(child,depth) for child in children] bestvalue = optimum(values) return [accessibles[index] for index in range(len(accessibles)) if values[index] == bestvalue] class grid: def __init__(self,window): self.window = window self.boardframe = Frame(window.root) self.rowframes = [Frame(self.boardframe) for anonymous in range(6)] self.squarebuttons = [Button(self.rowframes[number//7], width=3, command=self.window.squarecommand(number), background=blank) for number in range(42)] def pack(self): self.boardframe .pack(side=TOP) [frame .pack(side=TOP) for frame in self.rowframes] [button .pack(side=LEFT) for button in self.squarebuttons] class caption: def __init__(self,window): self.window = window self.statusframe = Frame(window.root) self.statuslabel = Label(self.statusframe, height=2) def pack(self): self.statusframe .pack(side=TOP) self.statuslabel .pack(side=LEFT) class buttonpanel: def __init__(self,window,depth): self.window = window self.controlframe = Frame(window.root) self.makemoveframe = Frame(self.controlframe) self.takebackframe = Frame(self.controlframe) self.startoverframe = Frame(self.controlframe) self.makemovebutton = Button(self.makemoveframe, text='make move', command=self.window.movecommand(depth)) self.takebackbutton = Button(self.takebackframe, text='take back', command=self.window.takeback) self.startoverbutton = Button(self.startoverframe, text='start over', command=self.window.startover) def pack(self): self.controlframe .pack(side=TOP) self.makemoveframe .pack(side=LEFT) self.takebackframe .pack(side=LEFT) self.startoverframe .pack(side=RIGHT) self.makemovebutton .pack(side=TOP) self.takebackbutton .pack(side=TOP) self.startoverbutton .pack(side=TOP) class window: def __init__(self, depth=2): self.root = Tk() self.grid = grid (self) self.caption = caption (self) self.buttonpanel = buttonpanel(self, depth=2) self.grid .pack() self.caption .pack() self.buttonpanel .pack() self.startover() self.root.title('connect four') self.root.mainloop() def startover(self): self.board = startboard self.movelist = [] self.display() def display(self): winner = getwinner(self.board) mover = getmover (self.board) tie = blank not in self.board.values() status = winner + ' wins' if winner else 'tied game' if tie else mover + ' to move' [self.grid.squarebuttons[number].config(background=self.board[divmod(number,7)]) for number in range(42)] self.caption.statuslabel.config(text = status.upper() if winner or tie else status) def squarecommand(self,number): def returnvalue(): if getwinner(self.board) or blank not in self.board.values(): return column = number % 7 self.board = makemove(self.board, column, getmover(self.board)) self.display() self.grid.squarebuttons[column].flash() self.movelist += [column] return returnvalue def movecommand(self,depth): def returnvalue(): if getwinner(self.board) or blank not in self.board.values(): return column = choice(getmoves(self.board,depth)) self.board = makemove(self.board, column, getmover(self.board)) self.display() self.grid.squarebuttons[column].flash() self.movelist += [column] return returnvalue def takeback(self): if not self.movelist: return self.board = takemoveback(self.board, self.movelist[-1]) self.display() self.movelist = self.movelist[:-1] -- https://mail.python.org/mailman/listinfo/python-list