'From VisualWorks(R) Release 2.0 of 4 August 1994 on 28 November 1996 at 10:38:57 am'! Model subclass: #GameBoard instanceVariableNames: 'theBoard gameFinished theWinner theWinningPositions ' classVariableNames: '' poolDictionaries: '' category: 'Puissance-4'! !GameBoard methodsFor: 'accessing'! atPoint: aPoint "Retourne le contenu de la case dont la position est donnee par le point [aPoint]." ((aPoint x) between: 1 and: 7) ifFalse: [ self error: 'column (x) in GameBoard::atPoint must be 1..7' ]. ((aPoint y) between: 1 and: 6) ifFalse: [ self error: 'row (y) in GameBoard::atPoint must be 1..7' ]. ^(theBoard at: (aPoint x) ) at: (aPoint y)! winner "Fournit la couleur des jetons du gagnant, s'il y en a un, ou le symbole #None sinon." ^theWinner! winningPositions "Fournit la combinaison gagnante, sous la forme d'une collection de points." ^theWinningPositions! ! !GameBoard methodsFor: 'playing'! inColumn: column play: token "Joue le jeton [token] dans la colonne numero [columnNumber]." | row | (self isColumnFull: column) ifTrue: [ self error: 'column full (inColumn)' ]. row := 5. "intentionally 5 instead 6; that's ok." [ row>1 & (( self atPoint: (column @ row)) = #Empty) ] whileTrue: [ row := row-1 ]. ( row = 1 & ( self atPoint: (column @ 1) ) ~= #Empty ) ifTrue: [ row := row+1 ]. (theBoard at: column) at: row put: token. self SearchWinningColor: token. self changed. ^self.! ! !GameBoard methodsFor: 'testing'! isAllColumnsFull "Returns true if isColumnFull [1..7]" 1 to: 7 do: [ :col | (self isColumnFull: col) ifFalse: [ ^false ] ]. ^true. "if not returned so far, everything is full, return true:"! isColumnFull: columnNumber "Teste si la colonne [columnNumber] est pleine." ^( ( (theBoard at: columnNumber) at: 6 ) ~= #Empty )! isGameFinished "Teste si la partie est terminee." ^gameFinished! ! !GameBoard methodsFor: 'private'! initializeInstanceVariables "This (private) instance method initializes the Instances variables. It is called (only!!) by the class method new." "DON'T do Array new: 7 withAll: (Array new: 6 withAll: #Empty. This will create shallow copies of the same array!!" theBoard := Array new: 7. 1 to: 7 do: [ :i | theBoard at: i put: (Array new: 6 withAll: #Empty) ]. theWinner :=#None. gameFinished := false. theWinningPositions := nil. "NOT Set new"! SearchWinningColor: color "Looks for four consecutive coins in the WHOLE board. Called only by InColumn." "Horizontal search" 1 to: 6 do: [ :row | gameFinished ifFalse: [self SearchWinningSetFromX: 1 Y: row DX: 1 DY: 0 Length: 7 Color: color] ]. "Vertical search" gameFinished ifFalse: [ 1 to: 7 do: [ :col | gameFinished ifFalse: [self SearchWinningSetFromX: col Y: 1 DX: 0 DY: 1 Length: 6 Color: color] ] ]. "Diagonals search in direction bottom left to top right" gameFinished ifFalse: [ self SearchWinningSetFromX: 1 Y: 3 DX: 1 DY: 1 Length: 4 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 1 Y: 2 DX: 1 DY: 1 Length: 5 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 1 Y: 1 DX: 1 DY: 1 Length: 6 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 2 Y: 1 DX: 1 DY: 1 Length: 6 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 3 Y: 1 DX: 1 DY: 1 Length: 5 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 4 Y: 1 DX: 1 DY: 1 Length: 4 Color: color ]. "Diagonals search in direction butom left right to top left" gameFinished ifFalse: [ self SearchWinningSetFromX: 4 Y: 1 DX: -1 DY: 1 Length: 4 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 5 Y: 1 DX: -1 DY: 1 Length: 5 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 6 Y: 1 DX: -1 DY: 1 Length: 6 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 7 Y: 1 DX: -1 DY: 1 Length: 6 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 7 Y: 2 DX: -1 DY: 1 Length: 5 Color: color ]. gameFinished ifFalse: [ self SearchWinningSetFromX: 7 Y:3 DX: -1 DY: 1 Length: 4 Color: color ]. "Finally, if still not found, check if whe board is completely full." gameFinished ifFalse: [ (self isAllColumnsFull) ifTrue: [ gameFinished := true ] ].! SearchWinningSetFromX: start_x Y: start_y DX: dx DY: dy Length: len Color: color "Looks at the len coins starting at (start_x, start_y) in direction (dx,dy) and checks if four coins of color can be found. No boundary checking. Returns true if yes and sets theWinningPositions, gameFinished, theWinner accordingly. Otherwise just return false. Called only by SearchWinningColor." | aSet x y end_x end_y | "(self atPoint: 4@1) = #Yellow ifTrue: [ x:= 1/0. ]." aSet := Set new. x := start_x. y:= start_y. end_x := start_x + (len * dx). end_y := start_y + (len * dy). [ ((x ~= end_x) | (y ~= end_y)) & ((aSet size)<4) ] whileTrue: [ (self atPoint: (x @ y)) = color ifTrue: [ aSet add: (x @ y) ] ifFalse: [ aSet := Set new. ]. x := x+dx. y := y+dy. ]. (aSet size) = 4 ifTrue: [ theWinningPositions:=aSet. gameFinished := true. theWinner := color. ^true. ] ifFalse: [ ^false ]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! GameBoard class instanceVariableNames: ''! !GameBoard class methodsFor: 'instance creation'! new "Cree et retourne un nouveau plateau de jeu de 6*7 cases vides." ^super new initializeInstanceVariables! !