I am attempting to make a reversi game using python. this is the code for a blank board
#reversi
import random
import sys
board = range(9)
def char_range(start, end, step=1):
for char in range(ord(start), ord(end), step):
yield char
def drawBoard(board):
###this prints out the board
HLINE = ' +-+-+-+-+-+-+-+-+'
VLINE = ' | | | | | | | | |'
print(' a b c d e f g h')
print(HLINE)
for y in range(8):
print(y+1, end = '|.|')
for x in char_range('a','h'):
print('| %s' %(board[x][y]), end='.')
print('|')
print(HLINE)
def resetBoard(board):
#blanks out the board
for x in char_range('a', 'h'):
for y in range(8):
board[x][y] = '.'
#starters
board[c][3] = 'X'
board[c][4] = 'O'
board[d][3] = 'O'
board[d][4] = 'X'
def getNewBoard():
#new board
board = []
for i in range(9):
board.append([' '] * 9)
return board
getNewBoard()
drawBoard(board)
resetBoard(board)
for some reason when i execute it i get this message:
File "C:\Users\Larry\Desktop\test.py", line 18, in drawBoard
print('| %s' % (board[x][y]), end='.')
IndexError: string index out of range
what does this mean. do i need to change
char_range()
or the
print('| %s' % (board[x][y]), end='.')
As wim commented, a dict is often a perfectly fine way to implement a board like this
def getNewBoard():
#new board
board = {}
for x in range(8): # or x in 'abcdefgh': if you prefer
for y in range(8):
board[x, y] = ' '
return board
And don't forget to assign the board to board
board = getNewBoard()
Related
the window of game.py I try out some of the python beginner project to practise my sense of coding.
And after i followed the youtube video step by step, i started to debug and play the
TicTacToe. It closed right after i input my first square/input. But i don't understand
where it goes wrong. I just start fighting with coding, i don't mind to get slap right out
of my face right now. Please, go easy on me. It keeps drive me to the wall.
#Player.py ||||
import math
import random
class Player:
def __init__(self,letter):
self.letter = letter
def get_move(self,game):
pass
class RandomComputerPlayer(Player):
def __init__(self, letter):
super().__init__(letter)
def get_move(self,game):
square = random.choice(game.available_moves())
return square
class HumanPlayer(Player):
def __init__(self, letter):
super().__init__(letter)
def get_move(self,game):
valid_square = False
val = None
while not valid_square:
square = input(self.letter + '\'s turn. Input move (0-8):')
try:
val = int(square)
if val not in game.available_moves():
raise ValueError
valid_square = True
except ValueError:
print('Invalid square. Try again.')
return val
And here's game.py:
#game.py ||||
import time
from player import HumanPlayer, RandomComputerPlayer
class TicTacToe:
def __init__(self):
self.board = [' ' for _ in range(9)]
self.current_winner = None
def print_board(self):
for row in [self.board[i*3:(i+1)*3] for i in range(3)]:
print('| ' + ' | ' .join(row) + ' |')
#staticmethod
def print_board_nums():
# 0 | 1 | 2 etc
number_board = [[str(i) for i in range(j*3, (j+1)*3)] for j in range (3)]
for row in number_board:
print('| ' + ' | '.join(row) + ' |')
def available_moves(self):
moves = []
for (i, x) in enumerate(self.board):
if spot == ' ':
moves.append(i)
def empty_squares(self):
return ' ' in self.board
def num_empty_squares(self):
return len(self.available_moves())
def make_move(self, square, letter):
if self.board[square] == ' ':
self.board[square] = letter
if self.winner(square, letter):
self.current_winner = letter
return True
return False
def winner(self, square, letter):
# winner if 3 in a row anywhere, check all of the possiblity
row_ind = square // 3
row = self.board[row_ind*3 : (row_ind + 1) * 3]
if all ([spot == letter for spot in row]):
return True
col_ind = square % 3
column = [self.board[col_ind + i*3] for i in range(3)]
if all ([spot == letter for spot in column]):
return True
# check diagonals
if square % 2 == 0:
diagonal1 = [self.board[i] for i in[0,4,8]]
if all ([spot == letter for spot in diagonal1]):
return True
diagonal2 = [self.board[i] for i in[2,4,6]]
if all ([spot == letter for spot in diagonal2]):
return True
# if all of the possibility not happen
return False
def play(game, x_player, o_player, print_game = True):
# returns the winner of the game! or None for a tie
if print_game:
game.print_board_nums()
letter = 'X'
while game.empty_squares():
if letter == '0':
square = o_player.get_move(game)
else:
square = x_player.get_move(game)
if game.make_move(square, letter):
if print_game:
print(letter + ' makes a move to square {square}')
game.print_board()
print('') # empty line
if game.current_winner:
if print_game:
print(letter + 'wins!')
return letter
letter = 'O' if letter == 'X' else 'X'
# if letter == 'X':
# letter = 'O'
# else:
# letter = 'X'
time.sleep(0.8)
if print_game:
print('It\'s a tie!')
if __name__ == '__main__':
x_player = HumanPlayer('X')
o_player = RandomComputerPlayer('O')
t = TicTacToe()
play(t, x_player, o_player, print_game = True)
When I copied the code and ran it locally on my computer, the traceback showed that there was an error in game.py, specifically in your available_moves() function.
def available_moves(self):
moves = []
for (i, x) in enumerate(self.board):
if spot == ' ':
moves.append(i)
The traceback specifically says, NameError: name 'spot' is not defined, which is true since spot is not defined. I am assuming spot and x are supposed to mean the same here since you are looking at the square on your Tic-Tac-Toe board. Also, this function should probably return moves; otherwise, any other function calling available_moves() is going to get a value of type None instead of the list of available moves.
def available_moves(self):
moves = []
# iterate through all spots on board
for (i, spot) in enumerate(self.board):
# if a spot is empty, add its index to moves
if spot == ' ':
moves.append(i)
return moves
Also I've been absolutely crushing myself against myself playing this game so thanks for that!
Edit: Just noticed after posting this that Tim Roberts basically summed up my answer. Oops.
import random
import linecache
import colorama
from colorama import Fore, Back, Style
def pickword():
global wrd
fp = open("dictionary.txt", "r")
x = random.randint(0,0)
wrd = fp.readlines()[x]
def split(word):
return list(word.lower())
def checkword():
var1 = 0
ans = input("\n\nEnter a Word: ")
lst = split(wrd)
wrdlst = []
for x in lst:
if x != "\n":
wrdlst.append(x)
anslst = split(ans)
k = anslst[var1]
l = wrdlst[var1]
for i in range(len(wrdlst)):
print(Style.RESET_ALL + l)
for m in range(1):
k = anslst[var1]
l = wrdlst[var1]
if k not in wrdlst:
print(Fore.RED + k)
elif k in wrdlst and k != l:
print(Fore.YELLOW + k)
elif k in wrdlst and k == l:
print(Fore.GREEN + k)
var1 = var1 + 1
print(var1)
# def playerInputCheck(anslist, wrdlist):
#x=1
#for i in wrdlst:
# for m in anslst:
# if m == i:
# print("3")
def main():
start = input(Fore.GREEN + "Hello, welcome to wordle! To get started press enter:\n\n*Hit enter to start* ")
pickword()
checkword()
main()
When I try to run this, it ends up outputting this:
Hello, welcome to wordle! To get started press enter:
*Hit enter to start*
Enter a Word: about
a
a
1
a
b
2
b
o
3
u
u
4
s
t
5
the word i am getting from the file is abuse, but for some reason it is outputting the first a twice and not getting to the e (the top letters are from abuse and the bottom ones are from about) I tried to make a work around but i just couldn't get it to work.
Let's break this down at the problem area (irrelevant parts removed):
l = wrdlst[var1]
for i in range(len(wrdlst)):
print(Style.RESET_ALL + l)
k = anslst[var1]
l = wrdlst[var1]
var1 = var1 + 1
print(var1)
The first time through, we have var1 = 0, l = wrdlst[var1] = 0th letter to start. Print out l.
We enter the loop, k = wrdlst[var1] = 0th letter, l = wrdlst[var1] = 0th letter. var1 goes up by 1. k gets printed.
Going into the loop the second time, we print out l (the 0th letter, again). k = wrdlst[var1] = 1st letter, l = wrdlst[var1] = 1st letter. var1 goes up by 1. k gets printed.
As you see, l gets set once outside the loop, and then printed inside the loop, and then gets accidentally reset back to the beginning inside the loop, so it's always one behind.
Simplest solution, move l = wrdlst[var1] to inside the loop, like so:
for i in range(len(wrdlst)):
l = wrdlst[var1]
print(Style.RESET_ALL + l)
for m in range(1):
k = anslst[var1]
if k not in wrdlst:
print(Fore.RED + k)
elif k in wrdlst and k != l:
print(Fore.YELLOW + k)
elif k in wrdlst and k == l:
print(Fore.GREEN + k)
var1 = var1 + 1
print(var1)
output of suggested code
I've just started learning and I've only learnt the basics but this is my current code. I need to put it in a loop and ask the user to place the number for up to 8 times.
num_list = ['1','2','3','4','5',]
import random
num = random.choice(num_list)
table = [[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ']]
ss = {"W1":[0,0],
"W2":[1,0],
"W3":[2,0],
"W4":[3,0],
"X1":[0,1],
"X2":[1,1],
"X3":[2,1],
"X4":[3,1],
"Y1":[0,2],
"Y2":[1,2],
"Y3":[2,2],
"Y4":[3,2],
"Z1":[0,3],
"Z2":[1,3],
"Z3":[2,3],
"Z4":[3,3]}
ans = input('where would you like to place it: ')
index_ = ss[ans][0]
columns_ = ss[ans][1]
table[index_][columns_] = num
print(table)
This code below here is supposed to make sure the user is placing the number adjacent to another number.
How do I make sure it only starts to check on the 2nd turn onwards? And how do I get it to repeat the turn if it is not adjacent? I also wanted to put the code above into functions and call it at the end to make it neater but I'm not sure what to put in and what to not.
def moveandclip(n, x, y):
n[0] = max(0, min(n[0] + x, 3))
n[1] = max(0, min(n[1] + y, 3))
return n
above = moveandclip(ss[ans], 0 ,1)
below = moveandclip(ss[ans], 0 ,-1)
left = moveandclip(ss[ans], -1 ,0)
right = moveandclip(ss[ans], 1 ,0)
if above == '' and below == '' and left == '' and right == '':
print('It must be placed adjacent to another number.')
repeat the turn
else:
continue to next turn
If you want to run the code 8 times, you can do like this:
def moveandclip(n, x, y):
n[0] = max(0, min(n[0] + x, 3))
n[1] = max(0, min(n[1] + y, 3))
return n
above = moveandclip(ss[ans], 0 ,1)
below = moveandclip(ss[ans], 0 ,-1)
left = moveandclip(ss[ans], -1 ,0)
right = moveandclip(ss[ans], 1 ,0)
for _ in range(8):
if above == '' and below == '' and left == '' and right == '':
print('It must be placed adjacent to another number.')
else:
# Do whatever you want to
# Add more code if you want to run some more statements regardless of the condition
while True:
# Turn code
if above == '' and below == '' and left == '' and right == '':
print('It must be placed adjacent to another number.')
else:
break
I`ve got some problem with the following task: a user enters some cells like "XXXOO__O_". I print out it then like this (kind of a matrix/board):
---------
| X X X |
| O O _ |
| _ O _ |
---------
then the user enters two coordinates from 1 to 3, for example 2 3. After that I do some checks and if cell is "_" I replace it with "X" and then print board with replaced element again.
print("Enter cells:")
cells = input()
print("---------")
print("|", cells[0], cells[1], cells[2], "|")
print("|", cells[3], cells[4], cells[5], "|")
print("|", cells[6], cells[7], cells[8], "|")
print("---------")
while True:
coord = input("Enter the coordinates:").split()
strng = "".join(coord)
is_0_3 = 0
if strng.isdigit() == True:
for c in coord:
if int(c) > 3 or int(c) <= 0:
is_0_3 = 1
if strng.isdigit() == True and len("".join(coord)) == 2:
index = (((int(coord[0]) - 1) * 3) + (int(coord[1]) + 2)) - 3 #turning usser`s coordinates #into list index
print("index", index)
mtrx = []
for y in range(len(cells)):
mtrx.append(cells[y])
is_occupied = 0
for i, cell in enumerate(mtrx):
if i == index:
print("i==index", i)
if mtrx[index] == "X" or mtrx[index] == "O":
is_occupied = 1
if strng.isdigit() == False:
print("You should enter numbers!")
elif len("".join(coord)) != 2:
print("You should enter 2 numbers!")
elif is_0_3 == 1:
print("Coordinates should be from 1 to 3!")
elif is_occupied == 1:
print("This cell is occupied! Choose another one!")
else:
print("ma[i] before", mtrx[index])
mtrx[i] = mtrx[index].replace("_", "X")
print(mtrx[i])
print("i", i)
new_mtrx = []
print("---------")
for i in range(0, 8, 3):
row = [mtrx[i], mtrx[i + 1], mtrx[i + 2]]
new_mtrx.append(row)
print(f"| {mtrx[i]} {mtrx[i + 1]} {mtrx[i + 2]} |")
print("---------")
break
The problem is that i in the last else is always 8 and the element with coordinates 3 3 is always replaced no matter what coordinates the user entered. I don't understand why... Could you explain how can I fix it, please? For user's input 2 3 index=5 and the cell is '_', but in the last for the element with coordinates 3 3 is replaced, not the element with 2 3. I need to replace the element with coordinates user entered
Looks like in your last last else statement, you need to enumerate the matrix again. This worked for me.
else:
for i, cell in enumerate(mtrx):
index == i
print("ma[i] before", mtrx[i])
mtrx[index] = mtrx[index].replace("_", "X")
print(mtrx[i])
print("i", i)
new_mtrx = []
print("---------")
for i in range(0, 8, 3):
row = [mtrx[i], mtrx[i + 1], mtrx[i + 2]]
new_mtrx.append(row)
print(f"| {mtrx[i]} {mtrx[i + 1]} {mtrx[i + 2]} |")
print("---------")
break
I would keep things simple and use basic string manipulations here:
def print_board(inp):
print("---------")
lines = re.findall(r'.{3}', inp)
lines_out = ["| " + x[0] + " " + x[1] + " " + x[2] + " |" for x in lines]
for line_out in lines_out:
print(line_out)
print("---------")
inp = "XXXOO__O_"
print_board(inp)
This prints:
---------
| X X X |
| O O _ |
| _ O _ |
---------
Updated 2.0
Currently updated it so every old "function" has been moved beneath my class. Now it seems like one of my only problems is figuring out all these drawBoard() takes 1 positional argument but 2 were given
This is just the start of my current class, just to show you what I am currently dealing with
Update based on:
Every run of the program will give the option which size the board
should be ...
every board in the code shall be the same size
We make size a class variable and only prompt for a size if it isn't already set. All subsequent board creations will use the same size as the first board:
class BoardHandler:
size = None
def __init__(self):
self.board = None
if BoardHandler.size is None:
self.ask_size()
self.getNewBoard()
def ask_size(self): # no self use, method could be a function
while True:
try:
BoardHandler.size = int(input("Which size would you want? "))
break
except ValueError:
print("Wrong! try again")
def getNewBoard(self):
self.board = []
for _ in range(BoardHandler.size):
self.board.append([' '] * BoardHandler.size)
def resetBoard(self):
for x in range(BoardHandler.size):
for y in range(BoardHandler.size):
self.board[x][y] = ' '
n = int(BoardHandler.size / 2 - 1)
self.board[n][n] = 'B'
self.board[n + 1][n] = 'W'
self.board[n][n + 1] = 'W'
self.board[n + 1][n + 1] = 'B'
def drawBoard(self):
HLINE = ' ' + '-' * (4 * BoardHandler.size) + '-'
print(HLINE)
for y in range(BoardHandler.size):
print("{:2d}".format(y + 1), end=' ')
for x in range(BoardHandler.size):
print('| {}'.format(self.board[x][y]), end=' ')
print('|')
print(HLINE)
handler = BoardHandler()
handler.resetBoard()
handler.board[0][0] = 'W'
handler.drawBoard()
print(BoardHandler.size)
handler2 = BoardHandler()
handler2.drawBoard() # empty board but same size as first
As I said in a comment, I think you should make the two functions in methods of class BoardHandler. This will give you better encapsulation and it's fairly easy to do, here's how:
class BoardHandler:
def __init__ (self, size, board):
self.size = size
self.board = board
def ask_size(self):
try:
self.size = int(input("Which size would you want?"))
except ValueError:
print("Wrong! try again")
ask_size()
def getNewBoard(self):
board=[]
for i in range(self.size):
board.append([' ']* self.size)
self.board = board
def resetBoard(self):
for x in range(self.size):
for y in range(self.size):
self.board[x][y] = ' '
n=int(size/2-1)
self.board[n][n] = 'B'
self.board[n+1][n] = 'W'
self.board[n][n+1] = 'W'
self.board[n+1][n+1] = 'B'
def drawBoard(self):
HLINE = ' ----------------------------------------'
for y in range(self.size):
print(y+1, end=' ')
for x in range(Q):
print('| %s' % (self.board[x][y]), end=' ')
print('|')
print(HLINE)
If you want to keep them outside the class for some reason, you will need to modify each of them to accept a BoardHandler class instance as an argument:
def resetBoard(board_handler):
for x in range(board_handler.size):
for y in range(board_handler.size):
board_handler.board[x][y] = ' '
n=int(board_handler.size/2-1)
board[n][n] = 'B'
board[n+1][n] = 'W'
board[n][n+1] = 'W'
board[n+1][n+1] = 'B'
def drawBoard(board_handler):
HLINE = ' ----------------------------------------'
for y in range(board_handler.size):
print(y+1, end=' ')
for x in range(Q):
print('| %s' % (board_handler.board[x][y]), end=' ')
print('|')
print(HLINE)
This assumes your program creates a single BoardHandler class instance, and does all operations to that object.