HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMajor

Bush Wanderer - code intended for teaching

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
intendedwandererbushteachingforcode

Problem

I am teaching computing to an AS class and this was their assignment:


Bush Wanderer


Task 1


Create a 5x5 grid of hashes(#) where the player is an x on the
board


Prompt the player to move in either N, E, S or W direction and then
reprint the board to show the new position.


Example:

x # # # #
# # # # #
# # # # #
# # # # #
# # # # #
Which way would you like to move?(N,E,S or W)



Task 2



-
Ensure the player does not move off of the board

-
Place a hidden chest somewhere on the board at random

-
End the game when the chest is found

-
Tell the player how many moves it took to find the chest

-
Add a visible (but blind) dragon that can teleport around the board at random and will eat you and end your game if it gets you before

you get the chest


This was my exemplar solution at the end and I wanted to get some feedback on what the professional community thought of it. How could this be improved?

`import random

grid = 5

moves = 0

x = 0
y = 0

cx = random.randint(0,(grid-1))
cy = random.randint(0,(grid-1))

while(True):

dx = random.randint(0,(grid-1))
dy = random.randint(0,(grid-1))

for i in range(grid):
if i == dy and i == y:
for u in range(grid):
if u == dx:
print('@ ', end='')
elif u == x:
print('x ', end='')
else:
print('# ', end='')
print()
elif i == y:
print('# '*x, end="")
print('x ', end="")
print('# '*((grid-x)-1))
elif i == dy:
print('# '*dx, end="")
print('@ ', end="")
print('# '*((grid-dx)-1))
else:
for i in range(grid):
print('# ', end="")
print()

if dx == x and dy == y:
if moves == 1:
print('You died in', moves,'move!')
elif moves > 1 or moves == 0:
print('You died in', moves,'moves!')
break
elif cx == x and cy == y:
if moves == 1:
print('

Solution

Because the code you write is to be used for teaching, the importance is not on performance, but on correctness and readability and understandability (comphrensiveness?).

So basically...

-
Add comments! Explain each step, so that the kids are gonna see the code, think "what does it do", and they can read it right there!

-
Don't use dx and dy, use more explanatory variables!

Let's combine them:

if dx == x and dy == y:
    if moves == 1:
      print('You died in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You died in', moves,'moves!')
    break
  elif cx == x and cy == y:
    if moves == 1:
      print('You won in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You won in', moves,'moves!')
    break


This is hard to understand. dx and dy were hard to grasp at first - when doing games programming, usually dx and dy are "delta-x" and "delta-y", to calculate object velocity.

But it's dragon x y and chest x y here!

So just call it that.

if dragon_x == x and dragon_y == y:
    if moves == 1:
      print('You died in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You died in', moves,'moves!')
    break
  elif chest_x == x and chest_y == y:
    if moves == 1:
      print('You won in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You won in', moves,'moves!')
    break


Next, I'd usually tell you to split this up into functions. But maybe these kids don't know functions yet, and it's remarkably frustrating to be shown "the solution" when "the solution" consists of "this magic trick I didn't teach you yet, haha".

Use comments instead, and be sure to teach them what a comment is and what its for. If you have to review homework, a comment might be all you get to understand their code.

#check for loss by comparing dragon and player location
  if dragon_x == x and dragon_y == y:
    if moves == 1:
      print('You died in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You died in', moves,'moves!')
    break
  #else, check for victory by comparing chest and player location
  elif chest_x == x and chest_y == y:
    if moves == 1:
      print('You won in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You won in', moves,'moves!')
    break


Note that function names make good comments. Instead of checkForVictory() we just put #check for victory. I recommend you start comments with why, and then with how. How-comments should eventually be removed (you can read the code), and why-comments should stay, but when learning how to program, having the explanation next to the code just helps. It also promotes micro problem-solution flow (in my opinion), which is what you need later if you want to split up code into smaller chunks or problems.

And this loop here...

for i in range(grid):
      if i == dy and i == y:
        for u in range(grid):
          if u == dx:
            print('@ ', end='')
          elif u == x:
            print('x ', end='')
          else:
            print('# ', end='')
        print()
      elif i == y:
          print('# '*x, end="")
          print('x ', end="")
          print('# '*((grid-x)-1))
      elif i == dy:
          print('# '*dx, end="")
          print('@ ', end="")
          print('# '*((grid-dx)-1))
      else:  
        for i in range(grid):
          print('# ', end="")
        print()


Is mighty confusing. There is no easily discernible pattern to it. If you had to explain the thought process that went into each step, what would you say? (Teacher, I don't understand, how did you create this?)

Here's mine:

per tile:
  print dragon if dragon is on tile
  print player if player is on tile
  print empty tile if nobody is on tile


Those are the requirements, next up is realizing that if we have a grid, we ought to do it by row and columns:

for each row
  for each column
    if the dragon is on that tile
     print dragon
    else if the player is on that tile
     print player
    else
     print empty tile
  print new line, to go to next row


And then translate to python (untested)

for i in range(grid)
  for u in range(grid)
    if i == dragon_y and u == dragon_x:
     print('@ ', end='')
    elif i == player_y and u == player_x:
     print('x ', end='')
    else:
     print('# ', end='')
  print()


Another reason for this is that if you were to get a question like, "how do we add mountains, where the dragon can wander, but the player can't?", you'd be stumped. Or at least I would be, if I had to add mountains into your display code. It's all about clever tricks with multiplying strings. You'd have to alter ALL your cases. Or if there were two dragons, because, you know, hard mode. Again, it would take you a major overhaul.

I'd just make a simple change:

```
for each row
for each column
if there is a dragon on that tile
print dragon
else if the player is on that tile
print player

Code Snippets

if dx == x and dy == y:
    if moves == 1:
      print('You died in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You died in', moves,'moves!')
    break
  elif cx == x and cy == y:
    if moves == 1:
      print('You won in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You won in', moves,'moves!')
    break
if dragon_x == x and dragon_y == y:
    if moves == 1:
      print('You died in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You died in', moves,'moves!')
    break
  elif chest_x == x and chest_y == y:
    if moves == 1:
      print('You won in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You won in', moves,'moves!')
    break
#check for loss by comparing dragon and player location
  if dragon_x == x and dragon_y == y:
    if moves == 1:
      print('You died in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You died in', moves,'moves!')
    break
  #else, check for victory by comparing chest and player location
  elif chest_x == x and chest_y == y:
    if moves == 1:
      print('You won in', moves,'move!')
    elif moves > 1 or moves == 0:
      print('You won in', moves,'moves!')
    break
for i in range(grid):
      if i == dy and i == y:
        for u in range(grid):
          if u == dx:
            print('@ ', end='')
          elif u == x:
            print('x ', end='')
          else:
            print('# ', end='')
        print()
      elif i == y:
          print('# '*x, end="")
          print('x ', end="")
          print('# '*((grid-x)-1))
      elif i == dy:
          print('# '*dx, end="")
          print('@ ', end="")
          print('# '*((grid-dx)-1))
      else:  
        for i in range(grid):
          print('# ', end="")
        print()
per tile:
  print dragon if dragon is on tile
  print player if player is on tile
  print empty tile if nobody is on tile

Context

StackExchange Code Review Q#121196, answer score: 35

Revisions (0)

No revisions yet.