#๐ Homework Help
428 messages ยท Page 1 of 1 (latest)
@high marlin
Remember to:
- Ask your Python question, not if you can ask or if there's an expert who can help.
- Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
- Explain what you expect to happen and what actually happens.
:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.
Ugh let's try this again
I'm having trouble with this code identifying the Kings position (marked by a lowercase k) and I tried to make a sub-function to do it for me, but no matter where I put it, it doesn't work
.Q..kb.r
p..n.ppp
....q...
....p.B.
........
........
PPP..PPP
..KR....
Here's the txt file being used
I know this is a lot but the person helping me disappeared and I honestly have no idea what to do
wdym doesn't work?
which function identifies the king's position?
can't help fully rn but fyi don't test types like == None and == str. use is None and isinstnace(obj, str), respectively
OK I see the problem
def find_king_coords(x, y, board, height, width, King_Position):
for y in range(height):
for x in range(width):
if board [y][x] == "k":
return King_Position == (x, y)
When you do this: King_Position == (x, y), it returns True or False
If you're supposed to get the coordinates of the king, you should return x, y
try something like x = board[y][x] and play with x
not do a comparison
how i work with dataframes anyhow
also, not sure about that double loop and coordinate in board[y][x], whereas the return of the King position is (x, y)
Okay then, so after I fix that ( I just did) should I update the final function to do this?
def bk_in_check(board):
height = len(board)
width = len(board[0])
King_Position = None
for y in range(height):
for x in range(width):
King_Position = find_king_coords(x, y, board, height, width, King_Position)
if board[y][x] == None:
pass
elif board[y][x] == str:
if check_path(board, x , y , height, width, King_Position):
return True
else:
pass
Because if I call it before the loop I get an error
Oh I should probably
def find_king_coords(x, y, board, height, width, King_Position):
for y in range(height):
for x in range(width):
if board [y][x] == "k":
return (x, y)
What's the error?
Yep. BTW, you don't need the brackets.
I assume because you don't need the x, y in the function parameters
Also, this: elif board[y][x] == str: If you want to know if there is a string in that position you want:
elif isinstance(board[y][x], str):
It won't be ==str because that will compare its value (some string like "k") with the type str. Never equal ๐
line 184, in bk_in_check
find_king_coords(x, y, board, height, width)
^
UnboundLocalError: cannot access local variable 'x' where it is not associated with a value
Yea that's what I thought
Possibly but also not really
Also
You probably just need to remove x and y from both the find_king_coords function call and the function find_king_coords parameters
Oh Mkay
Ill try that
Nope
It just gives me the wrong response
Still saying the Black King isn't in check
Wdym wrong response?
^
The Black King is clearly in check
It's running the else incase it's not in check
Black king is k, correct?
Ok
Lemme try something
Yea nvm
I was gonna try and have the function print the King Position somewhere
But it doesn't want to
AH
Got it
Yea so
It's not changing the value of King_position
Okay now it is
But it's still not...working
Okay think I found the issue
I tried also making the function report what position the Queen was checking
It never reported back
Which I think means that
The function isn't being called
So it is either a problem with
The value being returned by check_path
Or
elif board[y][x] == str:
if check_path(board, x , y , height, width, King_Position):
return True
else:
pass
This isn't being called
Welp
Looks like I was right
I changed it to
elif board[y][x]:
if check_path(board, x , y , height, width, King_Position):
return True
else:
pass
And immediately got
in check_path
if check_by_queen(x, y, King_Position):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: check_by_queen() missing 3 required positional arguments: 'board', 'height', and 'width'
Same error on check_path
Sounds like check_by_queen wants 6 parameters and you only supplied 3.
"missing 3 required positional arguments: 'board', 'height', and 'width'
"
HAHA
Now lemme test this some more
Okay so
On the grading script it got one failure
I think I did something wrong with the Rooks code
Weird
The grading script doesn't get an error
But when I put the test file in myself
I get an index error
But I get
if board[y][x] == None:
~~~~~~~~^^^
IndexError: list index out of range
This means that x or y is too big. (BTW, you want is None, not == None.)
Put a:
print("x =", x, "y =", y)
just before this line. At least you'll see what they are, which leads toward the problem.
Looks like the testing script expects all your indents to be by 4 spaces.
I know about the styling stuff
I save that for last
Wanna get the code functioning before it looks ncie ya know
*nice
Agreed.
Okay so found it
It's going to an index of 8 for some reason
When the highest it goes is 7
Which is
Weird to say the least
The loop shouldn't make that possible
And considering the rest of the tests don't do it either..
Might you be passing x+1 or similar when checking for adjacent cells? So at x == 7 you might do some test against x=8
Maybe. Derpends on the tests.
def bk_in_check(board):
height = len(board)
width = len(board[0])
King_Position = None
King_Position = find_king_coords(board, height, width, King_Position)
for y in range(height):
for x in range(width):
print("x =", x, "y =", y)
if board[y][x] is None:
pass
elif board[y][x]:
if check_path(board, x , y , height, width, King_Position):
return True
else:
pass
There should be nothing here causing that either
I'll check a subfunction rq
But's whats weird I notice
Is
It goes through EVERY row first
It gets through every row
And THEN manages to get the error
So it should be done checking by then
It was definitely this line?
if board[y][x] is None
?
I guess you're seeing an 8, so it must be.
Add from pprint import pprint to the top of your script.
The after that print() above, add:
pprint(board)
Obviously x seems wrong. better check that the board is actually the shape you expect.
... and print height and width.
Yes
Okay
Printed
x = 8 y = 7
[[None, None, 'R', None, None, None, 'k', None, '\n'],
['p', 'b', None, None, 'r', 'p', 'p', None, '\n'],
[None, 'p', None, 'p', None, 'n', None, 'p', '\n'],
[None, 'Q', None, 'p', None, 'q', None, None, '\n'],
[None, None, None, 'P', None, None, None, None, '\n'],
['P', None, None, 'N', None, None, 'P', None, '\n'],
[None, 'P', None, None, 'P', 'P', 'B', 'P', '\n'],
[None, None, None, None, 'R', None, 'K', None]]
I don't see anything wrong persay..
And width?
And it's only THIS board
You don't modify x or width anywhere in this function?
Odd that it gets to y=7 before x=8. Should have failed for y=0 also. You'd think.
Okay so uh
Called Height and Width
x = 8 y = 7
width is 9 height is 8
Huh???
Fuck you mean Nine????
No no I mean
Oh.
It's clearly an 8 x 8
You've got '\n' !!! You built this from reading a text file?
Show the code for that bit pls?
I just copy and pasted the txt file from the testing script
Right. But your program must read it in, yes?
No? Where's board come from?
x = 1 y = 0
width is 9 height is 8
[[None, 'Q', None, None, 'k', 'b', None, 'r', '\n'],
['p', None, None, 'n', None, 'p', 'p', 'p', '\n'],
[None, None, None, None, 'q', None, None, None, '\n'],
[None, None, None, None, 'p', None, 'B', None, '\n'],
[None, None, None, None, None, None, None, None, '\n'],
[None, None, None, None, None, None, None, None, '\n'],
['P', 'P', 'P', None, None, 'P', 'P', 'P', '\n'],
[None, None, 'K', 'R', None, None, None, None, '\n']]
This is the first test I was doing
So what do I do then?
Something must load values into the board list-of-lists. What does that?
Lemme get it
'''py
Ffs
Im dumb
def read_board(filename):
board = []
f = open(filename, 'r')
for line in f:
row = []
for ch in line:
if ch == '.':
row.append(None)
else:
row.append(ch)
board.append(row)
f.close()
return board
There
Also
board = read_board("chess.txt")
Yeah. You want for ch in line.rstrip(). When you read lines of text from a text file, the trailing newline is included in the line. And you've thus included that newline in the board lists.
So
So line.rstrip() removes trailing whitespace from line, which is the newline in this case.
Just add that to
for ch in line.rstrip()
for line in f:
?
Like that
I forgot the colon
But you get my point
Swap the code lines. But yes. strip the line.
Show new code. Show pprint(board).
def read_board(filename):
board = []
f = open(filename, 'r')
for line in f:
for ch in line.rstrip():
row = []
for ch in line:
if ch == '.':
row.append(None)
else:
row.append(ch)
board.append(row)
f.close()
return board
And
[[None, None, 'R', None, None, None, 'k', None, '\n'],
[None, None, 'R', None, None, None, 'k', None, '\n'],
[None, None, 'R', None, None, None, 'k', None, '\n'],
[None, None, 'R', None, None, None, 'k', None, '\n'],
[None, None, 'R', None, None, None, 'k', None, '\n'],
[None, None, 'R', None, None, None, 'k', None, '\n'],
[None, None, 'R', None, None, None, 'k', None, '\n'],
[None, None, 'R', None, None, None, 'k', None, '\n']]
Still the newlines. You did save the file and reload the board etc?
It should not be possible to have newlines if the rstrip() is there.
Are you sure that's the right code you gave me?
Is this a script, or something like a Jupyter file?
A script
Hey, why the 2 for loops?
for ch in line.rstrip():
row = []
for ch in line:
Move the upper for ch... to replace the lower for ch....
The lower for ch is iterating over the unstripped string, as before, thus the newlines.
You had this before:
def read_board(filename):
board = []
f = open(filename, 'r')
for line in f:
row = []
for ch in line:
if ch == '.':
row.append(None)
else:
row.append(ch)
board.append(row)
f.close()
return board
I wanted you to change: for ch in line:
into: for ch in line.rstrip():
Show updated code. Show pprint(board).
And doing that
width is 8 height is 8
[[None, None, 'R', None, None, None, 'k', None],
['p', 'b', None, None, 'r', 'p', 'p', None],
[None, 'p', None, 'p', None, 'n', None, 'p'],
[None, 'Q', None, 'p', None, 'q', None, None],
[None, None, None, 'P', None, None, None, None],
['P', None, None, 'N', None, None, 'P', None],
[None, 'P', None, None, 'P', 'P', 'B', 'P'],
[None, None, None, None, 'R', None, 'K', None]]
There
But the issue is still there
The rook is not recognizing the King
No
No
No
The width value comes the width variable
Not x
Its the len of x
Well not
Its
width = len(board[0])
Anyways I still have my issue
Yeah, and that was 9 when you had your IndexError. And now it should be 8.
The ROOK is still not recognizing the King as being in check
Yes, and it still isn't fixed
I still get
"Black king is not in check."
Still getting the indexError?
No it just won't recognize the King as being in check
When it clearly is
..R...k.
That is check
Then you need to show the code which checks the rook check stuff/
And it doesn't see it somehow
That is indeed check.
def check_by_rook(x, y, King_Position, board, height, width):
moving_x = x
moving_y = y
while moving_x > 0:
moving_x -= 1
if (moving_x, y) == King_Position:
return True
if board[y][moving_x]:
break
while moving_x < width - 1:
moving_x += 1
if (moving_x, y) == King_Position:
return True
if board[y][moving_x]:
break
while moving_y > 0:
moving_y -= 1
if (x, moving_y) == King_Position:
return True
if board[moving_y][x]:
break
while moving_y < height - 1:
moving_y += 1
if (x, moving_y) == King_Position:
return True
if board[moving_y][x]:
break
return False
There
That's the sub function to check the Rooks surroundings
Are (x,y) the position of the rook?
So this scans left, then right, then up, then down?
Their movement is tracked the same
Yes
Idk why it's not returning a True value
I can show the Queens function too
Because I know it's always working
It never failed its tests
Ah. You need to reset moving_x = x after the first moving_x loop. And reset moving_y = y after the first moving_y loop.
Because these loops change moxing_x or moving_y.
Nor did the bishop
In that case, how do I do that then?
Testing can show the presence of bugs, but not their absence.
Wait but
This issue didn't exist when the Queen was in the same position
To the left of the King
It got a check
And the Queen
Is just my code
Copy and Pasted
Seaparet function to test the queen stuff? Go look at it.
From the Bishop and Rook
I checked I have the script open
All Queen tests passed
Including diagonal, horizontal, and verticals
As an example, this code:
moving_x = x
moving_y = y
while moving_x > 0:
moving_x -= 1
if (moving_x, y) == King_Position:
return True
if board[y][moving_x]:
break
while moving_x < width - 1:
moving_x += 1
if (moving_x, y) == King_Position:
return True
if board[y][moving_x]:
break
This scans left. Then when it scans right, it starts the scan where it stopped the scan in the loop before. Not starting from x.
Then why isn't the Queen failing???
I have her check up, down, left, and right first
No idea. Again: show the code.
It is very dependent on the board being tested.
def check_by_queen(x, y, King_Position, board, height, width):
moving_x = x
moving_y = y
while moving_x > 0 and moving_y > 0:
moving_x -= 1
moving_y -= 1
if (moving_x, moving_y) == King_Position:
return True
if board[moving_y][moving_x]:
break
while moving_x < width - 1 and moving_y < height - 1:
moving_x += 1
moving_y += 1
if (moving_x, moving_y) == King_Position:
return True
if board[moving_y][moving_x]:
break
while moving_y > 0 and moving_x < width - 1:
moving_y -= 1
moving_x += 1
if (moving_x, moving_y) == King_Position:
return True
if board[moving_y][moving_x]:
break
while moving_y < height - 1 and moving_x > 0:
moving_y += 1
moving_x -= 1
if (moving_x, moving_y) == King_Position:
return True
if board[moving_y][moving_x]:
break
while moving_x > 0:
moving_x -= 1
if (moving_x, y) == King_Position:
return True
if board[y][moving_x]:
break
while moving_x < width - 1:
moving_x += 1
if (moving_x, y) == King_Position:
return True
if board[y][moving_x]:
break
while moving_y > 0:
moving_y -= 1
if (x, moving_y) == King_Position:
return True
if board[moving_y][x]:
break
while moving_y < height - 1:
moving_y += 1
if (x, moving_y) == King_Position:
return True
if board[moving_y][x]:
break
I put the original board at the top too
Passed that as well
Top of the thread
You can see it's just the rooks code
This has the same bugs. You need to reset moving_x and moving_y befor each loop so that they start from the correct position (the position of the queen. Or the rook.)
And then the diagonal movement I stole from the Bishop
It obviously doesn't have the same bug
It's not failing
It always puts the King in check
When its to the left or right
If it finds the king in the first loop, the bug for the second loop does not affect the outcome. Come on, think about this.
Need to go AFK.
Then how is the Queen able to pass the Diagonal test???
It shouldn't be able to
Because it's moving coords should be ruined
And yet a perfect test
Every time
And JUST in case I still don't convince ya
I will show every board for the Queen tests
rnbQk..r
ppp..pb.
.....n.p
....p.p.
....P...
..N..P..
PPP.N.PP
R.B.KB.R
r....rk.
.pp..p.p
..n..p..
pq..p...
....P.Q.
P.BP..P.
.....PKP
..R..R..
..r.....
.b..ppk.
.qn...pp
..pp....
.p..N...
.P.PP.P.
R.P..PBP
Q.....K.
.....bk.
...R.Qp.
.p..p..p
.P......
.q.p..P.
........
....PP.P
..r..BK.
r....r..
..p..k..
.p.p.Qp.
p......p
..P....P
......P.
PP...PK.
...R.R..
As you can see, the king is only horizontal to the Queen ONCE
Not to mention
........
R....k..
..P.....
.P..r.p.
.K......
........
....b..P
........
This is the first Rook test
Which PASSES
A rook
To the left of the king
Just like this test
It either has to be the Y value
Which should come SECOND in the code
As the X value gets changed first
Or
I don't know
If anyone else may be willing to interject, please do
It's 1 AM and I'm beginning to go hungry
A rook to the left is the first loop. That loop works.
Have you a test for the rook to the right of the king?
I might have left and right swapped in my head here.
Okay
Did the test that wasn't working
Swapped the Rook and King
Bingo
Works fine
Swap em back
Aaaand
Loud incorrect buzzer
Right.
So idk what this thing wants
Was it King left of rook which worked?
Yes
Yeah. That is the first loop.
This
This passes fine
So think about the second case, rook right of king.
With this code:
moving_x = x
moving_y = y
while moving_x > 0:
moving_x -= 1
if (moving_x, y) == King_Position:
return True
if board[y][moving_x]:
break
while moving_x < width - 1:
moving_x += 1
if (moving_x, y) == King_Position:
return True
if board[y][moving_x]:
break
With king to the left, the first loop finds it and we return True.
With king to the right, you need the second loop.
When you commence the second loop, what is the value in moving_x?
This the same scenaior
*scenario
A rook the left of the king
It is not
The X value
You just told me that king-left-of-rook passes and rook-left-of-king fails.
If you are right
This
Should not
Be able
To pass
Look at it
It is another Rook to the left
Passing the test
In broad daylight
Aye. But notice: in the test, the rook is at the left-most position. The first loop does nothing.
Which means it does not "damage" the value of moving_x.
Yes and the loop prevents itself from gaining values that cannot exist
Move the rook to position 1, not 0, and retry.
Sure it does.
We've got the rook-left-of-king failing, which is what we need to fix, yes?
Isn't that what
while moving_x > 0: and while moving_x < width - 1: does?
These should keep it going till it reaches its max value
Or min
The bug I'm trying to describe is that at the end of the first loop, if the scan-left did not find the king, we end up with moving_x==0.
Does that make ense? Ignoring everything else: just the value after the first loop.
Back up. Do you think this is true? That moving_x==0 after the first loop? Or not?
If the rook is left of the king, the scan-left first loop will not find the king, yes? So it runs all the way to the end, and moving_x==0.
Yea
Ok.
So: the scan-right. What positions on the board do you intend it to scan? Those from the right of the rook up to the king (or the end of the row)? or other positions?
To the right until it either
A. Finds a king
B. Finds a piece blocking it
C. Reaches the end of the board
Ok. So it should start the scan at x+1?
No.
moving_x += 1
It starts the scan at moving_x. Which you have just made 0.
Okay but
Not okay!
Yes.
That s why you need to reset moving_x = x before the second loop.
Not do that?
Like is there any way to reset that value back to x before the next loop?
So just put:
moving_x = x
just before the second loop.
Aight
You have the same problem with every single second loop, for moving_x or moving_y accordingly.
Better?
Yes
Have they taught you about the range() function?
Yea
Ok.
But briefly
I would write those loops using for and range.
Example:
for moving_x in range(x-1, -1, -1):
.......
and:
for moving_x in range(x+1, width, 1):
.......
The range(start,stop,step) function counts from start up to, but excluding, stop, in increments of step.
So to scan left we start from x-1, go to -1 (excluding -1 itself) in steps of -1.
To scan right we go from x+1 to width (excluding width itself) in steps of 1.
The for-loop sets moving_x and you don't need to assign to it directly at all, or increment/decrement it.
I see
I'll keep it in mind for the next time I gotta do something like this then
For now I'm gonna clean this up and finally eat something
Good.
This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.
๐ Homework Help