Do you like tic-tac-toe? If yes, would you like it on your calculator?
Yes
 60%  [ 6 ]
No
 40%  [ 4 ]
Total Votes : 10

You can do win checking on rows and columns with

Code:
Matr>list(cumSum([A]),3,L1     //for columns
Matr>list(cumSum([A]^^T),3,L2  // for rows
imag(max(max(iL1,iL2         //largest absolute value
If Ans=3
Then
//player (+) has won
Else
If Ans=-3
Then
//player (-) has won
End:End
//also need to check for diagonals at some point


Edit:


Code:
If L1(1)=A and L1(1)=L1(5)=L1(9

will not work. This expression evalutes to (boolean L1(1)=L1(5))=L1(9), so it is really comparing L1(9) to 0 or 1 depending on whether L1(1) equals L1(5).
Lirtosiast: I haven't looked into using cumSum(, it seems to be small and fast. The diagonals can be put in an If-Then. Looks great! Smile
Note: this was already tried. This does work, but then we switched over to matrices. And the matrix->list only works with the matrix columns. We would then have to write another win-check for all of the rows. But I'll try it anyways, just to see if it can be a little bit more optimized.
Well, well, well, well.... It turns out that using lists does work quite well. I manages to get the program to well within the 1 kb limit!!!!!!!!!!!!!!!!! Will post the code in a few days.(at the latest)



AND IT WORKS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Here is some fresh-ish AI code, with an addition in the end that likes to play along rows and columns of placed pieces and in the corners to try and counter opposing stragies:

SourceCoder 3 (NEWTTTAI) wrote:
:ClrList L1
:ClrList L2
:0->T
:4->U
:For(S,1,3
:If [A](S,1)=[A](S,2) and [A](S,1)not([A](S,3
:Then
:S->L1(1+dim(L1
:3->L2(1+dim(L2
:If [A](S,2)=U
:dim(L1->T
:End
:If [A](S,1)=[A](S,3) and [A](S,1)not([A](S,2
:Then
:S->L1(1+dim(L1
:2->L2(1+dim(L2
:If [A](S,3)=U
:dim(L1->T
:End
:If [A](S,2)=[A](S,3) and [A](S,2)not([A](S,1
:Then
:S->L1(1+dim(L1
:1->L2(1+dim(L2
:If [A](S,3)=U
:dim(L1->T
:End
:If [A](1,S)=[A](2,S) and [A](1,S)not([A](3,S
:Then
:3->L1(1+dim(L1
:S->L2(1+dim(L2
:If [A](2,S)=U
:dim(L1->T
:End
:If [A](1,S)=[A](3,S) and [A](1,S)not([A](2,S
:Then
:2->L1(1+dim(L1
:S->L2(1+dim(L2
:If [A](3,S)=U
:dim(L1->T
:End
:If [A](2,S)=[A](3,S) and [A](2,S)not([A](1,S
:Then
:1->L1(1+dim(L1
:S->L2(1+dim(L2
:If [A](3,S)=U
:dim(L1->T
:End
:End
:If [A](1,1)=[A](2,2) and [A](1,1)not([A](3,3
:Then
:3->L1(1+dim(L1
:3->L2(1+dim(L2
:If [A](2,2)=U
:dim(L1->T
:End
:If [A](1,1)=[A](3,3) and [A](1,1)not([A](2,2
:Then
:2->L1(1+dim(L1
:2->L2(1+dim(L2
:If [A](3,3)=U
:dim(L1->T
:End
:If [A](3,3)=[A](2,2) and [A](3,3)not([A](1,1
:Then
:1->L1(1+dim(L1
:1->L2(1+dim(L2
:If [A](2,2)=U
:dim(L1->T
:End
:If [A](3,1)=[A](2,2) and [A](3,1)not([A](1,3
:Then
:1->L1(1+dim(L1
:3->L2(1+dim(L2
:If [A](2,2)=U
:dim(L1->T
:End
:If [A](3,1)=[A](1,3) and [A](3,1)not([A](2,2
:Then
:2->L1(1+dim(L1
:2->L2(1+dim(L2
:If [A](1,3)=U
:dim(L1->T
:End
:If [A](1,3)=[A](2,2) and [A](1,3)not([A](3,1
:Then
:3->L1(1+dim(L1
:1->L2(1+dim(L2
:If [A](2,2)=U
:dim(L1->T
:End
://new stuff here
:If not(dim(L1
:Then
:For(G,1,3
:For(H,1,3
:If 1=[A](G,H) and not(G=2 and H=2
:Then
:For(S,1,3,2
:If not([A]G,S
:Then
:G->L1(1+dim(L1
:S->L2(1+dim(L2
:End
:If not([A](S,H
:Then
:S->L1(1+dim(L1
:H->L1(1+dim(L2
:End
:End
:End
:End
:End
:If [A](2,2
:Then
:For(G,1,3,2
:For(H,1,3,2
:If not([A](G,H
:Then
:G->L1(1+dim(L1
:H->L2(1+dim(L2
:End
:End
:End
:End
:End
://new stuff ends
:If dim(L1
:Then
:randInt(1,dim(L1->theta
:L1(theta->I
:L2(theta->J
:If T
:Then
:L1(T->I
:L2(T->J
:End
:Else
:Repeat not([A](I,J
:randInt(1,3->I
:randInt(1,3->J
:End
:End


It amounts to around 1.3kb on-calc. Many of the checks it makes are repetitive, and could probably be optimized to save space. It uses variables U,T,G,S,H,L1,and L2, reading from [A], and returning the move to make in reference to the matrix at I,J. Change to value of U to -1 or whatever number represents the computer in your matrix.
Going to do some optimization, I had created this, before the "new stuff" of NoahK:
SourceCoder 3 (TTT) wrote:
:ClrList L1
:ClrList L2
:0->T
:4->U
:For(S,1,3
:For(Q,1,3
:If [A](S,int(Q/3+1))=[A](S,int(Q/4+2.5)) and [A](S,int(Q/3+1))not([A](S,4-Q
:Then
:S->L1(1+dim(L1
:Q->L2(1+dim(L2
:If U=[A](S,int(Q/4+2.5
:dim(L1->T
:End
:If [A](int(Q/3+1),S)=[A](int(Q/4+2.5),S) and [A](int(Q/3+1),S)not([A](4-Q,S
:Then
:Q->L1(1+dim(L1
:S->L2(1+dim(L2
:If U=[A](int(Q/4+2.5),S
:dim(L1->T
:End
:End
:If [A](S-(S=2),S-(S=2))=[A](S+1-2(S=3),S+1-2(S=3)) and [A](S-(S=2),S-(S=2))not([A](4-S,4-S
:Then
:4-S->L1(1+dim(L1
:4-S->L2(1+dim(L2
:If U=[A](S+1-2(S=3),S+1-2(S=3
:dim(L1->T
:End
:If [A](4-S+(S=2),S-(S=2))=[A](3-S+2(S=3),S+1-2(S=3)) and [A](4-S+(S=2),S-(S=2))not([A](S,4-S
:Then
:S->L1(1+dim(L1
:4-S->3->L2(1+dim(L2
:If U=[A](3-S+2(S=3),S+1-2(S=3)
:dim(L1->T
:End
:End
://new stuff here
:If not(dim(L1
:Then
:For(G,1,3
:For(H,1,3
:If 1=[A](G,H) and not(G=2 and H=2
:Then
:For(S,1,3,2
:If not([A]G,S
:Then
:G->L1(1+dim(L1
:S->L2(1+dim(L2
:End
:If not([A](S,H
:Then
:S->L1(1+dim(L1
:H->L1(1+dim(L2
:End
:End
:End
:End
:End
:If [A](2,2
:Then
:For(G,1,3,2
:For(H,1,3,2
:If not([A](G,H
:Then
:G->L1(1+dim(L1
:H->L2(1+dim(L2
:End
:End
:End
:End
:End
://new stuff ends
:If dim(L1
:Then
:randInt(1,dim(L1->theta
:L1(theta->I
:L2(theta->J
:If T
:Then
:L1(T->I
:L2(T->J
:End
:Else
:Repeat not([A](I,J
:randInt(1,3->I
:randInt(1,3->J
:End
:End

Hopefully you can understand this.

Code:
int(Q/3+1) --> {1,1,3}
int(Q/4+2.5) --> {2,3,3}
S-(S=2) --> {1,1,2}
S+1-2(S=3) --> {2,3,3}
4-S+(S=2) --> {3,3,1}
3-S+2(S=3) --> {2,1,2}
Quote:

Hopefully you can understand this.

Code:
int(Q/3+1) --> {1,1,3}
int(Q/4+2.5) --> {2,3,3}
S-(S=2) --> {1,1,2}
S+1-2(S=3) --> {2,3,3}
4-S+(S=2) --> {3,3,1}
3-S+2(S=3) --> {2,1,2}


And what does the code mean/do?[/quote]
caleb1997 wrote:
Quote:

Hopefully you can understand this.

Code:
int(Q/3+1) --> {1,1,3}
int(Q/4+2.5) --> {2,3,3}
S-(S=2) --> {1,1,2}
S+1-2(S=3) --> {2,3,3}
4-S+(S=2) --> {3,3,1}
3-S+2(S=3) --> {2,1,2}


And what does the code mean/do?
[/quote]

These are snippets of code that PT_ used to convert 1,2,3 into usable numbers.
For example this:

Code:
NoahK wrote:
If [A](S,1) ...
.....
If [A](S,1) ...
.....
If [A](S,3) ...
.....

Since I use Q, and do the if-statement once, instead of 3 times, I replace it with this:

Code:
If [A](S,Q-(Q=2))
PT_ wrote:
For example this:

Code:
NoahK wrote:
If [A](S,1) ...
.....
If [A](S,1) ...
.....
If [A](S,3) ...
.....

Since I use Q, and do the if-statement once, instead of 3 times, I replace it with this:

Code:
If [A](S,Q-(Q=2))


And what does this mean? What does this code do? I don't see how it relates to the AI........... Confused
caleb1997 wrote:
And what does this mean? What does this code do? I don't see how it relates to the AI........... Confused
That you must ask NoahK, he creates it, I only optimized it.
PT_ wrote:
caleb1997 wrote:
And what does this mean? What does this code do? I don't see how it relates to the AI........... Confused
That you must ask NoahK, he creates it, I only optimized it.


Wow, I never would have thought I would be the one people are dependent on Laughing Those snippets of code, as I said before, PT_ used to optimize my AI. Where I had written:


Code:
:If [A](S,1)=[A](S,2) and [A](S,1)not([A](S,3
:Then
:S->L1(1+dim(L1
:3->L2(1+dim(L2
:If [A](S,2)=U
:dim(L1->T
:End
:If [A](S,1)=[A](S,3) and [A](S,1)not([A](S,2
:Then
:S->L1(1+dim(L1
:2->L2(1+dim(L2
:If [A](S,3)=U
:dim(L1->T
:End
:If [A](S,2)=[A](S,3) and [A](S,2)not([A](S,1
:Then
:S->L1(1+dim(L1
:1->L2(1+dim(L2
:If [A](S,3)=U
:dim(L1->T
:End


If you can see the numbers, going from top to bottom then left to right, wherever there is a [A](S,#), the numbers look like:


Code:
{1,1,2}
{2,3,3}
{1,1,2}
{3,3,1}


Those snippets turn the sequence {1,2,3} into those sequences, so a For-loop can be made. That would take those 3 If-Then's and turn them into one If-Then inside a For-loop. It is simply an optimization in size from what I previously posted.

Note: I'm still working to make the AI smarter, as I can consistently beat it with a sequence of select moves.
Here is a screenshot of my code with PT_'s optimizations:



Shown are 3 cases where the current AI has trouble not loosing, so I'm trying to make it smarter.

The AI could use a speed increase and a size decrease, and PT_ and I are on the case Smile
You can also use complex lists to store coordinates if you're not optimizing away this AI format.


Code:
S->L1(1+dim(L1 
3->L2(1+dim(L2

can be

S+3i->L1(1+dim(L1
Good thinking there, Lirtosaist! Very Happy

I am doing a re-design of the AI, and I am getting the AI's move priorities in line. So far, the routine's priorities are as follows:
NoahK wrote:
1) Place the winning move
2) Prevent the player from placing the winning move on the next turn (eg. if the player has 2 in a row, place the third one to block it)
3) Move in a corner adjacent to a spot already played
4) Move in an edge of a adjacent to a spot already played
5) Make a random move

I think it would work better like this:
NoahK wrote:
1) Place the winning move
2) Prevent the player from placing the winning move on the next turn (eg. if the player has 2 in a row, place the third one to block it)
3) Play the center spot
4) Move in a corner adjacent to a spot already played
5) Move in an edge adjacent to a spot already played
6) Make a random move


<Edit>

In searching for Tic-Tac-Toe AI, I found this little list:
StackExcange Link
recursion.ninja on StackExchange wrote:
The following algorithm will allow you (or the AI) to always deny your opponent victory:

Win: If you have two in a row, you can place a third to get three in a row.
Block: If the opponent has two in a row, you must play the third to block the opponent.
Fork: Create an opportunity where you have two threats to win (two non-blocked lines of 2).
Blocking an opponent's fork: If there is a configuration where the opponent can fork, you must block that fork.
Center: You play the center if open.
Opposite corner: If the opponent is in the corner, you play the opposite corner.
Empty corner: You play in a corner square.
Empty side: You play in a middle square on any of the 4 sides.

Pick the highest possible on the list


I will do my best to implement this, though the forking may be hard to do.




<Edit some more>

I've fiddled around with using that algorithm I found, and here are the results:


SourceCoder 3 (OPTICODE) wrote:
:ClrList L1
:0->T
:4->U
://Check for Win and Block (if Win, Winning move is located at T)
:For(S,1,3
:For(Q,1,3
:If [A](S,Q-1+(Q=1))=[A](S,Q+1-(Q=3)) and [A](S,Q-1+(Q=1))not([A](S,4-Q
:Then
:S+(4-Q)[i]->L1(1+dim(L1
:If U=[A](S,Q+1-(Q=3
:dim(L1->T
:End
:If [A](Q-1+(Q=1),S)=[A](Q+1-(Q=3),S) and [A](Q-1+(Q=1),S)not([A](4-Q,S
:Then
:4-Q+S[i]->L1(1+dim(L1
:If U=[A](Q+1-(Q=3),S
:dim(L1->T
:End
:End
:End
:
://Check for forking
:If not(dim(L1
:Then
://code coming soon (hopefully)
:End
:
://Check to block a fork
:If not(dim(L1
:Then
://code coming soon (hopefully)
:End
:
://Play the center if possible
:If not(dim(L1
:Then
:If not([A](2,2
:2+2[i]->L1(1+dim(L1
:End
:
://Play a corner opposite the opponent. (or opposite self, as that is a peudo-fork-maker, and will stand for the fork code for now
:If not(dim(L1
:Then
:For(S,1,3,2
:For(Q,1,3,2
:If [A](4-S,4-Q) and not([A](S,Q
:S+Q[i]->L1(1+dim(L1
:End
:End
:End
:
://Play random open corner
:If not(dim(L1
:Then
:For(S,1,3,2
:For(Q,1,3,2
:If not([A](S,Q
:S+Q[i]->L1(1+dim(L1
:End
:End
:End
:
://Play random open edge
:If not(dim(L1
:Then
:For(S,1,3,2
:If not([A](2,S
:2+S[i]->L1(1+dim(L1
:If not([A](S,2
:S+2[i]->L1(1+dim(L1
:End
:End
:
://Finish it off
:not(T)randInt(1,dim(L1))+T->S
:real(L1(S->I
:imag(L1(S->J


This also implements Lirtosaist's imaginary list idea. This code is a charm!
It is only 503 bytes on the calc, and that includes the empty If-Then's. And it's super smart acting now! Laughing

The shell I am using to use the AI code it the same as before, just with a call to this new program:

Code:
:DSS6
"0810081008100810FFFF081008500B100D500B500810FFFF0810081008100810"
SetUpEditor
AxesOff
0->O
0->N
Lbl 0
ClrHome
{3,3->dim([A]
Fill(0,[A]
Menu("Tic-Tac-Toe AI","Play",1,"Quit",2
Lbl 1
ClrDraw
~33->Xmin
61->Ymax
~1->Ymin
61->Xmax
For(A,0,60,20
Line(A,0,A,60
Line(0,A,60,A
End
Text(20,0,"GAMES WON
Text(26,0,"O: ",O
Text(32,0,"X: ",N
1->P
2->A
2->B
0->W
0->R
Repeat W or theta=45
If B>3
3->B
Text(0,0,"O'S TURN
Pt-On(20A-10,20B-10
Repeat theta
getKey->theta
End
Pt-Off(20A-10,20B-10
A+(theta=26 and A<3)-(theta=24 and A>1->A
B+(theta=25 and B<3)-(theta=34 and B>1->B
Pt-On(20A-10,20B-10
If theta=105 and not([A](A,B)
Then
R+1->R
Pt-Off(20A-10,20B-10
Circle(20A-10,20B-10,7
1->[A](A,B

0->D
0->E
0->W
For(C,1,3
[A](1,C)+[A](2,C)+[A](3,C->D
[A](C,1)+[A](C,2)+[A](C,3->E
If D=3 or E=3
1->W
If D=12 or E=12
2->W
End
[A](1,1)+[A](2,2)+[A](3,3->D
[A](3,1)+[A](2,2)+[A](1,3->E
If D=3 or E=3
1->W
If D=12 or E=12
2->W

If R<9 and not(W
Then
R+1->R
Text(0,0,"X'S TURN

prgmOPTICODE

4->[A](I,J
Line(20I-3,20J-3,20I-17,20J-17
Line(20I-3,20J-17,20I-17,20J-3
Pt-Off(20I-10,20J-10
End
End

0->D
0->E
0->W
For(C,1,3
[A](1,C)+[A](2,C)+[A](3,C->D
[A](C,1)+[A](C,2)+[A](C,3->E
If D=3 or E=3
1->W
If D=12 or E=12
2->W
End
[A](1,1)+[A](2,2)+[A](3,3->D
[A](3,1)+[A](2,2)+[A](1,3->E
If D=3 or E=3
1->W
If D=12 or E=12
2->W

If R=9 and not(W
45->theta
End
If W
Then
O+(W=1->O
N+(W=2->N
Text(0,0,sub("OX",W,1)," WINS!         "
Text(26,7,O
Text(32,7,N
Pause
Else
Text(0,0,"TIE!             "
Pause
End
Goto 0
Lbl 2
ClrHome
Stop


Once this gets optimized (PT_), we should be getting closer and closer to a <1kb size! (Right now the shell here is 1115 and the new AI is 527)

WHOOO THIS IS COMING ALONG AWESOMELY!!!
This is probably the 7th edit to this post...

Here is a screenshot of the new AI in action:

It's pretty good. Very Happy
Good job, guys!

I will try to optimize this code some more, but it's mainly up to you guys. I will also post the code that I have hopefully soon, as I am really busy with schoolwork. I even have barely enough time to type this post......
NoahK wrote:
Once this gets optimized (PT_), we should be getting closer and closer to a <1kb size! (Right now the shell here is 1115 and the new AI is 527)

I'm 'the optimizing boy'? Razz
Well, I wil take a look
Sorry for doubleposting!
NoahK wrote:
Once this gets optimized (PT_), we should be getting closer and closer to a <1kb size! (Right now the shell here is 1115 and the new AI is 527)
WHOOO THIS IS COMING ALONG AWESOMELY!!!


I HAVE GOOD NEWS, OPTIMIZED UPTO ONLY 954 BYTES!!!
First of all, my code:
SourceCoder 3 (TTT) wrote:
::DCS6
:"0810081008100810FFFF081008500B100D500B500810FFFF0810081008100810
:AxesOff
:0->O
:0->N
:Lbl 0
:0identity(3->[A]
:Menu("Tic-Tac-Toe AI","Play",1,"Quit",2
:Lbl 2
:ClrHome
:Stop
:Lbl 1
:ClrDraw
:~33->Xmin
:61->Ymax
:~1->Ymin
:61->Xmax
:For(A,0,60,20
:Line(A,0,A,60
:Line(0,A,60,A
:End
:Text(20,0,"GAMES WON
:Text(26,0,"O: ",O
:Text(32,0,"X: ",N
:2->A
:2->B
:0->W
:0->R
:Repeat W or theta=45 or (R=9 and not(W
:min(3,B->B
:Text(0,0,"O'S TURN
:Pt-On(20A-10,20B-10
:Repeat Ans
:getKey
:End
:Ans->theta
:Pt-Off(20A-10,20B-10
:min(3,max(1,A+(theta=26)-(theta=24->A
:min(3,max(1,B+(theta=25)-(theta=34->B
:Pt-On(20A-10,20B-10
:If theta=105 and not([A](A,B
:Then
:R+1->R
:Pt-Off(20A-10,20B-10
:Circle(20A-10,20B-10,7
:1->[A](A,B
:For(C,1,3
:sum(seq([A](X,C),X,1,3->D
:sum(seq([A](C,X),X,1,3->E
:sum(2(12={D,E})+(3={D,E->W
:End
:sum(seq([A](X,X),X,1,3->D
:sum(seq([A](4-X,X),X,1,3->E
:sum(2(12={D,E})+(3={D,E->W
:If R<9 and not(W
:Then
:R+1->R
:Text(0,0,"X'S TURN
:prgmOPTICODE
:4->[A](I,J
:Line(20I-3,20J-3,20I-17,20J-17
:Line(20I-3,20J-17,20I-17,20J-3
:Pt-Off(20I-10,20J-10
:End
:End
:For(C,1,3
:sum(seq([A](X,C),X,1,3->D
:sum(seq([A](C,X),X,1,3->E
:sum(2(12={D,E})+(3={D,E->W
:End
:sum(seq([A](X,X),X,1,3->D
:sum(seq([A](4-X,X),X,1,3->E
:sum(2(12={D,E})+(3={D,E->W
:End
:Text(0,0,"TIE!
:If W
:Then
:O+(W=1->O
:N+(W=2->N
:Text(0,0,sub("OX",W,1)," WINS!
:Text(26,7,O
:Text(32,7,N
:End
:Pause
:Goto 0

Now, I want to explain what I've changed. First of all, I removed the SetUpEditor. Next, I deleted some of the 0->[variable] when they are overwritten.
For finding D and E, I used sum( and seq( and for W another (weird Razz) thing.
At the end, you had a Pause in an If-statement double (if true -> Pause and also if false -> Pause).
And at least, in the If-statement, you always disp text at (0,0). I've changed that, so that if it is not a tie, the text will be overwritten.

Oh, and the most important thing what I've changed is that the getKey-routine is the fastets if you use Ans.

EDIT: I'm searching to delete variable R, I had the idea to do something like

Code:
prod([A])
but that isn't possible Laughing
All right then. Here's my code:

Code:
DelVar Str1:{3,3}->dim([A]):0->Z:0->P:Fill(0,[A]
Menu("TIC-TAC-TOE","PLAY",1,"QUIT",2
Lbl 1
ClrDraw:0->Xmin:60->Xmax:0->Ymin:60->Ymax:AxesOff:0->W:Zsquare
For(A,0,60,20
Line(A,0,A,60
Line(0,A,60,A
End
2->A:2->B
Repeat theta=45 or Z=9
getKey->theta
Text(0,0,sub("OX",P+1,1
Pt-Off(20A-10,20B-10
A+(theta=26 and A<3)-(theta=24 and A>1)->A
B+(theta=25 and B<3)-(theta=34 and B>1)->B
Pt-On(20A-10,20B-10
If theta=105 and P=0:Then
If not([A](A,B
Then
1->[A](A,B):not(P)->P:Z+1->Z:0->theta
Circle(20A-10,20B-10,10,10
End
Matr>list([A],L1,L2,L3
If sum(L1)=3 or sum(L2)=3 or sum(L3)=3 or L1(1)+L2(2)+L3(3)=3 or L1(3)+L2(2)+L3(1)=3 or L1(1)+L2(1)+L3(1)=3 or L1(2)+L2(2)+L3(2)=3 or L1(3)+L2(3)+L3(3)=3
Then
9->Z:1->W
End
End
If theta=105 and P=1:Then
If not([A](A,B
Then
~1->[A](A,B):not(P)->P:Z+1->Z:0->theta
Line(20A-20,20B,20A,20B-20,11
Line(20A,20B,20A-20,20B-20,11
End
Matr>list([A],L1,L2,L3
If sum(L1)=~3 or sum(L2)=~3 or sum(L3)=~3 or L1(1)+L2(2)+L3(3)=~3 or L1(3)+L2(2)+L3(1)=~3 or L1(1)+L2(1)+L3(1)=~3 or L1(2)+L2(2)+L3(2)=~3 or L1(3)+L2(3)+L3(3)=~3
Then
9->Z:2->W
End
End
End
If W!=0:Then
"PLAYER "+sub("12",W,1)+" WINS"->Str1
ClrHome:Pause Str1
DelVar Str1
ClrHome
Menu("PLAY AGAIN?","YES",1,"NO",2
Lbl 2
ClrHome:Stop
End


This works, and it's not too big.


Where should I put the AI code that you guys came up with?
Caleb, your code looks great! But the version PT_ and I compiled and optimized serves the same purpose and even adds more features. We did build upon your original code, as many of the fundamental organizational aspects are stemmed from your code, and we can still help you optimize and implement your code, but for upload and release purposes, PT_ and I's version, in my opinion, would be better.

Note to PT_: your most recent optimizations have 2 bugs, 1) "Tie" does not cover over the text already on screen, so "Tie "(12 or so spaces) would have to be used. 2) Win detection broke. I don't know why, but it broke.

Here is the updated AI code, I added some to it, and now I think it is impossible to beat. Please feel free to test and debug it!:

SourceCoder 3 (OPTICODE) wrote:
:ClrList L1
:0->T
:4->U
:
://check for win/win-block
:For(S,1,3
:For(Q,1,3
:If [A](S,Q-1+(Q=1))=[A](S,Q+1-(Q=3)) and [A](S,Q-1+(Q=1))not([A](S,4-Q
:Then
:S+(4-Q)[i]->L1(1+dim(L1
:If U=[A](S,Q+1-(Q=3
:dim(L1->T
:End
:If [A](Q-1+(Q=1),S)=[A](Q+1-(Q=3),S) and [A](Q-1+(Q=1),S)not([A](4-Q,S
:Then
:4-Q+S[i]->L1(1+dim(L1
:If U=[A](Q+1-(Q=3),S
:dim(L1->T
:End
:End
:End
:
://play in center
:If not(dim(L1
:Then
:If not([A](2,2
:2+2[i]->L1(1
:End
:
://block douple trap
:If not(dim(L1)) and (([A](1,1)=[A](3,3) and [A](1,1)=1) or ([A](3,1)=[A](1,3) and [A](3,1)=1))
:Goto 6
:
://opposite corner
:If not(dim(L1
:Then
:For(S,1,3,2
:For(Q,1,3,2
:If [A](4-S,4-Q)=1 and not([A](S,Q
:S+Q[i]->L1(1+dim(L1
:End
:End
:End
:
://random corner
:If not(dim(L1
:Then
:For(S,1,3,2
:For(Q,1,3,2
:If not([A](S,Q
:S+Q[i]->L1(1+dim(L1
:End
:End
:End
:
://random side
:Lbl 6
:If not(dim(L1
:Then
:For(S,1,3,2
:If not([A](2,S
:2+S[i]->L1(1+dim(L1
:If not([A](S,2
:S+2[i]->L1(1+dim(L1
:End
:End
:
://finish
:not(T)randInt(1,dim(L1))+T->S
:real(L1(S->I
:imag(L1(S->J


Use this program, for now, to test the AI:
SourceCoder 3 (TICTACTO) wrote:
::DCS6
:"0810081008100810FFFF081008500B100D500B500810FFFF0810081008100810"
:SetUpEditor
:AxesOff
:0->O
:0->N
:Lbl 0
:ClrHome
:{3,3->dim([A]
:Fill(0,[A]
:Menu("Tic-Tac-Toe AI","Play",1,"Quit",2
:Lbl 1
:ClrDraw
:~33->Xmin
:61->Ymax
:~1->Ymin
:61->Xmax
:For(A,0,60,20
:Line(A,0,A,60
:Line(0,A,60,A
:End
:Text(20,0,"GAMES WON
:Text(26,0,"O: ",O
:Text(32,0,"X: ",N
:1->P
:2->A
:2->B
:0->W
:0->R
:Repeat W or theta=45
:If B>3
:3->B
:Text(0,0,"O'S TURN
:Pt-On(20A-10,20B-10
:Repeat theta
:getKey->theta
:End
:Pt-Off(20A-10,20B-10
:A+(theta=26 and A<3)-(theta=24 and A>1->A
:B+(theta=25 and B<3)-(theta=34 and B>1->B
:Pt-On(20A-10,20B-10
:If theta=105 and not([A](A,B)
:Then
:R+1->R
:Pt-Off(20A-10,20B-10
:Circle(20A-10,20B-10,7
:1->[A](A,B
:
:0->D
:0->E
:0->W
:For(C,1,3
:[A](1,C)+[A](2,C)+[A](3,C->D
:[A](C,1)+[A](C,2)+[A](C,3->E
:If D=3 or E=3
:1->W
:If D=12 or E=12
:2->W
:End
:[A](1,1)+[A](2,2)+[A](3,3->D
:[A](3,1)+[A](2,2)+[A](1,3->E
:If D=3 or E=3
:1->W
:If D=12 or E=12
:2->W
:
:If R<9 and not(W
:Then
:R+1->R
:Text(0,0,"X'S TURN
:
:prgmOPTICODE
:
:4->[A](I,J
:Line(20I-3,20J-3,20I-17,20J-17
:Line(20I-3,20J-17,20I-17,20J-3
:Pt-Off(20I-10,20J-10
:End
:End
:
:0->D
:0->E
:0->W
:For(C,1,3
:[A](1,C)+[A](2,C)+[A](3,C->D
:[A](C,1)+[A](C,2)+[A](C,3->E
:If D=3 or E=3
:1->W
:If D=12 or E=12
:2->W
:End
:[A](1,1)+[A](2,2)+[A](3,3->D
:[A](3,1)+[A](2,2)+[A](1,3->E
:If D=3 or E=3
:1->W
:If D=12 or E=12
:2->W
:
:If R=9 and not(W
:45->theta
:End
:If W
:Then
:O+(W=1->O
:N+(W=2->N
:Text(0,0,sub("OX",W,1)," WINS! "
:Text(26,7,O
:Text(32,7,N
:Pause
:Else
:Text(0,0,"TIE! "
:Pause
:End
:Goto 0
:Lbl 2
:ClrHome
:Stop
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 2 of 4
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement