[squeak-dev] The Inbox: TicTacToe-Game-MJK.5.mcz
commits at source.squeak.org
commits at source.squeak.org
Wed Jun 12 15:02:02 UTC 2013
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.
].
].
!
More information about the Squeak-dev
mailing list
|