C++抽象编程——回溯算法(6)——设计一般的双人游戏

一般的双人游戏程序

上一篇博客的中的代码对Nim的解释非常具体。例如,play方法直接负责设置nCoins变量,并在每个play移动后对硬币数量进行更新。然而,双人游戏的总体结构应用的更为普遍。即使不同的游戏需要不同的实现细节,但是使用相同的整体策略可以解决许多游戏。
抽象编程中的一个关键概念是抽象概念(notion of abstraction),它是将问题的一般方面分离出来的过程,使其不再被特定领域的细节遮蔽。你可能不会Nim程序感兴趣; 毕竟,一旦你弄清楚,Nim看起来就是是无聊的。你可能会喜欢更多的是一个普遍的程序,适合玩Nim,tic-tac-toe或任何其他双人策略游戏。
创造这种一般性的可能性源自大多数游戏共享几个基本概念的。
- 第一个这样的概念是事件的概念。 对于任何游戏,都有数据值准确地定义了在任何时间点发生了什么。例如,在Nim游戏中,状态由其两个实例变量nCoins和whichTurn的值组成。对于像国际象棋这样的游戏,事件将需要包括当前放置在哪个方块上的棋子,尽管它可能会继续包含whoTurn变量,或者是满足相同功能的东西。然而,对于任何游戏,应该可以将相关数据存储在实现游戏的类的实例变量中。
- 第二个重要的概念就是移动。 在Nim中,一个移动包含一个代表被丢弃的硬币数量的整数。在国际象棋中,举动可能包含一对指示正在移动的棋子的开始和结束坐标,尽管这种方法实际上由于需要代表诸如城堡或销毁棋子这样的深奥动作而变得复杂化。然而,对于任何游戏,可以定义一个Move类,它封装了代表该游戏中的移动所需的任何信息。

然而,当我们实现Nim游戏时,以最简单的方式(下面的代码)定义Move类并不十分有效

class Move {
    int nTaken;
}

这里的问题是类中条目的默认可见性是私有的(private),这意味着实现游戏的类将无法访问实例变量nTaken。
但是我们同样可以采取几种策略来解决这个问题。
1. 一个策略是将nTaken变量公开(即设置为public),或者等效地通过传统的C风格的struct来替换类定义。(因为结构体的访问权限默认为public) 然而,这样做显然将Move类的详细信息提供给整个程序,该策略违反了基本的封装原则
2. 第二种方法是在类中介绍定义的getter和setter方法。该方法遵循现代面向对象编程的风格,范式这样以使Move类更难使用(每使用一次都要调用一次方法)。这个额外的复杂性似乎是一个没有必要的,唯一的客户可能是实现游戏的类。
3. 第三个策略就是我们之前提到过的将Move类声明为游戏类的朋友(friend)

一旦你有一个Move类,就可以定义一些额外的帮助方法,让你重写这样的play方法:

void play() {
    initGame();
    while (!gameIsOver()) {
        displayGame();
        if (getCurrentPlayerType() == HUMAN) {
            makeMove(getUserMove());
        } else {
            Move move = getComputerMove();
            displayMove(move);
            makeMove(move);
        }
    }
announceResult();
}

注意到play方法的实现最重要的是,该代码没有指示正在运行的游戏。 这可能是Nim也可能是其他的双人游戏,但是它也可以很容易地变得简单或其他策略游戏。每个游戏都需要自己定义的Move类,以及各种游戏特定的方法,如initGame和makeMove。 即使如此,play方法的结构也足以适用于许多不同的双人游戏。
如果你将play的一般化实现与Nim中的play代码进行比较,还将注意到,在此级别的实现中不再包含切换转换的代码。在程序的一般版本中,将游戏的这个方面嵌入到initGame,makeMove和getCurrentPlayerType的方法中。进行此更改意味着play方法不再直接引用到实例变量,而是调用方法来完成此工作。该策略允许在底层实现中有更多的灵活性。
这个play方法和轮流机制,却不是游戏的最令人兴奋的方面。**算法有趣的部分嵌入到方
法getComputerMove中,该方法负责为计算机选择最佳方式。**我们所写的Nim版本使用相互递归的方法findGoodMove和isBadPosition来实现这个策略,它搜索所有可能的选择,让每个玩家在当前位置找到一个获胜的动作。作为策略,该想法也独立于任何特定游戏的细节,因此应该以更一般的方式编写这些方法,将使其适合更广泛的游戏。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值