0

In order to implement a 'maze game' I need to move a character 'X' around a pre-built maze that exists as a .txt file. I have been trying to achieve this via various read/write/append methods but thus far have had no luck. The best I've been able to do is to read and print the coordinates of the 'X' in the text, but not manipulate it in any way. Any help in sorting out a means by which to move it would be greatly appreciated.

class game():

    def __init__(self):
        self.score = 0
        self.exit = False
        self.board = []
        filepath = 'maze.txt'
        with open(filepath,'r') as fp:
            line = fp.readline()
            while(line):
                self.board.append(list(line))
                line = fp.readline()



    def show_board (self):
        CSI="\x1b["
        print ("----------")
        print(CSI+"38;40m" + 'score:'+ str(self.score) + CSI + "0m")

        for i in range(len(self.board)):
            for j in range(len(self.board[i])):
                if self.board[i][j] == "X":
                    CSI="\x1b["
                    print(CSI+"33;91m" + ''.join(self.board[i][j])+ CSI + "0m", end='', flush=True)

                elif self.board[i][j] == "*":
                    CSI="\x1b["
                    print(CSI+"36;40m" + ''.join(self.board[i][j])+ CSI + "0m", end='', flush=True)

                elif self.board[i][j] == "@":
                    CSI="\x1b["
                    print(CSI+"32;40m" + ''.join(self.board[i][j])+ CSI + "0m", end='', flush=True)

                else:
                    CSI="\x1B["
                    print(CSI+"31;40m" + ''.join(self.board[i][j])+ CSI + "0m", end='', flush=True)



    def detect_start_point(self):
        for x in range(len(self.board)):
            for y in range(len(self.board[x])):
                if self.board[x][y] == 'X':
                    self.i,self.j = x,y

    def move_player(self, move):
        return
        #you may remove return (if it is not required)

board = game()
board.detect_start_point()
board.show_board()
while(True):  # you may need to change the condition

    # get the selected action from the user here
    move=input()

    # implement 
    board.move_player(move)
    board.show_board()

In theory I should only need to finish the:

def move_player(self, move):
        return
        #you may remove return (if it is not required)

But my attempts to produce even basic movement have failed.

For anyone interested in the particulars, the text file (referred to in the code as 'maze.txt') contains:

##############################
# X         *   #            #
#    ############     #      #
#      *        #     #      #
#               #  *  #      #
#               ######       #
#                            #
##########          @        #
#*      #                    #
#       #       ##############
#       #       *       #  * #
#                       #    #
#       *                    #
##############################

Where the * are items to collect, and @ is a gate to finish the level. I have no issue coding the conditions for those however.

PK-3
  • 3
  • 1
  • why do you want to move char in file? Can't you read all to memory, edit it memory and display without writing to file or write all in file after changing in memory? – furas Dec 16 '19 at 06:08
  • https://stackoverflow.com/questions/1325905/inserting-line-at-specified-position-of-a-text-file/1325927#1325927 – McLovin Dec 16 '19 at 06:11
  • 1
    as for me you don't need to move char in file but in `self.board` but it it list of list, not file. – furas Dec 16 '19 at 06:12
  • @furas Thank you, I hadn't considered that. Do you have any recommendation/ method for that? I'm still very new to Python, so I have a lot still to learn. – PK-3 Dec 16 '19 at 06:30
  • remove from old place `self.board[self.i][self.j] = ""` change position ie. `self.j += 1` and then put in new place `self.board[self.i][self.j] = "X"`. But before move you have to check if new place is empty – furas Dec 16 '19 at 06:40
  • @furas Thank you again, I'll give that a try now. – PK-3 Dec 16 '19 at 07:07

1 Answers1

0

You don't have to change in file but self.board.

First: you should remeber that self.board keeps data in [row][column] which means [y][x] instead of [x][y]

First you should check if new position is empty ie.

# move down (y+1) if self.board[self.y+1][self.x] in (' ', "@', '*'):

Next you have to remove player from old place, move its x,y and put in new place

self.board[self.y][self.x] = ' ' # clear old place
self.y += 1
self.board[self.y][self.x] = 'X' # put in new place

Before move it could be good to keep old value in some variable - to use it later to receognize if player is standing on @ or *

self.current = self.board[self.y][self.x]

I used io.StringIO to simulate file in memory so I could keep code and data in one file for test.

Only one direction: d moves down

text = """##############################
# X         *   #            #
#    ############     #      #
#      *        #     #      #
#               #  *  #      #
#               ######       #
#                            #
##########          @        #
#*      #                    #
#       #       ##############
#       #       *       #  * #
#                       #    #
#       *                    #
##############################"""
import io

# --- constants ---

CSI = "\x1b["

C0 = "\x1b[0m"     # color 0 (zero)
CX = "\x1b[33;91m" # color X (player)
CS = "\x1b[36;40m" # color * (star)
CA = "\x1b[32;40m" # color @ (at)
C_ = "\x1b[31;40m" # color _ (floor)

# ---

class Game():

    def __init__(self):
        self.score = 0
        self.exit = False
        self.board = []
        filepath = 'maze.txt'
        #with open(filepath,'r') as fp:
        with io.StringIO(text) as fp:    
            for line in fp:
                self.board.append(list(line))

    def show_board (self):
        print ("----------")
        print(CSI+"38;40m" + 'score:'+ str(self.score) + C0)

        for row in self.board:
            for item in row:
                if item == "X":
                    print(CX + item + C0, end='', flush=True)
                elif item == "*":
                    print(CS + item + C0, end='', flush=True)
                elif item == "@":
                    print(CA + item + C0, end='', flush=True)
                else:
                    print(C_ + item + C0, end='', flush=True)

    def detect_start_point(self):
        for y, row in enumerate(self.board):
            for x, item in enumerate(row):
                if item == 'X':
                    self.x, self.y = x, y

    def move_player(self, move):
        if move == 'd': # down
            #if self.board[self.y+1][self.x] in (' ', "@', '*'):
            if self.board[self.y+1][self.x] == ' ':
                self.board[self.y][self.x] = ' ' # clear old place
                self.y += 1
                self.board[self.y][self.x] = 'X' # put in new place
        return
        #you may remove return (if it is not required)

board = Game()
board.detect_start_point()
board.show_board()
while(True):  # you may need to change the condition

    # get the selected action from the user here
    move = input()

    # implement 
    board.move_player(move)
    board.show_board()

EDIT: version more univeral. Player can move u, d, l, r (up/down/left/right) but code is shorter.

text = """##############################
# X         *   #            #
#    ############     #      #
#      *        #     #      #
#               #  *  #      #
#               ######       #
#                            #
##########          @        #
#*      #                    #
#       #       ##############
#       #       *       #  * #
#                       #    #
#       *                    #
##############################"""
import io

# --- constants ---

CSI = "\x1b["

C0 = "\x1b[0m"     # color 0 (zero)
CX = "\x1b[33;91m" # color X (player)
CS = "\x1b[36;40m" # color * (star)
CA = "\x1b[32;40m" # color @ (at)
C_ = "\x1b[31;40m" # color _ (floor)

# ---

class Game():

    def __init__(self):
        self.score = 0
        self.exit = False
        self.board = []
        filepath = 'maze.txt'
        #with open(filepath,'r') as fp:
        with io.StringIO(text) as fp:    
            for line in fp:
                self.board.append(list(line))

    def show_board (self):
        print ("----------")
        print(CSI+"38;40m" + 'score:'+ str(self.score) + C0)

        for row in self.board:
            for item in row:
                if item == "X":
                    print(CX + item + C0, end='', flush=True)
                elif item == "*":
                    print(CS + item + C0, end='', flush=True)
                elif item == "@":
                    print(CA + item + C0, end='', flush=True)
                else:
                    print(C_ + item + C0, end='', flush=True)

    def detect_start_point(self):
        for y, row in enumerate(self.board):
            for x, item in enumerate(row):
                if item == 'X':
                    self.x, self.y = x, y

    def move_player(self, move):
        moved = False
        if move == 'r': # right
            new_x = self.x + 1
            new_y = self.y
            moved = True

        if move == 'l': # left
            new_x = self.x - 1
            new_y = self.y
            moved = True

        if move == 'd': # down
            new_x = self.x
            new_y = self.y + 1
            moved = True

        if move == 'u': # up
            new_x = self.x
            new_y = self.y - 1
            moved = True

        if moved:
            if self.board[new_y][new_x] in (' ', '@', '*'):
                self.current = self.board[new_y][new_x]
                self.board[self.y][self.x] = ' ' # clear old place
                self.x = new_x
                self.y = new_y
                self.board[self.y][self.x] = 'X' # put in new place

            if self.current == '*':
                self.score += 10
                self.current = ' ' # no more gold in current place

        return
        #you may remove return (if it is not required)

board = Game()
board.detect_start_point()
board.show_board()
while(True):  # you may need to change the condition

    # get the selected action from the user here
    move = input()

    # implement 
    board.move_player(move)
    board.show_board()
furas
  • 134,197
  • 12
  • 106
  • 148
  • Thank you so much! I had success with your previous suggestion and was beginning to implement these checks, this is a marvelous guide to reference as I go! I truly appreciate the help, you're a hero to me. – PK-3 Dec 16 '19 at 07:27