Hello
For some rather complicated mathematical calculations, I use the # tag to increase the precision. As a result of the calculations, errors arise. A professional astronomer suggested that he use more than 32 bits for his calculations. So the question is how to increase the accuracy of the calculations? Is the # sign already the most accurate option ?.
Regards Chris
A useful little tool for anyone who likes to play Scrabble.
Code: (Select All)
file$ = "Collins Scrabble Words (2019) with definitions.txt"
'279498 words
Type Dict_Type
word As String
definition As String
End Type
ReDim As String Word(1000000), Definition(1000000)
Open file$ For Binary As #1
Do Until EOF(1)
Line Input #1, text$
count = count + 1
p = InStr(text$, Chr$(9))
Word(count) = _Trim$(Left$(text$, p - 1))
Definition(count) = _Trim$(Mid$(text$, p + 1))
Loop
ReDim _Preserve Word(count) As String
ReDim _Preserve Definition(count) As String
Do
Color 4
Input "Give me a word to look up for you =>"; word$
If word$ = "" Then System
i = BinaryStringSearch(UCase$(word$), Word())
Color 15
Print
If i > -1 Then
Print word$; " found! It's definition is: "; Definition(i)
Else
Print word$; " doesn't exist! You big dummy! Cheater! Who's gonna play Scrabble with you?!!"
End If
Print
Loop
Function BinaryStringSearch (search$, Array() As String)
'These routines work with actual indexes, so we can search from Array(-10 to 10), if we want to.
'When the search string is found, it'll return a value = to the index proper.
'When it's not found, it'll return a value LESS THAN the LBOUND limit of the array,
'And the point where the string WOULD'VE appeared, if it existed, is after the shared variable LastIndex
BinaryStringSearch = BinaryStringSearchSome(search$, Array(), LBound(Array), UBound(Array))
End Function
Function BinaryStringSearchSome (search$, Array() As String, StartIndex As Long, EndIndex As Long)
'These routines work with actual indexes, so we can search from Array(-10 to 10), if we want to.
'When the search string is found, it'll return a value = to the index proper.
'When it's not found, it'll return a value LESS THAN the LBOUND limit of the array,
'And the point where the string WOULD'VE appeared, if it existed, is after the shared variable LastIndex
min = StartIndex
max = EndIndex
Do
gap = (max + min) \ 2
compare = _StrCmp(search$, Array(gap))
If compare > 0 Then
min = gap + 1
ElseIf compare < 0 Then
max = gap - 1
Else
BinaryStringSearchSome = gap
Exit Function
End If
If max - min < 1 Then
If search$ = Array(min) Then
BinaryStringSearchSome = min
Else
BinaryStringSearchSome = LBound(Array) - 1
If search$ < Array(min) Then
LastIndex = min - 1
Else
LastIndex = min
End If
End If
found = -1
End If
Loop Until found
End Function
Download and extract the word list/dictionary from below to use with this program.
As there's been several people asking about how to display extended characters (such as greek characters) onto the screen, I thought _MAPUNICODE would be a nice word for today.
First: Download the attached unicode font file and extract it into your qb64pe root directory (the same one with the qb64pe executable).
Then copy and paste the code below into qb64pe, and run it:
Code: (Select All)
Screen _NewImage(1280, 720, 32)
f = _LoadFont("DejaVuSansMono.ttf", 24, "monospace")
_Font f
fw = _FontWidth: fh = _FontHeight 'font width, font height
cpl = _Width \ fw: cpp = _Height \ fh 'characters per line, characters per page
For y = 0 To cpp - 1
For x = 0 To cpl - 1
i = i + 1
_PrintString (x * fw, y * fh), Chr$(i)
If i = 255 Then GoTo skip 'show the first 255 that people are used to seeing usually.
Next 'then exit... This is just lazy formatting
Next
skip:
Sleep
'Just to show all the tons of different unicode symbols inside the unicode file...
i = 0
For y = 4 To cpp - 1
For x = 0 To cpl - 1
i = i + 1
_MapUnicode i To 0
_PrintString (x * fw, y * fh), Chr$(0)
If i = 255 Then Sleep 'show the first 255 that people are used to seeing usually.
Next 'then fill the page with extra junk! (I dunno what any of these are supposed to be. :P )
Next
Sleep
'Greek codes are 913 to 969
'note that there is no greek symbol at 930, so that unicode value has been recycled to be something else.
'pay no attention to it, if you don't need it. (And I don't think most people would.)
Cls
i = 912
Print "The Greek character set:"
For y = 1 To cpp - 1
For x = 0 To cpl - 1
i = i + 1
_MapUnicode i To 0
_PrintString (x * fw, y * fh), Chr$(0)
If i = 969 Then GoTo done
Next
Next
done:
'Latin is 256 to 328
i = 255
Locate 5, 1: Print "The Latin character set:"
For y = 5 To cpp - 1
For x = 0 To cpl - 1
i = i + 1
_MapUnicode i To 0
_PrintString (x * fw, y * fh), Chr$(0)
If i = 328 Then GoTo done2
Next
Next
done2:
Sleep
System
Running the above, we start out with a burst of characters across the screen that everyone should be familiar with -- the 255 ASCII characters that we see and use all the time in QB64!
Hit any key, and then you can see what the unicode characters from 1 to 255 look like. A large portion of the first half maps directly over from our current ASCII set to the UNICODE set of characters (everything from 32 to 128), but, as you can see, there's no symbols defined in our font for unicode characters 1 to 31. Those are/were control codes back in the day, and the vast majority of them were non-printing, so many unicode fonts don't have those characters in them. Our ASCII code actually maps unicode symbols from other values, and puts it in those spots, to make the character set that we're used to seeing.
Now from 128 to 255, there's not a single character which matches up between the unicode values and our ASCII values. We tend to, by default, map the character codes from codepage 437 into those spots, so that our codes will match the same ones QB45 and all other basics used to use by default. Now, one problem with this is that we aren't offering a lot of the specialized characters (such as those with various accents and such), as we're offering the old character sets that were used to build boxes and such in old terminal screens.
So, how would one fix that, if they wanted to display other symbols besides the ones we currently offer??
Hit any key in the demo, and you can see that there's a whole bunch of other characters inside the font we loaded! Even though QB64 only makes use of 256 of those characters, that doesn't mean our font doesn't have a whole lot more than 256 that we can choose from! (After all, if we couldn't use other characters, I'd never be able to create the demo that you're now viewing, now would I??)
To pick and choose our display set, we simply make use of the _MAPUNICODE command. To easily get the most out of this command, I recommend the following steps:
1) Go to ✔️ ❤️ ★ Unicode Character Table (unicode-table.com) -- There's a ton of unicode symbols available out there. Find which code corresponds to the character you want.
2) Find a current ASCII character that you're not using. For my demo, I chose CHR$(0) for all my needs -- you can choose any of the 0 to 255 characters to replace that you want.
3) _MAPUNICDE unicode_number TO ascii_number
It's that simple!!
Now, whenever you need to display that character upon the screen, you can call upon it as needed.
PRINT "Hello World " + CHR$(150) '150 for whatever symbol/character you decided to map to 150.
Note that not every unicode font has every unicode character in it. When you run my demo, you'll see several square boxes -- that's default for "Nope! No symbol here!" If the font you have doesn't support the language/symbols you need, then you'll just have to swap to a different font. After all, you can't print characters that don't exist in your font set!
Posted by: PhilOfPerth - 11-22-2022, 03:03 AM - Forum: Programs
- No Replies
This is an updated version of my Wordfind programme. It now finds and displays all words that can be derived from a given word, using each letter only once, up to 30 characters in length.
Color 14: Locate 6, 35: Print "Word-Find": Color 15
Print Tab(30); "By Phil Taylor (2022)": Print
Print Tab(5); "This programme will find all English words up to 13 letters in length"
Print Tab(5); "that appear in the Collins (2019) dictionary, that can be formed from "
Print Tab(5); "the letters of a word or group of letters, with each letter only being"
Print Tab(5); "used once."
Print: Print Tab(10); "(You can specify minimum and maximum word-lengths to find)."
Print
Color 14: Print Tab(15);: Input "Minimum size of words (ENTER for default of 2)"; min$
If Val(min$) < 2 Then min = 2 Else min = Val(min$)
Color 15: Print Tab(30); "Minimum set at "; min: Color 14
Print
Print Tab(15);: Input "Maximum size of words (ENTER for default of 30)"; max$
If Val(max$) < 2 Then max = 30 Else max = Val(max$)
Color 15: Print Tab(30); "Maximum set at"; max
Print: Color 14: Print Tab(30); "Press a key to start": Color 15
While InKey$ <> "": Wend
While InKey$ = "": Wend
Start:
Cls
While InKey$ <> "": Wend
Locate 10, 20: Color 14: Input "What is the Base-Word (or group)"; base$: Color 15
If base$ < "A" Then base$ = "ANYTHING" ' just a word for demo purposes
base$ = UCase$(base$)
origbase$ = base$
Color 14: Print Tab(9); "Base word:"; origbase$; " Minimum length:"; min; " Maximum length:"; max: Color 15
sort:
swapped = 0
For a = 1 To Len(base$) - 1
If Mid$(base$, a, 1) > Mid$(base$, a + 1, 1) Then
t1$ = Mid$(base$, a, 1): t2$ = Mid$(base$, a + 1, 1)
Mid$(base$, a, 1) = t2$: Mid$(base$, a + 1) = t1$
swapped = 1
End If
Next
If swapped = 1 Then GoTo sort
Print a$
l = Len(base$)
found = 0: totfound = 0
sorted$ = Left$(base$, 1)
Cls
FindUnique
For bletrnum = 1 To l ' for each letter in base$
fileletr$ = Mid$(base$, bletrnum, 1)
po = InStr(unique$, fileletr$)
If po = 0 Then GoTo skip
Mid$(unique$, po, 1) = " "
dictfile$ = "wordlists/" + fileletr$
Close
Open dictfile$ For Input As #1
GetAWord:
While Not EOF(1)
Input #1, dictwrd$
l = Len(dictwrd$): If l < min Or l > max Then GoTo GetAWord
WORDCHECK
Wend
skip:
Next
Print: Color 14: Print Tab(35); "Finished!"
Print Tab(29); "Total words found:"; totfound
Sleep
GoTo Start
Sub WORDCHECK
fail = 0
dummy$ = base$
For a = 1 To l
dictletr$ = Mid$(dictwrd$, a, 1)
po = InStr(dummy$, dictletr$)
If po = 0 Then
fail = 1 ' letter is not in dummy$ so abandon word
Else
Mid$(dummy$, po, 1) = " "
End If
Next
If fail = 1 Then Exit Sub
found = found + 1: totfound = totfound + 1
Print dictwrd$; Space$(1);
If Pos(0) > 70 Then Print
If found = 220 Then
While InKey$ <> "": Wend
Color 14
Print: Print Tab(27); "Press a key for next group"
While InKey$ = "": Wend
found = 0
Cls
Color 14: Print Tab(9); "Base word:"; origbase$; " Minimum length:"; min; " Maximum length:"; max: Color 15
Color 15
End If
End Sub
Sub FindUnique
unique$ = ""
For a = 1 To l
l$ = Mid$(base$, a, 1)
po = InStr(unique$, l$)
If po = 0 Then unique$ = unique$ + l$
Next
End Sub
A program can be at one of two promotion levels: development or production.
When at the development level, there are two versions of the program available: development and production.
When at the production level, there is only the one version of the program: production. Until edited, at which point it is back at the development level.
That aside:
We may want a program to look/behave differently depending on what version we are running/exporting. This is where the "dev" and "prod" preprocessor directives come in.
Sample code:
Code: (Select All)
<<dev """
greet$ = "howdy buds, this is the development version of the program"
""">>
<<prod """
greet$ = "good day ladies and gentlement, this is the production version of the program"
""">>
print greet$
In the sample code above, greet$ will have one value when we are running the development version, and a different value when running the production version.
Today's Keyword of the Day is the first which has poor Steve shaking his head and sighing deeply over our documentation and wiki entries on it. Guys, do me a favor and toss the wiki examples out of your brains, as they're NOT what you want to do with _MOUSEINPUT at all.
Let me illustrate with the first example from the wiki:
Code: (Select All)
DO
DO WHILE _MOUSEINPUT ' Check the mouse status
PRINT _MOUSEX, _MOUSEY, _MOUSEBUTTON(1), _MOUSEWHEEL
LOOP
LOOP UNTIL INKEY$ <> ""
Seems to work as advertised, so what's the problem here?
Nothing should go inside your _MOUSEINPUT loop, except for a _MOUSEWHEEL counter!
Let me show you why:
Code: (Select All)
Do
Locate 1
i = 1
Do While _MouseInput ' Check the mouse status
Locate i, 1: Print _MouseX, _MouseY, _MouseButton(1), _MouseWheel
i = i + 1
Loop
If i <> 1 Then For z = i To 20: Locate z, 1: Print Space$(60): Next
Locate 21, 1: Print _MouseX, _MouseY, _MouseButton(1)
_Limit 120
Loop Until InKey$ <> ""
Take the first code and imagine trying to actually do something with it. Printing it inside that example loop isn't actually doing anything constructive for us -- it's just displaying all the mouse's minute movements as it crosses the screen. If we're going to check the mouse against a button, or some such, that we've draw upon our screen, we'll need to settle on o single value for that mouse position which we compare against -- and that's going to be AFTER WE EXIT THE LOOP.
Code: (Select All)
Do While _MOUSEINPUT
Loop
^The above says we're not going to actually do anything with our _MOUSEX and _MOUSEY values... We'll only respond to them outside the loop.
And, as you can see from my second set of code, the end result is *always* going to print the same values as the last pass inside the loop did...
So why would we waste time processing a couple of dozen events, assigning them to overwrite the same values over and over and whatnot, when we're just going to toss those values out the door at the end of the loop??
IF both sets of the following code produce the same results, which is more efficient for us?
Code: (Select All)
While _MouseInput
x = _MOUSEX: y = _MOUSEY
Wend
Code: (Select All)
While _MouseInput; Wend
x = _MouseX: y = _MouseY
Both are going to generate the exact same values for x and y, so which is more efficient for us? The first code is going to assign several dozen temporary values to x and y, before exiting and giving us a final value for x and y. The second code skips all that intermittent assignment and just gives us the final result after the mouseinput loop.
Our second example in the wiki is just as poorly written, and is just as bad of an example.
Code: (Select All)
SCREEN 12
DO ' main program loop
' your program code
DO WHILE _MOUSEINPUT'mouse status changes only
x = _MOUSEX
y = _MOUSEY
IF x > 0 AND x < 640 AND y > 0 AND y < 480 THEN
IF _MOUSEBUTTON(2) THEN
PSET (x, y), 15
LOCATE 1, 1: PRINT x, y
END IF
END IF
LOOP
' your program code
LOOP UNTIL INKEY$ = CHR$(27)
Once again, the example is processing all sorts of crap inside that _MOUSEINPUT loop that it doesn't need to. Compile it. Run it. Watch how it behaves. And then compare to the following:
Code: (Select All)
Screen 12
Do ' main program loop
' your program code
Do While _MouseInput: Loop 'mouse status changes only
' your program code
x = _MouseX
y = _MouseY
If x > 0 And x < 640 And y > 0 And y < 480 Then
If _MouseButton(2) Then
PSet (x, y), 15
Locate 1, 1: Print x, y
End If
End If
Loop Until InKey$ = Chr$(27)
The only thing that needs to go inside a _MOUSEINPUT loop is possibly a counter to deal with _MOUSEWHEEL. Everything else should go outside it, or else you're going to end up lagging up your program to the point of uselessness.
MouseInput code should generally look like one of the two varieties below:
Code: (Select All)
While _MouseInput: Wend
Code: (Select All)
While _MouseInput
scrollwheel = scrollwheel + _MOUSEWHEEL
Wend
Attempting to process other code inside that mouseinput loop is just asking for trouble. Our wiki examples work for what they're showing, but what they're showing is about the worst possible structure I could imagine for use with _MOUSEINPUT. Honestly, they must've just written into the wiki when _MOUSEINPUT was first added into the wiki and nobody knew much about it.. As it stands now, those examples need an overhaul to show how to actually use them properly.
Just published a small update to the last release of QBJS. I've added a screen pixel cache to improve the performance of programs that heavily utilize PSET for rendering.
For example, @vince's American flag now majestically waves at a more acceptable rate. Not quite as fast as native QB64 on my box, but a lot closer than before.
Also, there have been a number of posts recently of "Bubble Universes" which also run a lot faster:
Note: If you are not seeing an improvement when you try these examples, you might need to do a SHIFT+Refresh to clear the cached version in your browser.
I don't know much about this topic of accessing PC/Mac/Linux devices.
Is it possible to capture a still image from a USB camera from within a QB64 program? Or would this be incredibly complicated? Obviously the easiest thing to do is just manually capture the image (using the camera software) then _loadimage into QB64.
I'm wondering if QB64 could be used to capture a new image at a certain time interval and discard the previous image.
I would like to ask a question to the community here.
How easy is it for QB64 to support the Greek language?
That is, what is written in quotation marks.
For example,
PRINT "Den ypostirizo ellinikoys xaraktires>"
PRINT "I do not support Greek characters."
PRINT "Δεν υποστηρίζω ελληνικούς χαρακτηρισμούς."
SLEEP
Copy this little example and you'll see exactly what I mean.
I would like one day to be able to make my own programs and insert Greek characters where needed.