Paper Strip Game using Python
Posted by Samath
Last Updated: December 17, 2014
  4346

In the game Paper Strip, two players start with a strip of n white squares and they take
alternate turns. Each player is assigned a unique colour, except white. On each turn, a player
picks two contiguous white squares and paints them in his/her assigned colour. The first
player who cannot make a move loses. For example, if
- n = 1, there are no valid moves, so the first player loses automatically.
- n = 2, there is only one valid move, after which the second player loses.
- n = 3, there are two valid moves, but both leave a situation where the second player
loses.
- n = 4, there are three valid moves for the first player; she can win the game by painting the two middle squares.
- n = 5, there are four valid moves for the first player (shown below in red); but no matter what she does, the second player (blue) wins.

For this assignment we will write the code to create our own Python based version of Paper Strip, but first you will need to learn about turtle graphics. You will need to use a graphics library to actually draw and colour the strips. For this assignment, you will be utilising the graphics library that comes bundled with most Python interpreters, Tkinter. Within that library is what you will be using, turtle graphics. Be sure you import the library (remember, just include the command import turtle at the beginning of your code). The turtle is simply displayed in a separate window, as a small triangle by default. The following table contains some of the turtle commands you will need to use for this assignment (I will include the function that actually draws stuff further down this document anyway),

Try some of these out. Write a small program that starts with turtle.showturtle(), ends
with turtle.done() and has one or more of the other commands in between. For example,
the following bit of code draws a square in a window.

import turtle
turtle.showturtle()
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.done()

Experiment with turtle for a bit. When you think you've understood turtle, move on to the rest
of the assignment.

1. Let us begin by creating an ADT that we will use as the basic element of our game, a square. The attributes of a square that we want to maintain are the point at which we will draw it, the length of its sides and its colour. A square’s starting point is a 2 tuple of integers where the first integer represents the xcoordinate and the second, the ycoordinate. Our representation of a square will therefore be,

[“Square”, startPoint, sidelength, colour]

a. Write a constructor called makeSquarethat accepts 3 arguments: the starting
point as a tuple, the sidelength as an integer and its colour as a string.
makeSquare returns a square ADT as represented above i.e. as a list where
the first element is the tag “Square”, followed by the starting point, sidelength
and colour in that order

b. Write the following selectors,
i. getXcoord : accepts a starting point and returns its xcoordinate
ii. getYcoord : accepts a starting point and returns its ycoordinate
iii. getStartPt : accepts a square and returns its starting point
iv. getSidelength : accepts a square and returns its side length
v. getColour : accepts a square and returns its colour

c. Write a mutator called setColour that accepts a square and a colour and
redraws the square beginning at its current starting point and side length, but
with the colour that was passed as an argument.

2. drawSquare is the function that actually draws a square, using turtle, on a window that
will popup on your screen. Include the function below in your code,

def drawSquare(startPt,sidelength,colour):
angle=90
turtle.penup()
turtle.goto(startPt)
turtle.pendown()
turtle.fillcolor(colour)
turtle.begin_fill()
turtle.forward(sidelength)
turtle.left(angle)
turtle.forward(sidelength)
turtle.left(angle)
turtle.forward(sidelength)
turtle.left(angle)
turtle.forward(sidelength)
turtle.left(angle)
turtle.end_fill()
turtle.penup()

3. Our “strip of paper” will consist of a user specified number of white squares. Let us represent a strip as a dictionary called stripSquare where the key:value pair is,
{integer : square}

Globally define stripSquare by including the statement below in your code,
stripSquare=dict()

Throughout the game we will need to access specific squares from our strip. Write a function called getSquare that accepts an integer (a key) and returns the associated square from stripSquare

4. Write a function called drawStrip that accepts an integer as its argument and draws, square by square, a strip of length specified by the integer argument. For example, if the user specifies that a strip of length 7 squares is to be drawn, then the integer argument would be 7 and strip of 7 contiguous squares would be drawn in the turtle window. Within drawStrip, specify a sidelength for the squares (if you like, you can have the user specify this also) and then from within a loop: draw a square; add the square just drawn to stripSquare; and set the starting point for the next, contiguous square to be drawn. Turtle begins drawing at point (0,0) by default.

Now we will begin to write the functions that control the game play. For our version, the 2 players will be the user and the computer and play will alternate between them. The user will be offered the opportunity to decide whether or not he/she plays first.

5. Write a function called validPlay that accepts 2 arguments, a player’s selection and the number of squares in the strip. A player’s selection is the position of the first of the 2 contiguous squares that he/she wishes to change from white to his/her colour. validPlay checks that both the selected square and the next contiguous square are still white. If they both are, the play is deemed valid and it returns True, otherwise it is not and it returns False.

6. Below is the function called getPlayerPick that prompts the user for his/her selection of the first contiguous square for his/her play. Copy the code and include it in your own.

def getPlayerPick(length): # only the user enters a pick
  inRange=False
  while not inRange:
      pick=int(turtle.textinput("Your move",0))
      if pick in range(length):
        inRange=True
  return pick

7. We need to know when the game is over. We can figure this out by determining whether or not there are any pairs of contiguous squares remaining. Write a function called gameOver that accepts the number of squares in the strip as its argument and determines if there are any pairs of contiguous squares that are still white. If there are then it returns True, otherwise it returns False.

8. Using the randint function in the random library, simulate the computer making a selection by generating a random number that is between 0 and the number of squares in the strip.

9. You also need to write a function called togglePlayer that switches the value of the current player between the user and the computer. As a suggestion, you could create another dictionary that has 2 elements. The key is a number that represents the player while the value is the colour that will be assigned to that player.

10. Now, write a function called makePlay that accepts a player’s (validated) selection and a (player’s) colour and redraws the 2 contiguous squares at the same position, but in the player’s colour. makePlay must also update stripSquare with the new colour of the 2 squares.

11.We are almost finished. It is time to put all these functions together to create our game. Write the function play that accepts the number of squares in the strip and the user’s choice of whether he/she wishes to play first. play does the following,

a. draws the strip with the number of squares chosen by the user
b. assigns the value of the current player to the computer or user, whoever is
playing first
c. while the game is not over it loops and,
i. allows the current player to make a play i.e. selecting the first of 2
contiguous squares to recolour in his/her colour
ii. validates the selection. It should not proceed until the selection has
been validated
iii. makes the play by recolouring the pair of contiguous squares
iv. toggles the player
d. when the game is over, it returns who the winner is

12. Finally, write a function that initiates the playing of the game. It should prompt the user for the number of squares to draw in the strip, then ask the user if he/she wishes to play first, then call the function play that you wrote in part 11 above. play would therefore return who the winner is to this function which would then print who the winner is and end the game.

That’s it. Once you have your game working, you can try to determine if a particular player will always win depending on the specific move and/or the number of squares in the strip. I hope you have fun!

 

Here is the Solution to the problem above:

import turtle
import random

stripSquare=dict()

def makeSquare(startPoint, sidelength, colour):
    return ["Square", startPoint, sidelength, colour]


def getXcoord(startPoint):
    return startPoint[0]

def getYcoord(startPoint):
    return startPoint[1]

def getStartPt(square):
    return square[1]

def getSidelength(square):
    return square[2]

def getColour(square):
    return square[3]

def setColour(square, colour):
    drawSquare(getStartPt(square),getSidelength(square),colour)

def drawSquare(startPt,sidelength,colour):
    angle=90
    turtle.penup()
    turtle.goto(startPt)
    turtle.pendown()
    turtle.fillcolor(colour)
    turtle.begin_fill()
    turtle.forward(sidelength)
    turtle.left(angle)
    turtle.forward(sidelength)
    turtle.left(angle)
    turtle.forward(sidelength)
    turtle.left(angle)
    turtle.forward(sidelength)
    turtle.left(angle)
    turtle.end_fill()
    turtle.penup()

def getSquare(squareKey):
    for key, val in stripSquare.items():
        if(key == squareKey):
            return val

def drawStrip(myInt):
    incremove = 0
    sqrlength = 32;
  
    for x in range(myInt):
        sqrposition = (incremove,0)
        mysquare = makeSquare(sqrposition,sqrlength,"white")
        drawSquare(getStartPt(mysquare),getSidelength(mysquare),getColour(mysquare));

        stripSquare.update({x+1: mysquare })
        incremove = incremove + sqrlength

def validPlay(playerselection, numOfSquare):
    if(playerselection in stripSquare) and ((playerselection + 1) in stripSquare):
        if(getColour(getSquare(playerselection))=="white" and getColour(getSquare(playerselection+1))=="white"):
            return True
        else:
            return False
    else:
        return False
                     
    
def getPlayerPick(length): # only the user enters a pick
    inRange=False
    while not inRange:
        pick=int(turtle.textinput("Your move",0))
        if pick in range(length):
            inRange=True
    return pick

def gameOver(numOfSquare):
    for x in range(1,numOfSquare):
             if(getColour(getSquare(x)) == "white" and getColour(getSquare(x+1)) == "white"):
                 return True
    return False

def computerSim(numOfSquare):
    return random.randint(1,numOfSquare)

                     
def togglePlayer(player):
    if(player == 1):
        return "Player 1"
    elif(player == 2):
        return "Computer"

def makePlay(selection, colour):
         setColour(getSquare(selection),colour)
         setColour(getSquare(selection+1),colour)
         
         stripSquare[selection] = makeSquare(getStartPt(getSquare(selection)), getSidelength(getSquare(selection)), colour)
         stripSquare[selection+1] = makeSquare(getStartPt(getSquare(selection+1)), getSidelength(getSquare(selection+1)), colour)
        

def play(sqr_num, choice):
    turtle.clear()
    winner = 0
    ply_pick=0
    drawStrip(sqr_num)
    while gameOver(sqr_num):
       winner = choice
       if togglePlayer(choice) == "Player 1":
           ply_pick = getPlayerPick(sqr_num)
           while not validPlay(ply_pick,sqr_num):
               print("Invalid choice! pick another")
               ply_pick = getPlayerPick(sqr_num)
           makePlay(ply_pick,"Red")
       else:
           computer = computerSim(sqr_num)
           while not validPlay(computer,sqr_num):
               computer = computerSim(sqr_num)
           makePlay(computer, "Blue")

       if(choice == 1):
          choice+=1
       elif(choice == 2):
          choice-=1

    if winner == 1:
        return "Player 1"
    elif winner == 2:
        return "Computer"



def initGamePlay():
   notStart = True
   while notStart  :
       num_square = int(input("Enter the amount of square: "))
       player = int(input("Please enter 1 if you wish to play first\nPlease enter 2 if you want computer to play first:\nOption: "))
       if(player == 1 or player == 2):
           notStart = False   

   winner = play(num_square,player)
   print("Winner: ",winner)