590 likes | 847 Vues
Style Pointers. def tomorrow (self): """Changes the calling object so that it represents one calendar day after the date it originally represented. """ if self.month in [1,3,5,7,8,10] and self.day == 31: self.day = 0 self.month += 1
E N D
Style Pointers deftomorrow(self): """Changes the calling object so that it represents one calendar day after the date it originally represented. """ if self.month in [1,3,5,7,8,10] and self.day == 31: self.day = 0 self.month += 1 elif self.month in [4,6,9,11] and self.day == 30: self.day = 0 self.month += 1 elif self.month == 2: if self.isLeapYear() and self.day == 29: self.day = 0 self.month += 1 elif (self.isLeapYear() == False) and self.day == 28: self.day = 0 self.month += 1 elif self.month == 12 and self.day == 31: self.day = 0 self.month = 1 self.year += 1 self.day += 1
Style Pointers deftomorrow(self): """Changes the calling object so that it represents one calendar day after the date it originally represented. "”” self.day += 1 if self.isLeapYear() == True: DIM = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if self.day > DIM[self.month]: self.day = 1 self.month += 1 if self.month > 12: self.month = 1 self.year += 1 else: DIM = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if self.day > DIM[self.month]: self.day = 1 self.month += 1 if self.month > 12: self.month = 1 self.year += 1
A More Elegant Solution def tomorrow(self): """Changes the calling object so that it represents one calendar day after the date it originally represented. """ DIM = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if self.isLeapYear(): DIM[2] = 29 self.day += 1 if self.day > DIM[self.month]: self.day = 1 self.month += 1 if self.month > 12: self.month = 1 self.year += 1
Style Pointers defisBefore(self, d2): """ Returns true if self is before d2 """ if self.year < d2.year: returnTrue if self.month < d2.month and self.year == d2.year: returnTrue if self.day < d2.day and d2.month == self.month and \ self.year == d2.year: returnTrue returnFalse defisAfter(self, d2): """ Returns true if self is after d2 """ if self.year > d2.year: returnTrue if self.month > d2.month and self.year == d2.year: returnTrue if self.day > d2.day and d2.month == self.month and \ self.year == d2.year: returnTrue returnFalse
A More Elegant Solution def isBefore(self, d2): """ Returns true if self is before d2 """ if self.year < d2.year: returnTrue if self.month < d2.month and self.year == d2.year: returnTrue if self.day < d2.day and d2.month == self.month and \ self.year == d2.year: returnTrue returnFalse def isAfter(self, d2): """ Returns true if self is after d2 """ return d2.isBefore(self)
Style Pointers defdiff( self, d2 ): """ Returns the number of days between self and d2 """ dcopy = self.copy() difference = 0 if dcopy.isBefore(d2) == True: while dcopy.isBefore(d2) == True: dcopy.tomorrow() difference -= 1 else: while dcopy.isAfter(d2): dcopy.yesterday() difference += 1 return difference
An Elegant Solution defdiff( self, d2 ): """ Returns the number of days between self and d2 """ dcopy = self.copy() difference = 0 while dcopy.isBefore(d2): dcopy.tomorrow() difference -= 1 while dcopy.isAfter(d2): dcopy.yesterday() difference += 1 return difference
CS 121 Today Connect Four | | | | | | | | | | | | | | | | | | | | | | | | | | | |X| | | | | |X| |X|O| | | |X|O|O|O|X|O| | --------------- 0 1 2 3 4 5 6 X to move. Is there a way to win?
Aargh! Python has no Connect-four datatype… | | | | | | | | | | | | | | | | | | | | | | | | | | | |X| | | | | |X| |X|O| | | |X|O|O|O|X| |O| --------------- 0 1 2 3 4 5 6 … but we can correct that!
Designing classes 1) What data? (Data Members) Not limited to 7x6! 2) What are objects' crucial capabilities? (Methods)
Designing classes • What data? (Data Members) • - height, width • - Where the chips are • - Whose turn it is • - Winning condition • - End condition (number of chips played) Not limited to 7x6! 2) What are objects' crucial capabilities? (Methods)
Designing classes • What data? (Data Members) • - height, width • - Where the chips are • - Whose turn it is • - Winning condition • - End condition (number of chips played) Not limited to 7x6! • 2) What are objects' crucial capabilities? (Methods) • create a new object • check for win • print • get the next move/switch turn • check for full board
int int Connect Four: the objectb str str str str list width Board b data str str str str height str str str str data What is the name of the method that will construct this data?
int int Connect Four: the objectb str str str str list width Board b data str str str str height str str str str data What is the name of the method that will construct this data? __init__(…)
Connect Four: constructor class Board: """ a datatype representing a C4 board with an arbitrary number of rows and cols """ def__init__( self, width, height ): """ the constructor for objects of type Board """ self.width = width self.height = height self.data = [] # this will be the board for row in range( height ): # 6 boardRow = [] for col in range( width ): # 7 boardRow += [' '] # add a space to this row self.data += [boardRow]
int int Connect Four: the objectb str str str str list width Board b data str str str str height str str str str | | | | | | | | | | | | | | | | | | | | | | | | | | | |X| | | | | |X| |X|O| | | |X|O|O|O|X| |O| --------------- 0 1 2 3 4 5 6 What is the name of the method that will print this data?
Connect Four: __repr__ def__repr__(self): """ this method returns a string representation for an object of type Board """ s = '' for row in range( self.height ): s += '|' for col inrange( self.width ): s += self.data[row][col] + '|' s += '\n' return s which row is row 0, row 1, and so on? To remove? To add?
Connect Four: __repr__ def__repr__(self): """ this method returns a string representation for an object of type Board """ s = '' for row in range( self.height ): s += '|' for col inrange( self.width ): s += self.data[row][col] + '|' s += '\n‘ s += '--'*self.width + '-\n‘ for col in range( self.width ): s += ' ' + str(col % 10) s += '\n' return s which row is row 0, row 1, and so on?
a C4 board class Board defmystery(self, col, ox): for row inrange( self.height ): if self.data[row][col] != ' ': self.data[row-1][col] = ox self.data[self.height-1][col] = ox defallowsMove(self, col): col # 'X' or 'O' Step through this mystery method. What is each line doing? What's going wrong? Write allowsMove to return True if col is a valid move; False otherwise.
a C4 board class Board { defmystery(self, col, ox): for row inrange( self.height ): if self.data[row][col] != ' ': self.data[row-1][col] = ox self.data[self.height-1][col] = ox # Adds ox at the top of a column # But at the same time overwrites the existing # elements in the column… # Does not check if it is possible to write in a column… defallowsMove(self, col): } col # 'X' or 'O' Step through this mystery method. What is each line doing? What's going wrong? Write allowsMove to return True if col is a valid move; False otherwise.
a C4 board class Board defmystery1(self, col, ox): if allowsMove(col): for row inrange( self.height ): if self.data[row][col] != ' ': self.data[row-1][col] = ox return self.data[self.height-1][col] = ox defallowsMove(self, col): col # 'X' or 'O' Step through this mystery method. What is each line doing? What's going wrong? Write allowsMove to return True if col is a valid move; False otherwise.
a C4 board class Board defmystery1(self, col, ox): if allowsMove(col): for row inrange( self.height ): if self.data[row][col] != ' ': self.data[row-1][col] = ox return self.data[self.height-1][col] = ox defallowsMove(self, col): if 0 <= col < self.width: return self.data[0][col] == ' ' col # 'X' or 'O' Step through this mystery method. What is each line doing? What's going wrong? Write allowsMove to return True if col is a valid move; False otherwise.
C4 Board class: methods __init__( self, width, height ) the “constructor” allowsMove( self, col ) checks if allowed addMove( self, col, ox ) places a checker delMove( self, col ) removes a checker __repr__( self ) outputs a string isFull( self ) checks if any space is left winsFor( self, ox ) checks if a player has won hostGame( self ) play! Which of these will require the most thought?
winsFor( self, ox ) b b.winsFor( 'X' ) or 'O' X O Thoughts?
winsFor( self, ox ) b def winsFor(self, ox): # check for horizontal wins for row in range(0,self.height): for col in range(0,self.width-3): if self.data[row][col] == ox and \ self.data[row][col+1] == ox and \ self.data[row][col+2] == ox and \ self.data[row][col+3] == ox: return True # check for vertical wins X O Thoughts?
? Strategic thinking == intelligence Two-player games have been a key focus of AI as long as computers have been around… In 1945, Alan Turing predicted that computers would be better chess players than people in ~ 50 years… and thus would have achieved intelligence. Alan Turing memorial Manchester, England
? Strategic thinking == intelligence Two-player games have been a key focus of AI as long as computers have been around… humans computers good at evaluating the strength of a board for a player Particularly good at recognizing patterns good at looking ahead in the game to find winning combinations of moves … humans and computers have different relative strengths in these games.
How humans play games… An experiment (by A. deGroot) was performed in which chess positions were shown to novice and expert players… - experts could reconstruct these perfectly - novice players did far worse…
How humans play games… An experiment (by A. deGroot) was performed in which chess positions were shown to novice and expert players… - experts could reconstruct these perfectly - novice players did far worse… Random chess positions (not legal ones) were then shown to the two groups - experts and novices did equally well (badly) at reconstructing them!
The Player class Details Player pForX (data and methods) What data and methods are needed to construct and implement a Player object?
Player Picture of a Player object DATA 3 'LEFT' 'X' int ply string tbt string ox Player pForX tiebreakType checker, O or X __init__(self, ox, tbt, ply) __repr__(self) oppCh(self) METHODS scoreBoard(self, b) scoresFor(self, b) tiebreakMove(self, scores) nextMove(self, b)
scoreBoard ‘X’ ‘O’ Assigns a score to any board, b A simple system: 100.0 50.0 0.0 for a win for anything else for a loss Score for Score for Score for Score for
scoreBoard ‘X’ ‘O’ Assigns a score to any board, b A simple system: 100.0 50.0 0.0 for a win for anything else for a loss 100.0 Score for Score for 0.0 Score for Score for
scoreBoard ‘X’ ‘O’ Assigns a score to any board, b A simple system: 100.0 50.0 0.0 for a win for anything else for a loss 100.0 50.0 Score for Score for 0.0 50.0 Score for Score for
scoreBoard Assigns a score to any board, b A simple system: 100.0 50.0 0.0 for a win for anything else for a loss Implementation ideas… scoreBoard(self, b) This doesn't seem to be looking very far ahead ! What methods that already exist will come in handy? How can there be no 'X' or 'O' input? What class is this method in?
Looking further ahead… scoreBoard looks ahead 0 moves 0-ply If you look one move ahead, how many possibilities are there to consider? A 1-ply lookahead player will "see" an impending victory. to move… 1-ply score
Looking further ahead… scoreBoard looks ahead 0 moves 0-ply If you look one move ahead, how many possibilities are there to consider? A 1-ply lookahead player will "see" an impending victory. to move… 1-ply score -1 50 50 50 100 50 50
Looking further ahead… scoreBoard looks ahead 0 moves 0-ply If you look one move ahead, how many possibilities are there to consider? A 2-ply lookahead player will also "see" an opponent's impending victory. to move… 2-ply -1 0 0 0 50 0 0 score
Looking further ahead… scoreBoard looks ahead 0 moves 0-ply If you look one move ahead, how many possibilities are there to consider? 1-ply 2-ply scoresFor( self, b ) returns a LIST of scores, one for each column you can choose to move next…
Example 1-ply and 2-ply lookahead scores It is O’s move. What scores does a 1-ply lookahead for O assign to each move? |O| | | | | | | |X| | | |O| |X| |O| | | |X|O|X| |X| | | |O|O|X| |X| |X| |X|O|O| |X| |O|O|O|X|X| --------------- 0 1 2 3 4 5 6 col 0 col 1 col 2 col 3 col 4 col 5 col 6 Which change at 2-ply?
Example 1-ply and 2-ply lookahead scores It is O’s move. What scores does a 1-ply lookahead for O assign to each move? |O| | | | | | | |X| | | |O| |X| |O| | | |X|O|X| |X| | | |O|O|X| |X| |X| |X|O|O| |X| |O|O|O|X|X| --------------- 0 1 2 3 4 5 6 col 0 col 1 col 2 col 3 col 4 col 5 col 6 -1 100 50 50 100 100 50 Which change at 2-ply?
Example 1-ply and 2-ply lookahead scores It is O’s move. What scores does a 1-ply lookahead for O assign to each move? |O| | | | | | | |X| | | |O| |X| |O| | | |X|O|X| |X| | | |O|O|X| |X| |X| |X|O|O| |X| |O|O|O|X|X| --------------- 0 1 2 3 4 5 6 col 0 col 1 col 2 col 3 col 4 col 5 col 6 1-ply -1 100 50 50 50 100 50 col 0 col 1 col 2 col 3 col 4 col 5 col 6 -1 100 2-ply 0 0 100 100 50
Example 1-ply and 2-ply lookahead scores It is X’s move. What scores does a 2-ply lookahead for X assign to each move? | | | | | | |O| | | | | | | |O| | | | | | | |X| |X| |X|O| | |O| |X|O|O|X| |X|X| |X|O|O|O| |O|X| --------------- 0 1 2 3 4 5 6 col 0 col 1 col 2 col 3 col 4 col 5 col 6
Example 1-ply and 2-ply lookahead scores It is X’s move. What scores does a 2-ply lookahead for X assign to each move? | | | | | | |O| | | | | | | |O| | | | | | | |X| |X| |X|O| | |O| |X|O|O|X| |X|X| |X|O|O|O| |O|X| --------------- 0 1 2 3 4 5 6 col 0 col 1 col 2 col 3 col 4 col 5 col 6 100 0 0 0 50 0 -1
Practice b ‘X’ ‘O’ col 0 col 1 col 2 col 3 col 4 col 5 col 6 0-ply scores for O: col 0 col 1 col 2 col 3 col 4 col 5 col 6 1-ply scores for O: col 0 col 1 col 2 col 3 col 4 col 5 col 6 2-ply scores for O: col 0 col 1 col 2 col 3 col 4 col 5 col 6 3-ply scores for O:
Solutions b ‘X’ ‘O’ col 0 col 1 col 2 col 3 col 4 col 5 col 6 0-ply scores for O: 50 50 -1 50 50 50 50 col 0 col 1 col 2 col 3 col 4 col 5 col 6 1-ply scores for O: -1 50 50 50 50 100 50 col 0 col 1 col 2 col 3 col 4 col 5 col 6 2-ply scores for O: 0 0 -1 0 100 0 50 col 0 col 1 col 2 col 3 col 4 col 5 col 6 3-ply scores for O: 0 0 0 -1 0 100 100
‘X’ scoresFor each column ‘O’ new‘X’ b (1) For each possible move (2) Add it to the board Col 6 Col 0 Col 5 Col 1 Col 2 Col 3 Col 4
‘X’ scoresFor each column ‘O’ new‘X’ b (1) For each possible move (2) Add it to the board (3) Ask OPPONENT to score each board At what ply? 0.0 50.0 Col 6 Col 0 Col 5 Col 1 Col 2 Col 3 Col 4 50.0 50.0 0.0 0.0 0.0
‘X’ scoresFor each column ‘O’ new‘X’ b (1) For each possible move (2) Add it to the board (3) Ask OPPONENT to score each board (4) Take the opponent's MAX What to assign for a score? 0.0 50.0 Col 6 Col 0 Col 5 Col 1 Col 2 Col 3 Col 4 50.0 50.0 0.0 0.0 0.0
scoresFor (1) For each possible move (2) Add it to the board (3) Ask OPPONENT to score each board - at ? ply (4) the score is 100-max def scoresFor(self, b):