24 game: Difference between revisions

1,675 bytes added ,  26 days ago
(11 intermediate revisions by the same user not shown)
Line 5,838:
 
=={{header|FutureBasic}}==
24 Game
<syntaxhighlight lang="futurebasic">
// 24 Game
// May 2024 Rich Love
 
May 13, 2024
 
Rich Love
 
Modified to include 96 blocks of numbers for random selection.
 
Thanks to Ken and Bernie
<syntaxhighlight lang="futurebasic">
#build CompilerOptions @"-Wno-unused-variable"
 
Line 5,848 ⟶ 5,854:
 
void local fn EraseErrorText
 
CGRect r
r = fn CGRectMake(10, 200, 300400, 15)
rect fill r,fn ColorBlack
 
end fn
 
local fn ArcRandom( a as long, b as long ) as long
long i
cln i = (arc4random()%(b-a+1))+a;
end fn = fn floor(i)
 
local fn GetRandomNumbers as CFStringRef
CFArrayRef combos = @[¬
@"1 3 2 6", @"1 7 2 1", @"1 5 2 2", @"1 9 2 1", @"3 7 6 2",¬
@"1 2 3 9", @"1 6 3 1", @"1 4 3 3", @"1 4 5 6", @"1 3 4 4",¬
@"1 1 5 4", @"1 9 3 1", @"2 2 3 2", @"2 6 3 1", @"6 4 9 8",¬
@"2 8 2 1", @"3 2 5 2", @"6 5 4 4", @"2 6 2 1", @"2 4 3 1",¬
@"2 8 1 1", @"2 9 1 1", @"3 9 6 2", @"3 5 2 1", @"3 3 2 2",¬
@"3 7 1 1", @"3 2 4 1", @"2 5 7 8", @"3 8 1 6", @"4 2 9 1",¬
@"4 4 2 1", @"4 8 1 1", @"8 8 9 6", @"4 6 1 1", @"5 3 2 1",¬
@"5 7 1 1", @"5 1 2 2", @"1 5 1 4", @"5 2 2 2", @"5 4 1 1",¬
@"5 8 1 1", @"3 4 3 3", @"6 6 2 1", @"6 2 2 1", @"6 1 4 1",¬
@"9 6 2 3", @"9 5 5 9", @"7 1 3 1", @"7 5 1 1", @"8 1 8 6",¬
@"7 1 2 2", @"7 2 1 1", @"7 4 1 1", @"8 3 1 1", @"8 4 2 1",¬
@"8 1 3 1", @"8 2 1 1", @"9 3 2 1", @"2 3 5 3", @"9 1 2 1",¬
@"9 1 8 3", @"9 2 4 3", @"9 4 1 3", @"4 7 8 2", @"1 8 6 2",¬
@"6 1 6 1", @"1 6 2 2", @"1 8 3 1", @"5 7 1 3", @"6 2 3 4",¬
@"5 5 6 1", @"2 6 1 2", @"8 1 2 4", @"4 9 6 1", @"6 4 1 2",¬
@"4 7 3 2", @"5 5 4 9", @"7 3 6 2", @"6 1 2 2", @"6 2 1 2",¬
@"9 2 3 7", @"1 2 5 2", @"5 3 4 7", @"1 3 8 1", @"1 4 5 2",¬
@"1 4 7 1", @"1 5 6 2", @"1 5 8 1", @"2 6 7 1", @"2 3 4 2",¬
@"2 3 6 1", @"2 4 5 1", @"3 4 5 9", @"4 1 2 9", @"2 1 3 5",¬
@"2 2 3 4"]
 
long i = fn ArcRandom( 0, len(combos) - 1 )
end fn = combos[i]
 
 
local fn EvaluateMath( equation as CFStringRef ) as CFStringRef
equation = fn StringByReplacingOccurrencesOfString( lcase(equation), @"x", @"*" )
equation = fn StringByReplacingOccurrencesOfString( equation, @"%", @"*0.01" )
equation = fn StringByReplacingOccurrencesOfString( equation, @"^", @"**" )
CFStringRef result = NULL
RegularExpressionRef regex = fn RegularExpressionWithPattern( @"[0-9.]+", NSRegularExpressionCaseInsensitive, NULL )
CFArrayRef matches = fn RegularExpressionMatches( regex, equation, 0, fn CFRangeMake( 0, len(equation) ) )
NSInteger intConversions = 0
TextCheckingResultRef match
CFRange originalRange
CFRange adjustedRange
CFStringRef value
for match in matches
originalRange = fn TextCheckingResultRange( match )
adjustedRange = fn CFRangeMake( ( originalRange.location + ( intConversions * len( @".0") ) ), originalRange.length )
value = fn StringSubstringWithRange( equation, adjustedRange )
if fn StringContainsString( value, @"." )
continue
else
equation = fn StringByReplacingCharactersInRange( equation, adjustedRange, fn StringWithFormat( @"%@.0", value ) )
intConversions++
end if
next
ExceptionRef e
try
ExpressionRef expression = fn ExpressionWithFormat( equation )
CFNumberRef number = fn ExpressionValueWithObject( expression, NULL, NULL )
result = fn StringWithFormat( @"%.3f", dblval( number ) )
end try
catch (e)
result = fn StringWithFormat( @"%@", e ) : exit fn
end catch
// Test if result is an integer and, if so, return result as an integer
if( fn StringDoubleValue( result ) == fn floorf( fn StringDoubleValue( result ) ) )
result = fn ArrayFirstObject( fn StringComponentsSeparatedByString( result, @"." ) )
end if
end fn = result
 
CFStringRef result = NULL
RegularExpressionRef regex = fn RegularExpressionWithPattern( @"[0-9.]+", NSRegularExpressionCaseInsensitive, NULL )
CFArrayRef matches = fn RegularExpressionMatches( regex, equation, 0, fn CFRangeMake( 0, len(equation) ) )
NSInteger intConversions = 0
TextCheckingResultRef match
CFRange originalRange
CFRange adjustedRange
CFStringRef value
 
for match in matches
local fn WasDuplicateCharacter(TheString as str255) as boolean
originalRange = fn TextCheckingResultRange( match )
adjustedRange = fn CFRangeMake( ( originalRange.location + ( intConversions * len( @".0") ) ), originalRange.length )
bool NumberUsedTwice
value = fn StringSubstringWithRange( equation, adjustedRange )
NumberUsedTwice = _false
if fn StringContainsString( value, @"." )
short i
continue
short dc(50) // should not need 50 but just in case
else
for i = 1 to 50
equation = fn StringByReplacingCharactersInRange( equation, adjustedRange, fn StringWithFormat( @"%@.0", value ) )
dc(i) = 0
intConversions++
next i
end if
next
short counter
ExceptionRef e
counter = 0
try
short j
ExpressionRef expression = fn ExpressionWithFormat( equation )
CFNumberRef number = fn ExpressionValueWithObject( expression, NULL, NULL )
for i = 1 to len$(TheString)
result = fn StringWithFormat( @"%.3f", dblval( number ) )
if asc(mid$(TheString,i,1)) > 48 && asc(mid$(TheString,i,1)) < 58
end try
counter ++
dc(counter) = val(mid$(TheString,i,1))
end if
next i
short jCounter
jCounter = 0
for i = 1 to 4
for j = 1 to len$(TheString)
if val(str$(dc(i))) = int(val(mid$(TheString,j,1))) then jCounter ++
next j
next i
if jCounter > 4 then NumberUsedTwice = _true
if counter < 4 then NumberUsedTwice = _false
end fn = NumberUsedTwice
 
catch (e)
result = fn StringWithFormat( @"%@", e ) : exit fn
end catch
// Test if result is an integer and, if so, return result as an integer
if( fn StringDoubleValue( result ) == fn floorf( fn StringDoubleValue( result ) ) )
result = fn ArrayFirstObject( fn StringComponentsSeparatedByString( result, @"." ) )
end if
end fn = result
 
 
local fn QuitOrPlayAlert(GameResult as CFStringRef)
alert -2,,GameResult,@"You won!",@"Quit;Play Again"
AlertButtonSetKeyEquivalent( 2, 2, @"\e" )
alert -2,,GameResult,@"Game Over",@"Quit;Play Again"
short result
AlertButtonSetKeyEquivalent( 2, 2, @"\e" )
result = alert 2
short result
if ( result != NSAlertSecondButtonReturn ) then appterminate
result = alert 2
if ( result != NSAlertSecondButtonReturn ) then appterminate
end fn
 
 
local fn BuildWindow
CGRect r = fn CGRectMake( 0, 0, 580, 250)
window 1, @"24 Game", r
CGRect r = fn CGRectMake( 0, 0, 580, 250)
windowcenter(1)
window 1, @"24 Game", r
WindowSetBackgroundColor(1,fn ColorBlack)
windowcenter(1)
WindowSetBackgroundColor(1,fn ColorBlack)
end fn
 
end fn
 
///////// Start //////////
 
fn BuildWindow
 
 
short d(4), i
CFStringRef CheckForDuplicates(97)
for i = 1 to 96
CheckForDuplicates(i) = @""
next i
 
short DuplicatesCounter
DuplicatesCounter = 0
 
 
Line 5,966 ⟶ 5,971:
 
print
 
print %(10,15),"Given four numbers and using just the +, -, *, and / operators; and the"
print %(10,30),"possible use of parenthesis (), enter an expression that equates to 24."
print %(10,45),"You can onlymust use theall your numbers given and cannotonly usethose any number more than oncenumbers."
print %(10,60),"Examples: 9618 Solution 9 + 6 + 1 + 8 or 65383173 Solution 6 / ((3 5* -1) 3* 7) *+ 83"
print
print %(10,85),"Enter XQ to quit or QS to quitskip to the next number."
 
"GetFourNumbers"
 
CFArrayRef randomNumbers : randomNumbers= fn StringComponentsSeparatedByString( fn GetRandomNumbers, @" " )
"GetRandomNumbers"
CFStringRef RandomNumberblock : RandomNumberblock = @""
short i
CFStringRef RandomNumberblockAdd : RandomNumberblockAdd = @""
short d(4)
 
for i = 10 to 43
// create a string from the 4 numbers
d(i)= rnd(9) // digets 1..9
RandomNumberblockAdd = randomNumbers[i]
next
RandomNumberblock = fn StringByAppendingString(RandomNumberblock,RandomNumberblockAdd)
RandomNumberblock = fn StringByAppendingString(RandomNumberblock,@" ")
next i
 
 
if DuplicatesCounter = > 96
// reset counter when last number is retrieved and start from the first number block
DuplicatesCounter = 0
for i = 1 to 96
CheckForDuplicates(i) = @""
next i
end if
 
for i = 1 to 96
// check the current numbers with the numbers already used
if fn StringIsEqual(RandomNumberblock,CheckForDuplicates(i))
RandomNumberblock = fn StringWithString(CheckForDuplicates(DuplicatesCounter))
goto "GetFourNumbers"
end if
next i
 
DuplicatesCounter ++
CheckForDuplicates(DuplicatesCounter) = fn StringWithString(RandomNumberblock)
 
d(1) = fn StringIntegerValue( randomNumbers[0] )
d(2) = fn StringIntegerValue( randomNumbers[1] )
d(3) = fn StringIntegerValue( randomNumbers[2] )
d(4) = fn StringIntegerValue( randomNumbers[3] )
 
//d(1) = 9:d(2) = 6:d(3) = 1:d(4) = 8 // Uncomment to test with 9618 numbers. Solution 9 + 6 + 1 + 8
//d(1) = 6:d(2) = 5:d(3) = 3:d(4) = 8 // Uncomment to test with 6538 numbers. Solution 6 / ( 5 - 3 ) * 8
//d(1) = 3:d(2) = 1:d(3) = 7:d(4) = 3 // Uncomment to test with 3773 numbers. Solution ((3 * 1) * 7) + 3
//d(1) = 4:d(2) = 2:d(3) = 7:d(4) = 1 // Uncomment to test with 4271 numbers. Solution (4 * ( 7 - 2 + 1 )
 
bool NumberUsedTwice
NumberUsedTwice = _false
if d(1) = d(2) || d(1) = d(3) || d(1) = d(4) then NumberUsedTwice = _true
if d(2) = d(3) || d(2) = d(4) then NumberUsedTwice = _true
if d(3) = d(4) then NumberUsedTwice = _true
 
if NumberUsedTwice then "GetRandomNumbers"
 
print
 
text ,,fn colorGreen
print %(10,110),"These are your numbers: "
Line 6,001 ⟶ 6,028:
text ,18,fn colorGreen
for i = 1 to 4
print d(i); " ";
next
 
print
 
text ,12,fn colorWhite
printf @"\n\n\n"
 
CFStringRef expr
print:print:print:print
bool TryAgain : TryAgain = _false
CFStringRef MessageText
CFStringRef UserInput = NULL
 
str255 expr
bool TryAgain
TryAgain = _false
str255 MessageText
CFStringRef MessageTextRef
 
CFStringRef UserInput = 0
"InputExpression"
 
if TryAgain
MessageText = fn StringWithFormat( @"Enter math expression: [ " + expr + "'%@' was incorrect ]", expr )
UserInput = input %(10, 190), MessageText, @"123456789+-*/()qs", YES,, 0
MessageTextRef = fn StringWithPascalString(MessageText)
UserInput = input % (10, 190),MessageTextRef
else
UserInput = input % (10, 190), @"Enter math expression:", @"123456789+-*/()qs", YES,, 0
end if
 
if ( UserInput == NULL ) then "InputExpression"
expr = UserInput
fn CFStringGetPascalString (UserInput, @expr, 256, _kCFStringEncodingMacRoman)
if expr = @"" then "InputExpression"
if fn StringIsEqual(ucase$(expr) =, @"Q") then appterminate
if fn StringIsEqual(ucase$(expr) =, @"XS") then appterminate"Main"
 
 
//check expr for validity
short j
 
bool GotAllNumbers : GotAllNumbers = _false
short MatchNumber
short ThisNumberPosition : ThisNumberPosition = 0
MatchNumber = 0
short GotaNumber : GotaNumber = 0
 
short TotalNumbers : TotalNumbers = 0
short Number
str255 NumberString
 
for i = 1 to 4
GotaNumber = 0
Number = d(i)
for j = 0 to len(expr) -1
NumberString = right$(str$(Number),1)
ThisNumberPosition = instr( j, expr, right(str( d(i)),1 ))
if instr$(1,expr,NumberString ) > 0 then MatchNumber ++
ThisNumberPosition ++
if ThisNumberPosition then GotaNumber = _true
next j
if GotaNumber then TotalNumbers ++
next i
 
if TotalNumbers => 4 then GotAllNumbers = _true
if MatchNumber < 4
fn EraseErrorText
text ,,fn colorRed
print %(10,200);"ERROR! Must use all numbers": goto "InputExpression"
text ,,fn colorWhite
end if
 
if GotAllNumbers = _false
if fn WasDuplicateCharacter(expr)
fn EraseErrorText
text ,,fn colorRed
TryAgain = _true
print %(10,200);"Error! Cannot use the same number twice": goto "InputExpression"
print %(10,200);"ERROR! Must use all your numbers and only those numbers." : goto "InputExpression"
text ,,fn colorWhite
text ,,fn colorWhite
end if
 
fn EraseErrorText
 
if fn EvaluateMath( fn StringWithPascalString (expr)) = _false
text ,,fn colorRed
Print %(10,200);"Error! Incorrect math sequence."
goto "InputExpression"
text ,,fn colorWhite
end if
 
if fn EvaluateMath( expr ) = _false
text ,,fn colorRed
TryAgain = _true
Print %(10,200);"Error! Incorrect math sequence."
goto "InputExpression"
text ,,fn colorWhite
end if
 
CFStringRef AnswerRef
AnswerRef = fn EvaluateMath( fn StringWithPascalString (expr))
CFStringRef GameResult
if fn StringIntegerValue( fn EvaluateMath( expr ) ) == 24 then GameResult = @"Correct" else GameResult = @"Incorrect"
str255 AnswerString
AnswerString = fn StringPascalString(AnswerRef)
 
if int(val(AnswerString)) = 24 then GameResult = @"Correct" else GameResult = @"Incorrect"
 
 
if GameResult = @"Incorrect"
TryAgain = _true
goto "InputExpression"
end if
 
fn QuitOrPlayAlert(GameResult)
goto "Main"
 
 
handleevents
</syntaxhighlight>
 
 
=={{header|GAP}}==
44

edits