黑白棋(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/reversi-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 6 分钟阅读 - 2984 个词 阅读量 0黑白棋(译文)
原文地址:https://www.codeproject.com/Articles/24461/Reversi
原文作者:Zdravko Krustev
译文由本站 robot-v1.0 翻译
前言
An implementation of the popular game Reversi, written as a project for an AI course.
流行游戏Reversi的实现,被编写为AI课程的项目.
介绍(Introduction)
该项目是具有简单人工智能的Reversi游戏的实现.(This project is an implementation of the game Reversi with a simple artificial intelligence.)
背景(Background)
我的任务是为游戏编写人工智能(I had an assignment to write an artificial intelligence for the game) 黑白棋(Reversi) , 使用(, using the) alpha-beta修剪算法(alpha-beta pruning algorithm) .作业是我在大学学习的AI课程的一部分(. The assignment was a part of the AI course that I studied at the) 索非亚大学数学与信息学系(Sofia University, Faculty of Mathematics and Informatics) .这就是结果.(. And here is the result.)
使用代码(Using the code)
该项目包括几个实现游戏内部结构的类,以及用户界面的几个控件和形式.(The project consists of several classes implementing the inner structure of the game, and several controls and forms for the user interface.) 根据其功能,这些类是:(The classes, according to their functionality, are:)
-
DiscColor
-代表板上光盘的可能颜色:黑色,白色和无-板上的字段为空.(- represents the possible colors of discs on the board: Black, White, and None – the field of the board is empty.) -
Board
-实现一个二维数组,每个元素代表游戏板的一个区域(带有一个(- implements a two-dimensional array, with each element representing a field of the game board (with a)DiscColor
).该类提供了一些方法来确定玩家是否可以在指定位置进行移动,进行移动以及转换对手盘等.(). The class provides some methods for determining whether a player can make a move at a specified position, for making the move, and for converting the opponent disks, etc.) -
Game
-提供整个游戏过程:设置玩家的属性,开始新游戏,在玩家之间切换以及完成游戏.的实例(- provides the whole process of playing: setting the properties of the players, starting a new game, switching between players, and completion of the game. An instance of the)Game
类是使用的实例创建的(class is created with an instance of the)Board
类(就像在现实世界中一样-要玩游戏,您必须首先拥有一个棋盘).(class (like in the real world – to play a game, you must have a board first).) -
PlayerProperties
–您可以猜测,该类描述了游戏中每个玩家的属性.特定游戏的玩家是由(– as you can guess, this class describes the properties of each player in the game. Players for a specific game are created by the)CreatePlayer1(PlayerProperties properties)
和(and)CreatePlayer2(PlayerProperties properties)
的方法(methods of the)Game
类.的(class. The)PlayerProperties
类支持序列化,并且两个播放器的属性存储在配置文件中,如下所述.这允许在具有相同玩家属性的情况下玩下一个游戏.(class supports serialization, and properties for the two players are stored in a configuration file as described below. This allows the next game to be played with the same players' properties.) -
Player
–提供游戏中玩家基本功能的抽象类.的(– abstract class that provides the basic functionality of a player in the game. The)Type
该类的属性指示玩家类型,并且(property of the class indicates the player type, and the)StartMove()
方法允许在派生类中添加一些功能,当玩家开始新的移动时执行该功能.(method allows to add some functionality in the derived class that is executed when the player starts a new move.) -
HumanPlayer
,(,)ComputerPlayer
–当前游戏中可用的玩家类型的类.继承(– classes for the types of players available in the game for now. Inherit the)Player
类.(class.) -
MoveSolver
–为计算机播放器提供AI.(– provides the AI for a computer player.) 形式和控件如下:(The forms and controls are the following:) -
BoardFieldControl
–代表游戏板的一个区域.当玩家可以在指定字段上移动时,它会突出显示.(– represents a field of the game board. When a player can make a move on the specified field, it’s shown highlighted.) -
PlayerInfoControl
–显示有关指定播放器的信息–名称,类型,颜色,板上光盘.(– displays information about a specified player – name, type, color, disc on board.) -
BoardControl
–此控件提供游戏的整体外观–棋盘,以及有关玩家和结果的信息窗格.(– this control provides the whole look of the game – a board, and information panes about the players and the result.) -
PlayerPropertiesControl
–允许用户在新游戏开始时选择玩家的属性.(– allows a user to choose the properties of a player at the beginning of a new game.) -
StartNewGameForm
–很明显,在此表单中,您输入了开始新游戏所需的信息.这两个播放器的属性存储在名为"(– as it is obvious, in this form, you enter the information needed to start a new game. The properties of the two players are stored in a configuration file named “)玩家信息(PlayersInfo)",以及(”, and the)StartNewGameForm
加载时从此文件初始化其字段.单击"确定"按钮后,它将分别存储在此处.(initializes its fields from this file on load. Respectively, it stores them back there when the “OK” button is clicked.) -
MainForm
–包含一个(– contains one)BoardControl
,并称为(, and calls a)StartNewGameForm
加载时.(when loaded.)
玩游戏的过程(Process of playing the game)
- 的新实例(A new instance of the)
Game
使用的实例创建类(class is created, using an instance of the)Board
类;(class;) - 这两个玩家是使用(The two players are created using the)
CreatePlayer1()
和(and)CreatePlayer2()
的方法(methods of the)Game
实例(instance;) - 新游戏由(The new game is started by the)
Start()
的方法(method of the)Game
实例.(instance.) Player1
轮到.(takes turn.)- 的(The)
StartMove()
的方法(method of)Player1
叫做.当元素的(is called. The move ends when an element of the)Board
游戏的属性是使用(property of the game is set using the)SetFieldColor()
方法.(method.) - 如果(If)
Player2
可以移动(can move,)Player2
轮到.相同的动作(takes turn. The same actions for)Player2
被制造(are made, as for)Player1
在上一步.(at the previous step.) - 如果(If)
Player1
可以移动(can move,)Player1
轮到.(takes turn.) 重复步骤5-7,直到没有一个玩家可以采取行动为止.比赛结束了,(Steps 5-7 are repeated until none of the players could make his move. The game is over then, and the)Finished
的事件(event of the)Game
被提出.(is raised.) 创建新游戏的过程可以在(The process of creating a new game could be seen in the)StartNewGame()
的方法(method of the)MainForm
类:(class:)
Game game = new Game(new Board());
game.CreatePlayer1(frmStartNewGame.Player1Properties);
game.CreatePlayer2(frmStartNewGame.Player2Properties);
this.ctrlBoard.SetGame(game);
game.Start();
人工智能(The AI)
由于这是AI课程的项目,因此AI应该是其中最重要的部分.如上所述,该程序使用alpha-beta修剪算法来取得胜利.如您所知,整个搜索树的创建(包含从游戏开始到结束的所有可能动作)需要大量内存.因此,当到达搜索树中的指定深度时,正在使用启发式函数来评估当前节点.这发生在以下方法中(Since it is a project for an AI course, the AI should be the most important part of it. As mentioned above, the program uses the alpha-beta pruning algorithm to achieve victory. As you know, the creation of the whole search tree (containing all possible moves from the beginning till the end of the game) needs a lot of memory. That’s why, when reaching at a specified depth in the search tree, the current node is being evaluated using a heuristic function. This happens in the following method of the) MoveSolver
类:(class:)
private int EvaluateBoard(Board board)
{
DiscColor color = this.Player.Color;
DiscColor oppositeColor = DiscColor.GetOpposite(this.Player.Color);
List<int[]> oppositePlayerPossibleMoves = this.GetPossibleMoves(board, oppositeColor);
List<int[]> possibleMoves = this.GetPossibleMoves(board, color);
if ((possibleMoves.Count == 0) && (oppositePlayerPossibleMoves.Count == 0))
{
int result = board.GetDiscsCount(color) - board.GetDiscsCount(oppositeColor);
int addend = (int)Math.Pow(board.Size, 4) + (int)Math.Pow(board.Size, 3);
// because it is a terminal state, its weight must be bigger than the heuristic ones
if (result < 0)
{
addend = -addend;
}
return result + addend;
}
else
{
int mobility = this.GetPossibleConvertions(board, color, possibleMoves)
- this.GetPossibleConvertions(board, oppositeColor, oppositePlayerPossibleMoves);
int stability = (this.GetStableDiscsCount(board, color)
- this.GetStableDiscsCount(board, oppositeColor)) * board.Size * 2 / 3;
return mobility + stability;
}
}
如您所见(如果您试图弄清楚这段代码的实际作用),则为指定节点((As you can see (if you tried to figure out what this code really does), the heuristic value for the specified node (the) board
参数代表游戏当前状态下的整个棋盘)是使用两个标准形成的-稳定性(玩家棋盘上稳定盘的数量)和移动性(可以转换的对手盘的数量).使用一些"幻数"作为系数来评估最终值.这些系数是由我进行的一些测试所启发而来的,没有任何"合理"的解释.(parameter represents the whole board at the current state of the game) is formed using two criterions – stability (the number of stable discs on the player’s board) and mobility (number of opponent disks that could be converted). The final value is evaluated using some “magical numbers” as coefficients. These coefficients are inspired by some tests I have made, and do not have any “reasonable” explanation.)
如果当前节点是叶子,则意味着我们已经结束了,可以轻松查看该状态是否获胜.只需从玩家的光碟数量中减去对手光碟的数量,然后添加一个相当大的数字(正数或负数),这样结果将比在搜索树中相同深度进行的任何启发式评估都更好.这是因为游戏结束时的估值肯定是正确的,并且比我们进行的任何启发式估值都重要.(If the current node is a leaf, this means that we are at the end of the game and could easily see if the state is winning or not. Just subtract the number of opponent discs from the number of the player’s discs, and add a quite big number (positive or negative) so the result will be grater than any heuristic valuation made at the same depth in the search tree. That is because the valuation at the end of the game is surely correct and is more important than any heuristic valuation we have made.)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# C#2.0 .NET .NET2.0 Visual-Studio VS2005 Design Dev AI 新闻 翻译