Stuck and need help

BlitzMax Forums/BlitzMax Beginners Area/Stuck and need help

Bill246(Posted 2014) [#1]
I'm working on a simple game and am stuck. Hopefully someone here and help me out.

For now, all the game does is fill 1 of 4 squares in the middle of the screen. After hitting the space bar to begin, the player hits the Up arrow and fills the corresponding square at the top of the screen. Then the program fills a different square in the center and the user moves it to the top. The process repeats until all 4 upper squares are filled.

After the 4 upper squares are filled, the middle squares are supposed to be empty, but the previously filled square doesn't clear and I don't know why. I have debugging code to show which of the center (C1, C2..) and upper squares (U1, U2...) are filled. Why does the last center square not clear?

Disclaimer: I am a novice programmer and I know I don't follow the best programming practices.

Thanks for looking.

Bill


Graphics 800,600

Global i=0:Int
Global C1=0:Int
Global C2=0:Int
Global C3=0:Int
Global C4=0:Int
Global U1=0:Int
Global U2=0:Int
Global U3=0:Int
Global U4=0:Int
Global CU1=0:Int 
Global CU2=0:Int
Global CU3=0:Int
Global CU4=0:Int
Global Arrow:String=""
Global PickedNumber=0:Int
Global StartGame=0:Int
Global PlayerMove=0:Int 'this is changed to 1 once the player hits an arrow key.  It is changed back to 0 once the squares are moved.
Global CenterInPlay=0:Int 'if box in center is filled, don't call PickCenterSquare

SeedRnd MilliSecs ()

Function PickCenterSquare()
	Local TestNum=0:Int
	
	While TestNum=0
	
		PickedNumber=Rand(1,4)
			Select PickedNumber
				Case 1
					If U1=0 Then
							C1=1
							TestNum=1
					End If
				Case 2
					If U2=0 Then
							C2=1
							TestNum=1
					End If
				Case 3
					If U3=0 Then
							C3=1
							TestNum=1
					End If
				Case 4
					If U4=0 Then
						C4=1
						TestNum=1
					End If
			End Select	
	
	Wend
	
	Return

End Function

Function HitArrow()
	If Arrow = "U" Then
		If C1 = 1 Then
			If U1 = 0 Then
				U1 = 1
				CenterInPlay=0
				C1 = 0
			End If
		End If
		
		If C2 = 1 Then
			If U2 = 0  Then
				U2 = 1
				CenterInPlay = 0
				C2 = 0
			End If
		End If
		
		If C3 = 1 Then
			If U3 = 0 Then
				U3 = 1
				CenterInPlay=0
				C3 = 0
			End If
		End If
		
		If C4 = 1 Then
			If U4 = 0 Then
				U4 = 1
				CenterInPlay=0
				C4 = 0
			End If
		End If
		
	End If
			

End Function

Repeat

Cls
	
	While StartGame=0
		If KeyHit(KEY_SPACE) Then
			StartGame=1
		End If
	Wend
	
	'draw center box
	SetLineWidth(4)
	SetColor(0,200,100)
	DrawLine 349,249,451,249
	DrawLine 349,349,451,349
	DrawLine 349,249,349,349
	DrawLine 451,349,451,249
	
	'draw upper box
	DrawLine 349,49,451,49
	DrawLine 349,149,451,149
	DrawLine 349,49,349,149
	DrawLine 451,49,451,149 
	
	If CenterInPlay=0 Then 'clears center squares
		SetColor(0,0,0)
		DrawRect(401,250,50,50)
		DrawRect(401,300,50,50)
		DrawRect(350,300,50,50)
		DrawRect(350,250,50,50)	
		PickCenterSquare
		CenterInPlay=1
	End If
	
	Print "Picked number is: " +  PickedNumber
	Print "C1 is: " + C1 + " C2 is: " + C2 + " C3 is: " + C3 + " C4 is: " + C4
	Print "U1 is: " + U1 + " U2 is: " + U2 + " U3 is: " + U3 + " U4 is: " + U4


	If C1=1 Then
		SetColor(255,0,0)
		DrawRect(400,251,50,50)
	End If
	
	If C2=1 Then
		SetColor(255,0,0)
		DrawRect(400,299,50,50)
	End If
	
	If C3=1 Then
		SetColor(255,0,0)
		DrawRect(350,299,50,50)
	End If
	
	If C4=1 Then
		SetColor(255,0,0)
		DrawRect(350,251,50,50)	
	End If
	
	If KeyDown(KEY_UP) Then 
		If CenterInPlay = 1 Then
			Arrow="U"
			HitArrow
			Arrow =""
		End If
		
		Delay(100)
		
	End If
	
	If U1 = 1 Then
		SetColor(255,0,0)
		DrawRect 399,52,50,50
	End If
	
	If U2 = 1 Then
		SetColor(255,0,0)
		DrawRect 399,98,50,50
	End If
	
	If U3 = 1 Then
		SetColor(255,0,0)
		DrawRect 352,98,50,50
	End If
	
	If U4 = 1 Then
		SetColor(255,0,0)
		DrawRect 352,52,50,50
	End If

Flip
			
Until MouseHit(1)




TomToad(Posted 2014) [#2]
It would be easier to read your source if you put your code within code tags. Use [ code ] [ /code ] without the spaces. [ codebox ] [/codebox ] can be used for longer code

The reason your middle square is not clearing is because when you fill the forth square, u1,u2,u3 and u4 all = 1, which causes an endless loop in the PickCenterSquare function. This is why the program locks up when all 4 squares are filled. Do a test to make sure that there is a free square available.

Function PickCenterSquare()
If u1 And u2 And u3 And u4 Then Return 'test for free square
Local TestNum=0:Int
etc...

Also, you might want to spend a bit of time learning about arrays in BlitzMAX.


Derron(Posted 2014) [#3]



Your while loop is run forever in certain cases (I print a text there).


EDIT: Tom was faster ... but even if the source of your problem was narrowed down: also check how things could get shortened (I shortened your "if"-parts as an
if 1
--if 2
----do

could be written as
if 1 and 2
--do



bye
Ron

bye
Ron


Bill246(Posted 2014) [#4]
Thank you for the replies. I took your advice and now the program no longer gets stuck in an endless loop.

I have a long way to go on this game and will certainly ask more questions.

Bill


Xerra(Posted 2014) [#5]
I did a simple maze game example a while back which is in my worklog. I posted the full source code in the thread so that may help you out a bit with tracking what's in what square on a grid.


zoqfotpik(Posted 2014) [#6]
Bill, your code is straightforward and clear, it's very brute-force and linear but that's not necessarily a bad thing. If you indent it like Derron did with each block getting indented between an if and an endif like so

if such and such
     indent this bit
     and this bit
endif

it will improve the readability hugely. For you right now "best programming practices" are what keeps it simple and understandable for yourself. And that remains true to a surprising extent-- a lot of times things that are elegant are not easy to understand and a lot of times they are surprisingly slow and it's brute force linear logic that wins the day. If I have the choice between doing something clever or doing something a bit more brute force but simple to understand, I choose the latter every time especially when learning a new language. You can always go in later and make it more efficient. As some bearded philosopher once said, "Premature optimization is the root of much evil."

Also you don't need the "then" statements but by all means keep them there if it makes the code easier for you to understand.


Bill246(Posted 2014) [#7]
I've been working on my 'Moving Boxes' program over the last few weeks and have made a lot of progress. I have most of the game's functionality completed, but now it locks up after several moves. My code is quite long and inefficient, so I won't post it right now. Instead, does anyone have suggestions about debugging? I used the DebugStop command in a couple of locations, but I can't find what exactly is causing the lock up. Is there a way to trace the running code line by line?

Thanks again for all of the previous comments and suggestions.

Bill


Brucey(Posted 2014) [#8]
Is there a way to trace the running code line by line?

Not without dropping lots of DebugLog everywhere.


... which leads me to the thought that it might be nice to have a "profile/trace" option in bcc - to do just that. (although the amount of trace you can generate in a very short time in BlitzMax may give you other headaches).


Henri(Posted 2014) [#9]
Is there a way to trace the running code line by line?

Using the step button in MaxIDE toolbar ?

-Henri


col(Posted 2014) [#10]
[edit]
Is there a way to trace the running code line by line?

Instead, does anyone have suggestions about debugging?

[/edit]

This may help ...
http://www.blitzbasic.com/Community/posts.php?topic=95478


Brucey(Posted 2014) [#11]
Is there a way to trace the running code line by line?

...
Using the step button in MaxIDE toolbar ?

This may help ...

The code is not "running" when you are stepping through it. It is paused, waiting for you to do something.


If you have lots of functions, stick a DebugLog "function name" in each of them. That might give you a head start where to go next.


col(Posted 2014) [#12]
@Brucey,

You're right, I totally agree.
I've edited my post as I made a mistake with the 'quote' that I was replying to.


Derron(Posted 2014) [#13]
A "stuck" always means it ended in a dead loop.

Means: check your loops

debuglog("before loop3")
bla
debuglog("after loop3")


you will surely see a "before loop3" somewhere, but no "after loop3".



bye
Ron


zoqfotpik(Posted 2014) [#14]
Personally I never use software debuggers. I manually put breakpoints that print variables that are in question.

Break up your program into functions as much as you can and then test each individual function exhaustively and that way you know that each function is bulletproof so when you begin to write the main body of the program, it is like building with Legos that are already heavily tested as opposed to Legos that are in uncertain states of reliability. It also helps you compartmentalize confusion. There is only so much you can hold in your head at one time.

If something is confusing, but you get to a point where you can understand it momentarily, if you then write a function that is a simple interface hiding complex workings, you have canned your momentary understanding in a way that will be usable later when you no longer understand that piece of the puzzle.

You can then even chop those functions out and use them later in other programs.

When you have a program built up this way, bugs become a matter of "function foo not working and I don't know why" instead of "whole program not working and I don't understand why."

Later you can get into what's called test-driven development. There, you figure out what functions you need, then figure out an exhaustive test to make sure that a function works before actually coding that function. What happens if I feed it negative values or huge values? For this given input, I should get that specific output, is that happening?

When you have a bunch of these tests written, and you set them up to run every time you start the program, you will see immediately if the tests (called a "test harness") print PASS or FAIL for any given function.

This, if you change something and it breaks some other part of the program, you will know right away rather than fifteen minutes later when your gnat brain no longer remembers what it was doing.

And I'm not just talking to you-- a huge part if not all of debugging has to do with the recognition that we have tiny gnat brains, and accepting that, and then using the computer to automate as much of the testing process as possible.

Breaking things up also allows you to work on some other part of the program when you start getting brainfried. Debugging and programming in general are exceedingly taxing mentally and I am convinced that there is some chemical or brain nutrient that gets depleted.

Just some general thoughts.

It is probably a good idea to use the software debugger, I should learn. I didn't even know about debuglog until just now but I can imagine what it does.


Bill246(Posted 2014) [#15]
Thanks for the comments.

I printed the status of most of the variables and saw something was getting incremented when it shouldn't. This means it hits 4 when it should be 3, and locks up. At least that's what I think was the cause. I moved this code to a different location and now I can play forever.


zoqfotpik(Posted 2014) [#16]
http://en.wikipedia.org/wiki/Off-by-one_error


GfK(Posted 2014) [#17]
Personally I never use software debuggers. I manually put breakpoints that print variables that are in question.
o_O

Why on earth would you do that, when the debugger tells you the contents of every variable anyway??

(aside from the fact that a breakpoint doesn't print anything. It's a point where code execution stops and the debugger kicks in).


Xerra(Posted 2014) [#18]
Sometimes I find it helps to check if a number is > the max allowed rather than a specific "if x = 4" or similar. Of course this would mean you would still have something incrementing that shouldn't be, and might not notice it, so it's six of one and half a dozen of the other.


Derron(Posted 2014) [#19]
That is why someone invented the "else" or "default"

select x
case 1 ...
case 2 ...
default ...
endselect

if x=1...
elseif x=2 ...
else ...

bye
Ron


Bill246(Posted 2014) [#20]
I laughed when I saw there was a Wikipedia entry for the type of error I had. Now I feel like a real programmer.

I was able to fix a couple of bugs and now my game runs correctly. It's still far from complete, but as of right now, it's bug free.

Thanks for the help.

Bill