annabunches.net/_posts/technology/2011-07-06-project-treewars-how-to-write-bad-code.html

19 lines
6.0 KiB
HTML
Raw Normal View History

2016-04-11 22:01:00 +00:00
---
2016-05-04 18:41:25 +00:00
excerpt_separator: <br/>
category: technology
2016-04-11 22:01:00 +00:00
layout: post
title: 'Project TreeWars: How to write bad code'
date: '2011-07-06T08:00:00.000-04:00'
author: Anna Wiggins
tags:
- Programming
- C++
- TreeWars
- geometry
- math
modified_time: '2013-10-22T11:19:51.435-04:00'
blogger_id: tag:blogger.com,1999:blog-4209116010564764361.post-3638552600723441589
blogger_orig_url: http://www.stringofbits.net/2011/07/project-treewars-how-to-write-bad-code.html
---
The TreeWars project is a week and a half old (at the time of this writing). It's come a long way; in its current form, it actually looks pretty neat:<br/><br/><a href="http://stringofbits.files.wordpress.com/2011/07/treewars1.png"><img class="alignnone size-full wp-image-472" title="treewars1" src="http://stringofbits.files.wordpress.com/2011/07/treewars1.png" alt="" width="400" height="311" /></a><br/><br/>There are now stats, and hit points, and the basic gameplay mechanic is in place. I've also laid the groundwork for some more complex gameplay, as well. Of course, I haven't talked about gameplay all that much yet - we'll get to that at some point, I'm sure. But what I want to talk about right now is how to write bad code.<br/><br/>Bad code happens. Sometimes, when you're writing code, you will hit a stumbling block. Encounter a problem where the solution doesn't jump immediately to mind. And often, you'll look back on it later and say "what the hell was I thinking?" Well, here is an instructive example of that.<br/><br/>This blunder is actually pretty embarrassing; I really did know better, but that knowledge escaped me at the time. As you've probably noticed from the screenshot above, my program deals with drawing circles (called either 'nodes' or 'vertices'). If a user clicks to add a new node, my code has to check and see whether it will overlap with an existing node.<br/><br/>So, I had a function that answers the question "is there a node close enough to the point (x,y) that a new node there will overlap?" If you're good at geometry, you probably already see the <em>right</em> way to do it. But I bet you can't spot the <em>very very wrong</em> way!<br/><br/>My solution (and I stress that this is a really, really bad idea) was to create a 'bounding box' around each existing node, and a bounding box around the area that the new node would occupy, then do some complex logic to see whether the bounding boxes overlap. It looked like this (and if you're not a programmer, just note the general size and complexity of this code):<br/><br/>[sourcecode language="cpp" gutter="false" wraplines="false"]<br/>bool Graph::vertex_present(int x, int y, int size)<br/>{<br/>    int delta = size / 2;<br/> int x_min = x - delta;<br/> int x_max = x + delta;<br/> int y_min = y - delta;<br/> int y_max = y + delta;<br/><br/> for (list&lt;Vertex&gt;::iterator cursor = vertices.begin();<br/> cursor != vertices.end(); cursor++)<br/> {<br/> Vertex v = *(*cursor);<br/> if (((x_min &gt;= v.x_min &amp;&amp; x_min &lt;= v.x_max) &amp;&amp;<br/> ((y_min &gt;= v.y_min &amp;&amp; y_min &lt;= v.y_max) ||<br/> (y_max &gt;= v.y_min &amp;&amp; y_max &lt;= v.y_max))) ||<br/> ((x_max &gt;= v.x_min &amp;&amp; x_max &lt;= v.x_max) &amp;&amp;<br/>             ((y_min &gt;= v.y_min &amp;&amp; y_min &lt;= v.y_max) ||<br/> (y_max &gt;= v.y_min &amp;&amp; y_max &lt;= v.y_max))))<br/> {<br/> return true;<br/> }<br/> }<br/> return false;<br/>}<br/>[/sourcecode]<br/><br/>It's ugly, and hard to read, and I knew it felt like a hack when I wrote it. But at that moment, nothing better was coming to me. Now, for those of you who don't enjoy recreational geometry, here's the right way to do it: you know that the existing node is at (x1,y1) and that it has a radius of r1. The point you're checking is at (x2,y2) and the new node would have a radius of r2. So, all you do is get the distance between the two points (basic geometry, I could have googled "the distance formula" and about 8 billion websites would have popped up to tell me how much I fail here), and then compare that to r1 + r2. Like so:<br/><br/>[sourcecode language="cpp" gutter="false" wraplines="false"]<br/>bool vertex_present(int x, int y, int r)<br/>{<br/> for (list&lt;Vertex*&gt;::iterator cursor = vertices.begin();<br/> cursor != vertices.end(); cursor++)<br/> {<br/> float dy = y - v-&gt;y;<br/> float dx = x - v-&gt;x;<br/> if (sqrt(dy*dy +