编写国际象棋引擎的最佳方法?[关闭]


15

我是国际象棋爱好者和程序员。我最近决定开始使用我的国际象棋和编程知识来制作国际象棋引擎。所以这是我的问题:

编写国际象棋引擎时应采用哪种语言(我熟悉Java,C ++和Python)和方法?

一点指导将不胜感激。

编辑:

所以我决定用JavaScript制作它。我从github 下载 Chess UI,现在一切就绪!我的第一步是为此写法律动议。那么有人能指出我正确的方向吗?(我是jQuery的新手,但是有很多编程经验)。

PS:我并不是想制造一个非常高效的引擎(我知道它的方法太难了),我只是想熟悉该过程并在此过程中学习一些新技术。


5
任何主流语言和方法都可以,对于象棋引擎(在这方面)没有什么特别的。
扬尼斯

3
我会更具体地说明目标。如果您只是想将其简化为一系列死记硬背的规则,这是一项艰巨的任务,但是任何程序员都可以通过这种蛮力方式进行分类。如果您想涉足模式识别或权衡风险与回报之类的问题,那么答案可能会很麻烦。
埃里克·雷彭

您是否已检查了Chess Engine Wiki下的“教学法”部分。这些似乎专门用于教授国际象棋编程,并且都是开源的。即使您不使用实际的源代码,该文档也通常会解释开发背后的原因:en.wikipedia.org/wiki/Chess_engine#Categorizations
user60812

1
真正困难的部分是如何评估给定位置,因为您需要查看位置A是否优于位置B才能进行选择。

1
尚不清楚您想知道什么。您决定要代表职位吗?如果是这样,下一步就是编写并测试移动生成器。不知道您认为jQuery与之相关。
凯文·克莱恩

Answers:


19

这里有2072级棋手。我用一个周末用纯JavaScript 制作了这个网站。它不是国际象棋引擎(我将其设计为创建娱乐性的开场位置,就像不正常的Chess960引擎一样),但这是一个起点。源代码在这里

制作功能板涉及许多复杂问题。这些包括:

  • 首先,弄清楚如何代表基本的法律动作。您必须使用开始和结束坐标进行数学运算。例如,对于车子移动,坐标之一必须在前后相同。对于骑士移动,坐标更改的绝对值之和必须为3,并且两个坐标都必须更改。使用主教移动时,或者坐标的总和保持不变,或者它们都增加相同的量。兵是最棘手的,因为您不仅必须弄清楚它们是否可以移动两个或一个正方形(检查行和颜色,而不是存储它们已经进行了多少移动),而且还必须对角地处理整个捕获, -转发的东西。
  • 由于典当和检查,捕获是一个挑战。您不能只说如果一块移动到另一块的正方形,那就是捕获。毕竟,典当无法移动到另一块棋子的正方形进行捕捉-它们具有自己的特殊捕捉方法。
  • 您必须找出一种有效的方法来查看敌人的棋子是否妨碍棋子的移动,以便确定棋子是否合法。
  • 支票具有挑战性。每一步之后,您必须检查敌人的碎片可以进入的所有方格,并查看其中是否有一个涉及您的国王,如果是,这是非法的。
  • 卡斯丁,被动,晋升,僵局,强逼,重复-考虑到问题的严重性,这些都不是微不足道的。

所有国际象棋引擎的工作方式都是查看某个头寸中所有合法移动(可能是由启发式确定的子集),并通过进行这些移动并递归地对所得头寸进行相同的操作来评估数字以表示其相对价值。您的双胞胎问题是

  • 如何有效地存储这些数据
  • 如何进行这种递归搜索-毕竟,您不能让它永远持续下去,因此您必须设置一个限制,然后找出如何设计算法以在该限制内进行最佳和彻底的搜索。例如,您想确保它至少对每个可能的开始动作都进行了一些评估,但是您可能还希望它花费更多的时间来评估更有希望的动作,而不是给每个动作都等量的时间。

首先,这是在设计算法的基础上提供的大量信息。

至于使用哪种语言(尽管我猜您已经决定使用JavaScript),但我认为这取决于您的目标。我想让我的在线(并在JavaScript上变得更好),所以JavaScript是我的选择。但是任何面向对象的编程语言都可以。

一旦您对自己的工作感到满意,以下资源可能会证明确实有帮助:

祝好运!


非常感谢,它无疑帮助了我很多入门。尽管仍然有很多要学习和实现的东西,但象棋引擎从来都不容易编写。但是我认为与您喜欢的东西一起工作是件好事!
Adnan Zahid 2012年

我同意。我想拥有一份非常多样化的项目履历表,但老实说,我只是喜欢更多地开发象棋。
安德鲁·拉瑟姆

域名lathamcity.com当前正在出售。该代码现在可以在其他网站上使用吗?
IkWeetHetOokNiet

14

“象棋程序”作为一个概念存在的问题是,有很多棋子会占用很多时间,而目前并不一定会使您感兴趣。您可能需要花费数年的时间来从事图形,alpha-beta搜索或可视化的工作,以帮助开发搜索引擎,或者...嗯,有很多东西。

我建议找到一个开源国际象棋程序(必须有很多),并着手改进最感兴趣的部分。您最终可能会一次替换整个程序,或者一次替换一个功能,或者您可能学到了足够的知识并有动力将其丢弃,并从头开始设计自己的程序。无论如何,关键是要在尝试构建整个程序之前先“轻轻松松”并学习绳索。


通过遵循已建立的接口协议之一,您可以将任何现有的前端与引擎一起使用。

我希望Alpha Beta不需要花几年的时间写
凯文(Kevin)

1
不是要写很多年,而是要写很多年:)
ddyer 2012年


3

如前所述,构建国际象棋引擎并不困难。也许,您应该专注于如何使用和(潜在地)部署此应用程序,因为这可能会决定您选择的语言。

如果这只是一个有趣的练习,则可能需要用Javascript编写代码并将其部署为网页。如果您永远不想使其成为专业的国际象棋游戏,那么至少其他人将可以使用它及其源代码。

如果您想同时学习某种特定技术,例如WPF,那么这可能是用一块石头杀死两只鸟的好方法。MVVM对于此应用程序可能有些过分,但至少您会学到它。

如果您希望定位Android设备,那么Java将是一个不错的选择。同样,适用于iOS设备的Objective-C。

总而言之,语言的选择并非凭空存在的。


3

我假设您已经了解Min-Max,树木和修剪,启发式和其他基础知识的概念,而我在这里写的只是一些可能被低估的细节。

我有时和一个朋友一起写我们自己的象棋引擎。我分享一些我们遇到的问题和想法,希望您发现它们有用。

由于我们都是Java程序员,因此我们的语言将我们变成了Java,因此我们从面向对象的方法开始。棋子是物体,棋盘是物体,文件和等级(象棋文献中的行和列)是物体。这是错误的。开销很大,程序无法在搜索树中进行超过2步(4层)的移动。

因此,通过一些搜索,我们得出了一个绝妙的主意(虽然不是我们的主意):将棋子和棋盘表示为长整数(64位)。这是有道理的,因为棋盘有64个正方形。其余的都是按位操作(非常接近cpu =极快地运行)。例如,考虑一个二进制的64位整数,其中的一个表示您的棋子可以攻击的棋盘上的方块。现在,如果您像这样在两个数字之间执行逻辑“与”运算,则非零结果表示您与攻击者之间存在平方。有几种显示棋盘和棋子的方法,因此:

1-确定董事会的陈述

然后,您需要打开数据库。国际象棋的打开是解决蚂蚁的一种方式,强烈建议您打开它。在这种情况下,您在闪电战游戏中会有很多额外的时间。

2-为自己找到一本开始的书。

我们做了这些,但是我们仍然远远不够:

3-一个好的国际象棋引擎应该能够看到6个动作(12层)。

所以我们要做的是利用停滞时间(如果这是人机与计算机引擎)。

4-在对手考虑创建树的某些级别时使用时间。

而且我们离十二层还很远。通过更多的研究,我们发现了一些技巧!例如,建议跳过树的一层,然后从下一层开始(就像没有对手一样)。这个想法是,如果一个举动极其愚蠢,那么为什么要浪费时间,看看对手对该举动有何反应。但是,一个好的引擎应该能够区分愚蠢的举动和天才女王的牺牲。

5- 学习针对此特定问题(象棋)的编程技巧

在这种状态下,我和我的朋友仍然很糟糕://我们可以做的(并且部分完成了)是保存所计算的职位。如果您计算仓位,请保存以备将来使用!搜索树中的循环也是如此。关键是要有效地保存/检索:

6-有效地保存生成的数据...

最后:

7-具有最大优化的代码。

这个问题在CPU时间和内存上都是非常昂贵的。非常有效地编写代码非常重要。请记住,我们谈论的是35的分支因数。这意味着您的启发式方法中某处没有用的“如果”,可以变成3.3792205e+18搜索树深处某处的无用的“如果”。

国际象棋编程是一个非常非常有趣的挑战,现在是时候可以对编程功能进行严格的测试了。我可以提出几点建议,但是我敢肯定,您会自己发现它们的。还有很多我不知道的要点,但是您可以在Internet上找到它们!

祝好运并玩得开心点!

ps我不太了解javascript,但是基于问题的难度,有些事情告诉我,也许,考虑到C ++可以提供的所有功能,最好放下javascript并用C ++来做。


2

根据您的编辑,您已经到了定义“合法”动作的阶段。

有两种描述国际象棋动作的方法。 描述性符号和代数符号。您可能想要的功能是将样片,开始位置和结束位置作为参数。例如。从QN1到QB2的Knight无效,但从QN1到Q2的Knight有效。考虑到这一点,由于能够轻松计算“相对”位置,代数符号可能更简单。

为了确保你正在编写需要的代码的最低金额,我会与编写测试该功能启动第一。如果您使用的是代数表示法,则可能不需要对每个片段/开始/结尾进行测试。使每个测试正常工作,并在进行下一个“移动”之前重构重复项。您的代码将最终变得更干净。

一旦您充分了解了每个棋子的合法和非法移动,我便开始添加其他变量的检查(例如将King置于“ check”和“ mate”状态)。

我建议qunit单元测试和茉莉在JavaScript的行为测试。


1

我实际上已经写了一个象棋引擎。准备好自己的点心和噩梦。当我和我的朋友做到这一点时,它是在一个定时的编程竞赛中,我们决定使用的语言是Java。我认为Java或C是您的最佳选择,但我发现您已决定使用Javascript。我真的无法敲门,因为我不熟悉它。

这里的主要问题是您需要考虑的每一件都有很多移动/获胜方案,因此我建议您在实际开始编码之前为每一件写下所有可能的情况。只是不加计划地跳进去,就会把这个有趣的项目变成重复的琐事。但这确实是最主要的。只需先在代码外计划,并确保一次获得每种方案。

祝好运


1

对于游戏的计算机玩家决策部分,我不能推荐足够多的书“人工智能:一种现代方法”(本书网站http://aima.cs.berkeley.edu/)。根据您的数学背景(图论是有帮助的),它可能会有点高水平,但是它的编写方法很简单,因为它可能包含学术知识,并且包含了最新的技术概述(以及某些深度),使程序决定事情。

它将指出一些事情,例如陈述一个目标(即将死或无效),评估某个特定状态(板布局)与该目标的接近程度,如何从当前状态开始生成不同的可能后续状态,以及如何遍历什么是巨大的问题空间。

可能有助于设计AI算法的一件事是,从非常接近获胜游戏的情况出发,弄清楚如何决定接下来要玩的那一步,就好像您一直在世界上一样。您对其进行优化,以便它在合理的时间(小时)内找到解决方案,然后即使您尚未探索所有成果,也找到了选择获胜道路的方法,以便您实际上可以打断“思考”转弯值得的时间。

只有到那时,我才会着眼于优化的表示形式以加快单个计算的速度,例如建议使用长整数。不管有多快,您都可以进行单个比较,如果遍历问题空间的方式没有很好的启发法,那么这样做将需要很长时间。


0

您可以按照自己的意愿去做,但是这是我对这个问题的看法:

我会使用Java,因为它可以使您具有很高的水平,并可以直接使用用户界面库(AWT,Swing)。您可以使用面向对象的方法对国际象棋棋盘和棋子进行建模。其他对象可以代表移动历史和得分。即使是玩家也可能是对象,然后您将来可能会扩展Player课程,以提供一个人工智能计算机播放器。

您可能需要看一下model-view-controller(MVC),因为在这种情况下,这是将模型对象(域模型)绑定到用户界面(视图)并允许用户操纵模型对象的一种很好的方法。模型(通过控制器)。

您可能还希望应用测试驱动的开发,这不仅可以确保所有方法都按您期望的方式运行,还可以迫使您编写可测试的模块化代码。


4
国际象棋引擎与UI无关,仅与计算最佳移动的“头脑”无关。
CSE 2012年

@CSE-这取决于您对引擎的定义。
Daniel AA Pelsmaeker 2012年

@CSE -作为阿德南的编辑节目,他居然还找了UI。所以我的回答很重要。
Daniel AA Pelsmaeker 2012年

-8

国际象棋本身的规则很简单。您只需要能够为电路板创建一个矩阵(二维数组),并找到一种方式来编码样片的概念,每个样片的移动规则,验证移动是否合法以及发出信号的条件游戏结束。没什么特别困难的。您应该使用最熟悉的语言。

现在,如果您要制作象棋一样的AI来扮演其中一名玩家的角色,那就很麻烦了。但同样,语言选择不是这里最大的问题。了解所涉及的AI原理是。这将是一个更为重要的因素。

(话虽如此,这种决策可能需要大量的计算,并且您可能希望使用可编译为本机代码而不是脚本语言的东西。C++是一个非常糟糕的选择,不是因为它不是很好-适用于此问题,但仅因为它是一种非常糟糕的语言,而尝试在其中实现复杂的内容是为自己编写各种麻烦代码的好方法。)


15
我认为您必须更加详细地说明为什么C ++不适合该特定任务,以避免圣战。
埃里克·雷彭

9
-1为尝试进行一场圣战。
布朗

1
为什么您认为C ++通常是一种非常糟糕的语言?
安东尼

我想你当然误会他了。我同意他的观点,C ++是一门很好的语言,但是当您处理复杂的东西时,它变得很痛苦!
Adnan Zahid 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.