114 lines
3.5 KiB
AppleScript
114 lines
3.5 KiB
AppleScript
property OMask : missing value
|
|
property XMask : missing value
|
|
property winningNumbers : {7, 56, 73, 84, 146, 273, 292, 448}
|
|
property difficulty : missing value
|
|
|
|
repeat
|
|
set OMask to 0
|
|
set XMask to 0
|
|
|
|
if button returned of (display dialog "Who should start?" buttons {"I shoud", "CPU"}) = "CPU" then set OMask to npcGet()
|
|
set difficulty to button returned of (display dialog "Please choose your difficulty" buttons {"Hard", "Normal"})
|
|
|
|
repeat
|
|
set XMask to XMask + 2 ^ (nGet() - 1)
|
|
if winnerForMask(XMask) or OMask + XMask = 511 then exit repeat
|
|
set OMask to npcGet()
|
|
if winnerForMask(OMask) or OMask + XMask = 511 then exit repeat
|
|
end repeat
|
|
|
|
if winnerForMask(OMask) then
|
|
set msg to "CPU Wins!"
|
|
else if winnerForMask(XMask) then
|
|
set msg to "You WON!!!"
|
|
else
|
|
set msg to "It's a draw"
|
|
end if
|
|
|
|
display dialog msg & return & return & drawGrid() & return & return & "Do you want to play again?"
|
|
end repeat
|
|
|
|
on nGet()
|
|
set theMessage to "It's your turn Player 1, please fill in the number for X" & return & return & drawGrid()
|
|
repeat
|
|
set value to text returned of (display dialog theMessage default answer "")
|
|
if (offset of value in "123456789") is not 0 then
|
|
if not positionIsUsed(value as integer) then exit repeat
|
|
end if
|
|
end repeat
|
|
return value as integer
|
|
end nGet
|
|
|
|
on npcGet()
|
|
--first get the free positions
|
|
set freeSpots to {}
|
|
repeat with s from 1 to 9
|
|
if not positionIsUsed(s) then set end of freeSpots to 2 ^ (s - 1)
|
|
end repeat
|
|
--second check if 1 move can make the CPU win
|
|
repeat with spot in freeSpots
|
|
if winnerForMask(OMask + spot) then return OMask + spot
|
|
end repeat
|
|
|
|
if difficulty is "Hard" and OMask is 0 then
|
|
if XMask = 1 or XMask = 4 then return 2
|
|
if XMask = 64 or XMask = 256 then return 128
|
|
end if
|
|
--third check if a user can make make it win (defensive) place it on position
|
|
repeat with spot in freeSpots
|
|
if winnerForMask(XMask + spot) then return OMask + spot
|
|
end repeat
|
|
|
|
--fourth check if CPU can win in two moves
|
|
repeat with spot1 in freeSpots
|
|
repeat with spot2 in freeSpots
|
|
if winnerForMask(OMask + spot1 + spot2) then return OMask + spot2
|
|
end repeat
|
|
end repeat
|
|
--fifth check if player can win in two moves
|
|
repeat with spot1 in freeSpots
|
|
repeat with spot2 in reverse of freeSpots
|
|
if winnerForMask(XMask + spot1 + spot2) then return OMask + spot1
|
|
end repeat
|
|
end repeat
|
|
--at last pick a random spot
|
|
if XMask + OMask = 0 and difficulty = "Hard" then return 1
|
|
|
|
return OMask + (some item of freeSpots)
|
|
end npcGet
|
|
|
|
on winnerForMask(mask)
|
|
repeat with winLine in winningNumbers
|
|
if BWAND(winLine, mask) = contents of winLine then return true
|
|
end repeat
|
|
return false
|
|
end winnerForMask
|
|
|
|
on drawGrid()
|
|
set grid to ""
|
|
repeat with o from 0 to 8
|
|
if BWAND(OMask, 2 ^ o) = 2 ^ o then
|
|
set grid to grid & "O"
|
|
else if BWAND(XMask, 2 ^ o) = 2 ^ o then
|
|
set grid to grid & "X"
|
|
else
|
|
set grid to grid & o + 1
|
|
end if
|
|
if o is in {2, 5} then set grid to grid & return
|
|
end repeat
|
|
return grid
|
|
end drawGrid
|
|
|
|
on positionIsUsed(pos)
|
|
return BWAND(OMask + XMask, 2 ^ (pos - 1)) = 2 ^ (pos - 1)
|
|
end positionIsUsed
|
|
|
|
on BWAND(n1, n2)
|
|
set theResult to 0
|
|
repeat with o from 0 to 8
|
|
if (n1 mod 2) = 1 and (n2 mod 2) = 1 then set theResult to theResult + 2 ^ o
|
|
set {n1, n2} to {n1 div 2, n2 div 2}
|
|
end repeat
|
|
return theResult as integer
|
|
end BWAND
|