Search code examples
python2048

Issue assigning two self variables to each other in python


I'm working on building a 2048 game and trying to build a stopping condition. But facing some issues with two variables. The idea I tried was simple - stop the execution when two matrix values (one that holds the current 4x4 board values and another the previous step's values) equals each other.

So basically the code was something like this.

import numpy as np
import random

class Board():
    def __init__(self):
        self.board = np.zeros((4,4), dtype = np.int)
        self.prev_board = np.zeros((4,4), dtype = np.int)
        self.new_game()
        print("New Board Created")
        self.newgame = False

    def new_game(self):
        for cnt in range(2):
            i = random.randint(0,3)
            j = random.randint(0,3)
            self.board[i][j] = random.choice([2,4])

    def populate(self):
        empty = []
        for i in range(4):
            for j in range(4):
                if self.board[i][j] == 0:
                    empty.append([i,j])

        i,j = random.choice(empty)
        self.board[i][j] = random.choice([2,4])

    def move(self,board):
        k = 0
        for row in board:
            new_col = np.zeros(len(row), dtype=row.dtype)
            j = 0
            previous = None
            for i in range(row.size):
                if row[i] != 0:
                    if previous == None:
                        previous = row[i]
                    else:
                        if previous == row[i]:
                            new_col[j] = 2 * row[i]
                            j += 1
                            previous = None
                        else:
                            new_col[j] = previous
                            j += 1
                            previous = row[i]
            if previous != None:
                new_col[j] = previous  

            board[k] = new_col
            k += 1
        return board

    def next_move(self,direction):
        rotated_board = np.rot90(self.board, direction)
        rotated_board = self.move(rotated_board)
        self.board = np.rot90(rotated_board, -direction)

    def play_game(self,direction):
        self.next_move(direction)
        self.prev_board = self.board
        print("Before populate")
        print(self.prev_board)
        self.populate()
        print("After populate")
        print(self.prev_board)

game = Board()
for i in range(2):
    game.play_game(0)

This is the method that executes one step of the game and this method is being called repeatedly until the stopping criteria is obtained which was mentioned above. The problem is when I try this way, the self.prev_board value changes before and after the self.populate() is called. Just don't understand what is going on.

The output is,

Before populate
[[0 0 0 0]
 [2 0 0 0]
 [0 0 0 0]
 [2 0 0 0]]
After populate
[[0 0 0 0]
 [2 0 0 0]
 [0 0 0 0]
 [2 0 4 0]]
Before populate
[[0 0 0 0]
 [2 0 0 0]
 [0 0 0 0]
 [2 4 0 0]]
After populate
[[0 0 0 0]
 [2 0 2 0]
 [0 0 0 0]
 [2 4 0 0]]

P.S: self.next_move(direction) - makes the next move and self.populate() - populates with a new random value in the matrix.


Solution

  • https://docs.python.org/2/library/copy.html

    Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other. This module provides generic shallow and deep copy operations (explained below).

    Interface summary:

    copy.copy(x) Return a shallow copy of x.

    copy.deepcopy(x) Return a deep copy of x.

    Please read through the above link, that should help with your problem