Hello, everyone! I'm working on Xs&Os game (or tic tac toe) to learn pharo. Already uploaded a first version. Game is boring and very simple, but if somebody is interested here is a link: http://smalltalkhub.com/#!/~MarkRizun/XsAndOsGame/ As a novice in pharo, waiting for comments and advice. Сritique is welcome too ;) Regards, Mark.
To play it just type in workspace following: XsAndOsGame new openInWorld 2014-02-03 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Hello, everyone!
I'm working on Xs&Os game (or tic tac toe) to learn pharo. Already uploaded a first version. Game is boring and very simple, but if somebody is interested here is a link:
http://smalltalkhub.com/#!/~MarkRizun/XsAndOsGame/
As a novice in pharo, waiting for comments and advice. Сritique is welcome too ;)
Regards, Mark.
well done , now you only need to add a computer opponent, since playing against myself is boring because I win and lose every single time :D On Mon, Feb 3, 2014 at 12:40 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
To play it just type in workspace following: XsAndOsGame new openInWorld
2014-02-03 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Hello, everyone!
I'm working on Xs&Os game (or tic tac toe) to learn pharo. Already uploaded a first version. Game is boring and very simple, but if somebody is interested here is a link:
http://smalltalkhub.com/#!/~MarkRizun/XsAndOsGame/
As a novice in pharo, waiting for comments and advice. Сritique is welcome too ;)
Regards, Mark.
Sure, that is in my plans:) 2014-02-03 kilon alios <kilon.alios@gmail.com>:
well done , now you only need to add a computer opponent, since playing against myself is boring because I win and lose every single time :D
On Mon, Feb 3, 2014 at 12:40 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
To play it just type in workspace following: XsAndOsGame new openInWorld
2014-02-03 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Hello, everyone!
I'm working on Xs&Os game (or tic tac toe) to learn pharo. Already uploaded a first version. Game is boring and very simple, but if somebody is interested here is a link:
http://smalltalkhub.com/#!/~MarkRizun/XsAndOsGame/
As a novice in pharo, waiting for comments and advice. Сritique is welcome too ;)
Regards, Mark.
I am added my self as a watcher to your project , will definitely be following your progress. Rock on :) On Mon, Feb 3, 2014 at 12:54 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Sure, that is in my plans:)
2014-02-03 kilon alios <kilon.alios@gmail.com>:
well done , now you only need to add a computer opponent, since playing
against myself is boring because I win and lose every single time :D
On Mon, Feb 3, 2014 at 12:40 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
To play it just type in workspace following: XsAndOsGame new openInWorld
2014-02-03 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Hello, everyone!
I'm working on Xs&Os game (or tic tac toe) to learn pharo. Already uploaded a first version. Game is boring and very simple, but if somebody is interested here is a link:
http://smalltalkhub.com/#!/~MarkRizun/XsAndOsGame/
As a novice in pharo, waiting for comments and advice. Сritique is welcome too ;)
Regards, Mark.
Thx) That's nice 2014-02-03 kilon alios <kilon.alios@gmail.com>:
I am added my self as a watcher to your project , will definitely be following your progress. Rock on :)
On Mon, Feb 3, 2014 at 12:54 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Sure, that is in my plans:)
2014-02-03 kilon alios <kilon.alios@gmail.com>:
well done , now you only need to add a computer opponent, since playing
against myself is boring because I win and lose every single time :D
On Mon, Feb 3, 2014 at 12:40 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
To play it just type in workspace following: XsAndOsGame new openInWorld
2014-02-03 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Hello, everyone!
I'm working on Xs&Os game (or tic tac toe) to learn pharo. Already uploaded a first version. Game is boring and very simple, but if somebody is interested here is a link:
http://smalltalkhub.com/#!/~MarkRizun/XsAndOsGame/
As a novice in pharo, waiting for comments and advice. Сritique is welcome too ;)
Regards, Mark.
On Mon, Feb 3, 2014 at 11:39 AM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
As a novice in pharo, waiting for comments and advice. Сritique is welcome too ;)
random comments (tested on Pharo 3.0): - I played and things work perfectly as far as I saw :-) - your code is of very good quality! - 2 tests don't pass (EmptyCellTestCase, CellRendererTestCase) - usually we don't append 'Case' at the end of our test classes - the package name doesn't follow the convention ( https://ci.inria.fr/pharo-contribution/job/PharoForTheEnterprise/ws/Conventi... ) - you may want to avoid the use of non-alphanumeric characters in the package name (e.g., avoid &) - please indent your code (use ALT+Shift+u on each method to get automatic indentation) - "self should: [ offset = (50 @ 50) ]" --> "self assert: offset equals: 50@50" - "self should: [ cell isOff ]." --> "self assert: cell isOff" - all subclasses of Cell override #initialize in exactly the same way. Consider moving that to the superclass - you should try to avoid as much as possible doing a super send in a different method. For example, EmptyCell>>initializeState does a super send on #initialize. - OCell and XCell are exactly the same, this should not be and is very suspicious. - CellRenderer has 2 methods with an uppercase letter. This is not conventional - you use a lot of variables you use only once. Consider inlining them. For example in CellRenderer>>offsetWithinGridForm, all variables seem useless : "^ CellRenderer cellExtent * ((self cellLocation x - 1) @ (self cellLocation y - 1))" - CellRenderer>>renderContents uses branching on the class of objects instead of polymorphism. That's bad design in my opinion. Consider delegating to OCell and XCell or using double-dispatch. - Same thing for CellRenderer class>>rendererFor: All in all, very good job. Would you consider writing a tutorial on how to implement an Xs&Os game in Pharo? -- Damien Cassou http://damiencassou.seasidehosting.st "Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
Really appreciate your comments, they are very useful for me. I will do my best to make commits as soon as possible to fix problems that you pointed out. Plus I've learned so much from only one message! thx:) 2014-02-04 Damien Cassou <damien.cassou@gmail.com>:
Would you consider writing a tutorial on how to implement an Xs&Os game in
Pharo?
After finishing this game completely (it will take a while), I have in plans to implement another game. Then, if I have enoug experience in pharo, I want to write 2 tutorials for both games.
Mark
On 04 Feb 2014, at 18:04, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Really appreciate your comments, they are very useful for me. I will do my best to make commits as soon as possible to fix problems that you pointed out. Plus I've learned so much from only one message! thx:)
2014-02-04 Damien Cassou <damien.cassou@gmail.com>:
Would you consider writing a tutorial on how to implement an Xs&Os game in Pharo?
After finishing this game completely (it will take a while), I have in plans to implement another game. Then, if I have enoug experience in pharo, I want to write 2 tutorials for both games.
Iâd suggest you to start writing a tutorial on X&O now, and then do something more. Itâs important to have a constant impact. Also if you have a short tutorial (e.g. on Athens) which can help sleepy developers on their deadline hight, I can include you as an author of http://sleepycoders.blogspot.com Uko P.S. good job :)
Mark
On 04 Feb 2014, at 18:08, Yuriy Tymchuk <yuriy.tymchuk@me.com> wrote:
On 04 Feb 2014, at 18:04, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Really appreciate your comments, they are very useful for me. I will do my best to make commits as soon as possible to fix problems that you pointed out. Plus I've learned so much from only one message! thx:)
2014-02-04 Damien Cassou <damien.cassou@gmail.com>:
Would you consider writing a tutorial on how to implement an Xs&Os game in Pharo?
After finishing this game completely (it will take a while), I have in plans to implement another game. Then, if I have enoug experience in pharo, I want to write 2 tutorials for both games.
Iâd suggest you to start writing a tutorial on X&O now, and then do something more. Itâs important to have a constant impact. Also if you have a short tutorial (e.g. on Athens) which can help sleepy developers on their deadline hight, I can include you as an author of http://sleepycoders.blogspot.com
* deadline night
Uko
P.S. good job :)
Mark
That's a good idea:) I should think how to write this tutorial. 2014-02-04 Yuriy Tymchuk <yuriy.tymchuk@me.com>:
On 04 Feb 2014, at 18:08, Yuriy Tymchuk <yuriy.tymchuk@me.com> wrote:
On 04 Feb 2014, at 18:04, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Really appreciate your comments, they are very useful for me. I will do my best to make commits as soon as possible to fix problems that you pointed out. Plus I've learned so much from only one message! thx:)
2014-02-04 Damien Cassou <damien.cassou@gmail.com>:
Would you consider writing a tutorial on how to implement an Xs&Os game in
Pharo?
After finishing this game completely (it will take a while), I have in plans to implement another game. Then, if I have enoug experience in pharo, I want to write 2 tutorials for both games.
I'd suggest you to start writing a tutorial on X&O now, and then do something more. It's important to have a constant impact. Also if you have a short tutorial (e.g. on Athens) which can help sleepy developers on their deadline hight, I can include you as an author of http://sleepycoders.blogspot.com
* deadline night
Uko
P.S. good job :)
Mark
On 04 Feb 2014, at 20:58, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
That's a good idea:) I should think how to write this tutorial.
IMHO Your tutorial should guide a reader through the development process and give the understanding about key concepts that you are using (probably how to build a view or how to handle events). As for IA consider putting at least something. a) thing that selects first free cell (1 -> 9); b) takes a set of free cells and selects one randomly :) Uko
2014-02-04 Yuriy Tymchuk <yuriy.tymchuk@me.com>:
On 04 Feb 2014, at 18:08, Yuriy Tymchuk <yuriy.tymchuk@me.com> wrote:
On 04 Feb 2014, at 18:04, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Really appreciate your comments, they are very useful for me. I will do my best to make commits as soon as possible to fix problems that you pointed out. Plus I've learned so much from only one message! thx:)
2014-02-04 Damien Cassou <damien.cassou@gmail.com>:
Would you consider writing a tutorial on how to implement an Xs&Os game in Pharo?
After finishing this game completely (it will take a while), I have in plans to implement another game. Then, if I have enoug experience in pharo, I want to write 2 tutorials for both games.
Iâd suggest you to start writing a tutorial on X&O now, and then do something more. Itâs important to have a constant impact. Also if you have a short tutorial (e.g. on Athens) which can help sleepy developers on their deadline hight, I can include you as an author of http://sleepycoders.blogspot.com
* deadline night
Uko
P.S. good job :)
Mark
2014-02-04 Yuriy Tymchuk <yuriy.tymchuk@me.com>:
As for IA consider putting at least something. a) thing that selects first free cell (1 -> 9); b) takes a set of free cells and selects one randomly :)
You just stole my idea for AI (Easy level). Also there should be Normal and Impossible levels. On Impossible computer always wins;)
On Tue, Feb 4, 2014 at 8:58 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
I should think how to write this tutorial.
on the technical point of view, I advise you to use Pillar: http://www.smalltalkhub.com/#!/~Pier/Pillar -- Damien Cassou http://damiencassou.seasidehosting.st "Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
Thanks, I'll certainly take a look at it 2014-02-05 Damien Cassou <damien.cassou@gmail.com>:
On Tue, Feb 4, 2014 at 8:58 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
I should think how to write this tutorial.
on the technical point of view, I advise you to use Pillar: http://www.smalltalkhub.com/#!/~Pier/Pillar
-- Damien Cassou http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
Updated XsAndOsGame: added AI, also fixed some problems, that Damien mentioned in his comments. Btw, thanks to Damien, because I learned for myself a lot of new useful things. Note: The new version is XsAndOsGame (NOT Xs&OsGame) ! To play it type in workspace: XsAndOsGame new openInWorld. If you want to play vs computer press button "ToggleMode" and choose difficulty. Initially it is easy. Mark 2014-02-05 15:57 GMT+02:00 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Thanks, I'll certainly take a look at it
2014-02-05 Damien Cassou <damien.cassou@gmail.com>:
On Tue, Feb 4, 2014 at 8:58 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
I should think how to write this tutorial.
on the technical point of view, I advise you to use Pillar: http://www.smalltalkhub.com/#!/~Pier/Pillar
-- Damien Cassou http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
I really like the GUI , is it just Morphic ? Your impossible mode is quite easy to win. One thing I would change is when I use the ToggleMode to toggle to Player vs CPU I would like it to stick even after I finish the match. Because as it is now If I click New Game it reverts back to Player vs Player mode. Also I would like if you expand your window to add the bottom text because as it is if it mixes with other windows its hard to read being outside its window. Well done , looks very good indeed :) back to studying your code. On Sat, Feb 8, 2014 at 4:07 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Updated XsAndOsGame: added AI, also fixed some problems, that Damien mentioned in his comments. Btw, thanks to Damien, because I learned for myself a lot of new useful things. Note: The new version is XsAndOsGame (NOT Xs&OsGame) ! To play it type in workspace: XsAndOsGame new openInWorld. If you want to play vs computer press button "ToggleMode" and choose difficulty. Initially it is easy.
Mark
2014-02-05 15:57 GMT+02:00 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Thanks, I'll certainly take a look at it
2014-02-05 Damien Cassou <damien.cassou@gmail.com>:
On Tue, Feb 4, 2014 at 8:58 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
I should think how to write this tutorial.
on the technical point of view, I advise you to use Pillar: http://www.smalltalkhub.com/#!/~Pier/Pillar
-- Damien Cassou http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
2014-02-08 22:55 GMT+02:00 kilon alios <kilon.alios@gmail.com>:
I really like the GUI , is it just Morphic ?
Yes it is. Your impossible mode is quite easy to win.
Sure, because impossible and normal modes are about the same for now. Today or tommorow I will update game again, and it will be impossible to win.
One thing I would change is when I use the ToggleMode to toggle to Player vs CPU I would like it to stick even after I finish the match. Because as it is now If I click New Game it reverts back to Player vs Player mode.
You are right, I have to fix this. Thanks for being so helpful :)
Also I would like if you expand your window to add the bottom text because as it is if it mixes with other windows its hard to read being outside its window.
You mean that I should add some background on the place where the text is?
"You mean that I should add some background on the place where the text is?" yes exactly. Try to hover the window over another window like a Nautilus window to see why thats a problem.
Hi mark I read a bit your code It is nice for a first project!!!! Here are some feedback. I suggest that you take into account the easy one and produce a new version and if you want to train your skills you try to see how to address the difficult ones. Stef - Add it in the class comment XsAndOsGame new openInWorld. - you have some unclassified protocols on the class side. - you may want to run smallLint (criticBorwser on your code and see the hints that it can give you). - When you create a new game do not move the window to the top corner :) easyBtn -> easyButton (you do not pay per character :)) findEmptyCellPos -> findEmptyCellPosition not in accessing impBtn -> impossibleButton â¦. :) - Why do you need a separate class just for three colors? I would merge XsAndOsGameColors and XsAndOsGame XsAndOsGame>>initialize is long May be you should extract some methods from it (methods that you can then reuse for other tasks) renderOContents | delta offset x1 y1 x2 y2 rect | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x + self oCorner x. x2 := offset x + delta x - self oCorner x. y1 := offset y + self oCorner y. y2 := offset y + delta y - self oCorner y. rect := Rectangle new setOrigin: x1 @ y1 corner: x2 @ y2. self targetForm getCanvas fillOval: rect color: XsAndOsGameColors gameBoardBackgroundColor borderWidth: 3 borderColor: XsAndOsGameColors OColor What do you refer to CellRenderer direcly? self class ? rendererFor: aCell "VERY BAD IMPLEMENTATION OF THIS METHOD!!!" aCell class = EmptyCell ifTrue: [ ^ CellRenderer ]. aCell class = XCell ifTrue: [ ^ XCellRenderer ]. aCell class = OCell ifTrue: [ ^ OCellRenderer ] indeed :) why not implementing some methods call renderClass and sending a message to the object :) mptyCell>>initialize super initialize. CellRenderer>>offsetWithinGridForm "Returns a point - left top corner of current cell" ^ CellRenderer cellExtent * ((self cellLocation x - 1) @ (self cellLocation y - 1)) => self clas cellExtent CellRenderer >> renderBorderBottom | delta offset x1 y1 x2 y2 | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. self targetForm getCanvas line: x1 @ y1 to: x2 @ y2 width: 1 color: XsAndOsGameColors cellBorderColor => CellRenderer >> renderBorderBottom | delta offset x1 y1 x2 y2 | delta := self class cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. self targetForm getCanvas line: x1 @ y1 to: x2 @ y2 width: 1 color: XsAndOsGameColors cellBorderColor I was wondering why you need Grid (I would rename it CellGrid) and do not use a Matrix. grid sizeOfGrid -> I would rename sizeOfGrid into size like that your grid can be a bit more polymorphic from its API point of view makeGameBoarMorph -> typo :) Now I want wondering why you do not have an instance variable to hold it Future fun ideas for new versions: ââââââââââââââââââââââ playerVsComputer self vsComputer ifTrue: [ self vsComputer: false. self stateMorph contents: 'Player 1 VS Player 2' ] ifFalse: [ self vsComputer: true. self stateMorph contents: 'Player VS Computer ---> Difficulty: ' , self difficulty asString ]. self vsComputer ifTrue: [ self easyBtn enable. self normalBtn enable. self impBtn enable ] ifFalse: [ self easyBtn disable. self normalBtn disable. self impBtn disable ] This kind of code may be think that may be you need another object that represent the TwoUsers vsComputer strategy Iâm not sure but clicked look quite long. May be you should create another class that can represent the logic of the game. A really interesting exercise would be to see how you can create a boardGame for 15*15 and see how it breaks some hidden rules. On 08 Feb 2014, at 15:07, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Updated XsAndOsGame: added AI, also fixed some problems, that Damien mentioned in his comments. Btw, thanks to Damien, because I learned for myself a lot of new useful things. Note: The new version is XsAndOsGame (NOT Xs&OsGame) ! To play it type in workspace: XsAndOsGame new openInWorld. If you want to play vs computer press button "ToggleMode" and choose difficulty. Initially it is easy.
Mark
2014-02-05 15:57 GMT+02:00 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>: Thanks, I'll certainly take a look at it
2014-02-05 Damien Cassou <damien.cassou@gmail.com>:
On Tue, Feb 4, 2014 at 8:58 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
I should think how to write this tutorial.
on the technical point of view, I advise you to use Pillar: http://www.smalltalkhub.com/#!/~Pier/Pillar
-- Damien Cassou http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
Thanks for comment. I'll fix all problems and change everything you mentioned, hope to succeed in it. Mark 2014-02-09 22:51 GMT+02:00 Pharo4Stef <pharo4Stef@free.fr>:
Hi mark
I read a bit your code
It is nice for a first project!!!!
Here are some feedback. I suggest that you take into account the easy one and produce a new version and if you want to train your skills you try to see how to address the difficult ones.
Stef
- Add it in the class comment XsAndOsGame new openInWorld.
- you have some unclassified protocols on the class side.
- you may want to run smallLint (criticBorwser on your code and see the hints that it can give you).
- When you create a new game do not move the window to the top corner :)
easyBtn -> easyButton (you do not pay per character :))
findEmptyCellPos -> findEmptyCellPosition not in accessing
impBtn -> impossibleButton
.... :) - Why do you need a separate class just for three colors? I would merge XsAndOsGameColors and XsAndOsGame
XsAndOsGame>>initialize is long May be you should extract some methods from it (methods that you can then reuse for other tasks)
renderOContents | delta offset x1 y1 x2 y2 rect | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x + self oCorner x. x2 := offset x + delta x - self oCorner x. y1 := offset y + self oCorner y. y2 := offset y + delta y - self oCorner y. rect := Rectangle new setOrigin: x1 @ y1 corner: x2 @ y2. self targetForm getCanvas fillOval: rect color: XsAndOsGameColors gameBoardBackgroundColor borderWidth: 3 borderColor: XsAndOsGameColors OColor
What do you refer to CellRenderer direcly? self class ?
rendererFor: aCell "VERY BAD IMPLEMENTATION OF THIS METHOD!!!"
aCell class = EmptyCell ifTrue: [ ^ CellRenderer ]. aCell class = XCell ifTrue: [ ^ XCellRenderer ]. aCell class = OCell ifTrue: [ ^ OCellRenderer ]
indeed :) why not implementing some methods call renderClass and sending a message to the object :)
mptyCell>>initialize super initialize.
CellRenderer>>offsetWithinGridForm "Returns a point - left top corner of current cell"
^ CellRenderer cellExtent * ((self cellLocation x - 1) @ (self cellLocation y - 1)) => self clas cellExtent
CellRenderer >> renderBorderBottom | delta offset x1 y1 x2 y2 | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. self targetForm getCanvas line: x1 @ y1 to: x2 @ y2 width: 1 color: XsAndOsGameColors cellBorderColor
=> CellRenderer >> renderBorderBottom | delta offset x1 y1 x2 y2 | delta := self class cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. self targetForm getCanvas line: x1 @ y1 to: x2 @ y2 width: 1 color: XsAndOsGameColors cellBorderColor
I was wondering why you need Grid (I would rename it CellGrid) and do not use a Matrix.
grid sizeOfGrid -> I would rename sizeOfGrid into size like that your grid can be a bit more polymorphic from its API point of view
makeGameBoarMorph -> typo :) Now I want wondering why you do not have an instance variable to hold it
Future fun ideas for new versions: -------------------------------------------- playerVsComputer self vsComputer ifTrue: [ self vsComputer: false. self stateMorph contents: 'Player 1 VS Player 2' ] ifFalse: [ self vsComputer: true. self stateMorph contents: 'Player VS Computer ---> Difficulty: ' , self difficulty asString ]. self vsComputer ifTrue: [ self easyBtn enable. self normalBtn enable. self impBtn enable ] ifFalse: [ self easyBtn disable. self normalBtn disable. self impBtn disable ] This kind of code may be think that may be you need another object that represent the TwoUsers vsComputer strategy I'm not sure but clicked look quite long. May be you should create another class that can represent the logic of the game.
A really interesting exercise would be to see how you can create a boardGame for 15*15 and see how it breaks some hidden rules. On 08 Feb 2014, at 15:07, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Updated XsAndOsGame: added AI, also fixed some problems, that Damien mentioned in his comments. Btw, thanks to Damien, because I learned for myself a lot of new useful things. Note: The new version is XsAndOsGame (NOT Xs&OsGame) ! To play it type in workspace: XsAndOsGame new openInWorld. If you want to play vs computer press button "ToggleMode" and choose difficulty. Initially it is easy.
Mark
2014-02-05 15:57 GMT+02:00 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Thanks, I'll certainly take a look at it
2014-02-05 Damien Cassou <damien.cassou@gmail.com>:
On Tue, Feb 4, 2014 at 8:58 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
I should think how to write this tutorial.
on the technical point of view, I advise you to use Pillar: http://www.smalltalkhub.com/#!/~Pier/Pillar
-- Damien Cassou http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
I loaded the game in Pharo2.0 There is ImageMorph>>form: aForm missing but adding ImageMorph>>form: aForm self image: aFrom makes it work. Phil On Sun, Feb 9, 2014 at 9:59 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Thanks for comment. I'll fix all problems and change everything you mentioned, hope to succeed in it.
Mark
2014-02-09 22:51 GMT+02:00 Pharo4Stef <pharo4Stef@free.fr>:
Hi mark
I read a bit your code
It is nice for a first project!!!!
Here are some feedback. I suggest that you take into account the easy one and produce a new version and if you want to train your skills you try to see how to address the difficult ones.
Stef
- Add it in the class comment XsAndOsGame new openInWorld.
- you have some unclassified protocols on the class side.
- you may want to run smallLint (criticBorwser on your code and see the hints that it can give you).
- When you create a new game do not move the window to the top corner :)
easyBtn -> easyButton (you do not pay per character :))
findEmptyCellPos -> findEmptyCellPosition not in accessing
impBtn -> impossibleButton
â¦. :) - Why do you need a separate class just for three colors? I would merge XsAndOsGameColors and XsAndOsGame
XsAndOsGame>>initialize is long May be you should extract some methods from it (methods that you can then reuse for other tasks)
renderOContents | delta offset x1 y1 x2 y2 rect | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x + self oCorner x. x2 := offset x + delta x - self oCorner x. y1 := offset y + self oCorner y. y2 := offset y + delta y - self oCorner y. rect := Rectangle new setOrigin: x1 @ y1 corner: x2 @ y2. self targetForm getCanvas fillOval: rect color: XsAndOsGameColors gameBoardBackgroundColor borderWidth: 3 borderColor: XsAndOsGameColors OColor
What do you refer to CellRenderer direcly? self class ?
rendererFor: aCell "VERY BAD IMPLEMENTATION OF THIS METHOD!!!"
aCell class = EmptyCell ifTrue: [ ^ CellRenderer ]. aCell class = XCell ifTrue: [ ^ XCellRenderer ]. aCell class = OCell ifTrue: [ ^ OCellRenderer ]
indeed :) why not implementing some methods call renderClass and sending a message to the object :)
mptyCell>>initialize super initialize.
CellRenderer>>offsetWithinGridForm "Returns a point - left top corner of current cell"
^ CellRenderer cellExtent * ((self cellLocation x - 1) @ (self cellLocation y - 1)) => self clas cellExtent
CellRenderer >> renderBorderBottom | delta offset x1 y1 x2 y2 | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. self targetForm getCanvas line: x1 @ y1 to: x2 @ y2 width: 1 color: XsAndOsGameColors cellBorderColor
=> CellRenderer >> renderBorderBottom | delta offset x1 y1 x2 y2 | delta := self class cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. self targetForm getCanvas line: x1 @ y1 to: x2 @ y2 width: 1 color: XsAndOsGameColors cellBorderColor
I was wondering why you need Grid (I would rename it CellGrid) and do not use a Matrix.
grid sizeOfGrid -> I would rename sizeOfGrid into size like that your grid can be a bit more polymorphic from its API point of view
makeGameBoarMorph -> typo :) Now I want wondering why you do not have an instance variable to hold it
Future fun ideas for new versions: ââââââââââââââââââââââ playerVsComputer self vsComputer ifTrue: [ self vsComputer: false. self stateMorph contents: 'Player 1 VS Player 2' ] ifFalse: [ self vsComputer: true. self stateMorph contents: 'Player VS Computer ---> Difficulty: ' , self difficulty asString ]. self vsComputer ifTrue: [ self easyBtn enable. self normalBtn enable. self impBtn enable ] ifFalse: [ self easyBtn disable. self normalBtn disable. self impBtn disable ] This kind of code may be think that may be you need another object that represent the TwoUsers vsComputer strategy Iâm not sure but clicked look quite long. May be you should create another class that can represent the logic of the game.
A really interesting exercise would be to see how you can create a boardGame for 15*15 and see how it breaks some hidden rules. On 08 Feb 2014, at 15:07, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Updated XsAndOsGame: added AI, also fixed some problems, that Damien mentioned in his comments. Btw, thanks to Damien, because I learned for myself a lot of new useful things. Note: The new version is XsAndOsGame (NOT Xs&OsGame) ! To play it type in workspace: XsAndOsGame new openInWorld. If you want to play vs computer press button "ToggleMode" and choose difficulty. Initially it is easy.
Mark
2014-02-05 15:57 GMT+02:00 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Thanks, I'll certainly take a look at it
2014-02-05 Damien Cassou <damien.cassou@gmail.com>:
On Tue, Feb 4, 2014 at 8:58 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
I should think how to write this tutorial.
on the technical point of view, I advise you to use Pillar: http://www.smalltalkhub.com/#!/~Pier/Pillar
-- Damien Cassou http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
Hello everyone! Happy to inform you that I've just updated my game :) There where lots of changes made due to Stef's and kilon's comments. I really appreciate your feedback. Also thanks to Phil for his note (originally this game is written on Pharo 3.0). Update: - "impossible mode is quite easy to win" -kilon. Now it is harder to win, but it is possible despite the name of mode :) - if click New Game it keeps difficulty level + playing mode(PvsP or PvsComp) + now position of it is not 0@0 - added background for game log and game state for better visibility - added the class comment: XsAndOsGame new openInWorld. - all methods now are classifyied - fixed problems reported by criticBrowser(not all problems but many) - other many minor fixes to problems which were mentioned by Stef ToDo in next versions: - make some methods shorter - divide twoPlayers logic and PlayervsComputer logic in different classes - lots of other style changes and minor fixes - AND I want to provide a possibility to play not only just on 3X3 board but on any other (but I don't know yet how to implement AI) the last point about AI should be seriously thought through and requiers some of my time:) hope to get it done Link for project: http://smalltalkhub.com/#!/~MarkRizun/XsAndOsGame/versions/XsAndOsGame-MarkR... Again thanks to everyone! Mark 2014-02-10 10:22 GMT+02:00 phil@highoctane.be <phil@highoctane.be>:
I loaded the game in Pharo2.0
There is ImageMorph>>form: aForm missing but adding
ImageMorph>>form: aForm self image: aFrom
makes it work.
Phil
On Sun, Feb 9, 2014 at 9:59 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Thanks for comment. I'll fix all problems and change everything you mentioned, hope to succeed in it.
Mark
2014-02-09 22:51 GMT+02:00 Pharo4Stef <pharo4Stef@free.fr>:
Hi mark
I read a bit your code
It is nice for a first project!!!!
Here are some feedback. I suggest that you take into account the easy one and produce a new version and if you want to train your skills you try to see how to address the difficult ones.
Stef
- Add it in the class comment XsAndOsGame new openInWorld.
- you have some unclassified protocols on the class side.
- you may want to run smallLint (criticBorwser on your code and see the hints that it can give you).
- When you create a new game do not move the window to the top corner :)
easyBtn -> easyButton (you do not pay per character :))
findEmptyCellPos -> findEmptyCellPosition not in accessing
impBtn -> impossibleButton
.... :) - Why do you need a separate class just for three colors? I would merge XsAndOsGameColors and XsAndOsGame
XsAndOsGame>>initialize is long May be you should extract some methods from it (methods that you can then reuse for other tasks)
renderOContents | delta offset x1 y1 x2 y2 rect | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x + self oCorner x. x2 := offset x + delta x - self oCorner x. y1 := offset y + self oCorner y. y2 := offset y + delta y - self oCorner y. rect := Rectangle new setOrigin: x1 @ y1 corner: x2 @ y2. self targetForm getCanvas fillOval: rect color: XsAndOsGameColors gameBoardBackgroundColor borderWidth: 3 borderColor: XsAndOsGameColors OColor
What do you refer to CellRenderer direcly? self class ?
rendererFor: aCell "VERY BAD IMPLEMENTATION OF THIS METHOD!!!"
aCell class = EmptyCell ifTrue: [ ^ CellRenderer ]. aCell class = XCell ifTrue: [ ^ XCellRenderer ]. aCell class = OCell ifTrue: [ ^ OCellRenderer ]
indeed :) why not implementing some methods call renderClass and sending a message to the object :)
mptyCell>>initialize super initialize.
CellRenderer>>offsetWithinGridForm "Returns a point - left top corner of current cell"
^ CellRenderer cellExtent * ((self cellLocation x - 1) @ (self cellLocation y - 1)) => self clas cellExtent
CellRenderer >> renderBorderBottom | delta offset x1 y1 x2 y2 | delta := CellRenderer cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. self targetForm getCanvas line: x1 @ y1 to: x2 @ y2 width: 1 color: XsAndOsGameColors cellBorderColor
=> CellRenderer >> renderBorderBottom | delta offset x1 y1 x2 y2 | delta := self class cellExtent - 1. offset := self offsetWithinGridForm. x1 := offset x. x2 := x1 + delta x. y1 := offset y + delta y. y2 := y1. self targetForm getCanvas line: x1 @ y1 to: x2 @ y2 width: 1 color: XsAndOsGameColors cellBorderColor
I was wondering why you need Grid (I would rename it CellGrid) and do not use a Matrix.
grid sizeOfGrid -> I would rename sizeOfGrid into size like that your grid can be a bit more polymorphic from its API point of view
makeGameBoarMorph -> typo :) Now I want wondering why you do not have an instance variable to hold it
Future fun ideas for new versions: -------------------------------------------- playerVsComputer self vsComputer ifTrue: [ self vsComputer: false. self stateMorph contents: 'Player 1 VS Player 2' ] ifFalse: [ self vsComputer: true. self stateMorph contents: 'Player VS Computer ---> Difficulty: ' , self difficulty asString ]. self vsComputer ifTrue: [ self easyBtn enable. self normalBtn enable. self impBtn enable ] ifFalse: [ self easyBtn disable. self normalBtn disable. self impBtn disable ] This kind of code may be think that may be you need another object that represent the TwoUsers vsComputer strategy I'm not sure but clicked look quite long. May be you should create another class that can represent the logic of the game.
A really interesting exercise would be to see how you can create a boardGame for 15*15 and see how it breaks some hidden rules. On 08 Feb 2014, at 15:07, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
Updated XsAndOsGame: added AI, also fixed some problems, that Damien mentioned in his comments. Btw, thanks to Damien, because I learned for myself a lot of new useful things. Note: The new version is XsAndOsGame (NOT Xs&OsGame) ! To play it type in workspace: XsAndOsGame new openInWorld. If you want to play vs computer press button "ToggleMode" and choose difficulty. Initially it is easy.
Mark
2014-02-05 15:57 GMT+02:00 ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com>:
Thanks, I'll certainly take a look at it
2014-02-05 Damien Cassou <damien.cassou@gmail.com>:
On Tue, Feb 4, 2014 at 8:58 PM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote:
I should think how to write this tutorial.
on the technical point of view, I advise you to use Pillar: http://www.smalltalkhub.com/#!/~Pier/Pillar
-- Damien Cassou http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
Thanks damien It was on my todo :) Mark will come to visit us this summer :) Stef On 04 Feb 2014, at 17:37, Damien Cassou <damien.cassou@gmail.com> wrote:
On Mon, Feb 3, 2014 at 11:39 AM, ÐаÑкÑÑн Ð ÑзÑн <mrizun@gmail.com> wrote: As a novice in pharo, waiting for comments and advice. Сritique is welcome too ;)
random comments (tested on Pharo 3.0):
- I played and things work perfectly as far as I saw :-) - your code is of very good quality! - 2 tests don't pass (EmptyCellTestCase, CellRendererTestCase) - usually we don't append 'Case' at the end of our test classes - the package name doesn't follow the convention (https://ci.inria.fr/pharo-contribution/job/PharoForTheEnterprise/ws/Conventi...) - you may want to avoid the use of non-alphanumeric characters in the package name (e.g., avoid &) - please indent your code (use ALT+Shift+u on each method to get automatic indentation) - "self should: [ offset = (50 @ 50) ]" --> "self assert: offset equals: 50@50" - "self should: [ cell isOff ]." --> "self assert: cell isOff" - all subclasses of Cell override #initialize in exactly the same way. Consider moving that to the superclass - you should try to avoid as much as possible doing a super send in a different method. For example, EmptyCell>>initializeState does a super send on #initialize. - OCell and XCell are exactly the same, this should not be and is very suspicious. - CellRenderer has 2 methods with an uppercase letter. This is not conventional - you use a lot of variables you use only once. Consider inlining them. For example in CellRenderer>>offsetWithinGridForm, all variables seem useless : "^ CellRenderer cellExtent * ((self cellLocation x - 1) @ (self cellLocation y - 1))" - CellRenderer>>renderContents uses branching on the class of objects instead of polymorphism. That's bad design in my opinion. Consider delegating to OCell and XCell or using double-dispatch. - Same thing for CellRenderer class>>rendererFor:
All in all, very good job. Would you consider writing a tutorial on how to implement an Xs&Os game in Pharo?
-- Damien Cassou http://damiencassou.seasidehosting.st
"Success is the ability to go from one failure to another without losing enthusiasm." Winston Churchill
participants (6)
-
Damien Cassou -
kilon alios -
Pharo4Stef -
phil@highoctane.be -
Yuriy Tymchuk -
ÐаÑкÑÑн Ð ÑзÑн