Using Your Memory (Any Blitz, Any Level)
Blitz3D Forums/Blitz3D Tutorials/Using Your Memory (Any Blitz, Any Level)
| ||
TITLE: Using Your Memory (Any Blitz, Any Level) DESCRIPTION: These are just some random examples on using memory to save CPU time and make code look nice. The action game programmer probably will not run into many instances where you can use memory to make things simpler, but a puzzle game programmer might. The first 4 problems are all things I've run into when making puzzle games. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> PROBLEM 1: N0n-Repeating Random Numbers >>>>>>>>>>>>>>>>>>>>>>>> Fill a 1,000,000 element array with random integers from 1 to 1,000,000 such that no integer is repeated. A first intuition might be to pick a random number and test it aginst all the numbers we have picked so far until you find a random number that hasn't already been choosen. And do that for each element. In BlitzBasic this might look like: Dim array(1000000) For i=1 To 1000000 Repeat new=True number=Random(1,1000000) For j=1 To i-1 If array(i)=array(j) Then new=False Next Until new=True Next But, imagine trying to place the last number. We have 1 number left, and the chances of picking it are 1 in a million. And for each number we pick we have 999,999 comparison tests. Thats too much time. Make a 1,000,000 element array that will hold all the numbers we have left to choose. We will maintain this array so that if we still have N numbers to pick, the first N elements of this array will contain these numbers (not neccessarily in order). ***NOTE: We are going to choose random elements where the numbers will be, not randomly choose the numbers themselves. When we choose a random element, we will put the value of the N'th element (the last of the unchoosen numbers) in the spot we just choose. This removes the choosen number from the unchoosen numbers, and keeps that last number in the pool when N decreases by 1 on the next pass. For example, say we have 5 numbers not a million. Our unused numbers array will start off like: 1,2,3,4,5 Lets say we pick a random element 2. 2 is whats in element 2. Now we put the 5 where the 2 is so our unused numbers array looks like: 1,5,3,4,5 We still have 4 numbers left we havent picked, and the first 4 elements of this array are these numbers. So picking a random element from 1 to 4 we know will give us an unused number without any comparison tests like in the first way we solved this problem. In BlitzBasic this might look like: Dim array(1000000) Dim unused(1000000) For i=1 To 1000000 unused(i)=i Next For i=1 To 1000000 element=Random(1,1000000-(i-1)) array(i)=unused(element) unused(element)=unused(1000000-(i-1)) Next >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> PROBLEM 2: 1->2 & 2->1 >>>>>>>>>>>>>>>>>>>>>>>> We have a varrible x thats either a 1 or a 2 and we want to flip it. A first intuition might be: If x=1 Then x=2 Else x=1 EndIf Other methods include: x=3-x ;Note: you can always flip 2 numbers by subtracting from their sum x=(2*x) Mod 3 x=(x Mod 2)+1 But, by setting up a 2 element array: Dim flip(2) flip(1)=2 flip(2)=1 We can just say: x=flip(x) You would really want to do it this way if x could be more than just 1 or 2 and their was no pattern in changing x's value. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> PROBLEM 3: Greatest Number Less Than Or Equal To >>>>>>>>>>>>>>>>>>>>>>>> Lets say we have some numbers: 3,6,7,10,14 And we want to find the greatest number less than or equal to some number x. If x is 13, then the answer would be 10 in the above case. You can make some type of algorithm to hunt for the number. Or you can make an array that looks like: 0,0,3,3,3,6,7,7,7,10,10,10,10,14 So that the x'th element has the answer for x. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> PROBLEM 4: Find A Number And Move It >>>>>>>>>>>>>>>>>>>>>>>> Lets say we have an array of numbers 1 to 9 in no specific order: array1=3,6,1,2,4,9,7,8,5 And we want to move a number, say 9 to the left. Then we would swap the 9 and the 4. But, hunting for the 9 would be a pain. Lets make another array so that we can jump right to it. This second array will hold the location for each number in array1. To correspond with the above array1, it would look like: array2=3,4,1,5,9,2,7,8,6 For instance, the 1 is in the 3rd element in array1, so we give the first element a value of 3 in array2. The 9 (which is what we want) is the 6th element in array1. So, array2(9)=6. If we want to swap the 9 with whatever is to the left of it, our BlitzBasic code might look like: leftNumber=array1(array2(9)-1) array1(array2(leftNumber))=9 array1(array2(9))=leftNumber array2(9)=array2(leftNumber) array2(leftNumber)=array2(leftNumber)+1 >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> PROBLEM 5: Sorting >>>>>>>>>>>>>>>>>>>>>>>> Lets say we want to put the numbers: 3,4,1,2,7,9,10,11,14,13,12 in order. Notice the 5,6, and 8 are missing. Instead of using quick sort or insertion sort, you could make a 14 element array and put the 3 in element 3, the 4 in 4, ... , and the 14 in 14 so it would look like: 1,2,3,4,0,0,7,0,9,10,11,12,13,14 Then shift all the numbers after the first 0 (where the missing 5 would go) to the left 1, after the 2nd 0 to the left 2, etc... So the first 11 elements would look like: 1,2,3,4,7,9,10,11,12,13,14 If numbers could repeat you would could make an N by 2 matrix to hold the number of a certain type of number. So 1,3,4,1,3,5 might look like: 1,0,3,4,5 2,0,2,1,1 (since there are 2 1's and 2 3's) If you had alot of gaps, you might want to use the radix sort which works digit by digit. Do an internet search for more info. And, even with the radix sort there is a way to use memory to make it twice as fast as I have seen most people do it. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> GENERAL TID-BITS >>>>>>>>>>>>>>>>>>>>>>>> Sometimes people make an array for Sin and Cos and precalculate 360 degrees or so, so they can just copy the values later on without having to do actually Sin and Cos calculations. It's called a look-up table. And, a long time ago I used to program in Basic on a TI calculator. It interpreted and was extremely slow. And for some reason, If tests were extra slow. I tried to avoid them at all costs. We had the GetKey command. And I would build an array with the elements of the movement keys holding the direction, so I didn't need 4 If tests like If key=34 Then direction=1. It could just be direction=array1(array2(key)) where array2 held the element to get the direction from in array1. That way if no key was pressed or a non-movement key was pressed, it would refere to the element of array1 that held the direction you were already heading. And to make sure you couldn't go through a wall, no If tests were used either. You had an array that held your old and current locations. Where there was no wall, the wall value refered to your current location, and where there was, to your old location. Luckly BlitzBasic isn't like that. |
| ||
Your first example, 'shuffling' an array, doesn't need a second array to track usage. It can be done simply like this: N = 9 Dim array(N) For i=1 To N array(i)=i Next For i=1 To N-1 ; put random array element into position i k = Rand(i,N) temp = array(i) : array(i) = array(k) : array(k) = temp Next For i = 1 To N Print array(i) Next WaitKey : End |
| ||
Good call. This way is actually a tiny fraction faster though cause it doesn't need to use that temp varrible to swap. Dim array(1000000) Dim unused(1000000) For i=1 To 1000000 unused(i)=i Next For i=1 To 1000000 element=Random(i,1000000) array(i)=unused(element) unused(element)=unused(i) Next |
| ||
I think that I have a TI 83 game to rewrite :) |
| ||
1.000.000 random numbers? no problem 1) create dim-array DIM array(1000000) 2) set values: for i=1 to 1000000 array(i)=i next 3) swap values for i=1 to 1000000 nr=rand(1,1000000) ;can rand handle large numbers? tmp=array(i) array(i)=array(nr) array(nr)=tmp next that's it - you need only 1 array |
| ||
Take your time to read what Floyd posted |
| ||
I think that I have a TI 83 game to rewrite :) I think i have a few TI-83 games to rewrite =) |
| ||
Using memory like that i do use it for Cos and Sin commands it speeds up about 50th of a second a game that uses Cos and Sin a lot this little trick would realy help! |