so my code is designed to basically create a bingo card, then when you press enter draws a number and changes the bingo card value to 0 if the drawn number matches. My issue is that my code isn't properly producing a bingo or not a bingo which you can see towards the end of the code. How should I change this so that my code will return bingo when I have bingo.
import random #Condernsed solo version with call and player together
import numpy as np
def bingo_card(): #Code to generate BINGO card using numpy array
test1=np.array(random.sample(range(1,16),5))
test2=np.array(random.sample(range(16,31),5))
test3=np.array(random.sample(range(31,46),5))
test4=np.array(random.sample(range(46,61),5))
test5=np.array(random.sample(range(61,76),5))
test= np.concatenate((test1,test2,test3,test4,test5))
test= test.reshape(5,5)
test[2,2]=0
bingo_card.test = test
BINGO= print("Your Card")
print("B", test[0]),
print("I", test[1]),
print("N", test[2]),
print("G", test[3]),
print("O", test[4])
card = BINGO
return card
def called_value(): #should be close to the code we use to check if called value is in generated matrix, may need some formatting and fixing
checked_card = bingo_card.test
while True:
called_num = input ("Type called number to mark card or press 's' to quit if you think you have bingo").lower()
if called_num != "s":
number_check = int(called_num)
checked_card = np.where(checked_card==number_check,0,checked_card)
BINGO = print("Your Card")
print("B", checked_card[0]),
print("I", checked_card[1]),
print("N", checked_card[2]),
print("G", checked_card[3]),
print("O", checked_card[4])
elif called_num == "s":
BINGO = print("Your Card")
print("B", checked_card[0]),
print("I", checked_card[1]),
print("N", checked_card[2]),
print("G", checked_card[3]),
print("O", checked_card[4])
row_zeros = np.count_nonzero(checked_card == 0, axis=1)
col_zeros = np.count_nonzero(checked_card == 0, axis=0)
diagonal_zeros = np.count_nonzero(np.diag(checked_card) == 0)
diagonal1_zeros = np.count_nonzero(np.diag(np.fliplr(checked_card)) == 0)
for i in range (5):
if (row_zeros[i] or col_zeros[i]) == 5:
return ("Bingo!")
elif (diagonal_zeros or diagonal1_zeros) == 5:
return ("Bingo!")
else:
return ("Not Bingo")
def solo():
bingo_card()
called_value()
solo()
You've committed one of the classic blunders.
for i in range (5):
if (row_zeros[i] or col_zeros[i]) == 5:
return ("Bingo!")
elif (diagonal_zeros or diagonal1_zeros) == 5:
return ("Bingo!")
else:
return ("Not Bingo")
row_zeros[i] or col_zeros[i] is going to be True or False (usually True), which is never equal to 5. And you don't need to loop to check the diagonals. You need:
if diagonal_zeros == 5 or diagonal1_zeros == 5:
return ("Bingo!")
for i in range (5):
if row_zeros[i] == 5 or col_zeros[i] == 5:
return ("Bingo!")
return ("Not Bingo")
Related
I'm making a tic tac toe game and I need a way to check winning conditions. I made an
if statement to check if X has 3 in a row, but for some reason I can't reach a winning condition. I can have this X| |X but when I try to fill in the blank it tells me that I can't do that.
tiles = [1, 2, 3, 4, 5, 6, 7, 8, 9]
tiles_str = ("1", "2", "3", "4", "5", "6", "7", "8", "9")
global turn_count
turn_count = 0
def board():
divider = "-----"
play_board = str(tiles[0]) + "|" + str(tiles[1]) + "|" + str(tiles[2])
play_board_1 = str(tiles[3]) + "|" + str(tiles[4]) + "|" + str(tiles[5])
play_board_2 = str(tiles[6]) + "|" + str(tiles[7]) + "|" + str(tiles[8])
print(play_board)
print(divider)
print(play_board_1)
print(divider)
print(play_board_2)
while True:
def Turn_X():
board()
x_turn = input("X take your turn: ")
if x_turn in tiles_str:
x_turn = int(x_turn)
if x_turn in tiles:
if isinstance(tiles[x_turn], int):
global turn_count
turn_count = turn_count+1
tiles[x_turn -1] = "X"
if turn_count < 9:
Turn_O()
else:
print("Not an option")
Turn_X()
else:
print("Not an option")
Turn_X()
else:
print("Not an option")
Turn_X()
def Turn_O():
board()
o_turn = input("O take your turn: ")
if o_turn in tiles_str:
o_turn = int(o_turn)
if o_turn in tiles:
if isinstance(tiles[o_turn], int):
global turn_count
turn_count = turn_count+1
tiles[o_turn -1] = "O"
print(turn_count)
Turn_X()
else:
print("Not an option")
Turn_O()
else:
print("Not an option")
Turn_O()
else:
print("Not an option")
Turn_O()
if turn_count >= 9:
board()
print("\nDraw")
break
if tiles[0] == "X" and tiles[1] == "X" and tiles[2] == "X":
print("X wins")
break
Turn_X()
This is what I have for my game so far. I don't know if it's interfering with something else because I didn't have this issue before hand.
x_turn = int(x_turn)
if x_turn in tiles:
if isinstance(tiles[x_turn], int):
Python lists are zero-indexed. If the player entered 3, you're checking tiles[3] which is actually the fourth square.
Your architecture has some issues. Don't define functions inside a while loop; prepare all your functions at the front, then USE them.
Don't use recursion for retrying an input. That's wasteful. Instead, use a while loop.
Note that the X and O functions are practically identical. Just use the same code and pass the letter.
Your code only checked for a top line. There's no reason to check X and O separately; just check whether the set of three are identical to each other.
This works:
def board():
divider = "-----"
play_board = f"{tiles[0]}|{tiles[1]}|{tiles[2]}"
play_board_1 = f"{tiles[3]}|{tiles[4]}|{tiles[5]}"
play_board_2 = f"{tiles[6]}|{tiles[7]}|{tiles[8]}"
print(play_board)
print(divider)
print(play_board_1)
print(divider)
print(play_board_2)
def Turn(xo):
board()
while True:
turn = input(xo + " take your turn: ")
if not "1" <= turn <= "9":
print( "Not an option." )
continue
turn = int(turn)-1
if isinstance(tiles[turn], int):
tiles[turn] = xo
if turn_count < 9:
return
print("Not an option")
def checkdraw(tiles):
return not any(isinstance(i,int) for i in tiles)
def checkwin(tiles):
if tiles[0] == tiles[1] == tiles[2]:
return tiles[0]
if tiles[3] == tiles[4] == tiles[5]:
return tiles[3]
if tiles[6] == tiles[7] == tiles[8]:
return tiles[6]
if tiles[0] == tiles[3] == tiles[6]:
return tiles[0]
if tiles[1] == tiles[4] == tiles[7]:
return tiles[1]
if tiles[2] == tiles[5] == tiles[8]:
return tiles[2]
if tiles[0] == tiles[4] == tiles[8]:
return tiles[4]
if tiles[2] == tiles[4] == tiles[6]:
return tiles[4]
return False
tiles = [1, 2, 3, 4, 5, 6, 7, 8, 9]
turn_count = 0
while True:
Turn('X')
turn_count = turn_count+1
if checkdraw(tiles):
print("Draw")
board()
break
if checkwin(tiles):
print("X wins!")
board()
break
Turn('O')
turn_count = turn_count+1
if checkdraw(tiles):
print("Draw")
board()
break
if checkwin(tiles):
print("O wins!")
board()
break
One cute optimization:
def checkwin(tiles):
for l in (
(0,1,2),(3,4,5),(6,7,8),
(0,3,6),(1,4,7),(2,5,8),
(0,4,8),(2,4,6)
):
if tiles[l[0]] == tiles[l[1]] == tiles[l[2]]:
return tiles[l[0]]
return False
Sorry but there is too much wrong to fix it without changing everything. You only check if x won when you have set all 9 fields. Check it before you call turn_o or turn_x.
Look for try: and except: and custom error class instead of the 3 if statements.
You can print a break line with \n so you have one variable instead of 4 to print your field and you can do this for example:
field = f"{str(tiles[0])}|"
And you have much code duplication which you could fix when you use functions with parameters
My tic-tac-toe doesn't seem to work properly. I have tried various things, but nothing changes.
You can run the script yourself, just to see that every time after asking the player's move the game makes a vertical line of X's at the desired column and ends there.
It's probably a problem with my implementation of minimax or the computedMove function, although i cannot locate any errors in there.
# Boardsize initialization
boardSize = 0
# Board initialization
board = []
person = 'X'
ai = 'O'
#This variable indicates the player who has their turn at the moment.
currentPlayer = ''
# This shows the board.
for n in range (boardSize):
for m in range (boardSize):
print (" - "),
print ("\n")
#Checking if somebody won (only horizontal or vertical)
def winLine(line, letter):
return all(n == letter for n in line)
#New list from diagonals
def winDiagonal(board):
return (board[n][n] for n in range (boardSize))
#The function universally checks whether somebody has won, or not.
def checkWinner (board):
#Liczenie wolnych pol
openSpots = 0
for n in range(boardSize):
for m in range(boardSize):
if board[n][m] == '0':
openSpots += 1
#Transposition of the board, so it's possible to use winline() here
for letter in (person, ai):
transPos = list(zip(*board))
#Horizontal check
if any(winLine(row, letter) for row in board):
return letter
#Vertical check
elif any (winLine(col, letter) for col in transPos):
return letter
#Diagonal check
elif any (winLine(winDiagonal(dummy), letter) for dummy in (board, transPos)):
return letter
elif openSpots == 0: return 'tie'
else: return 'N/A'
#This function returns the player's move
def playerMove (row, col):
#Checking if the field is clear
if board[row][col] == '0':
board[row-1][col-1] = person
else:
print('You cannot make that move.')
#Minimax constants
plusInf = float('inf')
minusInf = float('-inf')
#Lookup table for minimax scores
scores = {
'X': 10,
'O': -10,
'None': 0
}
#Minimax itself
def minimax(baord, depth, maximizes):
#Checking whether anybody has won
res = checkWinner(board)
if (res != 'N/A'):
return scores[res]
#Maximizing player
if maximizes:
minmaxBoard = board.copy()
maxTarget = minusInf
for n in range(boardSize):
for m in range(boardSize):
if minmaxBoard[n][m] == '0':
minmaxBoard[n][m] = ai
score = minimax(minmaxBoard, depth + 1, False)
maxTarget = max(score, maxTarget)
return maxTarget
#Minimizing player
else:
minTarget = plusInf
minmaxBoard = board.copy()
for n in range(boardSize):
for m in range(boardSize):
if minmaxBoard[n][m] == '0':
minmaxBoard[n][m] = person
score = minimax(minmaxBoard, depth + 1, True)
minTarget = min(score, minTarget)
return minTarget
#The computer uses this function to make its move
def computedMove():
computedTarget = minusInf
for n in range(boardSize):
for m in range(boardSize):
newBoard = board.copy()
if newBoard[n][m] == '0':
newBoard[n][m] = ai
score = minimax(newBoard, 0, False)
if score > computedTarget:
computedTarget = score
move = (n,m)
board[move[0]][move[1]] = ai
# Getting input for the player's move
def getPlayerMove():
res = input('Please type in your move on the form \"x y\", x being the number of the column and y the number of the row of your choosing.\n')
col, row = res.split(" ")
row = int(row)
col = int(col)
move = (row, col)
return move
# Drawing the board
def drawBoard():
for n in range(boardSize):
for m in range(boardSize):
if board[n][m] == '0':
print(' - ', end='')
else:
print(' '+board[n][m]+' ', end='')
print('\n')
# Current state of the game, False at first
playing = False
#The game loop
while True:
currentPlayer = person
boardSize = int(input("Please enter the size of the board. (one sie)\n"))
board = [['0']*boardSize]*boardSize
print("You go first.")
playing = True
while playing:
if currentPlayer == person:
drawBoard()
move = getPlayerMove()
playerMove(move[0]-1, move[1]-1)
if checkWinner(board) == person:
drawBoard()
print("Yaay, you won!")
playing = False
else:
if checkWinner(board) == 'tie':
drawBoard()
print('It\'s a tie!')
break
else:
currentPlayer = ai
if currentPlayer == ai:
computedMove()
if checkWinner(board) == ai:
drawBoard()
print('You lose!')
playing = False
else:
if checkWinner(board) == 'tie':
drawBoard()
print('It\'s a tie!')
break
else:
currentPlayer = person
if not input('Do you want to play again?').lower().startswith('y'):
break
Check out this statement:
board = [['0']*boardSize]*boardSize
You're essentially creating a list of references to the same list boardSize times. That's why when you're assigning something to board[i][j] element, it gets assigned to j-th elements of all rows (from board[0] to board[len(board)]), because all rows are referencing the same list.
Use this instead:
board = [['0'] * boardSize for _ in range(boardSize)]
There are other issues with this code though. I'm sure you're decrementing your (x, y) indexes multiple times, for example. I didn't check it further.
I'm currently working on my Programming Fundamentals w/ Python final project which is a collection of small games. I'm trying to make the game "High Card", where 2 random numbers between 1 & 13(the face values of a 52 card deck) are generated, then compared for the higher number and a winner is displayed.
We are required to have seperate files for the Class and Program code. This is what my Class looks like.
import random
class card:
def __init__(self, value):
self.card_value = value
def deal(self):
numb = random.randrange(1, 13)
def set_value(self, value):
self.card_value = value
def get_value(self):
return self.card_value
def find_face_value(self, numb):
#face = 'test'
print(numb)
if numb == 1:
print("numb == 1")
return 'Ace'
elif numb == 2:
return 'two'
## elif numb == 3:
## face = 'three'
## elif numb == 4:
## face = 'four'
## elif numb == 5:
## face = 'five'
## elif numb == 6:
## face = 'six'
## elif numb == 7:
## face = 'seven'
## elif numb == 8:
## face = 'eight'
## elif numb == 9:
## face = 'nine'
## elif numb == 10:
## face = 'ten'
## elif numb == 11:
## face = 'jack'
## elif numb == 12:
## face = 'queen'
## elif numb == 13:
## face = 'king'
#return face
def __str__(self):
return 'Numeric Value: ' + str(self.card_value)
I've commented out those (if numb == ...) statements b/c I am testing to see if I can get one correct return.
And Here is my Program code for the game.
def high_card():
#player1_card = cardClass.card(random.randrange(1, 13))
player1_card = cardClass.card(1)
player2_card = cardClass.card(2)
card1 = player1_card.find_face_value(player1_card)
#player2_card = cardClass.card(random.randrange(1, 13))
card2 = player2_card.find_face_value(player2_card)
print('Player 1 got', card1, player1_card, '\nPlayer 2 got', card2, player2_card)
And this is the output I recieve when I run the high_card() function.
>>> high_card()
Numeric Value: 1
Numeric Value: 2
Player 1 got None Numeric Value: 1
Player 2 got None Numeric Value: 2
My problem is in the last 2 lines of the output. It should say "Player 1 got Ace Numeric Value: 1" and "Player 2 got two Numeric Value: 2". I need the find_face_value function in my class to return a string of the "face" of a card. Instead, Python is printing "None", implying that I did not return anything inside the find_face_value function. I'm stumped on what to do to get this working and would greatly appreciate some help.
card1 = player1_card.find_face_value(player1_card)
In the statement above, numb is neither 1 nor 2. numb is a card class (you assigned numb=player1_card). So those if statements inside find_face_value are both false, thus return values are skipped. Python returns None by default. You have to check self.card_value inside if statements, instead of checking numb.
def find_face_value(self):
if self.card_value == 1:
print("card value is 1")
return 'Ace'
elif self.card_value == 2:
return 'two'
card1 = player1_card.find_face_value()
print(card1)
the statement above should print 'Ace'.
I am converting an array into a string to print, but the compiler still says not iterable.
Traceback (most recent call last):
File "python", line 157, in <module>
File "python", line 56, in total
TypeError: 'int' object is not iterable
The function total() is located on line 56, if you think it is the problem, but if you run the script, you should find that the function works properly every other instance.
import random
import time
def makeDeck():
cards = []
num = 1
for card in range(52):
cards.append(num)
num += 1
if num == 13:
num = 1
return cards
#def shuffle(cards):
#for card in cards:
#num = random.randint(0,51)
#cards.insert(0, cards[num])
#return cards
def shuffle(deck):
for card in deck:
hold = deck.pop(0)
deck.insert(random.randint(1,51),hold)
return deck
def cardToString(hand):
cardString = []
for card in hand:
if card == 1:
cardString.append('Ace')
elif card == 11:
cardString.append('Jack')
elif card == 12:
cardString.append('Queen')
elif card == 13:
cardString.append('King')
else:
cardString.append(str(card))
for card in cardString:
return card
def deal(user,deck):
hand = []
for x in range(2):
hand.append(deck.pop(0))
return hand
def deal1(user,deck):
hand = []
for card in deck:
hand.append(deck.pop(0))
return hand
def total(hand):
score = 0
for card in hand:
if(card>10):
score += 10
elif(card != 1):
score += card
else:
if(score>=11):
score+=1
else:
score+=11
return score
#def playGame():
#to do
name1 = input('Player 1, please enter your name:\n')
p2q = input('Will there be two plaers? (y/n)')
if(p2q == 'y' or p2q == 'Y' ):
p2yn = 1
name2 = input('Player 2, please enter your name:\n')
elif(p2q == 'n' or p2q == 'N'):
p2yn = 0
deck = makeDeck()
shuffle(deck)
p1hand = deal(name1,deck)
if(p2yn == 1):
p2hand = deal(name2,deck)
else:
print(end = ' ')
hs=0
print(str(name1)+', your hand is:', end = ' ' )
cardToString(p1hand)
print(str(p1hand[0])+',',p1hand[1], end = ' ')
print('and your total is', total(p1hand))
time.sleep(2)
tot1 = total(p1hand)
while(tot1 < 21):
p1cvar = input('Would you like another card? (y/n)\n')
if(p1cvar =='n' or p1cvar == 'N'):
break
else:
p1hand.append(deck.pop(0))
newCard = str(p1hand[-1])
cardToString(newCard)
print('You got a', newCard)
time.sleep(1)
print('Your total is now', total(p1hand))
time.sleep(1)
if(total(p1hand) <= 21):
hs = total(p1hand)
else:
print('You went over 21!')
p1hand=0
time.sleep(1)
break
if(p1hand != 0):
print('The high score is', total(p1hand), 'held by', str(name1)+'.')
time.sleep(1)
shuffle(deck)
if(p2yn == 1):
print(str(name2)+', your hand is:', end = ' ' )
cardToString(p2hand)
print(str(p2hand[0])+',',p2hand[1], end = ' ')
print('and your total is', total(p2hand))
time.sleep(2)
tot1 = total(p2hand)
while(tot1 < 21):
p2cvar = input('Would you like another card? (y/n)\n')
if(p2cvar =='n' or p2cvar == 'N'):
break
else:
p2hand.append(deck.pop(0))
newCard = str(p2hand[-1])
cardToString(newCard)
print('You got a', newCard)
time.sleep(1)
print('Your total is now', total(p2hand))
time.sleep(1)
if(total(p2hand)>21):
print('You went over 21!')
p2hand=0
time.sleep(1)
break
if(p2hand != 0 and total(p2hand)>hs):
print('The high score is', total(p2hand), 'held by', str(name2)+'.')
hs = total(p2hand)
time.sleep(1)
dealerHand = deal('Dealer',deck)
print("The dealer's hand is:", end = ' ' )
cardToString(dealerHand)
print(str(dealerHand[0])+',',dealerHand[1], end = ' ')
print('and their total is', total(dealerHand))
time.sleep(2)
totD = total(dealerHand)
while(totD < 21):
tdh = total(dealerHand)
if(tdh<hs and tdh<22):
dealerHand.append(deck.pop(0))
newCard = str(dealerHand[-1])
cardToString(newCard)
print('Dealer got a', newCard)
time.sleep(.5)
print("Dealer's total is now", total(dealerHand))
time.sleep(1)
if(total(dealerHand) <= 21 and total(dealerHand)>hs):
hs = total(dealerHand)
else:
print('Dealer went over 21!')
dealerHand=0
else:
break
if(dealerHand != 0):
print('The high score is', total(dealerHand), 'held by', str("Dealer")+'.')
while(total(p1hand)>21 or total(dealerHand)>21):
if(total(dealerHand)>21):
print('Dealer has been eliminated from play!')
elif(total(p1hand)>21):
print(name1,'has been eliminated from play!')
About 11 lines up from the bottom of your code block, you are setting the dealers hand to 0:
....
else:
print('Dealer went over 21!')
dealerHand=0
This is concerning since their hand should be a list. Thus when you try to iterate over it to count the total, you get that an int isn't iteratable.
Should probably be something like
dealerHand = []
Also, a few lines after that, you are asking if dealerHand!=0, when I think you mean total(dealerHand)
You should also be careful with your other assignments that change a variable from a list to an int such as
#Around line 111
print('You went over 21!')
p1hand=0
time.sleep(1)
break
.....
#Around line 140
print('You went over 21!')
p2hand=0
time.sleep(1)
break
Because Python is not strongly type, changing the type of a given variable name can lead to a lot of these kinds of problems
#Stephen gave you the direct answer. I suggest using pylint3 (or some other linter) on your code. It would have told you the problem
R:170, 6: Redefinition of dealerHand type from list to int
(redefined-variable-type)
This will help you in the future.
I'm building out Battleships game in Python. I have a list and I'm trying to build a validation tool in Python to catch user inputs that are outside the 10x10 range of my list.
Here is the code:
from random import randint
player = "User"
board = []
board_size = 10
ships = {"Aircraft Carrier":5,
"Battleship":4,
"Submarine":3,
"Destroyer":3,
"Patrol Boat":2}
def print_board(player, board): # to print joined board
print("Here is " + player + "'s board")
for row in board:
print(" ".join(row))
def switch_user(player): # to switch users
if player == "User":
player = "Computer"
elif player == "Computer":
player = "User"
else:
print("Error with user switching")
for x in range(0, board_size): # to create a board
board.append(["O"] * board_size)
print_board(player,board)
def random_row(board): # generate random row
return randint(0, len(board) - 1)
def random_col(board): # generate random column
return randint(0, len(board[0]) - 1)
def user_places_ships(board, ships): # user choses to place its ships by providing starting co-ordinate and direction.
for ship in ships:
valid = False
while(not valid):
user_input_coordinates = input("Please enter row & column number for your " + str(ship) + ", which is " + str(ships[ship]) + "-cells long (row, column).")
ship_row, ship_col = user_input_coordinates.split(",")
ship_row = int(ship_row)
ship_col = int(ship_col)
user_input_dir = input("Please enter direction for your " + str(ship) + ", which is " + str(ships[ship]) + "-cells long (h for horizontal or v for vertical).")
valid = validate_coordinates(board, ships[ship], ship_row, ship_col, user_input_dir)
if not valid:
print("The ship coordinates either outside of" , board_size, "X" , board_size, "range, overlap with or too close to another ship.")
place_ship(board, ships[ship], ship_row, ship_col, user_input_dir)
print("You have finished placing all your ships.")
def validate_coordinates(board, ship_len, row, col, dir): # validates if the co-ordinates entered by a player are within the board and don't overlap with other ships
if dir == "h" or dir == "H":
for x in range(ship_len):
if row-1 > board_size or col-1+x > board_size:
return False
elif row-1 < 0 or col-1+x < 0:
return False
elif board[row-1][col-1+x] == "S":
return False
elif dir == "v" or dir == "V":
for x in range(ship_len):
if row-1+x > board_size or col-1 > board_size:
return False
elif row-1+x < 0 or col-1 < 0:
return False
elif board[row-1+x][col-1] == "S":
return False
return True
def place_ship(board, ship_len, row, col, dir): # to actually place ships and mark them as "S"
if dir == "h" or dir == "H":
for x in range(ship_len):
board[row-1][col-1+x] = "S"
elif dir == "v" or dir == "V":
for x in range(ship_len):
board[row-1+x][col-1] = "S"
else:
print("Error with direction.")
print_board(player,board)
user_places_ships(board,ships)
If a user enters "10,10" for ship coordinates and "h" for horizontal direction, then Python generates the following error message:
Traceback (most recent call last): File "C:/Users/Elchin's PC/Downloads/battleships game.py", line 85, in <module>
user_places_ships(board,ships) File "C:/Users/Elchin's PC/Downloads/battleships game.py", line 49, in user_places_ships
valid = validate_coordinates(board, ships[ship], ship_row, ship_col, user_input_dir) File "C:/Users/Elchin's PC/Downloads/battleships game.py", line 62, in validate_coordinates
elif board[row-1][col-1+x] == "S": IndexError: list index out of range
I know that the error is in this line:
elif board[row-1][col-1+x] == "S":
return False
But I don't know how to fix it. Could you please help me figure out the solution?
If a list has length n, you can access indices from 0 to n-1 (both inclusive).
Your if statements however check:
if row-1+x > board_size or col-1 > board_size: # greater than n
return False
elif row-1+x < 0 or col-1 < 0: # less than 0
return False
elif board[row-1+x][col-1] == "S":
return False
So as a result, if we reach the last elif part, we have guarantees that the indices are 0 < i <= n. But these should be 0 < i < n.
So you should change the first if statement to:
if row-1+x >= board_size or col-1 >= board_size: # greater than or equal n
return False
elif row-1+x < 0 or col-1 < 0: # less than 0
return False
elif board[row-1+x][col-1] == "S":
return False
You can make the code more elegant by writing:
if not (0 < row-1+x < board_size and 0 < col-1 < board_size) or \
board[row-1+x][col-1] == "S":
return False