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!
/*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.