自对弈算法
Ⅰ 自学围棋的AlphaGo Zero,你也可以造一个
- 01
遥想当年,AlphaGo的Master版本,在完胜柯洁九段之后不久,就被后辈AlphaGo Zero(简称狗零) 击溃了。
从一只完全不懂围棋的AI,到打败Master,狗零只用了21天。
而且,它不需要用人类知识来喂养,成为顶尖棋手全靠自学。
如果能培育这样一只AI,即便自己不会下棋,也可以很骄傲吧。
于是,来自巴黎的少年Dylan Djian (简称小笛) ,就照着狗零的论文去实现了一下。
他给自己的AI棋手起名SuperGo,也提供了代码(传送门见文底) 。
除此之外,还有教程——
一个身子两个头
智能体分成三个部分:
一是特征提取器(Feature Extractor) ,二是策略网络(Policy Network) ,三是价值网络(Value Network) 。
于是,狗零也被亲切地称为“双头怪”。特征提取器是身子,其他两个网络是脑子。
特征提取器
特征提取模型,是个残差网络 (ResNet) ,就是给普通CNN加上了跳层连接 (Skip Connection) , 让梯度的传播更加通畅。
跳跃的样子,写成代码就是:
1classBasicBlock(nn.Mole):
2 """
3 Basic resial block with 2 convolutions and a skip connection
4 before the last ReLU activation.
5 """
6
7def__init__(self, inplanes, planes, stride=1, downsample=None):
8 super(BasicBlock, self).__init__()
9
10 self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3,
11 stride=stride, padding=1, bias=False)
12 self.bn1 = nn.BatchNorm2d(planes)
13
14 self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,
15 stride=stride, padding=1, bias=False)
16 self.bn2 = nn.BatchNorm2d(planes)
17
18
19defforward(self, x):
20 resial = x
21
22 out = self.conv1(x)
23 out = F.relu(self.bn1(out))
24
25 out = self.conv2(out)
26 out = self.bn2(out)
27
28 out += resial
29 out = F.relu(out)
30
31returnout
然后,把它加到特征提取模型里面去:
1classExtractor(nn.Mole):
2def__init__(self, inplanes, outplanes):
3 super(Extractor, self).__init__()
4 self.conv1 = nn.Conv2d(inplanes, outplanes, stride=1,
5 kernel_size=3, padding=1, bias=False)
6 self.bn1 = nn.BatchNorm2d(outplanes)
7
8forblockinrange(BLOCKS):
9 setattr(self, "res{}".format(block),
10 BasicBlock(outplanes, outplanes))
11
12
13defforward(self, x):
14 x = F.relu(self.bn1(self.conv1(x)))
15forblockinrange(BLOCKS - 1):
16 x = getattr(self, "res{}".format(block))(x)
17
18 feature_maps = getattr(self, "res{}".format(BLOCKS - 1))(x)
19returnfeature_maps
策略网络
策略网络就是普通的CNN了,里面有个批量标准化(Batch Normalization) ,还有一个全连接层,输出概率分布。
1classPolicyNet(nn.Mole):
2def__init__(self, inplanes, outplanes):
3 super(PolicyNet, self).__init__()
4 self.outplanes = outplanes
5 self.conv = nn.Conv2d(inplanes, 1, kernel_size=1)
6 self.bn = nn.BatchNorm2d(1)
7 self.logsoftmax = nn.LogSoftmax(dim=1)
8 self.fc = nn.Linear(outplanes - 1, outplanes)
9
10
11defforward(self, x):
12 x = F.relu(self.bn(self.conv(x)))
13 x = x.view(-1, self.outplanes - 1)
14 x = self.fc(x)
15 probas = self.logsoftmax(x).exp()
16
17returnprobas
价值网络
这个网络稍微复杂一点。除了标配之外,还要再多加一个全连接层。最后,用双曲正切 (Hyperbolic Tangent) 算出 (-1,1) 之间的数值,来表示当前状态下的赢面多大。
代码长这样——
1classValueNet(nn.Mole):
2def__init__(self, inplanes, outplanes):
3 super(ValueNet, self).__init__()
4 self.outplanes = outplanes
5 self.conv = nn.Conv2d(inplanes, 1, kernel_size=1)
6 self.bn = nn.BatchNorm2d(1)
7 self.fc1 = nn.Linear(outplanes - 1, 256)
8 self.fc2 = nn.Linear(256, 1)
9
10
11defforward(self, x):
12 x = F.relu(self.bn(self.conv(x)))
13 x = x.view(-1, self.outplanes - 1)
14 x = F.relu(self.fc1(x))
15 winning = F.tanh(self.fc2(x))
16returnwinning
未雨绸缪的树
狗零,还有一个很重要的组成部分,就是蒙特卡洛树搜索(MCTS) 。
它可以让AI棋手提前找出,胜率最高的落子点。
在模拟器里,模拟对方的下一手,以及再下一手,给出应对之策,所以提前的远不止是一步。
节点 (Node)
树上的每一个节点,都代表一种不同的局势,有不同的统计数据:
每个节点被经过的次数n,总动作值w,经过这一点的先验概率p,平均动作值q (q=w/n) ,还有从别处来到这个节点走的那一步,以及从这个节点出发、所有可能的下一步。
1classNode:
2def__init__(self, parent=None, proba=None, move=None):
3 self.p = proba
4 self.n = 0
5 self.w = 0
6 self.q = 0
7 self.children = []
8 self.parent = parent
9 self.move = move
部署 (Rollout)
第一步是PUCT (多项式上置信树) 算法,选择能让PUCT函数 (下图) 的某个变体 (Variant)最大化,的走法。
写成代码的话——
1defselect(nodes, c_puct=C_PUCT):
2 " Optimized version of the selection based of the PUCT formula "
3
4 total_count = 0
5foriinrange(nodes.shape[0]):
6 total_count += nodes[i][1]
7
8 action_scores = np.zeros(nodes.shape[0])
9foriinrange(nodes.shape[0]):
10 action_scores[i] = nodes[i][0] + c_puct * nodes[i][2] *
11 (np.sqrt(total_count) / (1 + nodes[i][1]))
12
13 equals = np.where(action_scores == np.max(action_scores))[0]
14ifequals.shape[0] > 0:
15returnnp.random.choice(equals)
16returnequals[0]
结束 (Ending)
选择在不停地进行,直至到达一个叶节点 (Leaf Node) ,而这个节点还没有往下生枝。
1defis_leaf(self):
2 """ Check whether a node is a leaf or not """
3
4returnlen(self.children) == 0
到了叶节点,那里的一个随机状态就会被评估,得出所有“下一步”的概率。
所有被禁的落子点,概率会变成零,然后重新把总概率归为1。
然后,这个叶节点就会生出枝节 (都是可以落子的位置,概率不为零的那些) 。代码如下——
1defexpand(self, probas):
2 self.children = [Node(parent=self, move=idx, proba=probas[idx])
3foridxinrange(probas.shape[0])ifprobas[idx] > 0]
更新一下
枝节生好之后,这个叶节点和它的妈妈们,身上的统计数据都会更新,用的是下面这两串代码。
1defupdate(self, v):
2 """ Update the node statistics after a rollout """
3
4 self.w = self.w + v
5 self.q = self.w / self.nifself.n > 0else0
1whilecurrent_node.parent:
2 current_node.update(v)
3 current_node = current_node.parent
选择落子点
模拟器搭好了,每个可能的“下一步”,都有了自己的统计数据。
按照这些数据,算法会选择其中一步,真要落子的地方。
选择有两种,一就是选择被模拟的次数最多的点。试用于测试和实战。
另外一种,随机 (Stochastically) 选择,把节点被经过的次数转换成概率分布,用的是以下代码——
1 total = np.sum(action_scores)
2 probas = action_scores / total
3 move = np.random.choice(action_scores.shape[0], p=probas)
后者适用于训练,让AlphaGo探索更多可能的选择。
三位一体的修炼
狗零的修炼分为三个过程,是异步的。
一是自对弈(Self-Play) ,用来生成数据。
1defself_play():
2whileTrue:
3 new_player, checkpoint = load_player()
4ifnew_player:
5 player = new_player
6
7 ## Create the self-play match queue of processes
8 results = create_matches(player, cores=PARALLEL_SELF_PLAY,
9 match_number=SELF_PLAY_MATCH)
10for_inrange(SELF_PLAY_MATCH):
11 result = results.get()
12 db.insert({
13 "game": result,
14 "id": game_id
15 })
16 game_id += 1
二是训练(Training) ,拿新鲜生成的数据,来改进当前的神经网络。
1deftrain():
2 criterion = AlphaLoss()
3 dataset = SelfPlayDataset()
4 player, checkpoint = load_player(current_time, loaded_version)
5 optimizer = create_optimizer(player, lr,
6 param=checkpoint['optimizer'])
7 best_player = deep(player)
8 dataloader = DataLoader(dataset, collate_fn=collate_fn,
9 batch_size=BATCH_SIZE, shuffle=True)
10
11whileTrue:
12forbatch_idx, (state, move, winner)inenumerate(dataloader):
13
14 ## Evaluate a of the current network
15iftotal_ite % TRAIN_STEPS == 0:
16 pending_player = deep(player)
17 result = evaluate(pending_player, best_player)
18
19ifresult:
20 best_player = pending_player
21
22 example = {
23 'state': state,
24 'winner': winner,
25 'move' : move
26 }
27 optimizer.zero_grad()
28 winner, probas = pending_player.predict(example['state'])
29
30 loss = criterion(winner, example['winner'],
31 probas, example['move'])
32 loss.backward()
33 optimizer.step()
34
35 ## Fetch new games
36iftotal_ite % REFRESH_TICK == 0:
37 last_id = fetch_new_games(collection, dataset, last_id)
训练用的损失函数表示如下:
1classAlphaLoss(torch.nn.Mole):
2def__init__(self):
3 super(AlphaLoss, self).__init__()
4
5defforward(self, pred_winner, winner, pred_probas, probas):
6 value_error = (winner - pred_winner) ** 2
7 policy_error = torch.sum((-probas *
8 (1e-6 + pred_probas).log()), 1)
9 total_error = (value_error.view(-1) + policy_error).mean()
10returntotal_error
三是评估(Evaluation) ,看训练过的智能体,比起正在生成数据的智能体,是不是更优秀了 (最优秀者回到第一步,继续生成数据) 。
1defevaluate(player, new_player):
2 results = play(player, opponent=new_player)
3 black_wins = 0
4 white_wins = 0
5
6forresultinresults:
7ifresult[0] == 1:
8 white_wins += 1
9elifresult[0] == 0:
10 black_wins += 1
11
12 ## Check if the trained player (black) is better than
13 ## the current best player depending on the threshold
14ifblack_wins >= EVAL_THRESH * len(results):
15returnTrue
16returnFalse
第三部分很重要,要不断选出最优的网络,来不断生成高质量的数据,才能提升AI的棋艺。
三个环节周而复始,才能养成强大的棋手。
有志于AI围棋的各位,也可以试一试这个PyTorch实现。
本来摘自量子位,原作 Dylan Djian。
代码实现传送门:
网页链接
教程原文传送门:
网页链接
AlphaGo Zero论文传送门:
网页链接
Ⅱ 博弈算法里的剪枝怎么用(具体的)
极大极小过程,以及阿尔法-贝塔剪纸。极小极大搜索方法是博弈树搜索的基本方法,现在博弈树搜索中最常用的α-β剪枝搜索方法,就是从这一方法发展而来的。
首先假定,有一个评价函数可以对所有的棋局进行评估。当评价函数值大于0时,表示棋局对我方有利,对对方不利。当评价函数小于0时,表示棋局对我方不利,对对方有利。而评价函数值越大,表示对我方越有利。当评价函数值等于正无穷大时,表示我方必胜。评价函数值越小,表示对我方越不利。当评价函数值等于负无穷大时,表示对方必胜。假设双方都是对弈高手,在只看一步棋的情况下,我方一定走评价函数值最大的一步棋,而对方一定走评价函数值最小的一步棋。会下棋的读者都知道,在只看一步的情况下最好的棋,从全局来说不一定就好,还可能很不好。因此为了走出好棋,必须多看几步,从多种可能状态中选择一步好棋。
想一想人是如何下棋的呢?人实际上采用的是一种试探性的方法。首先假定走了一步棋,看对方会有那些应法,然后再根据对方的每一种应法,看我方是否有好的回应......这一过程一直进行下去,直到若干步以后,找到了一个满意的走法为止。初学者可能只能看一、两个轮次,而高手则可以看几个,甚至十几个轮次。
极小极大搜索方法,模拟的就是人的这样一种思维过程。当轮到我方走棋时,首先按照一定的搜索深度生成出给定深度d以内的所有状态,计算所有叶节点的评价函数值。然后从d-1层节点开始逆向计算:对于我方要走的节点(用MAX标记,称为极大节点)取其子节点中的最大值为该节点的值(因为我方总是选择对我方有利的棋);对于对方要走的节点(用MIN标记,称为极小节点)取其子节点中的最小值为该节点的值(对方总是选择对我方不利的棋)。一直到计算出根节点的值为止。获得根节点取值的那一分枝,即为所选择的最佳走步。
在图3.5所示的例子中,假定搜索深度为2,D~J是7个叶节点,在它们下边括号中的数字是这些节点的评价函数值(假定可以计算得到)。A、B、C是三个极小节点,它们分别取各自子节点最小值为自己的值,得到三个节点的值分别为-6、-2和-4。s是极大节点,从A、B、C三个节点的值中取最大值,得到-2。由于-2来自于节点B,所以搜索的结果是应选择B作为我方的走步。对于我方来说,-2并不是一个好的结果,但却是在对方不犯错误的情况下,对我方最有利的结果。因为从图中可以看出,如果选择A为我方的走步,如果对方回应D的话,我方可以得到评价值9,固然对我方有利。但是如果对方是一个高手的话,他一定回选择E,而不是D。在这种情况下,我方只能得到-6,结果岂不是更差。因此,极小极大过程是一种假定对手每次回应都正确的情况下,如何从中找出对我方最有利的走步的搜索方法。
值得注意的是,不管设定的搜索深度是多少层,经过一次搜索以后,只决定了我方一步棋的走法。等到对方回应一步棋之后,需要在新的棋局下重新进行搜索,来决定下一步棋如何走。极小极大搜索策略是考虑双方对弈若干步之后,从可能的走步中选一步相对好棋的着法来走,即在有限的搜索深度范围内进行求解。为此要定义一个静态估计函数f,以便对棋局的势态(节点)作出优劣估值,这个函数可根据势态优劣特征来定义(主要用于对端节点的"价值"进行度量)。一般规定有利于MAX的势态,f(p)取正值,有利于MIN的势态,f(p)取负值,势均力敌的势态,f(p)取0值。若f(p)=+∞,则表示MAX赢,若f(p)=-∞,则表示MIN赢。下面的讨论规定:顶节点深度d=0,MAX代表程序方,MIN代表对手方,MAX先走。
图3.5是一个表示考虑两步棋的例子,图中端节点给出的数字是用静态函数f(p)计算得到,其他节点不用f(p)估计,因为不够精确,而应用倒推的办法取值。例如A、B、C是MIN走步的节点,MAX应考虑最坏的情况,故其估值应分别取其子节点f(p)估值中最小者,而s是MAX走步的节点,可考虑最好的情况,故估值应取A、B、C值中的最大者。这样求得f(s)=-2,依此确定了相对较优的走步应是走向B,因为从B出发,对手不可能产生比f(s)=-2更差的效果。实际上可根据资源条件,考虑更多层次的搜索过程,从而可得到更准确的倒推值,供MAX选取更正确的走步。当用端节点的静态估计函数f(p)求倒推值时,两位选手应采取不同的策略,从下往上逐层交替使用极小和极大的选值方法,故称极小极大过程。
Ⅲ 王者荣耀ELO算法是怎么计算的 ELO值是什么意思
近期很多小伙伴表示自己在玩王者荣耀时,匹配人的速度变慢了许多,那是因为你的ELO值过高导致,那么王者荣耀ELO算法是怎么计算的,ELO值是什么意思。
王者荣耀策划Donny 微博原文如下
1、排位赛中的匹配机制最重要的目标就是给每一位玩家匹配实力相近的队友和对手,如果你是大神,那希望你的队友和对手都是大神,如果你实力普通,那希望你的队友和对手也都和你实力相近也比较普通,同时在机制上是完全希望避免让大神匹配到小白的。这是单排的情况,组排会更复杂些,比如一个大神和一个小白一起双排,那在匹配时会希望找到对手也是有一个实力相近的大神和一个小白双排的,同时他们的队友分别也是处于在这实力区间里同时敌我双方实力均等。
2、那怎么定义每个玩家的真实实力呢?段位是很重要的因素,但并不是全部的因素,比如某职业选手平时排位玩的很少,段位可能只有星耀,但他只要排位基本就都是赢,那这个段位和他的实力就是不相符的,让他和其他星耀的普通玩家一起排位,这可能就是不太合理的(同样某些王者段位玩家开小号到低端局炸鱼也是类似的情况)。所以在现在排位赛的匹配机制中,会同时考虑玩家的段位和elo值,希望做到的是让对战双方10名玩家的段位相近(这是第一目标),同时elo值也相近(这是第二目标)。
3、回到上述例子的话,就是希望做到这职业选手在星耀段位排位的时候,他的队友和对手都是星耀段位同时elo值也相近的玩家,如果等待时间过长,那会在保证段位相近的基础上逐渐放大elo值的寻找范围,最终的结果是会得到10个段位相近的玩家,同时排位等待时间越短大家的elo值差异也越小。(这其实也是在排位等待时间和排位对局质量间需要取的平衡点)
4、那么肯定有同学会问,什么是elo值呢?它是一个衡量各类对弈活动水平的评价方法,被广泛用于国际象棋、围棋、足球、篮球等运动,是一套非常完善的评分规则和机制。简单来说,玩家们在各个段位的排位赛里的胜率、胜场数、局内表现等等就会决定其elo值。
5、另外,在排位中引入elo值肯定也需要考虑对应的“跳跃机制”,就是如何让玩家可以快速的达到其真实实力所在的段位,所以在游戏中所设定的连胜时获得的勇者积分以及金/银牌奖励的勇者积分就是为了这个目的而做的,让那部分自身实力超过当前段位的可以比较快速的达到符合其自身实力的段位上。当然目前的勇者积分设定还有优化空间,我们也计划在下个赛季时会勇者积分这块再做一次比较大的优化升级,以更好的满足这套系统所应该达到的目标哈~
6、所以,当了解了上述这些以后,不少职业选手和主播反馈最近他们的钻石星耀号排位等待时间很长的问题也就有了答案,其根本原因就是如上所述,排位中需要同时满足段位相近和elo值相近,而随着等待时间的增加会逐步放大elo值的范围。我们后续也会优化随等待时间发大elo值范围的幅度和频率,以进一步优化并寻找排位等待时间和排位对局质量间的平衡点。
7、上述讨论的只是排位赛的情况,匹配赛/赏金赛/娱乐赛的情况会有比较大的区别,后续可以和玩家朋友们再逐个沟通了解下,我们也希望将这块做的更加透明,改进所有不合理的地方~
8、最后,也想跟各位玩家朋友们引荐一位同学:狄仁杰大大,他会专门负责我们的对局质量相关问题并和玩家们做沟通互动,包括对于挂机、送人头、演员、举报、惩罚力度、匹配机制之类大家经常吐槽的问题等等。狄仁杰大大此前在王者荣耀微信公众号跟大家见过面了,后续他也会活跃在微博上跟大家沟通的,反馈大家遇到的各种对局质量方面的问题,狄大人会定期对这里的内容处理的。总的来说,我们希望能够和玩家们一起,不断的解决目前大家在对局环境方面所吐槽的问题,不断的改进并提升玩家们的游戏体验哈~
王者荣耀ELO算法是怎么计算的
elo值:衡量各类对弈活动水平的评价方法,被广泛用于国际象棋、围棋、足球、篮球等运动,是一套非常完善的评分规则和机制。
不过还好策划也进一步解释了,elo在游戏中具体的表现为:玩家们在各个段位的排位赛里的胜率、胜场数、局内表现等等就会决定其elo值。不过策划并没有给出详细的计算方式,所以自然也是无法直接在游戏中查看的。
另外策划也特别提到了,玩家真实水平和段位的差异,比如职业选手少打排位段位比较低,或者是王者段位开小号在低端局炸鱼,所以也再次引入了勇者积分设定,让那部分自身实力超过当前段位的可以比较快速的达到符合其自身实力的段位上,另外策划也透露了将在S12赛季优化勇者积分。
关于排位匹配时间过长的时间,策划也表示后续也会优化随等待时间发大elo值范围的幅度和频率,以进一步优化并寻找排位等待时间和排位对局质量间的平衡点。
网友评论
李白“加强”一波,没了控制加伤害,结果伤害还削弱两次,现在比正式服低一千多, 韩信也“加强”一波,没了控制加伤害,结果大招免伤没了伤害又削了。 “露娜”重做一波,控制没了伤害低了,建模“重做”紫霞从少女变成不知道哪来的一脸病态的妇女 结论:贵游无比擅长反向优化,还有人要补充的吗
诸葛亮强度和皮肤优化关注下,谢谢,顶我上去
如果仅靠段位和elo值作为排位匹配因素,那么很难解释为什么单排连胜或者渡劫局的系统制裁,这也是体验最糟糕的地方,最近连续三个赛季已经没法打排位了
Ⅳ 高分求算法:关于井字棋(三子棋)的算法!!面谈感谢!!!!
“井字棋”游戏(又叫“三子棋”),是一款十分经典的益智小游戏,想必很多玩家都有玩过。“井字棋”的棋盘很简单,是一个3×3的格子,很像中国文字中的“井”字,所以得名“井字棋”。“井字棋”游戏的规则与“五子棋”十分类似,“五子棋”的规则是一方首先五子连成一线就胜利;“井字棋”是一方首先三子连成一线就胜利。
井字棋(英文名Tic-Tac-Toe)
井字棋的出现年代估计已不可考,西方人认为这是由古罗马人发明的;但我们中国人认为,既然咱们都发明了围棋、五子棋,那发明个把井字棋自然是不在话下。这些纯粹是口舌之争了,暂且不提。
想起小时候上课喜欢玩井字棋,只要一张草稿纸、一支笔、同桌两人就可以玩了。上体育课,也可以拿着树枝在沙坑里玩。但一直感觉这游戏太简单了,后来接触了五子棋,着迷了一阵,但水平总是很差,便也不玩了。
一字棋游戏极小极大分析法
设有九个空格,由MAX,MIN二人对弈,轮到谁走棋谁就往空格上放一只自己的棋子,谁先使自己的棋子构成“三子成一线”(同一行或列或对角线全是某人的棋子),谁就取得了胜利。
用叉号表示MAX,用圆圈代表MIN。
比如右图中就是MIN取胜的棋局。
为了不致于生成太大的博弈树,假设每次仅扩展两层。估价函数定义如下:
设棋局为P,估价函数为e(P)。
(1) 若P对任何一方来说都不是获胜的位置,则e(P)=e(那些仍为MAX空着的完全的行、列或对角线的总数)-e(那些仍为MIN空着的完全的行、列或对角线的总数)
(2) 若P是MAX必胜的棋局,则e(P)=+∞。
(3) 若P是B必胜的棋局,则e(P)=-∞。
比如P如右图示,则e(P)=6-4=2
要注意利用棋盘位置的对称性,在生成后继节点的位置时,下列博弈结局
都是相同的棋局(在博弈中,一宇棋的分枝系数比较小起初是由于对称性,而后是由于棋盘上未布子的空格减少所致)。图3.15画出了经过两层搜索生成的博弈树,静态估值记在端节点下面,倒推值记在圆圈内。
由于右图所示位置具有最大的倒推值,它应当选取为MAX的第一步(正好是MAX的最好的优先走步)。
现在我们假设MAX走了这一步,而MIN的回步是直接在X上方的空格里放上一个圆圈(对MAX来说这是一步坏棋,他一定没有采用好的搜索策略)。下一步,MAX又在新的格局下搜索两层,产生如图3.16所示的搜索图。
现在图中MAX有两个可能“最好的”优先走步,假设MAX走了图上指明的那一步。而MIN为了避免立即败北被迫走了另一步,从而产生如下棋局:MAX再次搜索,产生如图3.17所示的树。
在这棵树中某些端节点(例如其中一个标记着A)代表MIN获胜,因此它们的估值为—∞。当这些估值被倒推回去时,可看到MAX的最好的也是唯一能使他避免立即失败的一个走步。现在,MIN可以看出MAX必然在他的下一走步中获胜,因此,MIN只好认输。
按极大极小算法编程下一字棋的演示(右图,可以点击操作)...
我们就利用Visual Basic编写一个“井字棋”的小游戏。
【设计思路】
首先,我们要知道,“井字棋”游戏是一款典型的棋类游戏,游戏时一方式是电脑,另一方是玩家。所以,这类游戏在开始时有两种方式:一种是玩家先走;另一种是电脑先走。这是我们要考虑的第一个问题。
其次,由于与玩家对战的是计算机,所以我们要编写一个过程(Chuqi),它可以使程序模拟人的思维与人下棋(其实就是“人工智能”的体现),这个Chuqi过程也是本游戏软件的关键。此外,我们还要编写两个过程(Lianxian和Shuying),Lianxian过程用来时刻判断棋盘中是否有三个棋子连成一线;Shuying过程用来判断如果有三个棋子连成一线,是哪一方连成一线的,即判断哪一方获胜。
以上几个问题就是该“井字棋”游戏实现的关键思路。....
QQ:744192659
邮箱:[email protected]
Ⅳ 阿法元完爆他哥阿法狗,金庸下笔如神助
文/雅木风
还记得前天,是个差不多阳光明媚的日子吧,连续的雨天阴天,让人没有一点点精神。吃过午饭,我想要在校园里溜达一下,顺便寻找一丢丢光的影子。无聊打开手机,一瞬间,朋友圈都要被《今日Nature》这篇推文刷屏了。仔细阅读完这篇文章,我的内心也是说不出来的滋味,感叹于人工智能的飞速发展,又忧心于人工智能的厉害。心心念念了好多天,总想来点碎碎念。
我们都知道去年,阿法狗勤奋刻苦,读遍了人世间的所有棋谱,用高超精进的棋艺,以4-1打败了世界冠军李世石,从此无敌天下,就差孤独求败了。就在前天DeepMind在世界顶级科学杂志《Nature》上发表文章《Mastering the game of Go without human knowledge》,引发了科研学术界的巨大轰动。这篇文章让我们知道了,阿法狗有了一个弟弟叫AlphaGo Zero阿法元,他在没有看过一个棋谱,没有一个人指点的前提下,从零开始,完全依靠自我的强化学习和参悟,棋艺增长,在短短三天内,成为顶级高手,以100-0击败哥哥阿法狗,可谓是百战百胜。
在得知这个消息后,中国棋手柯洁在微博上发文称“一个纯净、纯粹自我学习的alphago是最强的...对于alphago的自我进步来讲...人类太多余了”......这可能是一种略带调侃又无奈的情绪吧, 毕竟AI的迅速发展对于人类社会来说,是利是弊,还有待定论,关键还是看人类如何去应用AI的发展吧。
不过,就这篇文章来说,阿法元的学习不受人类知识的限制,并且足够的“低碳”。只用到了一台机器和4个TPU,极大的节省了资源。而此前版本的阿法狗在强化学习的监督学习中结合数百万人类围棋专家的棋谱,依靠的是多台机器和48个TPU。
据AlphaGo Zero团队负责人Dave Sliver介绍AlphaGo Zero使用新的强化学习方法,让自己变成老师。 系统一开始甚至不知道什么是围棋,只是从单一神经网络开始,通过神经网络强大的搜索算法,精心自我对弈。随着自我对弈的增加,神经网络逐渐调整,提升预测下一步的能力,最终赢得比赛。并且DeepMind团队发现,AlphaGo Zero独立发现了游戏规则,走出了新的策略,为围棋这项古老的游戏注入了新的见解。简直是研究中的惊喜。
不过这篇文章让大家也关注到了一个 白板理论 (Tabula rasa),而AlphaGo Zero最大的突破是实现了白板理论。 所谓的白板理论是哲学上的一个着名观点,认为婴儿生下来是白板一块,通过不断训练、成长获得知识和智力。 只不过现代科学了解到的事实并非如此,婴儿生下来就有先天的一些能力,比如偏爱高热量的食物,饿了就会哭闹以希望得到注意。这是生物体在亿万年的演化中学来的。
作为 AI 领域的先驱,图灵使用了这个想法。在提出的着名的“图灵测试”的论文中,他从婴儿是一块白板出发,认为只要能用机器制造一个类似小孩的 AI,然后加以训练,就能得到一个近似成人的智力,甚至超越人类智力的AI。
不过,在将这个理论应用于机器身上的同时,也许我们也可以关注到我们人类自身的学习,我们究竟该如何看待人类经验的作用呢?勿过分依赖于经验,还是经验至上。
也许摆脱现有经验模块是意义重大的。我们的经验是基于对世界的观察和探索,只是这观察结果的局部正确可能会导致后续研究的止步不前。同时,随着AI的快速发展,我们不得不承认机器的学习及运算速度是远远超过人类的。
碎碎念之后,不禁感叹于金庸武侠小说的思想之广博,逻辑之精深。犹记得射雕英雄传中老顽童在山洞里,左手画圆右手画方,就是这左右互博术,自己和自己打,不断参悟,不断提升自我。还有倚天屠龙记中,张三丰教张无忌太极剑,待张无忌将剑法忘得干干净净之后,让他前去应敌。 果然,人一生最大的敌人从来都只有自己,自我博弈,自我突破,自我提升。
阿法元就像一个无招胜有招的独孤大侠,完胜。
Ⅵ douzero训练和自我对弈有什么用
DouZero在不借助任何人类知识的情况下,通过自我博弈学习,在几天内战胜了所有已知的斗地主打牌机器人,并达到了人类玩家水平。
通过深度神经网络、动作编码(actionencoding)和平行角色(parallelactors)来增强蒙特卡洛方法。
快手团队开发的斗地主AI命名为DouZero,意思是像AlphaZero一样从零开始训练,不需要加入任何人类知识。
Ⅶ 求西洋跳棋的人机对弈算法或人机对战的c或c++代码,不必太复杂
你好!
西洋跳棋的没有做过,是什么规则
Ⅷ 在围棋中如何计算棋子的数目
一局棋在双方棋手下完以后,根据双方棋手所围出来的地域的交叉点叫做“目”,目的多少叫做目数,对方的死子也算入目数,一般一子算两目,交叉点的目为一目,这样计算双方的交叉点和死子就能算出双方的目数,根据比赛规则就可知输赢双方。
另一种计算方法是数子法,收完最后一枚单官后,将双方地域的交叉点上放满各自的黑白子,然后,数出黑子和白子,就可以知道双方的胜负了。
Ⅸ 国际象棋软件和象棋软件哪个的算法要复杂些
国际象棋要复杂,看规则多少
象棋:
第一章 行棋规定
第1条 棋盘和棋子
1.1象棋盘由九道直线和十道横线交叉组成。棋盘上共有九十个交叉点,象棋子就摆在和活动在这些交叉点上。
棋盘中间没有划通直线的地方,叫做“河界”;划有斜交叉线的地方,叫做“九宫”。
九道直线,红棋方面从右到左用中文数字一至九来代表;黑棋方面用阿拉伯数字1至9来代表。
1.2 棋子共有三十二个,分为红、黑两组,每组共十六个,各分七种,其名称和数目如下: 象棋的摆法
红棋子:帅一个,车、马、炮、相、士各两个,兵五个。
黑棋子:将一个,车、马、炮、象、士各两个,卒五个。
1.3 对局开始前,双方棋子在棋盘上的摆法见右图(印刷体棋图规定:红方棋子在下,用阳文;黑方棋子在上,用阴文)。
1.4 比赛用的标准棋盘,应每格都为正方形,每方格长宽均应为3.2至4.6cm。每个平面圆形棋子直径应为2.7至3.2cm,大小与棋盘合适配套。棋盘和棋子底色,均应为白色或浅色。棋盘上直线和横线应为红色或深色,四周应有适当空白面积。棋子面色分为红黑两组,字体和圆框应当醒目。
演示比赛用的大棋盘为直式,红方在下,黑方在上。棋盘和棋子大小,应配合场所相应增大。
第2条 走棋和吃子
2.1 对局时,由执红棋的一方先走,双方轮流各走一着,直至分出胜、负、和,对局即终了。
轮到走棋的一方,将某个棋子从一个交叉点走到另一个交叉点,或者吃掉对方的棋子而占领其交叉点,都算走了一着。
双方各走一着,称为一个回合。
2.2 各种棋子的走法如下:
帅(将)每一着只许走一步,前进、后退、横走都可以,但不能走出“九宫”。将和帅不准在同一直线上直接对面,如一方已先占据,另一方必须回避。
士每一着只许沿“九宫”斜线走一步,可进可退。
相(象)不能越过“河界”,每一着斜走两步,可进可退,即俗称“相(象)走田字”。当田字中心有别的棋子时,俗称“塞(相)象眼”,则不许走过去。
马每着走一直(或一横)一斜,可进可退,即俗称“马走日字”。如果在要去的方向有别的棋子挡住。俗称“蹩马腿”,则不许走过去。
车每一着可以直进、直退、横走,不限步数。
炮在不吃子的时候,走法同车一样。
兵(卒)在没有过“河界”前,每着只许向前直走一步;过“河界”后,每着可向前直走或横走一步,但不能后退。
2.3 走一着棋时,如果己方棋子能够走到的位置有对方棋子存在,就可以把对方棋子吃掉而占领那个位置。只有炮吃子时必须隔一个棋子(无论是哪一方的)跳吃,即俗称“炮打隔子”。
除帅(将)外其他棋子都可以听任对方吃,或主动送吃。吃子的一方,必须立即把被吃掉的棋子从棋盘上拿走。
第3条 将死和困毙
3.1 一方的棋子攻击对方的帅(将),并在下一着要把它吃掉,称为“照将”,或简称“将”。“照将”不必声明。
被“照将”的一方必须立即“应将”,即用自己的着法去化解被“将”的状态。
如果被“照将”而无法“应将”,就算被“将死”。
3.2 轮到走棋的一方,无子可走,就算被“困毙”。
第4条 胜、负、和
4.1 对局时一方出现下列情况之一,为输棋(负),对方取胜;
4.1.1 帅(将)被对方“将死”。
4.1.2 走棋后形成帅(将)直接对面。
4.1.3 被“困毙”。
4.1.4 在规定的时限内未走满规定的着数。
4. 1.5 超过了比赛规定的迟到判负时限。
4. 1.6 走棋违反行棋规定。
4.1.7 走棋违反禁例,应变着而不变。
4.1.8 在同一棋局中,三次“犯规”。
4.1.9 自己宣布认输。
4.1.10 在对局中拒绝遵守本规则或严重违反纪律。
4.2 出现下列情况之一,为和棋:
4.2.1 双方均无可能取胜的简单局势。
4.2.2 一方提议作和,另一方表示同意。
4.2.3 双方走棋出现循环反复三次,符合“棋例”中“不变作和”的有关规定。
4.2.4 符合自然限着的回合规定,即在连续60个回合中(也可根据比赛等级酌减),双方都没有吃过一个棋子。
国际象棋:
国际象棋由黑白两棋组成,执白先行,国际象棋的对局目的是把对方的王将死。
比赛规定:
一方的王受到对方棋子攻击时,成为王被照将,攻击方称为"将军",此时被攻击方必须立即"应将",如果无法避开将军,王即被将死。除"将死"外,还有"超时判负"与"和局"。出现以下情况,算和局:
一方轮走时,提议作和,对方同意;
双方都无法将死对方王时,判和;
一方连续不断将军,对方王却无法避开将军时,成为"长将和";
轮到一方走棋,王没有被将军,但却没有任何棋子可以移动,成为"逼和";
对局中同一局面出现三次,而且每次都是同一方走的,判为和局。
棋盘和棋子
国际象棋棋盘是个正方形,由横纵各8格、颜色一深一浅交错排列的64个小方格组成。深色格称黑格,浅色格称白格,棋子就放在这些格子中移动。棋子共三十二个,分为黑白两组,各十六个,由对弈双方各执一组,兵种是一样的,分为六种: 王(1)、后(1)、车(2)、象(2)、马(2)、兵(8)。
中文全称 国王 皇后 城堡 主教 骑士 兵卒
英文全称 King Queen Rook Bishop Knight Pawn
中文简称 王 后 车 象 马 兵
英文简称 K Q R B N P
在正式比赛中,国际象棋棋子采用立体棋子,非正式比赛中可以采用平面图案的棋子。
布子规则:
对于初学者,摆棋时记住:王对王,后对后;白后站白格,黑后站黑格。黑王站白格,白王站黑格。
注意:比赛时为了便于记忆和记录,布置棋盘时总是让自己的右下角是白色格。
走子规则:
· 王:横、直、斜都可以走,但每次限走一步。
(1)除易位时外,王可走到未被对方棋子攻击的任何相邻格子.
(2)易位是由王已方任何一个车一起进行仍被视作王的一着的走法,其进行方式如下:王从原始位置向任何一位的方向横移两格,然后那人横越过王而置于王刚经过的格子.
(3)如果一方先触摸车一起然后再触摸王,那么他不能用那个车进行易位,这种情况须按以下A和B条处理
A:除上述上,如果行棋方有意识地触摸了同一方的一个或更多的棋子,他触动或吃掉所触措的第一个可以走动或可以被吃的棋子;或者一个已方的棋子和 个对方的棋子,他用前者吃掉后者;如果这种吃法不合规则,如果无法确定先触摸哪一个棋子,则以已方棋子作为已被触摸的棋子.
B:如果所触摸的已方棋子均没有合乎规则的着法(或者对所触摸的对方棋子均没有合乎规则的吃法),行棋方有权走任何合乎规则的着法.
(4)如果一方在准备易位时触摸了王,或者同时触摸了王和车,然后发现易位不合规则,他可以选择走王或者向另一翼易位,前提是向那一翼易位是合乎规则的,如果王没有合乎规则的走法,该方有权造反走任何规则的着法.
(5)不符合规则的易位: 王已经移动过,或者 用来易位的车已经移动过.
(6)下列情况暂不能易位: 王的原始格子或者将要越过的格子或者将要占据的格子正受到对方棋子的攻击,或者王和用来易位的车之间尚有别的棋子
· 后:横、直、斜都可以走,步数不受限制,但不能越子。它是国际象棋中威力最大的子。
· 车:横、竖均可以走,步数不受限制,不能斜走。一般情况下不能越子。
· 象:只能斜走。格数不限,不能越子。每方有两象,一个占白格,一个占黑格。
· 马:每步棋先横走或直走一格,然后再斜走一格(每次斜走六个正方格子),可以越子,没有"中国象棋"中"蹩马腿"的限制。
· 兵:只能向前直走,每着只能走一格。但走第一步时,可以最多直进两格。兵的吃子方法与行棋方向不一样,它是直进斜吃,即如果兵的斜进一格内有对方棋子,就可以吃掉它而占据该格。
特殊着法:
除了上面所有棋子的一般着法外,国际象棋中存在下面三种特殊着法:
· 吃过路兵:如果对方的兵第一次行棋且直进两格,刚好形成本方有兵与其横向紧贴并列,则本方的兵可以立即斜进,把对方的兵吃掉。这个动作必须立刻进行,缓着后无效。 记录时记为 “en passant” 或 “en pt”, 法语中表示 “路过”。
·兵的升变:任何一个兵直进达到对方底线时,即可升变为除"王"和"兵"以外的任何一种棋子,不能不升变。一般情况下升变成为“后”因为“后”威力最大;在特殊情况下也可升变为“车”、“马”、“象” 。
·王车易位:每局棋中,双方各有一次机会,让王朝车的方向移动两格,然后车越过王,放在与王紧邻的一格上。王车易位根据左右分为"长易位"和"短易位"。
在下面四种情况下,王车易位不允许:
王或车已经移动过;
王和车之间有其他棋子阻隔;
王正被对方"将军";
王经过或达到的位置受对方棋子的攻击。
胜、负、和:
· 国际象棋的对局目的是把对方的王将死。比赛规定:一方的王受到对方棋子攻击时,成为王被照将,攻击方称为“将军”,此时被攻击方必须立即“应将”,如果无法避开将军,王即被将死。除“将死”外,还有“超时判负”与“和局”。出现以下情况,算和局:
·一方轮走时,提议作和,对方同意;
·双方都无法将死对方王时,判和;
· 一方连续不断将军,对方王却无法避开将军时,成为“长将和”;
·轮到一方走棋,王没有被将军,但却无路可走,成为“逼和”;
· 对局中同一局面出现三次,而且每次都是同一方走的,并且没有任何可走棋步的差别,判为和局。
·双方在连续50回合内都没有吃掉对方任何一子的,判为和局。
(说明:“没有任何可走棋步的差别”主要指过路兵和易位,我记得见过一个NB的排局有一方就是在3次重复但对方车、王有移动后赢的~~~)
Ⅹ 四子棋的AI算法求助,悬赏500一分不少
我写过五子棋程序,也思考过棋类程序的算法,希望能给楼主参考
双方对弈棋类算法,其基本思想就是人工智能中关于 最小-最大问题 的 alpha-beta 剪枝,楼主可搜索一下,这个随便一本人工智能书里都有讲。
下面就是具体程序中该如何实现其思想
一般都要先有一个招法生成器,用于给出当前局面下所有可走的行棋可能。对四子棋来说就相当简单了,只要看一下每一列,只要未满即可。
然后要有一个局面评估函数,大体评价下双方局势的分数。此函数尽量简单能反映优劣即可,因为后面的 alpha-beta 算法要大量调用此函数
最后实现 alpha-beta 的算法,采用迭代加深的广度优先搜索能有效剪枝。(剪枝效率取决于前面的局面评估函数,如果评估函数能非常准确的估值,那么将会大大减小搜索范围,但复杂的评估函数又会增加开销,这是一个两难的抉择)
不过对于四子棋由于非常简单,楼主也可以尝试仅用简单的广度优先搜索。按每个局面 7 列只有 7 种走法来算,5步深的全搜索也只有 1 万多种情况。对一般人来说5步深也足够强了。不满意的话再考虑上面的正统算法。
然后是一点小技巧,关于棋盘的存储和运算,尽量采用位棋盘和位运算来完成,多利用位运算的并行性来提高效率
这里毕竟字数有限,如果还想更深入了解的话推荐来这里看看:http://www.elephantbase.net/computer.htm
一个相当好的棋类算法网站
虽然是讲象棋的,但基本思路都一样,绝对能学到很多东西。