160 likes | 172 Views
HW 6: Problems 2 & 3. Simulating Connect 4. HW 6: Overview. Connect 4 : Variation of Tic-Tac-Toe Board: Vertical 7x6 Two players take alternating move Move = Placing checkers on the board Winning = 4 checkers in a row (vert., horz., diag.) Move constraints: On top of each other, or
E N D
HW 6: Problems 2 & 3 Simulating Connect 4
HW 6: Overview • Connect 4: Variation of Tic-Tac-Toe • Board: Vertical 7x6 • Two players take alternating move • Move = Placing checkers on the board • Winning = 4 checkers in a row (vert., horz., diag.) • Move constraints: • On top of each other, or • Start a new column • Problems: Board class (p2), Player class (p3)
Problem 2: Connect 4 BoardVariables • Board Representation: • Two-dimensional List • Width & height vary (i.e. not just 7x6) • Board Class variables • Variable data storing the 2D list • Variable height storing the number of rows • Variable width storing the number of columns
Problem 2: Connect 4 BoardMethod: Constructor • The Constructor __init__: • Return nothing • Take in the board dimension • Set board height, width, & initialize data elements def __init__( self, width, height ): self.width = width self.height = height self.data = [] for row in range( self.height ): boardRow = [] for col in range( self.width ): boardRow += [' '] self.data += [boardRow]
Problem 2: Connect 4 BoardMethod: Representation • Method __repr__: Print out the board | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | --------------- 0 1 2 3 4 5 6 def __repr__(self): s = '' for row in range(self.height): s += '|' for col in range(self.width): s += self.data[row][col]+'|' s += '\n' #print out separator ... (your code here) #print out column numbers ... (your code here) return s
Problem 2: Connect 4 BoardMethod: addMove • Method addMove: take in column & symbol >>> b = Board(7,5) >>> b.addMove(0, 'X') >>> b.addMove(1, 'O') >>> b.addMove(1, 'X') >>> b.addMove(3, 'O') | | | | | | | | | | | | | | | | | | | | | | | | | |X| | | | | | |X|O| |O| | | | --------------- 0 1 2 3 4 5 6 def addMove(self, col, ox ): if allowMove(col): # find the first row in # col without a checker ... (your code here) # put ox in this position ... (your code here)
Problem 2: Connect 4 BoardMethods: clear, delMove, allowMove, isFull • Method clear(self): Clear all data to ' ' • Method delMove(self, col): • Opposite of addMove • Delete the top checker of column col • Do nothing if column is empty • Method allowMove(self, col): • False if col is an invalid column number, or full • True otherwise • Method isFull(self)checks if the board is full
Problem 2: Connect 4 BoardMethod: setBoard • Method setBoard: take in the string of moves >>> b = Board(7,5) >>> b.setBoard('02353') | | | | | | | | | | | | | | | | | | | | | | | | | | | |O| | | | |O| |X|O| |X| | --------------- 0 1 2 3 4 5 6 def setBoard(self,moveStr): ch = 'O' for colStr in moveStr: col = int(colStr) if 0<=col<=self.width: self.addMove(col,ch) if ch == 'X': ch = 'O' else: ch = 'X'
Problem 2: Connect 4 BoardMethods: winFor • Method winFor(self, ox): • Check if there are 4 ox ’s in a run • Horizontal, vertical, and diagonal • Possible direction: • Anchor checkers = checks that may start run • Check each of these anchor checkers in 8 directions
Problem 2: Connect 4 BoardMethods: hostGame • Method hostGame(self): • Runs until the game ends: • A player wins • The board is full (draw) • Alternatively ask player 'O' and 'X' to move • Print out the board before asking to move • Invalid move = ask the same player to move again • Valid move = place checker & check for win • At game end report the winner (or tie)
EC Problem 3: Connect 4 PlayerOverview • Goal: Creating an automated player • Player class: • Examine the board • Find appropriate move • May look for several moves ahead • The variables: At least the following • Character ox • Tie breaking type tbt (either 'LEFT', 'RIGHT' or 'RANDOM', more detail later) • Number of moves ahead ply
EC Problem 3: Connect 4 PlayerThe Essential Methods • Construction __init__(self,ox,tbt,ply) • Representation __repr__(self) def __init__( self, ox, tbt, ply ): self.ox = ox self.tbt = tbt self.ply = ply def __repr__( self ): s = 'Player for ' + self.ox + '\n' s += 'with tiebreak type: ' + self.tbt + '\n' s += 'and ply == ' + str(self.ply) + '\n\n' return s
EC Problem 3: Connect 4 PlayerThe Required Methods • Opposite character oppCh(self): • Returns 'X'if own character is 'O', vice versa • Evaluating Board scoreBoard(self, b): • Given a board b, return 100.0, 50.0 and 0.0 respectively for win, tie, and lose situation • Tie-breaking: tiebreakMove(self, scores): • Score = list of floating point • Returns the column with the highest score • Multiple highest score: select one based on tbt • Example: tiebreakMove([0,50,0,50]) returns 1 if self.tbt == ‘LEFT’
EC Problem 3: Connect 4 PlayerThe Brain: scoreFor • Returns a list of scores: • The cth score = goodness after a move to column c • Goodness = what happens after self.ply moves • Using recursion: • Base case 1: A full column = score of -1.0 • Base case 2: 0-ply = state of the game right now (hence, all non-full columns have the same score) • Base case 3: Game-over = state of the game right now • Recursive case: Make a move into a corresponding column, change the (local) board, evaluate recursively
b EC Problem 3: Connect 4 Player ‘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
EC Problem 3: Connect 4 PlayerPut them all together • Choose the next move: nextMove(self,b): • Return the best column to move to • Wrapper method (heavy lifting is already done) • Play the game playGame(self,px,po): • Modify hostGame from the Board class • Instead of getting user input, it use moves getting from px and po alternatively • Additional twist: if one of px and po is a string human, then get the input from the user instead