I usually start learning new technologies by doing something more than hello world example. This time I wanted to learn Silverlight and decided to build Othello game. I have done it with other technologies as well like Java ME so I was quite familiar with the game concepts. So I just rushed to code.
My first task was to create the game board. Game board in Othello is 8x8 in size and each of the places can be in one of the following state: white,black or empty. I first created a UserControl called GameButton to visualize the state of the game board place. The Game button contains visualization of all the states. When the state changes from white to black or vise versa the state change is animated by flipping the button along x-pane.
Next I created the main Window with one Grid called LayoutRoot. Because I have strong background on Windows Forms I thought that it is impossible to creating the board dynamically without writing some code behind code (you will notice how wrong I was).
List<List<GameButton>> buttons = new List<List<GameButton>>();
for(int i = 0; i < 8; i++)
{
buttons.Add(new List<GameButton>());
for(int j=0; j < 8; j++)
{
GameButton button = new GameButton();
button.ButtonState = GameButtonState.Empty;
button.SetValue(Grid.RowProperty, i);
button.SetValue(Grid.ColumnProperty, j);
LayoutRoot.Children.Add(button);
buttons[i].Add(button);
}
}
buttons[3][3].ButtonState = GameButtonState.White;
buttons[3][4].ButtonState = GameButtonState.Black;
buttons[4][3].ButtonState = GameButtonState.Black;
buttons[4][4].ButtonState = GameButtonState.White;
This code smells, my game state (Model) is not separated from the view. Also I have UI logic both in XAML file and code behind. This means that designer tools like Expression Studio will not have any glue what controls the Grid contains.
I knew that there has to be a better way to do this in XAML. I investigated a bit and found out that this can be fairly easily implemented. Here is the result of new version written in XAML.
<Grid x:Name="LayoutRoot" Background="White">
<ItemsControl x:Name="GameButtons" ItemsSource="{Binding GameBoard}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl x:Name="Row" ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:GameButton ButtonState="{Binding GameRegionState}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
As you can see I have two nested ItemsControls. The first one is bind to the GameBoard property (List<List<State>>) of the OthelloGame class. The Row ItemsControl contains now the GameButton and the ButtonState is bind. I have now only few lines of code in code behind to bind the game state to the view. Now this starts to look good. Also if I would like to have bigger board it could be easily done by just adding more States to the List.
I would still like to get rid of GameButton UserControl. It contains some actions what would be nice to get from code behind to XAML side and also it is not needed because the binding takes care of creating new instances of it. The problem is that in Silverlight the triggers, actions and conditions are very limited. For silverlight 4.0 there is interesting extension library for triggers and actions called Slex. It requires Silverlight 4.0 and I was using 3.0 so I had to forget it. So if I would move the GameButton to the main view, benefits wouldn’t be that big. So the GameButton can stay. With WPF the GameButton would be dead and buried.
The transition from the Windows Forms to Silverlight/WPF is quite big. The controls etc. are not that different but the biggest challenge is to get your brains to work with new mindset. Lot of things that was done before in code can be done in XAML with DataTemplates, Triggers, Actions and more.
Below is my first Silverlight application live and kicking. Computer uses minmax algorithm with a few optimizations on the normal level and calculates 4 moves ahead.
Download full source here.







Per Lundberg (26.1.10 17:37)
Yes! I won 32-31 in my first attempt to play it. (Oh, then I realized that there was one free spot as well, so the actual victory was a total of 39-25 to my advantage)
Really cool Tero, very good work. How about putting up the full source here? I'll gladly take a look at it and share my opinions.
Best regards,
Per
Tero Tapanainen (27.1.10 15:58)
Yep, the computer could be tweaked a lot but with limited time (less that a week, mostly evenings) this was the best I could come up with :).
I added link to the full source at the end of the post.
-Tero
Per Lundberg (28.1.10 13:44)
I should mention that this was on "easy" mode. :-)
Thanks for the source link! I might look into it some day. Some potential improvements/changes I've been thinking about:
- Add a "high score" table. This is an interesting challenge from a security point of view. If you just let the client report in the score after the game has been played, how can you trust the content to be reliable? A malicious user (developer) could place a handcrafted webservice call and "cheat" his way into the highscore chart. The only reliable way to implement this feature that I can think of would be to change the application to a client/server app, where each turn is validated by the server (rather than just the client).
This will change the app rather fundamentally, though. :-) Do you have any other ideas about how we could implement a high score listing in a secure manner?
Best regards,
Per
Jon Wickström (2.2.10 22:02)
A somewhat secure highscore could be implemented by also submitting the moves. Number of turns is quite finite in reversi... A server could replay the game and chek the computer moves are moves it possibly would have chosen.
But there is no easy way to check the player is human...
Tero Tapanainen (3.2.10 15:49)
Yes, if we want high secure version the moves should be send to the server. This way the server holds the state of the game and knows if illegal moves are tried to make.
Actually to separate the AI etc. logic from the client and move to the server side woulnd't be that hard. Also the high score feature would be cool. Let's see if I have time to implement it.
-Tero
Johnny Ribacka (3.2.10 16:57)
I already beat the "normal" computer 63-0, so in order for a high score table to be of use, the AI would probably need to be better.
The trick to really wiping the floor with the computer is to play a few games until you find a starting sequence where the computer surrenders a corner to you quite early in the game. After that it is often quite easy to win in a way that leaves the computer at 0...
Hi Jonte! :-)