[RESOLVED] Player vs A.I Tic Tac Toe
Hi,
I have been trying to create a method so the player can play against the computer for my Tic Tac Toe game here. The problem is that "x" always seems to win or the game ends in a draw even when its not. Not only that for some reason the first computer turn "o" is displayed as you would expect but after that only blank disabled buttons represent the shot the computer has taken.
This is how I am trying to do the A.I:
VB Code:
Private Sub cmdTile_Click(index As Integer)
If result = vbYes Then
If (CLICKCOUNT Mod 2 = 1) Then
cmdTile(index).Caption = "x"
Else
cmdTile(index).Caption = "o"
End If
cmdTile(index).Enabled = False
'CLICKCOUNT = CLICKCOUNT + 1
CheckWinner
Else
computer (index)
End If
End Sub
Private Sub computer(index As Integer)
MsgBox (CLICKCOUNT)
If (CLICKCOUNT Mod 2 = 1) Then
cmdTile(index).Caption = "x"
cmdTile(index).Enabled = False
CLICKCOUNT = CLICKCOUNT + 1
Else
index = Rnd(index + i)
cmdTile(index).Caption = "o"
cmdTile(index).Enabled = False
End If
CLICKCOUNT = CLICKCOUNT + 1
CheckWinner
End Sub
Also, before anyone asks I have had a look at a couple of Martin's A.I examples but they left me with this look on my face :ehh: and I couldn't figure out how to make the automation work with my current code.
Thanks,
Nightwalker
Re: Player vs A.I Tic Tac Toe
You seem to be getting into a bit of a logic muddle there.
If result = vbYes Then ?? Is something missing?
You could use one routine to update the GUI for both human and AI (I replaced CLICKCOUNT with MoveCount)
Code:
Private MoveCount as Long
Private Sub MakeMove(index As Long)
If ((MoveCount And 1) = 0) ' 0 if even 1 if odd
cmdTile(index).Caption = "x"
Else
cmdTile(index).Caption = "o"
End If
cmdTile(index).Enabled = False
MoveCount = MoveCount + 1
End Sub
Try using it in your code, it might help you to see what you have going on more clearly.
Re: Player vs A.I Tic Tac Toe
I forgot to post that part of the code. Here it is:
vb Code:
Dim CLICKCOUNT, i, index As Integer, result As VbMsgBoxResult
Private Sub Play()
CLICKCOUNT = 0
Winner = -1
For i = 0 To 8
cmdTile(i).Caption = ""
cmdTile(i).Enabled = True
Next i
result = MsgBox("Do you want to play Single player a game?", vbYesNo)
End Sub
Re: Player vs A.I Tic Tac Toe
I confess that I don't have VB6 installed any more but that should be close to VB6 code. Forgive me if it does not work.
What I can remember about VB6 is that Long is often a better choice of datatype than Integer (Long is the same as Integer in Net)
When you declare variables like you have you are declaring variants (Dim CLICKCOUNT, i, index As Integer, result As VbMsgBoxResult)
At module level it is considered better practice to use the scope specifiers Public, Private or Friend instead of Dim. It's clearer.
Your code is easier for other people to read if you indent it.
The code I posted was intended to simplify your code and help you see where the problems are.
Re: Player vs A.I Tic Tac Toe
Quote:
Originally Posted by
Milk
I confess that I don't have VB6 installed any more but that should be close to VB6 code. Forgive me if it does not work.
That post was for akhileshbc sorry! However, he seem to have mysteriously deleted his post.
Quote:
What I can remember about VB6 is that Long is often a better choice of datatype than Integer (Long is the same as Integer in Net)
When you declare variables like you have you are declaring variants (Dim CLICKCOUNT, i, index As Integer, result As VbMsgBoxResult)
At module level it is considered better practice to use the scope specifiers Public, Private or Friend instead of Dim. It's clearer.
Your code is easier for other people to read if you indent it.
The code I posted was intended to simplify your code and help you see where the problems are.
I haven't tested your code but what is the difference to how the code in the computer sub in the first post works?
Re: Player vs A.I Tic Tac Toe
Night
I gave it a try.
If I click "Yes" to the 1st MsgBox, all is fine.
But if I click "No", this happens ...
- I click Play
- I get the MsgBox .. Do you want to play Single player a Game
- I click .. No ... (to enable the Computer "mode")
- I click Lower-Left Tile .. #6 >> an "o" appears in Top-Middle .. #1 (it always goes there)
- I click Lower-Left Tile again >> an "x" appears there
- I click Lower-Middle >> an "x" appears there
- I click Lower-Right >> an "x" appears there
- MsgBox .. Player x is victorious! Play again?
So, I have this configuration ...
Code:
0 1 2 . o .
3 4 5 . . .
6 7 8 x x x
Questions:
- Where are the extra "o's" ?
- Who is "o" .. me or the computer?
- What am I missing?
I tried it to at least see if I could replicate your problem.
Despite not having much luck there, here is an idea that
may be of some use in creating a "trace" so you can track
down the problem ... create a Public 2-D array.
That way, each time you click Play, increment a PlayCounter
variable (1st dim of array), and track each Tile_Click in the
2nd dim of the array.
Spoo
Re: Player vs A.I Tic Tac Toe
Quote:
Originally Posted by
Spoo
Questions:
- Where are the extra "o's" ?
- Who is "o" .. me or the computer?
- What am I missing?
1. That is one of the problems I mentioned above. I don't know why it is happening.
2. "o", the player starts first but I might change that after I can solve these problems.
3. Nothing as far as I know.
Re: Player vs A.I Tic Tac Toe
Quote:
Originally Posted by
Nightwalker83
That post was for akhileshbc sorry! However, he seem to have mysteriously deleted his post.
I haven't tested your code but what is the difference to how the code in the computer sub in the first post works?
I have posted links to C# and JAVA codes thinking that you have previous experience in C# and JAVA (in your site, you mentions that you have done projects in C#).
:wave:
Re: Player vs A.I Tic Tac Toe
Quote:
Originally Posted by
akhileshbc
I have posted links to C# and JAVA codes thinking that you have previous experience in C# and JAVA (in your site, you mentions that you have done projects in C#).
So you only accept codes that are pure VB6 ?
No, I don't only except VB6 codes although, people browsing these forum might find it confusing as I did how one language's way of doing thing works in another language.
Quote:
BTW, I have noticed that you have negatively reputed me saying:
Was it necessary ?
Now, I realize what you did no probably not. However, when you use the wrong tags when posting in can easily confuse someone reading the threads. That is why I thought you were posting VB.NET code at first and also since they are similar without the extra stuff such as that VB.NET uses for command buttons. I would think it is better to use separate tags when posting in the different sections, i.e [highlight="vb"] for the vb6 section and [highlight="vb.net"] for the vb.net section.
Re: Player vs A.I Tic Tac Toe
Night
OK, I think I may have found the problem, or
at least a problem ...
The value of CLICKCOUNT at entry of this sub
is as follows
You never get any "even numbered" CLICKCOUNT.
I've annotated this below
Code:
Private Sub Computer(Index As Integer)
'
' ' CLICKCOUNT
' pass 1 pass 2
' ' ========== ==========
' ' 0 1
If (CLICKCOUNT Mod 2 = 1) Then ' no yes
cmdTile(Index).Caption = "x"
cmdTile(Index).Enabled = False
CLICKCOUNT = CLICKCOUNT + 1 ' 2
Else ' yes
Index = Rnd(Index + I)
cmdTile(Index).Caption = "o"
cmdTile(Index).Enabled = False
End If
CLICKCOUNT = CLICKCOUNT + 1 ' 1 3
CheckWinner
'
End Sub
Hope that gives you some ideas.
Spoo
Re: Player vs A.I Tic Tac Toe
Ah now, guess I need to figure out which
vb Code:
CLICKCOUNT = CLICKCOUNT + 1
to remove.
Re: Player vs A.I Tic Tac Toe
Night
Besides that issue, you might also want to reconsider how
you are dealing with randomization.
I played around, and came up with this revision ...
Code:
Private Sub Computer(Index As Integer)
'
' set Player's tile
cmdTile(Index).Caption = "o"
cmdTile(Index).Enabled = False
' set Computer's tile
Index = Int(8 * Rnd)
' revise if randomly selected Tile already "used"
If cmdTile(Index).Enabled = False Then
For ii = 0 To 8
' even this randomly selected Tile is "used"
If cmdTile(Index).Enabled = False Then
Index = Int(8 * Rnd)
' ok now
Else
Exit For
End If
Next ii
End If
cmdTile(Index).Caption = "x"
cmdTile(Index).Enabled = False
'
CLICKCOUNT = CLICKCOUNT + 2
CheckWinner
'
End Sub
.. and here, too.
Code:
Private Sub CheckWinner()
'
...
'MsgBox (winner)
If (Winner = 0 Or Winner = 2 Or Winner = 4 Or ...
Result = MsgBox("Player o is victorious! Play Again?", vbYesNo)
If Result = vbYes Then
Randomize
Play
Else
EndGame
End If
End If
If (Winner = 1 Or Winner = 3 Or Winner = 5 Or ...
Result = MsgBox("Player x is victorious! Play Again?", vbYesNo)
If Result = vbYes Then
Randomize
Play
Else
EndGame
End If
End If
If CLICKCOUNT = 9 Then
MsgBox ("This game is a draw!")
EndGame
End If
'
End Sub
This works fine now, as long as there is an outright winner (x or o)
The only problem involves a draw, as CLICKCOUNT is now always
an even number and thus can never be 9.
Anyhow, hope that gives you a little more to work with.
EDIT:
I have in mind a solution for the "draw" issue, but as there is
more than one way to slice a piece of bread, I'll let you first
try on your own before I spill the beans .. ;)
Spoo
Re: Player vs A.I Tic Tac Toe
@ spoo,
Can you please confirm whether there are bouts of cheating when using that code? I could swear several games I've played against the computer using that code would have ended in a draw if not for the computer pinching on of my tiles. :lol:
Edit:
Set the buttons to graphical style then use this code and you should see what I am referring to.
vb Code:
Private Sub Computer(Index As Integer)
'
' set Player's tile
cmdTile(Index).Caption = "x"
cmdTile(Index).Enabled = False
' set Computer's tile
Index = Int(8 * Rnd)
' revise if randomly selected Tile already "used"
If cmdTile(Index).Enabled = False Then
For ii = 0 To 8
' even this randomly selected Tile is "used"
If cmdTile(Index).Enabled = False Then
Index = Int(8 * Rnd)
cmdTile(Index).BackColor = vbRed
MsgBox (Index)
' ok now
Else
Exit For
End If
Next ii
End If
cmdTile(Index).Caption = "o"
cmdTile(Index).Enabled = False
If finished = False Then
CLICKCOUNT = CLICKCOUNT + 2
CheckWinner
End If
End Sub
Re: Player vs A.I Tic Tac Toe
Night
I'm not quite sure of what you mean by "cheating".
However, perhaps this modification will help.
- I added two TextBoxes
- Name = txtPlayer and txtComputer
- Font = courier
- Multiline = True
- I also added a Public var called nRun
The textboxes maintain a "trace" of all moves
- Player .. just the one clicked
- Computer .. all "other" tiles tried before one is picked
These 2 subs are changed.
Code:
Sub Play()
'
nRun = 0
CLICKCOUNT = 0
Winner = -1
txtPlayer.Text = "Player" + vbCrLf
txtComputer.Text = "Computer" + vbCrLf
For I = 0 To 8
cmdTile(I).Caption = ""
cmdTile(I).Enabled = True
cmdTile(I).BackColor = RGB(220, 255, 220) ' lite green
Next I
cmdExit.SetFocus
'
End Sub
Code:
Private Sub Computer(Index As Integer)
nRun = nRun + 1
' set Player's tile
cmdTile(Index).Caption = "o"
cmdTile(Index).Enabled = False
txtPlayer.Text = txtPlayer.Text + Trim(nRun) + "--" + Trim(Index) + vbCrLf
CheckWinner
If nRun = 0 Then
Exit Sub
End If
' set Computer's tile
Index = Int(8 * Rnd)
txtComputer.Text = txtComputer.Text + Trim(nRun) + "--" + Trim(Index)
' revise if "used"
If cmdTile(Index).Enabled = False Then
cmdTile(Index).BackColor = RGB(255, 255, 200) ' lite yellow
For ii = 0 To 8
' even this randomly selected Tile is "used"
If cmdTile(Index).Enabled = False Then
Index = Int(8 * Rnd)
cmdTile(Index).BackColor = RGB(220, 255, 255) ' lite cyan
txtComputer.Text = txtComputer.Text + Trim(Index)
' ok now
Else
txtComputer.Text = txtComputer.Text + Trim(Index) + vbCrLf
Exit For
End If
Next ii
Else
txtComputer.Text = txtComputer.Text + vbCrLf
End If
cmdTile(Index).Caption = "x"
cmdTile(Index).Enabled = False
CLICKCOUNT = CLICKCOUNT + 2
CheckWinner
cmdExit.SetFocus
End Sub
Does that address your "cheating" issue?
As far as I can tell, there is none.
Spoo
Re: Player vs A.I Tic Tac Toe
Yes, it seems to resolve the problem although, I still can not be sure. What I mean by "cheating" is say the game is a move away from being a draw and the player "o" selects the last tile putting "o" inside thus making the game a draw but since the still needs to finish its current action it takes on of the "o" tiles thus making the computer win.
Re: [RESOLVED] Player vs A.I Tic Tac Toe
Night
Aha, that's what you meant by cheating.
Yeah, I found myself doing the same thing .. :)
I always started in the lower left corner, and found the
Computer inordinately daft .. I could invariably get 3-in-a-row
across the bottom. Only once in a blue moon did the Computer
initially go to Tile-7 (middle bottom).
Perhaps your next step is to advance the Computer algo a bit ..
start out in random, but if it "detects" an impending winning "o",
have it exit the "random mode" and go into a "block mode."
Spoo
Re: [RESOLVED] Player vs A.I Tic Tac Toe
I noticed that a couple of times, the computer did block me from a winning move although, like you said it might just be a random move causing this to happen.
Re: [RESOLVED] Player vs A.I Tic Tac Toe
This is one of the possible outcomes in the case of a draw
x|o|x
o|o|x
o|x|o
If you get draw then when the computer has it's next turn it might end up such as this:
x|o|x
o|o|x
o|x|x
If that happens please let me know although, I have run the game in the vb6 debugger but fail to trigger the above case.
Re: [RESOLVED] Player vs A.I Tic Tac Toe
Night
I'm not quite sure what you are suggesting here ..
Quote:
If you get draw then when the computer has it's next turn it might end up such as this:
x|o|x
o|o|x
o|x|x
If the game ends in a draw ...
x|o|x
o|o|x
o|x|o
... the Computer's "next turn" would be after Player makes
his first move in a new game, right?
Spoo
Re: [RESOLVED] Player vs A.I Tic Tac Toe
No, that isn't always the case because when you click "OK" to close the message box telling you the game was a draw then the computer may have its next turn.
Re: [RESOLVED] Player vs A.I Tic Tac Toe
Night
Oops.
I must confess that I altered the code a bit while I was
in the trouble-shooting mode .. I eliminated the MsgBox
stuff so I could quickly go to the next game.
I assumed (mistakenly) that Player always went first.
So, you are suggesting that if a game is a draw, and Player
went last, Computer will have the "rights" to begin the next
game. I haven't coded for that, but will revise and study
when I get some free time.
Spoo
Re: [RESOLVED] Player vs A.I Tic Tac Toe
I have uploaded version 2 to the code bank (link to thread in first post). In version 2 I put:
vb Code:
If result = vbNo And cc = 10 And Won = False Then
which, hopefully concludes the game but if not in version 3 I have put:
vb Code:
If result = vbYes And Won = False And cc >= 10 Then
to end the game if the number clicks is only 10. I have also, changed the "Yes/No" around from the previous version so now the cheating hopefully does not happen.