现在的位置: 首页 > 综合 > 正文

Silverlight版井字棋,附解释-[Silverlight开发 ]

2012年05月05日 ⁄ 综合 ⁄ 共 1909字 ⁄ 字号 评论关闭
文章目录

Tic-tac-toe, also spelled tick tack toe, or noughts and crosses/Xs and Os as it is known in the UK, Australia and New Zealand, is a pencil-and-paper game for two players, X and O, who take turns marking the spaces in a 3×3 grid.

井字棋可能是最简单的棋类游戏了,它简单到了成年人之间玩几乎总是平局的地步。因此,这个游戏貌似最多只能哄哄小孩子。对井字棋突然感兴趣是看到一张图片,里面解释了最佳的首选策略,然后在网上查看了下具体的说明(原文章)。井字棋可以算是决策树最简单的游戏之一了。在历史上,对井字棋的类似分析很大程度上启发了人们对组合游戏的认识,在博弈论中起着举足轻重的作用。兴致一来,就想着用Silverlight简单的实现下。

简单的实现效果

需要安装Silverlight环境。

为什么第一步走在角上才是最佳的策略

首先看下面这张图,点击查看:http://xkcd.com/832/ & 声明:以下为转载,版权归原作者所有:matrix67

题外话:自己很喜欢这种科普性的文章,像果壳,像松树科学会等都有很多这种类型的文章,可以激发下自己对事物新的看法,挺好的。

先手先占角

游戏开始后,二话不说先占上一个角(比如左下角吧),那么对方总共有五种本质不同的应对策略:占据靠近你的那条边,占据靠近你的那个角,占据远离你的那条边,占据远离你的那个角(即对角),以及占据正中央的位置。不可思议的是,在这五种策略中,前面四种都是陷阱——如果对方不慎选择了前面四种策略中的任意一种,他就必然输掉。

上图显示了在这四种情况下你可以如何把对方一步步逼上绝路。假设对方走正下方,占据了一个靠近你的边(最左边的那个图),你就可以占据正中央来应对,逼迫对方不得不走右上角。这时,只需要在左上角放下一子,你就赢定了——图中出现了两条只差一子的连线,对方不可能兼顾得了。右边几个图显示了对方第一步棋的其它几种走法。选择合适的位置应对他,都可以在下一步迫使对方只剩一种走法,接下来你便可以下出“一箭双雕”的棋,让对方无法彻底封杀你。也就是说,当你占据棋盘一角后,在对方下一步棋的八个可选位置中,其中七个位置都是必输的,陷阱摆满了几乎整个棋盘。在面对“先走一角”的诡异开局时,你的朋友说不准就会慌了手脚,没能冷静地占住中间,决定了必败的命运。

对方要是真的走了正中间,你仍然有赢的机会。你可以占住右上角的位置(如上图)。如果对方不幸走了剩下的两个角中的一个(上图左),你便能故技重施,再次取得胜利。只有对方选择了边上的位置(上图右),才能躲过这一系列的陷阱,最终变成平局。

后手先占角

作为后行者,你遇到的往往是“先走中间”的经典开局。此时,千万别忘了,先占角仍然是一条金科玉律。如果你不慎走了某条边的位置,对方可就赢定了!对方可以向上面的第一幅图那样,在正右方下子应对,逼迫你把下一步棋落在正左方。此时,对方便可占据右上方的位置,同时产生出两条仅差一子的连线。右边三幅图则显示,如果你在角上应对,最终总会是一盘和棋。

本程序背后算法简单说明

其实背后的算法很简单的, 只是简单的模拟一下人类想问题的思路而已,并且很有可能不是最佳的实现方式。

首先定义两个矩阵,一个表示棋盘上的9个位置,另外一个是权重矩阵。解释下权重矩阵,这里的权重是指电脑在思考下一步的过程中得到的,哪个位置权重高点,就先下在那个位置上。所以这里就涉及到权重大小的判断问题,按照正常来说,"求胜"的权重是最大,也就是说电脑在计算的过程中,如果可以获胜就下那个位置,然后到防止对方获胜,也就是当玩家有两个棋子和一个空位置时就堵那个位置。这是基本的两点,然后就到基本位置的判断问题。如下面的代码就是设置"求胜"的权重。

if (sMatrix[i, 0+ sMatrix[i, 1]+stMatrix[i, 2== 2)
              weightMatrix[i, j] 
+= 6;
//如果可以连成线,则胜利

一开始我设置电脑在中点下子的权重更高,看到文章的分析,就设置在边角的权重更高些,可能由于游戏本来简单,看不出这两者有什么区别。然后,最后一个权重需要考虑的地方就是最好能构成两个连起来的棋子,最后自己得到的权重比例应该是:"获胜">"防止玩家获胜">"边角下子">"中心下子">"连成两个棋子",最后,权重都一样的话就随机找个空的位置下子。

其中,在每次的下子过后都调用一个函数来检查游戏是否结束,这些都是小细节而已。简单的说明就到这里呵。

抱歉!评论已关闭.