| | |
C++ TicTacToe Turn variable and AI questions
Please support our Game Development advertiser: Programming Forums - DaniWeb Sister Site
![]() |
•
•
Join Date: Nov 2008
Posts: 3
Reputation:
Solved Threads: 0
Hello, I am working on a Tic-Tac-Toe program in C++ which I want to have AI that will either win or draw every time, but will never lose. I think that this is within my grasp, though I am not at all an expert programmer.
I would really appreciate if someone would please read my code and tell me if it is ready to start on the AI, because at the moment I have been trying to write a program that will make it easy to put AI into. I have been trying to put in a variable or something that will keep track of the turn, starting at 1 and going up until 9, because if I did this then there would be no need to check for a win every turn, as the earliest a player can win is on the fifth turn. (If X goes first, as it always will in my program, it can win after it has played 3 times.) Also, I could forgo checking for a draw at all and simply end the game after the ninth turn.
I also would be grateful for any help with checking the wins, though this is not my biggest priority. The graphics library I am using is Allegro, in case anyone needs that information.
The code to my program is below. I can tell you that when you run the program, its window comes up on the screen (this is the opener) and asks if you want to be X or O, explaining that X goes first and O goes second. When you click one or the other, the window becomes a blank board. You are the only player, and so you can click on any square and your marker will appear there. This can be done until the board fills up, but the program does not terminate.
What I want to happen when it is run, is once you get to the board, if you are X then you can place your marker and then an O will appear in the computer's square of choice, or if you are O then the computer's X will appear letting you choose your square. When a player wins, the program will change to a win/lose-congratulation screen, from the point of view of the human. (if human loses the lose screen is presented.) As for draws, it will automatically go to a draw screen after Turn==9 or when all of the squares are filled.
The program is in three files: Main, Classes, Functions, and soon to be AI functions. Sorry for the abundance of it, I know that it is probably too complicated and that I need to clean it up a bit. Thanks anyway in advance!
PS: To explain all of the Terms and Conditions on the opening screen, I am doing this for a school project and as I will be using human subjects to test the program, it is possible that I will have to have them read all of that information and agree to play.
I would really appreciate if someone would please read my code and tell me if it is ready to start on the AI, because at the moment I have been trying to write a program that will make it easy to put AI into. I have been trying to put in a variable or something that will keep track of the turn, starting at 1 and going up until 9, because if I did this then there would be no need to check for a win every turn, as the earliest a player can win is on the fifth turn. (If X goes first, as it always will in my program, it can win after it has played 3 times.) Also, I could forgo checking for a draw at all and simply end the game after the ninth turn.
I also would be grateful for any help with checking the wins, though this is not my biggest priority. The graphics library I am using is Allegro, in case anyone needs that information.
The code to my program is below. I can tell you that when you run the program, its window comes up on the screen (this is the opener) and asks if you want to be X or O, explaining that X goes first and O goes second. When you click one or the other, the window becomes a blank board. You are the only player, and so you can click on any square and your marker will appear there. This can be done until the board fills up, but the program does not terminate.
What I want to happen when it is run, is once you get to the board, if you are X then you can place your marker and then an O will appear in the computer's square of choice, or if you are O then the computer's X will appear letting you choose your square. When a player wins, the program will change to a win/lose-congratulation screen, from the point of view of the human. (if human loses the lose screen is presented.) As for draws, it will automatically go to a draw screen after Turn==9 or when all of the squares are filled.
The program is in three files: Main, Classes, Functions, and soon to be AI functions. Sorry for the abundance of it, I know that it is probably too complicated and that I need to clean it up a bit. Thanks anyway in advance!
/*Main*/
#include <allegro.h>
#include "Classes.h"
#include "Functions.h"
int main()
{
allegro_init();
install_keyboard();
install_mouse();
set_color_depth(24);
set_gfx_mode(GFX_AUTODETECT, 480, 480, 0, 0);
theBlank=create_bitmap(480, 480);
theOpener=load_bitmap("Opener.bmp", NULL);
theWin=load_bitmap("Wim.bmp", NULL);
theLose=load_bitmap("Lose.bmp", NULL);
theDraw=load_bitmap("Draw.bmp", NULL);
theX=load_bitmap("X pic.bmp", NULL);
theO=load_bitmap("O pic.bmp", NULL);
show_mouse(screen);
Opener();
destroy_bitmap(theBlank);
destroy_bitmap(theOpener);
destroy_bitmap(theWin);
destroy_bitmap(theLose);
destroy_bitmap(theDraw);
destroy_bitmap(theX);
destroy_bitmap(theO);
return 0;
}
END_OF_MAIN();/*Class Declarations*/
#include <allegro.h>
int Square[9]={0, 0, 0, 0, 0, 0, 0, 0, 0};//This is used for occupation, wins, and losses
short box;//Global Variable for what Square[], use ONLY with GetPosition(), XMove(), and OMove()
/****************************************************************************************/
//When you put in the coordnates for the X or O to be drawn at, you must add two to each
//coordnate (eg. (0, 0) becomes (2, 2))
BITMAP *theBlank;
BITMAP *theOpener;
BITMAP *theWin;
BITMAP *theLose;
BITMAP *theDraw;
BITMAP *theX;
BITMAP *theO;
class XMarker//X
{
public:
//constructors
XMarker(int Box);
~XMarker(){}
void DrawX();
private:
int Xx;//For clarification, this is X's x coordnate.
int Xy;
};
XMarker::XMarker(int Box)
{
if(Box==0){Xx=481; Xy=481;}
else if(Box==1){Xx=2; Xy=2;}
else if(Box==2){Xx=162; Xy=2;}
else if(Box==3){Xx=322; Xy=2;}
else if(Box==4){Xx=2; Xy=162;}
else if(Box==5){Xx=162; Xy=162;}
else if(Box==6){Xx=322; Xy=162;}
else if(Box==7){Xx=2; Xy=322;}
else if(Box==8){Xx=162; Xy=322;}
else if(Box==9){Xx=322; Xy=322;}
}
void XMarker::DrawX()
{
acquire_screen();
draw_sprite(screen, theX, Xx, Xy);
release_screen();
}
/****************************************************************************************/
class OMarker//O
{
public:
//constructors
OMarker(int Box);
~OMarker(){}
void DrawO();
private:
int Ox;//This is O's x coordnate, not an ox.
int Oy;
};
OMarker::OMarker(int Box)
{
if(Box==0){Ox=481; Oy-481;}
else if(Box==1){Ox=2; Oy=2;}
else if(Box==2){Ox=162; Oy=2;}
else if(Box==3){Ox=322; Oy=2;}
else if(Box==4){Ox=2; Oy=162;}
else if(Box==5){Ox=162; Oy=162;}
else if(Box==6){Ox=322; Oy=162;}
else if(Box==7){Ox=2; Oy=322;}
else if(Box==8){Ox=162; Oy=322;}
else if(Box==9){Ox=322; Oy=322;}
}
void OMarker::DrawO()
{
acquire_screen();
draw_sprite(screen, theO, Ox, Oy);
release_screen();
}/*Function Declarations*/
#include <allegro.h>
void GetPosition()
{
if((mouse_b & 1) && (mouse_x > 0 && mouse_x < 160) && (mouse_y > 0 && mouse_y < 160) && (Square[0]==0)){
box=1;}
else if((mouse_b & 1) && (mouse_x > 160 && mouse_x < 320) && (mouse_y > 0 && mouse_y < 160) && (Square[1]==0)){
box=2;}
else if((mouse_b & 1) && (mouse_x > 320 && mouse_x < 480) && (mouse_y > 0 && mouse_y < 160) && (Square[2]==0)){
box=3;}
else if((mouse_b & 1) && (mouse_x > 0 && mouse_x < 160) && (mouse_y > 160 && mouse_y < 320) && (Square[3]==0)){
box=4;}
else if((mouse_b & 1) && (mouse_x > 160 && mouse_x < 320) && (mouse_y > 160 && mouse_y < 320) && (Square[4]==0)){
box=5;}
else if((mouse_b & 1) && (mouse_x > 320 && mouse_x < 480) && (mouse_y > 160 && mouse_y < 320) && (Square[5]==0)){
box=6;}
else if((mouse_b & 1) && (mouse_x > 0 && mouse_x < 160) && (mouse_y > 320 && mouse_y < 480) && (Square[6]==0)){
box=7;}
else if((mouse_b & 1) && (mouse_x > 160 && mouse_x < 320) && (mouse_y > 320 && mouse_y < 480) && (Square[7]==0)){
box=8;}
else if((mouse_b & 1) && (mouse_x > 320 && mouse_x < 480) && (mouse_y > 320 && mouse_y < 480) && (Square[8]==0)){
box=9;}
}
void Check(short order)
{
if((Square[0]==order) && (Square[1]==order) && (Square[2]==order)){//Top Row
acquire_screen();
while(!key[KEY_ESC]){draw_sprite(screen, theWin, 0, 0);}
release_screen();}
else if((Square[3]==order) && (Square[4]==order) && (Square[5]==order)){//Middle Row
acquire_screen();
while(!key[KEY_ESC]){draw_sprite(screen, theWin, 0, 0);}
release_screen();}
else if((Square[6]==order) && (Square[7]==order) && (Square[8]==order)){//Bottom Row
acquire_screen();
while(!key[KEY_ESC]){draw_sprite(screen, theWin, 0, 0);}
release_screen();}
else if((Square[0]==order) && (Square[3]==order) && (Square[6]==order)){//Left Column
acquire_screen();
while(!key[KEY_ESC]){draw_sprite(screen, theWin, 0, 0);}
release_screen();}
else if((Square[1]==order) && (Square[4]==order) && (Square[7]==order)){//Middle Column
acquire_screen();
while(!key[KEY_ESC]){draw_sprite(screen, theWin, 0, 0);}
release_screen();}
else if((Square[2]==order) && (Square[5]==order) && (Square[8]==order)){//Right Column
acquire_screen();
while(!key[KEY_ESC]){draw_sprite(screen, theWin, 0, 0);}
release_screen();}
else if((Square[0]==order) && (Square[4]==order) && (Square[8]==order)){//Down Diagonal
acquire_screen();
while(!key[KEY_ESC]){draw_sprite(screen, theWin, 0, 0);}
release_screen();}
else if((Square[6]==order) && (Square[4]==order) && (Square[2]==order)){//Up Diagonal
acquire_screen();
while(!key[KEY_ESC]){draw_sprite(screen, theWin, 0, 0);}
release_screen();}
}
void XMove()
{
GetPosition();
XMarker X1(box);
X1.DrawX();
Square[-1+box]==1;
}
void OMove()
{
GetPosition();
OMarker O1(box);
O1.DrawO();
Square[-1+box]==2;
}
void DrawBoard()
{
acquire_screen();
draw_sprite(screen, theBlank, 0, 0);//Blank background to get rid of theOpener
line(screen, 160, 0, 160, 480, makecol(255, 255, 255));//Left Vertical
line(screen, 320, 0, 320, 480, makecol(255, 255, 255));//Right Vertical
line(screen, 0, 160, 480, 160, makecol(255, 255, 255));//Top Horizontal
line(screen, 0, 320, 480, 320, makecol(255, 255, 255));//Bottom Horizontal
release_screen();
}
void Opener()
{
acquire_screen();
draw_sprite(screen, theOpener, 0, 0);
release_screen();
while(!key[KEY_ESC]){
if((mouse_b & 1) && (mouse_x > 80 && mouse_x < 185) && (mouse_y > 345 && mouse_y < 466)){
DrawBoard();
rest(150);
while(!key[KEY_ESC]){XMove();}}
else if((mouse_b & 1) && (mouse_x > 286 && mouse_x < 400) && (mouse_y > 345 && mouse_y < 466)){
DrawBoard();
rest(150);
while(!key[KEY_ESC]){OMove();}}
}
}PS: To explain all of the Terms and Conditions on the opening screen, I am doing this for a school project and as I will be using human subjects to test the program, it is possible that I will have to have them read all of that information and agree to play.
•
•
Join Date: Nov 2008
Posts: 29
Reputation:
Solved Threads: 0
Well generally, you will always have the ability of a loss. Even the computer defined AI will screw up alot of times. To make it so that it will always win or always draw are almost impossible. There will always be a chance that the Human Opponent will win, wether by chance or knowledge, there is always the possibility of that.
•
•
•
•
Well generally, you will always have the ability of a loss. Even the computer defined AI will screw up alot of times. To make it so that it will always win or always draw are almost impossible. There will always be a chance that the Human Opponent will win, wether by chance or knowledge, there is always the possibility of that.
Here is a link to the page that contains all the information
http://www.programmingforums.org/sho...ht=Tic-Tac-Toe
Also some very helpful links on how to always win or draw a game of tic tac toe.
http://ostermiller.org/tictactoeexpert.html
http://en.wikipedia.org/wiki/Tic-Tac-Toe
http://www.mathrec.org/old/2002jan/solutions.html
Chris
Knowledge is power -- But experience is everything
•
•
Join Date: Nov 2008
Posts: 3
Reputation:
Solved Threads: 0
hi everyone,
@shinedevil:
Actually this is possible, and has been done before. I don't want to waste words so here is the link to an unbeatable tic tac toe program: http://ostermiller.org/calc/tictactoe.html Choose the Expert computer level and try to beat it.
@Freaky_Chris:
Thanks very much! I took a look at all the sites you recommened and they are great!
A lot of the code that is on this post is now out of date, as i recently cleaned everything up a lot, and began the AI. It is still very long though, and now as I am working on the AI, there is a whole other file, but I dont think I will post the code unless anyone asks me to because of its length. The only problem I have is this:
When the AI goes first and goes to a corner, and then the human goes to the opposite corner
[X][ ][ ]
[ ][ ][ ]
[ ][ ][O]
then the Ai should go to one of the remaining corners. sometimes it does, but other times it goes to both. The only solution I can think of is as about as crude as it gets, is to draw a blank spot over the second corner and pretend nothing ever happened. Unfortunately, I doubt that anyone will be able to help me with this problem withought running the code or, and I cant upload the .exe file for the game on here.
I am still open to more suggestions for AI however!
Thanks again!
@shinedevil:
Actually this is possible, and has been done before. I don't want to waste words so here is the link to an unbeatable tic tac toe program: http://ostermiller.org/calc/tictactoe.html Choose the Expert computer level and try to beat it.
@Freaky_Chris:
Thanks very much! I took a look at all the sites you recommened and they are great!
A lot of the code that is on this post is now out of date, as i recently cleaned everything up a lot, and began the AI. It is still very long though, and now as I am working on the AI, there is a whole other file, but I dont think I will post the code unless anyone asks me to because of its length. The only problem I have is this:
When the AI goes first and goes to a corner, and then the human goes to the opposite corner
[X][ ][ ]
[ ][ ][ ]
[ ][ ][O]
then the Ai should go to one of the remaining corners. sometimes it does, but other times it goes to both. The only solution I can think of is as about as crude as it gets, is to draw a blank spot over the second corner and pretend nothing ever happened. Unfortunately, I doubt that anyone will be able to help me with this problem withought running the code or, and I cant upload the .exe file for the game on here.
I am still open to more suggestions for AI however!
Thanks again!
![]() |
Other Threads in the Game Development Forum
- Previous Thread: wanna be games developer - but donno wht 2 do?
- Next Thread: Game Programming Challenges
| Thread Tools | Search this Thread |
3d advertising ai algorithm ban c++ cambridge camera censorship china competition console development engine fov fpx game gamer games gaming gauntanamo government idaho in-gameadvertisement intellectualproperty l-systems laracroft lindenmayer live manhunt math mathematics matrix mercenaries microsoft mmorpg modded msn naked news nintendo obama opengl palin physics pirate playstation politics projection ps3 rpg search selection software sony stephenhawking stocks studio technology terrorism tombraider uk videogame web wii world-of-warcraft xbox xbox-live xbox360





