Some of you may have seem my thread on creating this game initially; in either case, I've decided to post it here for critique since it's my first "live" PHP application (I've built many in the past but only I use them personally). The good thing is that you don't need to configure any SQL databases! Yay! The bad thing is that you need to chmod (*nix) or change the security permisions of (Windows) gameData.txt so PHP can edit the file.
Let me know what you think!
P.S. Thanks to Leatherback for the CSS link code ;-)
bubblenut
07-10-2005, 09:40 AM
WOW! Very, very cool :D
I have a few points on it though. If you could make two extra images, on for the bombs and one for the "safe" so that the board doesn't suddenly jump when you hit a bomb. It's a little confusing the first time it happens and it makes it a little difficult to see how the board was layed out. Also, when you complete a column or a row it shrinks to the width/height of the text, it would be nice if you could force the width and height so that these stay constant.
Possible Next Steps: I'm sure you've thought of these already but just in case.
1. Ability to set dimentions and number of mines
2. Timer
3. Not quite so obvious this one but maybe a little fun. The nature of your storage method makes it incredibly easy to have stored boards. You could have some pre-stored ones which come up every now and then (they'd have to be bigger), prehapse the mines spell out a word, or draw a face?
4. Does the board have to be square? It wouldn't require a big change in your algorithm to find out how well it works.
5. You could Ajax it to prevent that little flicker when the page reloads. I'd say this might be quite a nice topical exercise as it would look pretty good on a CV to have a nice slick Ajax app, even if it is a game.
I'd never tried to write a minesweeper app before but I'd never have imagined the algorithm was so simple. I've done it with a loop below but just for fun really, it's no better and will in fact have to do one more check (and the loops as well). It checks the cell which was clicked but we know it's not a bomb so we know it won't cause a problem.
I had heard about that table widths/hights before, but since I just wanted functionality, I didn't worry about them. I probably could do it with two other pics; but I'm not a good artist :-)
Next Steps:
1. Dimensions and number of mines are an interesting idea, but the way the program is currently set-up to record the mines (look at "new.php"), if someone entered a *really* big field and only 3 mines, all of them would be concentrated in the beginning and not spread out. I haven't found out how to spread them out evenly yet; again, look at "new.php" code for how I do it right now.
2. That actually doesn't seem to hard; possibly store the value in a session variable when the page refreshes it and re-write it onto the page with AJAX....the only problem is, i I have JavaScript dynamically increment it (like a real time), how would JS give the variable back to PHP when the page loads?
3. I like that idea a lot. You're right; it would require bigger boards but it's pretty cool. I'll definitely try that out at some point.
4. A different shape board would be way too out of my league to code an algorithim for ;-)
5. I love the idea but my AJAX skills aren't the best...passing the variables back and forth between PHP and JS would be too confusing for me...if you have ideas/starter tips let me know, and I might try to do it.
Now that I think about it, a loop to check for the bombs might have been better, but, I didn't think about it back then, and now I have this. Although if I rewrite it with your earlier suggestions I may put your loop in if that's allright.
BTW, I know it's a bad habit but I rarely comment my code. Not because I feel arrogant or anything that I will *always* be able to read it or that I subscribe to the "if it was hard to write, it should be hard to read" mentology, but because if I don't bother writing comments, I can get debugging done a lot quicker. Usually, if it's a production-piece of code (I've done work before in VB and C++), after I'm done I'll go back and comment what's needed.
Thanks for your review! Let me know about that AJAX.
*Edit* Just noticed this was my 42nd post! w00t
**Edit** Not anymore it's not (I deleted another post of mine)
***Edit*** Back to 42
bubblenut
07-11-2005, 06:35 PM
Well, you could sort out the col/row width/heights really simply with a little CSS. Make all the cells of a particular class and then set the width and height of that class explicitly.
1. Ah, yes, I see what you mean. I think there's a better way of calculating where the mines are though. Say, you have $n mines to place on a $x x $y map. Set up a loop to run $n times and then generate one number between 0 and $x for one dimention and another between 0 and $y for the other. Then build the whole board, every time you come accross a cell which is already filled just ignore it and carry on. See my little bit of code below, I got halfway through and realized it needed some collision detection so that's in there to. Pretty crude atm, I don't like using parameters for return values, it just feels funny. It wouldn't be necesarry if an object oriented approach was taken, it should be noted.
function generateMine($xlim, $ylim, &$x, &$y) {
static $cache=array();
$xrand = mt_rand(0, $xlim);
$yrand = mt_rand(0, $ylim);
if(!in_array("$xrand,$yrand", $cache) {
$cache[] = "$xrand,$yrand";
$x = $xrand;
$y = $yrand;
} else {
generateMine($xlim, $ylim, $x, $y);
}
}
$n = 10; //Number of mines to place
$xlim = 10; //Number of columns
$ylim = 10; //Number of rows, this doesn't have to be the same as $i
//generate the mine locations and place them in the board
for($i=0; $i<$n; $i++) {
generateMine($xlim, $ylim, $x, $y);
$board[$x][$y] = 'b';
}
//generate the rest of the cells around them
for($i=0; $i<$xlim; $i++) {
for($j=0; $j<$ylim; $j++) {
if(!isset($board[$x][$y])) {
$board[$x][$y] = 's';
}
}
}
2. I wasn't actually thinking of having a live timer going up as you play, that would be a little more tricky, but certainly possible. I was actually thinking about just showing the total time taken at the end which you can then use for a score board. Having the timer implemented in javascript would become a very simple matter if the Ajax method was used for board clicks as there would be no page loads.
4. Well, your current algorithm could handle it quite easily. Think of a differntly shaped board as a square with some of the cells taken away, all you would need to do is build in a third state, so you have "has a bomb", "has no bomb" and "is not in use". The "is not in use" state would only really be for display and then whenever you're counting the number of bombs ajacent to a cell you'd count "is not in use" cells as having no bomb.
5. Well, you'd need to read a tutorial on Ajax but the basic idea would be to set up an event handler for each of the cells and then when one clicked make a requiest back to the server which would return the number of ajacent bombs (or something different if it's a bomb). Then you'd update the board using javascript's DOM model.
LoganK
07-11-2005, 07:12 PM
Wow, that code of yours is complex :-) No offense, but I'm not *that* good in PHP! ...so I have a question: what does "(static)" mean? BTW, I've never used recursion because (again), it's confusing to me!!!
2. It would be simple. Just got to figure out #5.
3/4. Again, also simple. Just add another if statement.
5. Hardest one of all. I'll need to definitely learn AJAX at one point. Although, while I'm here, could you explain by what you mean by "make a request" to the server? I'm assuming then my PHP script would return just a value to my JS app which would dynamically update the page. Not too hard in theory, but I have no clue how JS would communicate with the server/PHP.
bubblenut
07-11-2005, 07:29 PM
Ack, sorry, looks like the bbcode php code parser getts confused with multi line comments. In essence it's a variable which is in the global space, well actually, it's not but it appears that way to the function. Basically, it means that you can call the function, make a change to the static variable and then when you call the function again that change will still be present in the variable rather than getting reset on each invocation of the function. Now that you can actually see the code it may make more sense. The $x and $y parameters are passed in by reference so that any changes made to the variables are reflected in the relevant parameters where the function was called. This is one way of returning multiple results with a function. Another option would be to return an array or an object.
With regard to Ajax, I found this (http://developer.apple.com/internet/webcontent/xmlhttpreq.html) tutorial over at apple really helpfull. As you'll find out in the article, you can pass back data from the php script to the javascript in two ways, as raw text (how you suggested) or as xml. In this case, yes, raw text would be perfectly adequite(sp?)
LoganK
07-11-2005, 07:49 PM
Yeah, I noticed the bug with the parser too so I pasted it into Dreamweaver to take a look at it, colored and everything! In reference to static, wouldn't that be the same as calling global for the variable?
I understand pass-by-reference, actually, I just finished reading chapter 2 of Sitepoint's excellent book, The PHP Antholoy. In it it explains all about pass-by-reference, as well as call-time-pass-by-something and other, confusing things ("variable variables"?!?!).
I'll take a look at the AJAX tutorial; if I do end up re-coding it I'd probably pass as raw text because for XML I'd have to write a parser for it; correct?
bubblenut
07-11-2005, 08:17 PM
Yea, it is similar to using a global variable except that the variable isn't available in the global space. This means that you can happily use a variable by the same name in the global space without worrying that it might collide with your static variable. With regard to fetching XML with ajax, you don't need a parser as you can get javascript to give it to you as a dom object which you can then traverse with javascript's built in dom support. I would say that this wouldn't be needed for this app.
LoganK
07-11-2005, 08:24 PM
Ok, I get the static now and I understand how I can basically return it as a web page and JS can traverse it through its nativ DOM support. I've got a few other things on my plate right now (my birthday [!], writing a firefox extension, updating another firefox extension, and a redesign of my personal site), but if I decide to re-code it into AJAX, I'll let you know and post problems to the appropriate forum(s).
Thanks for your help and critique!
If anyone else would like to critique, go ahead!
PHP Builder
Copyright WebMediaBrands Inc. All Rights Reserved.