[Tutor] Reversi Game Logic

Danny Yoo dyoo at hashcollision.org
Fri Mar 20 19:01:02 CET 2015


Hi Ni'Yana,

Here's a little transcript of what I'd do if I were to take a testing
approach to the problem.

---

Let's say that we start with a fresh board.  Imagine that we've just
created a fresh ReversiGameLogic.


What does the board look like?  Let's look at the state in the initializer.

#################################
  def __init__(self) :
     # Use a 2-D array to represent the board.
    self._gameBoard = Array2D(8, 8)
    self._gameBoard.clear(EMPTY)
    self._gameBoard[4,3] = BLACK
    self._gameBoard[3,4] = BLACK
    self._gameBoard[3,3] = WHITE
    self._gameBoard[4,4] = WHITE
    self._currentPlayer = BLACK
    ...
#################################

Let's visualize this.  The board looks like this:

. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . W B . . .
. . . B W . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .

and we'll keep in mind that the current player is black.



You mention the following:

################################################
> I am having trouble with a function in my reversi logic code. The function is the isLegalMove I am asked to "Return a Boolean indicating if the current player can place their chip in the square at position (row, col). Both row and col must be valid indices."
################################################


What moves are illegal when the board is just starting off?  Well, if
I try placing on the same points as what's already on the board,
that's definitely wrong.  Let me try writing this as a unit test.


##############################
import unittest

class ReversiTests(unittest.TestCase):
    def testIslegalMoveOnExistingSpots(self):
        logic = ReversiGameLogic()

        self.assertFalse(logic.isLegalMove(4, 3))
        self.assertFalse(logic.isLegalMove(3, 4))
        self.assertFalse(logic.isLegalMove(3, 3))
        self.assertFalse(logic.isLegalMove(4, 4))


if __name__ == '__main__':
    unittest.main()
##############################


I'd then run these tests, and they'd all pass, so I'd like that your
code is doing *something* good.


But then, I'd notice that the tests don't really say too much yet:
they've only said that it's illegal to play where there's already a
piece.


What at the places where black can play when the board looks like this?

. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . W B . . .
. . . B W . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .


According to:

    http://en.wikipedia.org/wiki/Reversi

the legal places where black can play next are here, marked with *'s.

. . . . . . . .
. . . . . . . .
. . . * . . . .
. . * W B . . .
. . . B W * . .
. . . . * . . .
. . . . . . . .
. . . . . . . .


So let's say that in the unit tests.  Add assertions that we want
those four starred points to be legal moves.

#############################################
import unittest

class ReversiTests(unittest.TestCase):
    def testIslegalMoveOnExistingSpots(self):
        logic = ReversiGameLogic()
        # Placing on existing spots should not be legal.
        self.assertFalse(logic.isLegalMove(4, 3))
        self.assertFalse(logic.isLegalMove(3, 4))
        self.assertFalse(logic.isLegalMove(3, 3))
        self.assertFalse(logic.isLegalMove(4, 4))


    def testIsLegalMoveGood(self):
        logic = ReversiGameLogic()
        # But here are spots that should be legal.
        self.assertTrue(logic.isLegalMove(2, 3))
        ...  ## fill me in with the other three legal moves!


if __name__ == '__main__':
    unittest.main()
##############################################


If this is the first time you've seen a testing approach, notice that
writing tests is a matter of asking yourself: "if this is what the
world looks like, what *should* happen if my code were working?"
That's an easier thing to do than to actually write the working code.

But it's not just something that we ponder: it's something we can run!
  Once we have the other three legal moves in play, now we have
something we can execute.  This is something that will say "yes" or
"no" to our implementation of isLegalMove().  This is the sort of
thing we *need* in order to tell if the logic is working or not.

It will also point out very clearly that your isLegalMove() is not
working, since it's going to fail.  But these are going to tell more
than than things are broken: they're going to tell you that things are
partially working, which is good!

That is, if you have these tests in place, one of the tests will
succeed, and the other will fail.  And that failure is going to point
out where you're missing something in your definition of
isLegalMove().


More information about the Tutor mailing list