Issues with 'movement' across multi-dimensional array, text-based game - python-3.x

I'm currently messing around with the code right now to solve some issues in movement. Ideally, i want to be able to move the character to any spot in the array(worldMap) containing ' ', and marking the player's position with 'P'.
I'm lost to what the issue I am running into is, and some of the issues I am running into are as follows...
- when I move E it always goes to worldMap[3][3]
- N only moves up from worldMap[3][x] to worldMap [2][x]
- S doesn't work
Below is my current code...
import math
import random
import sys
import os
import time
gameplay= True
#world map lay out, X--> wall, player can't go that way. ' ', possible area for player to move, 'P', player indicator.
worldMap = [['X','X','X','X','X'],
['X',' ',' ',' ','X'],
['X',' ',' ',' ','X'],
['X','P',' ',' ','X'],
['X','X','X','X','X']]
west=str("w" or "W")
east=str("e" or "E")
north=str('n' or 'N')
south=str('s' or 'S')
for row in worldMap:
for column in row:
print(column, end=' ')
print()
while gameplay == True:
x=str((input("\nWhat direction would you like to move?\n ")))
if x==west:
for row in worldMap:
for i, column in enumerate(row):
if column == 'P':
if((i>0) and (i<4) and row[i-1]) == ' ':
row[i-1] = 'P'
row[i]=' '
else:
print("\nCan't do that.\n")
for row in worldMap:
for column in row:
print(column, end=' ')
print()
elif x==east:
for row in worldMap:
for i, column in enumerate(row):
if column == 'P':
if((i>0) and (i<4) and row[i+1]) == ' ':
row[i+1] = 'P'
row[i]=' '
else:
print("\nCan't do that.\n")
for row in worldMap:
for column in row:
print(column, end=' ')
print()
elif x == north: #move north
for column in worldMap:
for i, row in enumerate(column):
if row == 'P':
if((i>0) and (i<4) and column[i-1]) == ' ':
column[i-1] = 'P'
column[i]=' '
else:
print("\nCan't do that.\n")
for row in worldMap:
for column in row:
print(column, end=' ')
print()
elif x== south: #move south
for column in worldMap:
for i, row in enumerate(column):
if column == 'P':
if((i>0) and (i<4) and column[i+1]) == ' ':
column[i+1] = 'P'
column[i]=' '
else:
print("\nCan't do that.\n")
for row in worldMap:
for column in row:
print(column, end=' ')
print()
else:
for row in worldMap:
for column in row:
print(column, end=' ')
print()
print("\nCan't do that.\n")

I have tided up your code a bit. A good clue to needing to refactor your code is if you have written the same thing alot in your code. In those cases its better to write a function and then call the function from your code. The below code is just an example to help set you on the right path.
In this example instead of scanning the whole map for the player, i just keep track of the players position and calculate the new position and if its a space then move the player. We can easily move the player by adding or subtracting 1 to the x or y co-ordinate of the player.
I also cleaned up the print map function and its now only called at the start of each loop.
from random import randint
def generate_map(size):
# world map lay out, X--> wall, player can't go that way. ' ', possible area for player to move, 'P', player indicator.
world_map = [[wall for _ in range(size)]]
for i in range(1, size - 1):
world_map.append([wall])
for j in range(1, size - 1):
#generate random walls in our map (currently set to genearete spaces 90% of the time
if randint(1,100) < 90:
world_map[i].append(space)
else:
world_map[i].append(wall)
world_map[i].append(wall)
world_map.append([wall for _ in range(size)])
return world_map
def print_map():
for row in worldMap:
print(" ".join(row))
def move_player():
x, y = player_position
if direction == "W":
y -= 1
elif direction == "E":
y += 1
elif direction == "N":
x -= 1
elif direction == "S":
x += 1
if worldMap[x][y] == space:
worldMap[player_position[0]][player_position[1]] = space
worldMap[x][y] = player
player_position[0] = x
player_position[1] = y
else:
print("Cannot more there")
#Genearte a map and position the player
wall, space, player = "X", " ", "P"
map_size = 10
worldMap = generate_map(map_size)
player_position = [1, 1]
worldMap[player_position[0]][player_position[1]] = player
#Run the game
gameplay = True
while gameplay:
print_map()
direction = input("\nWhat direction would you like to move? ").upper()
if direction:
move_player()
else:
break

Related

index-error: string out of range in wordle similar game

So i'm making a Wordle clone and i keep getting a "indexerror: string is out of range" and i dont know what to do and every time i do the second guess it will say indexerrror string is out off range
at line 30
import random
def Wordle():
position = 0
clue = ""
print("Welcome to Wordle, in this game your're going to be guessing a random word of 5 letters, if the word have a a correct letters it will tell you, if the letter is in the word but isn't at the place that it's supposed to be it will say that the letter is in the word but ins't at the correct place, and if it ins't at the word it will say nothing.And you only have 6 tries")
user_name = input("Enter your name:")
valid_words = ['sweet','shark','about','maybe','tweet','shard','pleat','elder','table','birds','among','share','label','frame','water','earth','winds','empty','audio','pilot','radio','steel','words','chair','drips','mouse','moose','beach','cloud','yours','house','holes','short','small','large','glass','ruler','boxes','charm','tools']
TheAnswer = random.choice(valid_words)
print(TheAnswer)
number_of_guesses = 1
guessed_correct = False
while number_of_guesses < 7 and not guessed_correct:
print(' ')
TheGuess = input('Enter your guess (it have to be a 5-letter word and not captalied letters):')
if len(TheGuess) > 5:
print('word is not acceptable')
else:
print(' ')
for letter in TheGuess:
if letter == TheAnswer[position]:
clue += ' V'
elif letter in TheAnswer:
clue += ' O'
else:
clue += ' F'
position += 1
print(clue)
if TheGuess == TheAnswer:
guessed_correct = True
else:
guessed_correct = False
number_of_guesses += 1
clue = ""
if guessed_correct:
print('Congradulations', user_name,', you won and only used', number_of_guesses,'guesses, :D')
else:
print(user_name,'Unfortunatealy you usead all your guesses and lost :( . the word was', TheAnswer)
You are indexing TheAnswer[position] which basically means if TheAnswer is x length long, then the position should be,
But since the position variable is a local variable of the function, it continuously increases on each guess. Does not get reset on each guess.
Try moving the
position = 0
Into top of the while loop.
Code,
import random
def Wordle():
clue = ""
print("Welcome to Wordle, in this game your're going to be guessing a random word of 5 letters, if the word have a a correct letters it will tell you, if the letter is in the word but isn't at the place that it's supposed to be it will say that the letter is in the word but ins't at the correct place, and if it ins't at the word it will say nothing.And you only have 6 tries")
user_name = input("Enter your name:")
valid_words = ['sweet', 'shark', 'about', 'maybe', 'tweet', 'shard', 'pleat', 'elder', 'table', 'birds', 'among', 'share', 'label', 'frame', 'water', 'earth', 'winds', 'empty', 'audio',
'pilot', 'radio', 'steel', 'words', 'chair', 'drips', 'mouse', 'moose', 'beach', 'cloud', 'yours', 'house', 'holes', 'short', 'small', 'large', 'glass', 'ruler', 'boxes', 'charm', 'tools']
TheAnswer = random.choice(valid_words)
print(TheAnswer)
number_of_guesses = 1
guessed_correct = False
while number_of_guesses < 7 and not guessed_correct:
position = 0
print(' ')
TheGuess = input(
'Enter your guess (it have to be a 5-letter word and not captalied letters):')
if len(TheGuess) > 5:
print('word is not acceptable')
else:
print(' ')
for letter in TheGuess:
if letter == TheAnswer[position]:
clue += ' V'
elif letter in TheAnswer:
clue += ' O'
else:
clue += ' F'
position += 1
print(clue)
if TheGuess == TheAnswer:
guessed_correct = True
else:
guessed_correct = False
number_of_guesses += 1
clue = ""
if guessed_correct:
print('Congradulations', user_name, ', you won and only used',
number_of_guesses, 'guesses, :D')
else:
print(
user_name, 'Unfortunatealy you usead all your guesses and lost :( . the word was', TheAnswer)
Thanks!

Printing a kind of matrix in python

I have to print this Python-code:
Placement Name Won Played Percent Won
1 B Borg 5 10 0.5
2 J Smith 3 6 0.5
3
.
.
.
The number of players will vary, as the players are imported from a txt-file.
The top row (placement, name etc) is constant.
How can I use formatting to do this? Or if there is an easier way.
The info of the players should be aligned as is shown in the example code above.
EDIT:
def showLeaderboard(players):
print()
print("Placement, Name, Won, Played, Percent Won")
position = 1
for i in players:
print(position, end=" ")
i.showPlayerInfo()
position += 1
def readPlayers():
fileplacement = "leads to a directory"
if os.path.exists(fileplacement) and os.path.getsize(fileplacement) > 6:
txtinfo = open("players.txt", "r")
players = []
for row in txtinfo:
infoplayers = row.split(",")
players.append(Spelare(infoSpelare[0], float(infoSpelare[3]), int(infoSpelare[1]), int(infoSpelare[2]))) # "players" is a class, the rest is to import from my txt-file
return players
else:
print("players.txt does not seem to exist or contains unreasonables.")
raise SystemExit(0)
You need to iterate over your data two times. First, to see how wide each column must be, and next to actually print the data.
from typing import List
def prettyprint(headers: List[str], data: List[List[str]], separator: str=" ") -> None:
# initial column width is the width of the headers
columnwidths = [len(s) for s in headers]
for row in data:
# width of the columns in this row
cwidths = [len(s) for s in row]
# Take the max of the previously measured columnwidths and those of this row
columnwidths = [max(ow, cw) for ow, cw in zip(columnwidths, cwidths)]
prints = [headers] + data
for row in prints:
# Pad the data in each cell to the correct width
row_print = [cell.ljust(cwid) for cwid, cell in zip(columnwidths, row)]
print(separator.join(row_print))
d = [['1', 'B Borg', '5', '10', '0.5'], ['2', 'J Smith', '3', '6', '0.5']]
h = ['Placement', 'Name', 'Won', 'Played', 'Percent', 'Won']
prettyprint(h, d)
Gives the output:
Placement Name Won Played Percent
1 B Borg 5 10 0.5
2 J Smith 3 6 0.5
Obviously, you're going to have to modify this to work with your Spelare class. You can also use the functions rjust() and center() if you want a different alignment.
What you want to use is the following string methods:
ljust
rjust
center
Here is an example to get you started:
import sys
player_data = {
"Name": "B Borg",
"Placement": 1,
"Won": 5,
"Played": 10,
"Percent Won": 0.5
}
def print_format(k, val):
if k == "Name":
sys.stdout.write(val.ljust(20, ' '))
if k == "Placement":
sys.stdout.write(val.ljust(15, ' '))
if k == "Won":
sys.stdout.write(val.center(10, ' '))
if k == "Played":
sys.stdout.write(val.center(20, ' '))
if k == "Percent Won":
sys.stdout.write(val.center(10, ' '))
# Print the header
[print_format(k, k) for k in player_data.keys()]
print()
# Print the data:
[print_format(k, str(v)) for k, v in player_data.items()]
print()
(venv) [ttucker#zim bot]$ python justify.py
Name Placement Won Played Percent Won
B Borg 1 5 10 0.5

How can I daw a playing board with the help of python

Create a function that takes in two parameters: rows, and columns, both of which are integers. The function should then proceed to draw a playing board (as in the examples from the lectures) the same number of rows and columns as specified. After drawing the board, your function should return True.
def tictactoeboard(rowsorcolumns):
rowsorcolumns = int(rowsorcolumns)
# Number of rows and columns have been equated to keep a square tic-tact-toe board
if (rowsorcolumns) < 3 or (rowsorcolumns) > 21:
print("The number of rows or columns must be at least 3 OR at most 20")
return False
# For my screen, a comfortable size is that with 13 rows and columns
else:
for rows in range(rowsorcolumns):
if rows != rowsorcolumns-1:
for columns in range(rowsorcolumns):
if columns == 0:
print("__", end="")
elif columns != 0 and columns != rowsorcolumns-1:
print("|__", end="")
else:
print("|__")
else:
for columns in range(rowsorcolumns):
if columns == 0:
print(" ", end="")
elif columns != 0 and columns != rowsorcolumns-1:
print("| ", end="")
else:
print("| ")
return True
tictactoeboard(input("Enter the number of rows OR columns that you want for the board = "))
def Game_Board(rows, columns):
max_columns = 100
max_rows = 50
rows = int(rows)
columns = int(columns)
if columns <= max_columns and rows <= max_rows:
for r in range((rows-1)*2+1):
if r%2 == 1:
print("-"*(2*columns-1))
else:
print(" |"*(columns-1))
else:
print("rows and columns are above table values")
return
Print_Board = Game_Board(50, 100)
print(Print_Board)
Creating a playing board
def playingBoard(row, col):
for r in range(row):
if r % 2 == 0:
for c in range(1, col):
if c % 2 == 1:
if c != 5:
print(" ", end=" ")
else:
print(" ")
else:
print("|", end=" ")
else:
print("--------")
row = 5enter code here
col = 6
print(playingBoard(row, col))

How to code win/tie conditions in TicTacToe game in python

I have made the main-game mechanics for the TicTacToe game; however, I don't know a way to code the end-game win conditions, i.e. How to find when someone wins/ties.
I tried using the all() function, but either this did not work, or I used it incorrectly (probably the latter).
Here is the full code, and the list of variables for the code (as there are no comments):
def get_grid():
r1 = ['-','-','-']
r2 = ['-','-','-']
r3 = ['-','-','-']
return r1, r2, r3
def get_coords():
x = 0
y = 0
while True:
try:
x = int(input("x coord : "))
y = int(input("y coord : "))
except ValueError:
print("Must be an integer")
if x < 0 or x > 3 or y < 0 or y > 3:
print('Both values must be in the grid!')
else:
break
return x, y
def pgrid(x, y, r1, r2, r3, player):
rdict = {1:r1, 2:r2, 3:r3}
if x != 0 and y != 0:
while True:
if rdict[y][x-1] == '-':
rdict[y][x-1] = player
break
else:
print("Invalid Space!")
x, y = get_coords()
print('\t1\t2\t3')
print(' 1 |', end = '\t')
for i in r1:
print(i, end = ' | ')
print()
print(' 2 |', end = '\t')
for i in r2:
print(i, end = ' | ')
print()
print(' 3 |', end = '\t')
for i in r3:
print(i, end = ' | ')
print()
def main():
r1, r2, r3 = get_grid()
players = ['X', 'O']
pgrid(0, 0, r1, r2, r3, None)
win = False
while win == False:
for i in players:
x, y = get_coords()
pgrid(x, y ,r1 ,r2 , r3, i)
Variables
r1, r2 and r3 are the first, second, and third rows for the board. List
x and y are the coordinates where the 'X' or 'O' is placed. Integer
rdict navigates between the y value entered and the row of the board. Dictionary
player is the player. String
players is a List of the players ('X' and 'O')
win is true when a player has won / the game has tied. Boolean
The win variable is what needs to change in answers to this question, I just need the code or at least an idea on how to code it (because I don't have any!).
Thanks in advance!
What's the simplest way to check if three of the same letters are in a row or column? For the first column take r1[0], r2[0] and r3[0] and check if they all contain the same letter:
if r1[0] == 'X' and r2[0] == 'X' and r3[0] == 'X':
print('First column meets victory conditions', 'X')
Now it would be a bit cumbersome to do this for all rows and columns and both letters, but fortunately we can just let some for loops do the work for us.
for letter in 'XO':
for i in range(3):
if r1[i] == letter and r2[i] == letter and r3[i] == letter:
print('Column', i, letter)
For the rows just iterate over (r1, r2, r3) instead of the range(3) and check:
if row[0] == letter and row[1] == letter ...
And of course you can also use the all function and a list comprehension or generator expression to see if all letters are equal.
for row in (r1, r2, r3):
if all(item == letter for item in row):
You can try my function :
def check_who_won(board):
for letter in 'xo':
if all(col == letter for row in board for col in row):
return True
for col in range(3):
if all(board[row, col] == letter for row in range(3)):
return True
if (board[2, 0] and board[1, 1] and board[0, 2]) in letter:
return True
if all(board[index, index] == letter for index in range(3)):
return True
return False

tic tac toe for python3

how do I add a score counter to this tic tac toe game:
i need to be able to keep score of the tic tac toe games so that the users (its a 2 player game) can play mutable games in a row and the program will keep score for them.The program bellow already allows the users to continue to play so that they can play multiple games in a row however the program does not keep track of the score of player x and o or the number of ties. how to I add to this so that it will tray player x's wins, player o's wins, and the number on ties
def drawboard(board):
print(' | |')
print(' ' + str(board[7]) + ' | ' +str( board[8]) + ' | ' + str(board[9]))
print(' | |')
print('-----------')
print(' | |')
print(' ' + str(board[4]) + ' | ' + str(board[5]) + ' | ' + str(board[6]))
print(' | |')
print('-----------')
print(' | |')
print(' ' + str(board[1]) + ' | ' + str(board[2]) + ' | ' + str(board[3]))
print(' | |')
def draw(board):
print(board[7], board[8], board[9])
print(board[4], board[5], board[6])
print(board[1], board[2], board[3])
print()
def t(board):
while True:
try:
x = int(input())
if x in board:
return x
else:
print("\nSpace already taken. Try again")
except ValueError:
print("\nThat's not a number. enter a space 1-9")
def GO(win,board):
for x, o, b in win:
if board[x] == board[o] == board[b]:
print("Player {0} wins!\n".format(board[x]))
print("Congratulations!\n")
return True
if 9 == sum((pos == 'X' or pos == 'O') for pos in board):
print("The game ends in a tie\n")
return True
def tic_tac_toe():
board = [None] + list(range(1, 10))
win = [(1, 2, 3),(4, 5, 6),(7, 8, 9),(1, 4, 7),(2, 5, 8),(3, 6, 9),(1, 5, 9),(3, 5, 7),]
for player in 'XO' * 9:
drawboard(board)
if GO(win,board):
break
print("Player {0}".format(player))
board[t(board)] = player
print()
def main():
while True:
tic_tac_toe()
if input("Play again (y/n)\n") != "y":
break
main()
Seeing that the code is already a bit messy and still without answer, I would suggest a quick & dirty solution.
You can define a global variable outside of all the functions, like:
scoreboard = {"X": 0, "O": 0, "T": 0}
Then you simply increment the scores in your GO function.
def GO(win,board):
for x, o, b in win:
if board[x] == board[o] == board[b]:
print("Player {0} wins!\n".format(board[x]))
print("Congratulations!\n")
scoreboard[board[x]] += 1
return True
if 9 == sum((pos == 'X' or pos == 'O') for pos in board):
print("The game ends in a tie\n")
scoreboard["T"] += 1
return True
And just print the scores from scoreboard wherever you want.
However, I would recommend to learn how to make your code more readable. It will help you to write more difficult programs more easily. It will help to avoid quick and dirty solutions like this one and make a lot of difficult things fall into place without much effort.
In any case, congrats on writing a working TTT game, keep it up :)
def GO(win,board):
for x, o, b in win:
if board[x] == board[o] == board[b]:
print("Player {0} wins!\n".format(board[x]))
print("Congratulations!\n")
return True
if 9 == sum((pos == 'X' or pos == 'O') for pos in board):
print("The game ends in a tie\n")
# return False if there is no winner
return False
def tic_tac_toe():
board = [None] + list(range(1, 10))
win = [(1, 2, 3),(4, 5, 6),(7, 8, 9),(1, 4, 7),(2, 5, 8),(3, 6, 9),(1, 5, 9),(3, 5, 7),]
for player in 'XO' * 9:
drawboard(board)
if GO(win,board):
# returns the winner if there is one
return player
elif GO(win, board) is False:
# returns False if winner is a tie
return False
print("Player {0}".format(player))
board[t(board)] = player
print()
First, you should create unique output values for different game outcomes rather than only True. Then, you can keep score in your while loop based on the value of the function call.
def main():
count_x = 0
count_o = 0
while True:
score = tic_tac_toe()
if score == 'X':
count_x += 1
elif score == 'O':
count_o += 1
print("The running score is " + '('+ str(count_x), str(count_y) +')')
if input("Play again (y/n)\n") != "y":
break
main()

Resources