0

我正在通过 Chris Pine 的“Learn to Program”学习 Ruby。我试图在没有全局变量的情况下应对。我有一个看起来很草率的命令提示符二十一点程序(还不能拆分) 我的前三种方法说明了我遇到的问题。在 Pascal 中,我会使用全局变量,并使用方法来操作这些全局变量。它看起来像这样(使用 ruby​​ 伪语言)

$deck_of_cards = []
$player_hand   = []
$dealer_hand   = []

def create_deck
    $deck_of_cards = #numbers 1-52
end

def shuffle_deck
    $deck_of_cards = #shuffled up deck of cards
end

def opening_deal
    2.times do
        $player_hand.push $deck_of_cards.pop
        $dealer_hand.push $deck_of_cards.pop
    end
end

create_deck
shuffle_deck
opening_deal

我最终会得到一个洗牌的牌组、一个玩家手和一个庄家手。

去掉全局变量,前两个方法现在看起来像这样:

def create_deck deck_of_cards
    deck_of_cards = #numbers 1-52
    return deck_of_cards
end

def shuffle_deck deck_of_cards
    deck_of_cards = #shuffled up deck of cards
    return deck_of_cards
end

deck = create_deck([])
deck = shuffle_deck(deck)

这感觉有点奇怪,但我可以习惯它。

但是我完全坚持最后一种方法,它需要返回两个变量,player_hand 和dealer_hand。我可以将这两个数组推入另一个数组并返回它,但这似乎并没有简化任何事情。

是否有解决此问题的一般策略,或者每种情况都有其独特的解决方案?

想到的另一种情况是国际象棋程序。为什么将棋盘设为全局变量没有意义,因为国际象棋程序中的几乎所有方法都需要使用它的值?

4

3 回答 3

3

简短的回答:对象。面向对象编程允许您封装数据,以免污染全局命名空间。随着您的项目变得越来越大,将所有数据都放在全局命名空间中变得无法维护。对象允许您将数据和方法分组为有意义的单元,然后可以更轻松地重用和维护这些单元。

因此,例如,通过您提供的示例,我们可以制作甲板和手对象。这使我们能够轻松地创建多个甲板和手,因为这些对象封装和管理它们的数据。

作为如何组织类/方法的粗略概述:

class Deck
  def shuffle
  end

  def draw_hand
  end
end

class Hand
end

class Card
end
于 2013-05-26T04:55:18.020 回答
1

通常,使用面向对象的编程技术,您将定义类并创建这些类的对象,然后传递这些对象。您可以将对象视为类似于数组,因为它们可以包含大量相关数据,但比数组更好的是,数据元素可以具有名称并且可以是任何类型,并且不需要是相同的类型,并且它们带有用于对数据进行操作的命名函数。(其实在 Ruby 中,Array 元素可以是任意类型,不需要是同一类型,Hash 元素也是如此,加上 Hash 元素有名称,但 Ruby 有特殊之处,很少有其他语言允许。)

不过,为了简单起见,您可以像这样继续您的程序:

def opening_deal deck_of_cards
    player_hand = []
    dealer_hand = []
    2.times do
        player_hand.push deck_of_cards.pop
        dealer_hand.push deck_of_cards.pop
    end
    return player_hand, dealer_hand
end

player_hand, dealer_hand = opening_deal deck
于 2013-05-26T07:11:28.687 回答
1

拥有全局变量是一个坏习惯,但拥有全局常量也不错,换句话说,在主名称空间中定义的常量。当需要全局变量时,您始终可以在主名称空间中定义一个常量。即使是常量,也可以修改字符串、哈希、数组等可变对象。如果这还不够,你需要更复杂的东西,那么你可以定义一个模块(这是常量的一种特殊情况),并在该模块上定义方法来访问你想要做的事情,并封装复杂的信息在该模块中使用实例变量。

于 2013-05-26T08:47:05.640 回答