Saturday, October 24, 2009

Programming Challenge 1 - Mow the Lawn - Results

There were three projects submitted.  One by a brand new .Net developer, Brandon, one by a C#/Flash developer, Kyle, and another one by myself.

This programming challenge presented some common problems that had to be over come like how store the grass, the position of the lawnmower, and what the grass should be after it has mowed.  Some solutions for these problems were extremely similar and others were surprisingly different.

Brandon’s code was the shortest and the simplest taking around 120 lines of code.  He used a two dimensional char array to store the lawn and class level variables to store the position of the lawn mower, and what the grass under the mower is.  This is his code to handle the move with the other 3 directions taken out.

private void MowerForm_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Down:
if (MowerY < 9)
{
grassArray[MowerY, MowerX] = underMower;
MowerY++;
checkCutStatus();
}
break;
}
PrintGrass();

if (numcut == 100)
MessageBox.Show("The lawn is mowed!! Daryl's mom is lathered up and waiting to congratulate you inside!");

}


It’s very simple, first checking to be able to move in that direction and then updating the lawn under the mower, and moving the mower.  His checkCutStatus() would then update underMower, and place the mower at the new location.  Pretty simple but I would also add an else to the if, that had a return statement.  That way if you couldn’t move, you wouldn’t reprint the grass.  Whenever a piece of grass goes from medium to short, the numcut get incremented and once all 100 are cut, the congratulations message gets displayed.  I would suggest at least making it a class level constant for the 100 and the 9.  It makes it easier to update and (numcut == AllGrass) makes more sense then (numcut == 100).



Kyle’s code was the second shortest.  He also used a two dimensional array but he created a Grass class that kept track of the grass type, Label, and whether it had been marked as counted.  Below is his move function. 



protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
switch (keyData)
{
case Keys.Right:
if (mower_location.X < lawn_width - 1)
{
mower_location.X += 1;
update_grass();
}
break;
}
return true;
}



update_grass() keeps track of the old mower position and handles cutting the grass, moving the lawn mower, and keeping track of the previous position.  One of the more unique aspects of Kyle’s program is that rather than having one label with 100 squares, he has 100 labels.  This makes it easier and quicker to update since only the text that gets changed needs to be updated.  Brandon and my solution requires the entire 100 squares to be redrawn.



My code was the longest, and with the most extra classes, but since I knew what the next programming challenge would be, I thought it would be worth it to add that additional complexity.  Instead of using a 2 dimensional array, I used an array of an array incase I wanted the yard to not be square. Below is my move function.



private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Down:
case Keys.Up:
case Keys.Left:
case Keys.Right:
if (Lawn.Move(Mower, GetDirection(e.KeyCode)))
{
lblLawn.Text = Lawn.ToString();

if (DisplayMessage && Lawn.IsMowed)
{
MessageBox.Show("Have a Lemonade, you're finished!");
DisplayMessage = false;
}
}
break;

default:
break;
}
e.Handled = true;
}



I actually pulled out the lawn logic out of my main form in an effort to make it more MVC-ish.  The Lawn.Move() returns true if the object that is attempted to be moved, was move.  Similar to Brandon’s counting of cut grass, the Lawn class keeps track of the grass left uncut, and encapsulates it with the IsMowed property.  The main work of moving the mower around is handled in Lawn.Move().



public static bool Move(LawnBase obj, Direction direction)
{
if (!obj.IsMovable) { return false; }

LawnBase nextObject = GetObjectInDirection(obj, direction);

if (nextObject == null || !nextObject.CanMoveOver) { return false; }

var mobileObject = ((MoveableLawnBase)obj);
_lawn[obj.Row][obj.Column] = mobileObject.GroundBeneath;
mobileObject.Move(direction, nextObject);
DecrementGrassCount(nextObject, mobileObject.GroundBeneath);
_lawn[obj.Row][obj.Column] = obj;

return true;
}


There are some additional checks to see if an object can be moved over, so later if we add more objects to our yard, they’ll be able to interact nicely.



Feel free to comment:

Monday, October 12, 2009

Programming Challenge 1 - Mow the Lawn

A friend of mine has just switched from developing in COBALT, to C#. As a fun way to help him learn C# and to argue over better methods of programming, we decided to make little programming challenges that were designed to be short, simple and fun. This contest is open to anyone, just feel free to e-mail me your zipped project solution and I'll post it and comment on it.

So here goes the first challenge:
Write a winform ASCII lawn mowing application with these properties:
  • It should start with a 10x10 grid of capital "X"'s.
  • The lawn mower should be represented by an "@" symbol, and start in the upper left hand corner.
  • The user should be able to use the arrow keys to move the lawnmower around the lawn.
  • The first time the lawn mower passes over an X, it gets converted to a lower case "v".
  • When the lawn mower passes over a "v", it gets converted to a ".".
  • When the entire lawn has been reduced to "."'s a message should be displayed to the user.

Good luck and happy mowing!

* Legal Notice * These Programming Challenges shall not be reproduced in any form without my express written consent.