Code archives/Algorithms/Tic tac toe that learns
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This is a fun tic tac toe game that I made that has VERY basic controls and graphics. This basic program slowly learns from its mistakes. The better you are at tic-tac-toe the better it will become after a few hundred games against you :) If you make tons of mistakes or tie a lot then it will end up the same way. Enough about that here's how it works... The first time you play it, it saves your game after moving almost completely randomly... The second time you play it, it will do the same but this time if you are playing the opposite side you were on the first time it may try and pull the same trick on you, however there is a 2 in 10 chance it will try a new move that it doesnt know will make it win... ... 1000 plays later it has figured out all of your moves and how to defend them and it is hard for you to beat... or its at least a little challenge :) thats how it works so here it is... Very sorry for the extremely simple graphics and controls but that was not the point of this project... controls are 1 2 3 q w e a s d for each square on the board other things to know sometimes it goes first sometimes you go first there is a delay of 400 ms before it moves the bigger the number above the board the better its chances of winning p.s. sorry its not commented but that shouldnt be too much of a problem because it is relatively simple and I just explained it IMPORTANT: make this program its own folder with nothing else in it so that it doesnt fill your other folders with junk :) | |||||
; ID: 2370
; Author: Nate the Great
; Date: 2008-12-10 02:54:40
; Title: Tic tac toe that learns
; Description: Learns... slowly but surely
SeedRnd(MilliSecs())
Graphics 160,120,0,2
Dim mov(9)
Dim grid(3,3)
Dim moved(9)
Global membankcount = 0, test = 0
Type game
Field m[9],winner
End Type
cnt = 0
While ext <> 1
fileopn$ = "membank" + cnt + ".mem"
cnt = cnt + 1
file = OpenFile(fileopn$)
If Not file = 0 Then
g.game = New game
g\m[1] = ReadInt(file)
g\m[2] = ReadInt(file)
g\m[3] = ReadInt(file)
g\m[4] = ReadInt(file)
g\m[5] = ReadInt(file)
g\m[6] = ReadInt(file)
g\m[7] = ReadInt(file)
g\m[8] = ReadInt(file)
g\m[9] = ReadInt(file)
g\winner = ReadInt(file)
membankcount = membankcount + 1
CloseFile(file)
file = OpenFile(fileopn$)
g.game = New game
g\m[7] = ReadInt(file)
g\m[4] = ReadInt(file)
g\m[1] = ReadInt(file)
g\m[8] = ReadInt(file)
g\m[5] = ReadInt(file)
g\m[2] = ReadInt(file)
g\m[9] = ReadInt(file)
g\m[6] = ReadInt(file)
g\m[3] = ReadInt(file)
g\winner = ReadInt(file)
CloseFile(file)
file = OpenFile(fileopn$)
g.game = New game
g\m[9] = ReadInt(file)
g\m[8] = ReadInt(file)
g\m[7] = ReadInt(file)
g\m[6] = ReadInt(file)
g\m[5] = ReadInt(file)
g\m[4] = ReadInt(file)
g\m[3] = ReadInt(file)
g\m[2] = ReadInt(file)
g\m[1] = ReadInt(file)
g\winner = ReadInt(file)
CloseFile(file)
file = OpenFile(fileopn$)
g.game = New game
g\m[3] = ReadInt(file)
g\m[6] = ReadInt(file)
g\m[9] = ReadInt(file)
g\m[2] = ReadInt(file)
g\m[5] = ReadInt(file)
g\m[8] = ReadInt(file)
g\m[1] = ReadInt(file)
g\m[4] = ReadInt(file)
g\m[7] = ReadInt(file)
g\winner = ReadInt(file)
g.game = New game
g\m[3] = ReadInt(file)
g\m[2] = ReadInt(file)
g\m[1] = ReadInt(file)
g\m[6] = ReadInt(file)
g\m[5] = ReadInt(file)
g\m[4] = ReadInt(file)
g\m[9] = ReadInt(file)
g\m[8] = ReadInt(file)
g\m[7] = ReadInt(file)
g\winner = ReadInt(file)
CloseFile(file)
file = OpenFile(fileopn$)
g.game = New game
g\m[9] = ReadInt(file)
g\m[6] = ReadInt(file)
g\m[3] = ReadInt(file)
g\m[8] = ReadInt(file)
g\m[5] = ReadInt(file)
g\m[2] = ReadInt(file)
g\m[7] = ReadInt(file)
g\m[4] = ReadInt(file)
g\m[1] = ReadInt(file)
g\winner = ReadInt(file)
CloseFile(file)
file = OpenFile(fileopn$)
g.game = New game
g\m[7] = ReadInt(file)
g\m[8] = ReadInt(file)
g\m[9] = ReadInt(file)
g\m[4] = ReadInt(file)
g\m[5] = ReadInt(file)
g\m[6] = ReadInt(file)
g\m[1] = ReadInt(file)
g\m[2] = ReadInt(file)
g\m[3] = ReadInt(file)
g\winner = ReadInt(file)
CloseFile(file)
file = OpenFile(fileopn$)
g.game = New game
g\m[1] = ReadInt(file)
g\m[4] = ReadInt(file)
g\m[7] = ReadInt(file)
g\m[2] = ReadInt(file)
g\m[5] = ReadInt(file)
g\m[8] = ReadInt(file)
g\m[3] = ReadInt(file)
g\m[6] = ReadInt(file)
g\m[9] = ReadInt(file)
g\winner = ReadInt(file)
CloseFile(file)
Else
ext = 1
EndIf
Wend
tmprndnum = Rnd(100)
If tmprndnum > 50 Then
tmprndnum = 1
Else
tmprndnum = 0
EndIf
Global move = tmprndnum,num
Global start = move
SetBuffer BackBuffer()
Cls
AppTitle("Tic-Tac-Toe")
Text 1,1, "Tic-Tac-Toe"
;Text 1,20,"Press a key."
Flip
;WaitKey()
;Delay 1000
FlushKeys()
Cls
Text 1,1, "Tic-Tac-Toe"
Line 14,40,14,95
Line 34,40,34,95
Line 1,54,54,54
Line 1,74,54,74
Flip
ext = 0
While Not ext
Cls
If KeyDown(1) Then ext = True
Text 1,1, "Tic-Tac-Toe"
;If move = 0 Then
If move = 0 Then
Goto wngplc2
.wngplc
num = num - 1
.wngplc2
WaitKey()
num = num + 1
If KeyHit(2) Then
If moved(1) = 0 Then
mov(num) = 1
moved(1) = 1
Else
FlushKeys()
Goto wngplc
EndIf
ElseIf KeyHit(3)
If moved(2) = 0 Then
mov(num) = 2
moved(2) = 1
Else
FlushKeys()
Goto wngplc
EndIf
ElseIf KeyHit(4)
If moved(3) = 0 Then
mov(num) = 3
moved(3) = 1
Else
FlushKeys()
Goto wngplc
EndIf
ElseIf KeyHit(16)
If moved(4) = 0 Then
mov(num) = 4
moved(4) = 1
Else
FlushKeys()
Goto wngplc
EndIf
ElseIf KeyHit(17)
If moved(5) = 0 Then
mov(num) = 5
moved(5) = 1
Else
FlushKeys()
Goto wngplc
EndIf
ElseIf KeyHit(18)
If moved(6) = 0 Then
mov(num) = 6
moved(6) = 1
Else
FlushKeys()
Goto wngplc
EndIf
ElseIf KeyHit(30)
If moved(7) = 0 Then
mov(num) = 7
moved(7) = 1
Else
FlushKeys()
Goto wngplc
EndIf
ElseIf KeyHit(31)
If moved(8) = 0 Then
mov(num) = 8
moved(8) = 1
Else
FlushKeys()
Goto wngplc
EndIf
ElseIf KeyHit(32)
If moved(9) = 0 Then
mov(num) = 9
moved(9) = 1
Else
FlushKeys()
Goto wngplc
EndIf
EndIf
Else
Delay 400
Goto wngplc4
.wngplc3
num = num - 1
.wngplc4
match = 0
smmove = 0
count = 0
For g.game = Each game
count = count + 1
same = 0
If g\winner = 1 And start = 1 And num > 0 Then
same = 1
For a = 1 To num
If g\m[a] <> mov(a) Then same = 0
Next
ElseIf g\winner = 2 And start = 0 And num > 0 Then
same = 1
For a = 1 To num
If g\m[a] <> mov(a) Then same = 0
Next
EndIf
If num = 0 And g\winner = 1 Then
same = 1
EndIf
If same = 1 Then
chnce = Rnd(0,10)
If chnce > 5 Then
smmove = g\m[num+1]
test = True
EndIf
Else
Delete g.game
EndIf
Next
If smmove = 0 Then
tmppic = Rnd(1,9)
Else
tmppic = smmove
EndIf
num = num + 1
If tmppic = 1 Then
If moved(1) = 0 Then
mov(num) = 1
moved(1) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
ElseIf tmppic = 2 Then
If moved(2) = 0 Then
mov(num) = 2
moved(2) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
ElseIf tmppic = 3 Then
If moved(3) = 0 Then
mov(num) = 3
moved(3) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
ElseIf tmppic = 4 Then
If moved(4) = 0 Then
mov(num) = 4
moved(4) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
ElseIf tmppic = 5 Then
If moved(5) = 0 Then
mov(num) = 5
moved(5) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
ElseIf tmppic = 6 Then
If moved(6) = 0 Then
mov(num) = 6
moved(6) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
ElseIf tmppic = 7 Then
If moved(7) = 0 Then
mov(num) = 7
moved(7) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
ElseIf tmppic = 8 Then
If moved(8) = 0 Then
mov(num) = 8
moved(8) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
ElseIf tmppic = 9 Then
If moved(9) = 0 Then
mov(num) = 9
moved(9) = 1
Else
FlushKeys()
Goto wngplc3
EndIf
EndIf
EndIf
For a = 1 To 9
If a = 1 Or a = 3 Or a = 5 Or a = 7 Or a = 9 Then
Select mov(a)
Case 1
Text 1,40,"X"
Case 2
Text 20,40,"X"
Case 3
Text 40,40,"X"
Case 4
Text 1,60,"X"
Case 5
Text 20,60,"X"
Case 6
Text 40,60,"X"
Case 7
Text 1,80,"X"
Case 8
Text 20,80,"X"
Case 9
Text 40,80,"X"
End Select
Else
Select mov(a)
Case 1
Text 1,40,"O"
Case 2
Text 20,40,"O"
Case 3
Text 40,40,"O"
Case 4
Text 1,60,"O"
Case 5
Text 20,60,"O"
Case 6
Text 40,60,"O"
Case 7
Text 1,80,"O"
Case 8
Text 20,80,"O"
Case 9
Text 40,80,"O"
End Select
EndIf
Next
Line 14,40,14,95
Line 34,40,34,95
Line 1,54,54,54
Line 1,74,54,74
move = Not move
If checkwin() Then ext = 1
If num = 9 Then ext = 1
Text 1,20,count
Flip
Wend
winner = checkwin()
Cls
If winner = 1
If start = 0
Text 1,1,"Player Wins"
Else
Text 1,1,"Computer Wins"
EndIf
ElseIf winner = 2
If start = 1
Text 1,1,"Player Wins"
Else
Text 1,1,"Computer Wins"
EndIf
EndIf
fileopn$ = "membank" + membankcount + ".mem"
filetmp = WriteFile(fileopn$)
For a = 1 To 9
WriteInt(filetmp,mov(a))
Next
WriteInt(filetmp,winner)
Delay 1000
Flip
Delay 1000
End
Function checkwin()
win = 0
For x = 1 To 3
For y = 1 To 3
grid(x,y) = 0
Next
Next
For a = 1 To 9
If mov(a) > 0 Then
If a = 1 Or a = 3 Or a = 5 Or a = 7 Or a = 9 Then
If mov(a) > 3 And mov(a) < 7
grid(2,mov(a)-3) = 1
ElseIf mov(a) > 6
grid(3,mov(a)-6) = 1
ElseIf mov(a) < 4
grid(1,mov(a)) = 1
EndIf
Else
If mov(a) > 3 And mov(a) < 7
grid(2,mov(a)-3) = 2
ElseIf mov(a) > 6
grid(3,mov(a)-6) = 2
ElseIf mov(a) < 4
grid(1,mov(a)) = 2
EndIf
EndIf
EndIf
Next
For a = 1 To 3
If grid(a,1) = 1 And grid(a,2) = 1 And grid(a,3) = 1 Then win = 1
If grid(a,1) = 2 And grid(a,2) = 2 And grid(a,3) = 2 Then win = 2
If grid(1,a) = 1 And grid(2,a) = 1 And grid(3,a) = 1 Then win = 1
If grid(1,a) = 2 And grid(2,a) = 2 And grid(3,a) = 2 Then win = 2
Next
If grid(1,1) = 1 And grid(2,2) = 1 And grid(3,3) = 1 Then win = 1
If grid(1,3) = 1 And grid(2,2) = 1 And grid(3,1) = 1 Then win = 1
If grid(1,1) = 2 And grid(2,2) = 2 And grid(3,3) = 2 Then win = 2
If grid(1,3) = 2 And grid(2,2) = 2 And grid(3,1) = 2 Then win = 2
Return win
End Function |
Comments
| ||
| some things I forgot to mention in my first post... here is how it "learns" there are 3 stages after bout 100 plays = 1st stage it now generally knows how to get 3 in a row but its not perfect and it is vulnerable after bout 500 plays = 2nd stage it now can block some/most attacks depending on how well you play after bout 1000 plays = 3rd stage it is now pretty good and it keeps you alert please post if you get different results hmm... I guess it is too good lol after playing a long time I realized I was playing some of the same games over and over. I assume this is because i have been the only one playing it and it has become like me in the way it plays... therefore it is like playing yourself... I recommend having many people play it so that this doesn't happen as it did to me |
| ||
| You need to include the save file. |
| ||
| it doesnt really need a save file... it senses whether there is already a file and if there isnt it creates one. |
| ||
| moved a closefile. Tht fixed the problem. |
| ||
| oh sorry I will update that thanks! |
| ||
| hmmm... are you useing blitz plus or b3d? that may be the problem |
| ||
| B3D. The closefile was outside of the if statement, so even though it didn't exist, that closefile would still execute. |
| ||
| Interesting, but you must keep in mind that tic-tac-toe is really a set game. If the first move is an "X" in one corner, it will always be a tie or X's win if the X player knows how to move, no matter what O does (ever seen those "Beat The Bird" games at carnivals, that is how they work). Still impressive, and I would love to see something like this with checkers! |
| ||
| H. T. U. that is exactly what this program takes advantage of! however it could be applied to games like checkers and chess possibly if it is modified |
| ||
| Cool - I'll have to look at this to see how it works. It seems like a form of machine learning. Have you considered modifying it so that two computers could play against each other? It would quickly become invincible - or crash. :-) I'm very interested in neural networks, machine learning, and other AI. This is cool! On a related topic, has anyone created a neural network with Blitz?.. |
| ||
| Have you considered modifying it so that two computers could play against each other? It would quickly become invincible - or crash. :-) yep and it doesnt learn very fast pleying against an opponent that knows just as much as itself :) On a related topic, has anyone created a neural network with Blitz?.. as far as I know the answer is no :( although it would be interesting |
| ||
| Showing my age here but I had a flashback to http://www.haar.clara.co.uk/Lights/merlin.html |
| ||
| What's key here, of course, is the code for HOW the computer 'learns', and it's "understanding" of how to play. It's well done here, for tic-tac-toe, and a very clear example, but would need sdome heavy work for something like chess and other gameplay where the potential for strategc moves increases and the releveance of moves varies by greater amounts to more possible favours such as defensive play, offensive play, and the various "values" that can be ascribed to defending or attacking a particular piece. I prefer to go with chess AI where the difference between a "good AI level" to a "poor AI level" is the numebr of iterations of possible moves checked for 'better overall values' and consideration of (depth of numbers of ) counter-moves. Essentially, the AI would spend more time 'thinking' on a move. Allowing a chess program to 'learn' as in the above Tic-Tac-Toe method, would be somewhat specific to circumstances, popponent and opening strategies, which are MUCH more versatile than Tic-Tac-Tow, and where the generalised gameplay strategy is sufficient. |
| ||
| It is possible to use learning AI's in games: - The learning AI was one of the main selling points for Fear (the "can't beat it the 3rd time" line is because the AI has learned enough to be nigh unbeatable the 3rd time through). - Although I haven't heard it mentioned before, C&C Tiberium Wars seems to have a learning AI that gets reset after every patch - I've noticed that the brutal AI especially is pathetic for the first couple games after a patch, but them it regains its strength. If you want to make a learning AI for like chess or something, try to figure out a way for it to access a data file on some website so you can have lots of computers providing input and thereby getting it to learn much faster. |
Code Archives Forum