A new version of TicTacToe-Game was added to project The Inbox:
http://source.squeak.org/inbox/TicTacToe-Game-MJK.5.mcz ==================== Summary ==================== Name: TicTacToe-Game-MJK.5 Author: MJK Time: 6 January 2009, 12:30:01 am UUID: d6b2b9aa-8ea7-c444-a102-eeedf20d219d Ancestors: TicTacToe-Game-MJK.4 Added window title. ==================== Snapshot ==================== SystemOrganization addCategory: #'TicTacToe-Game'! BorderedMorph subclass: #TTTBoard instanceVariableNames: 'board logic cellWidth cellHeight win' classVariableNames: '' poolDictionaries: '' category: 'TicTacToe-Game'! !TTTBoard commentStamp: 'MJK 1/5/2009 03:05' prior: 0! Implements a game board and connects game logic and all pieces of the board together. Use command: TTTBoard new openInWindow. To start the game.! ----- Method: TTTBoard>>initialize (in category 'initialization') ----- initialize super initialize. logic := TTTLogic new. cellHeight := 64. cellWidth := 64. self borderWidth: 2. self borderColor: Color black. self color: Color darkGray. self height: cellHeight * 3 + 4. self width: cellWidth * 3 + 4. board := Matrix new: 3 tabulate: [:y :x | self setCellAt: y at: x logic: logic]. logic board: board. ! ----- Method: TTTBoard>>openInWindow (in category 'initialization') ----- openInWindow win := SystemWindow new. win setLabel: 'Tic Tac Toe'. win addMorph: self frame: (0.0 @ 0.0 extent: 1.0 @ 1.0). win openInWorld. win width: 64 * 3 + 4 + 10. win height: 64 * 3 + 4 + 30. win removeCornerGrips. ! ----- Method: TTTBoard>>setCellAt:at:logic: (in category 'helper') ----- setCellAt: y at: x logic: gameLogic "Creates a new cell object for given location and sends game logic handler to the cell." | c | logic := gameLogic. c := TTTCell new. c width: cellWidth. c height: cellHeight. c logic: logic. self addMorph: c. c position: ((x - 1) * c width + 2) @ ((y - 1) * c height + 2). c addMouseUpActionWith: 'logic actionAt:', y printString, ' at: ', x printString. ^c. ! BorderedMorph subclass: #TTTCell instanceVariableNames: 'cellValue logic' classVariableNames: '' poolDictionaries: '' category: 'TicTacToe-Game'! !TTTCell commentStamp: 'MJK 10/11/2008 23:08' prior: 0! Implements a cell component for the game board.! ----- Method: TTTCell>>initialize (in category 'initialization') ----- initialize super initialize. self borderWidth: 1. self borderColor: Color black. self color: Color lightGray. self value: 0. ! ----- Method: TTTCell>>logic (in category 'accessing') ----- logic ^logic. ! ----- Method: TTTCell>>logic: (in category 'accessing') ----- logic: gameLogic logic := gameLogic. ! ----- Method: TTTCell>>value (in category 'accessing') ----- value ^cellValue. ! ----- Method: TTTCell>>value: (in category 'accessing') ----- value: value "Set value to 0 to clear the cell. Set value to 1 to set human player move. Set value to 10 to set computer player move." cellValue := value. (value = 1) ifTrue: [self color: Color blue]. (value = 10) ifTrue: [self color: Color red]. (value = 100) ifTrue: [self color: Color black]. (value = 0) ifTrue: [self color: Color lightGray]. ! Object subclass: #TTTLogic instanceVariableNames: 'board' classVariableNames: '' poolDictionaries: '' category: 'TicTacToe-Game'! !TTTLogic commentStamp: 'MJK 10/11/2008 23:09' prior: 0! The game logic. Includes management for moves made by a human and computer player and also takes care of checking the game state and handles computer moves.! ----- Method: TTTLogic>>actionAt:at: (in category 'game logic') ----- actionAt: y at: x "Accept user move, check if the game is over, make machine move." (self isCellEmptyAt: y at: x) ifFalse: [^false]. self cellValue: 1 at: y at: x. (self checkVictory) ifTrue: [^true]. (self doComputerMove) ifFalse: [self setVinner: 100. ^false]. (self checkVictory) ifTrue: [^true]. ! ----- Method: TTTLogic>>board (in category 'accessing') ----- board ^board. ! ----- Method: TTTLogic>>board: (in category 'accessing') ----- board: gameBoard board := gameBoard. ! ----- Method: TTTLogic>>calculateCellValueAt:at: (in category 'game logic') ----- calculateCellValueAt: y at: x "Calculates cell value for a given cell. This value determines, which cell is the best for the next move made by the computer." " Rules: Returns... 4 points: computer will have a full row with this move 3 points: human will have a full row with this move 2 points: computer will have a full row in two moves 1 point: everything else 0 points: cell not available " | i | "Check if the cell is already taken." (self isCellEmptyAt: y at: x) ifFalse: [^0]. ((x = 1) & (y = 1)) ifTrue: [ i := (self pickLargestOf: (self calculateDiagonal: 1) of: (self calculateRow: y) of: (self calculateColumn: x)) ]. ((x = 2) & (y = 1)) ifTrue: [ i := (self pickLargestOf: (self calculateRow: y) of: (self calculateColumn: x)) ]. ((x = 3) & (y = 1)) ifTrue: [ i := (self pickLargestOf: (self calculateDiagonal: -1) of: (self calculateRow: y) of: (self calculateColumn: x)) ]. ((x = 1) & (y = 2)) ifTrue: [ i := (self pickLargestOf: (self calculateRow: y) of: (self calculateColumn: x)) ]. ((x = 2) & (y = 2)) ifTrue: [ i := (self pickLargestOf: (self calculateRow: y) of: (self calculateColumn: x)) ]. ((x = 3) & (y = 2)) ifTrue: [ i := (self pickLargestOf: (self calculateRow: y) of: (self calculateColumn: x)) ]. ((x = 1) & (y = 3)) ifTrue: [ i := (self pickLargestOf: (self calculateDiagonal: -1) of: (self calculateRow: y) of: (self calculateColumn: x)) ]. ((x = 2) & (y = 3)) ifTrue: [ i := (self pickLargestOf: (self calculateRow: y) of: (self calculateColumn: x)) ]. ((x = 3) & (y = 3)) ifTrue: [ i := (self pickLargestOf: (self calculateDiagonal: 1) of: (self calculateRow: y) of: (self calculateColumn: x)) ]. (i = 20) ifTrue: [^4]. "Computer may win at next move!!" (i = 2) ifTrue: [^4]. "Human may win at next move!!" (i = 10) ifTrue: [^3]. "Computer has one, human has none." (i = 1) ifTrue: [^2]. "Human has one at otherwise empty row." (i = 11) ifTrue: [^1]. "Human has one, computer has one." ^1. ! ----- Method: TTTLogic>>calculateColumn: (in category 'helper') ----- calculateColumn: x "Adds all cells from the given column and returns the result." | result | ((x < 1) | (x > 3)) ifTrue: [^-1]. result := (self cellValueAt: 1 at: x) + (self cellValueAt: 2 at: x) + (self cellValueAt: 3 at: x). ^result. ! ----- Method: TTTLogic>>calculateDiagonal: (in category 'helper') ----- calculateDiagonal: i "Adds all cells diagonally and returns the result. i = 1 --> from top left to lower right i = -1 --> from top right to lower left," | result | result := -1. (i = 1) ifTrue: [result := (self cellValueAt: 1 at: 1) + (self cellValueAt: 2 at: 2) + (self cellValueAt: 3 at: 3)]. (i = -1) ifTrue: [result := (self cellValueAt: 1 at: 3) + (self cellValueAt: 2 at: 2) + (self cellValueAt: 3 at: 1)]. ^result. ! ----- Method: TTTLogic>>calculateRow: (in category 'helper') ----- calculateRow: y "Adds all cells from the given row and returns the result." | result | ((y < 1) | (y > 3)) ifTrue: [^-1]. result := (self cellValueAt: y at: 1) + (self cellValueAt: y at: 2) + (self cellValueAt: y at: 3). ^result. ! ----- Method: TTTLogic>>cellValue:at:at: (in category 'accessing') ----- cellValue: value at: y at: x (board at: y at: x) value: value. ! ----- Method: TTTLogic>>cellValueAt:at: (in category 'accessing') ----- cellValueAt: y at: x | retval | retval := (board at: y at: x) value. ^retval. ! ----- Method: TTTLogic>>checkVictory (in category 'game logic') ----- checkVictory | result | "8 different possibilities for victory:" "Rows:" 1 to: 3 do: [:j | result := 0. result := self calculateRow: j. (result = 3) ifTrue: [self setVinner: 1. ^true]. (result = 30) ifTrue: [self setVinner: 10. ^true]. ]. "Columns:" 1 to: 3 do: [:i | result := 0. result := self calculateColumn: i. (result = 3) ifTrue: [self setVinner: 1. ^true]. (result = 30) ifTrue: [self setVinner: 10. ^true]. ]. "Diagonals:" result := 0. result := self calculateDiagonal: 1. (result = 3) ifTrue: [self setVinner: 1. ^true]. (result = 30) ifTrue: [self setVinner: 10. ^true]. result := 0. result := self calculateDiagonal: -1. (result = 3) ifTrue: [self setVinner: 1. ^true]. (result = 30) ifTrue: [self setVinner: 10. ^true]. ^false ! ----- Method: TTTLogic>>doComputerMove (in category 'game logic') ----- doComputerMove "This calculates the best possible move for the computer." | x y result pointMatrix | pointMatrix := Matrix new: 3 tabulate: [:j :i | self calculateCellValueAt: j at: i]. result := 0. x := -1. y := -1. 1 to: 3 do: [:j | 1 to: 3 do: [:i | ((pointMatrix at: j at: i) > result) ifTrue: [ result := pointMatrix at: j at: i. x := i. y := j.] ]. ]. ((x = -1) | (y = -1)) ifTrue: [^false]. self cellValue: 10 at: y at: x. ^true. ! ----- Method: TTTLogic>>isCellEmptyAt:at: (in category 'helper') ----- isCellEmptyAt: y at: x ((board at: y at: x) value == 0) ifTrue: [^true]. ^false. ! ----- Method: TTTLogic>>isEmptyCells (in category 'helper') ----- isEmptyCells | result | result := false. 1 to: 3 do: [:y | 1 to: 3 do: [:x | (self isCellEmptyAt: y at: x) ifTrue: [result := true]. ]. ]. ^result. ! ----- Method: TTTLogic>>pickLargestOf:of: (in category 'helper') ----- pickLargestOf: a of: b "Returns the largest value of the given a, b and c." "Exception: if human is winning (2 == opponent has two cells in a row) then forget strategy and try to stop it." ((a = 2) | (b = 2)) ifTrue: [^2]. (a > b) ifTrue: [^a]. (b > a) ifTrue: [^b]. ^a. ! ----- Method: TTTLogic>>pickLargestOf:of:of: (in category 'helper') ----- pickLargestOf: a of: b of: c "Returns the largest value of the given a, b and c." "Exception: if human is winning (2 == opponent has two cells in a row) then forget strategy and try to stop it." ((a = 2) | (b = 2) | (c = 2)) ifTrue: [^2]. (a > b) ifTrue: [(a > c) ifTrue: [^a] ifFalse: [^c]] ifFalse: [(b > c) ifTrue: [^b] ifFalse: [^c]]. (b > c) ifTrue: [(b > a) ifTrue: [^b] ifFalse: [^a]] ifFalse: [(c > a) ifTrue: [^c] ifFalse: [^a]]. (c > a) ifTrue: [(c > b) ifTrue: [^c] ifFalse: [^b]] ifFalse: [(a > b) ifTrue: [^a] ifFalse: [^b]]. ^a. ! ----- Method: TTTLogic>>setVinner: (in category 'helper') ----- setVinner: value 1 to: 3 do: [:y | 1 to: 3 do: [:x | (board at: y at: x) value: value. ]. ]. ! |
Free forum by Nabble | Edit this page |