• 0

Now my c++ tictactoe has some AI to it and will play against a computer


Question

I am also taking an Artificial Intelligence class so I decided to add AI to my c++ project.Unfort I used abunch of IF statements to it.... Is there a better way to do this?

download here:

http://togermano.com/homework/cpp/tonysAItictactoe.exe


#include <windows.h>
//#include <stdlib.h>
#include <time.h>
#include <stdio.h>
// Made By Anthony Germano For Elms College Final Project
#define BUTTON1 100
#define BUTTON2 200
#define BUTTON3 300
#define BUTTON4 400
#define BUTTON5 500
#define BUTTON6 600
#define BUTTON7 700
#define BUTTON8 800
#define BUTTON9 900
#define BUTTON10 1000
int v1;
int compturnstop;
char const* b1 = "1";
char const* b2 = "2";
char const* b3 = "3";
char const* b4 = "4";
char const* b5 = "5";
char const* b6 = "6";
char const* b7 = "7";
char const* b8 = "8";
char const* b9 = "9";
char const* t1 = "1";
char const* t2 = "2";
char const* t3 = "3";
char const* t4 = "4";
char const* t5 = "5";
char const* t6 = "6";
char const* t7 = "7";
char const* t8 = "8";
char const* t9 = "9";
char win[16] = " wins"; //for msgbox
char out1[16] = ""; //for msgbox
char const* winner = "N"; //variable for if the last move is a winner and uses all buttons it doesnt say winner and tie
char const* tic = "X";
void enablebuttons(HWND hwnd){
EnableWindow(GetDlgItem(hwnd, BUTTON1), true);
EnableWindow(GetDlgItem(hwnd, BUTTON2), true);
EnableWindow(GetDlgItem(hwnd, BUTTON3), true);
EnableWindow(GetDlgItem(hwnd, BUTTON4), true);
EnableWindow(GetDlgItem(hwnd, BUTTON5), true);
EnableWindow(GetDlgItem(hwnd, BUTTON6), true);
EnableWindow(GetDlgItem(hwnd, BUTTON7), true);
EnableWindow(GetDlgItem(hwnd, BUTTON8), true);
EnableWindow(GetDlgItem(hwnd, BUTTON9), true);

}

void changetic(){
if (tic == "X"){
tic = "O";}
else if (tic == "O"){
tic = "X";
}
}
void disablebuttons(HWND hwnd){
EnableWindow(GetDlgItem(hwnd, BUTTON1), false);
EnableWindow(GetDlgItem(hwnd, BUTTON2), false);
EnableWindow(GetDlgItem(hwnd, BUTTON3), false);
EnableWindow(GetDlgItem(hwnd, BUTTON4), false);
EnableWindow(GetDlgItem(hwnd, BUTTON5), false);
EnableWindow(GetDlgItem(hwnd, BUTTON6), false);
EnableWindow(GetDlgItem(hwnd, BUTTON7), false);
EnableWindow(GetDlgItem(hwnd, BUTTON8), false);
EnableWindow(GetDlgItem(hwnd, BUTTON9), false);

}
void checkwin(HWND hwnd){
if (b1 == b2 && b1 == b3){
winner = "Y";
strcat(out1, b1);
strcat(out1, win);
disablebuttons(hwnd);
MessageBoxA(hwnd,out1,"TicTacToe",MB_OK|MB_ICONINFORMATION);}

if (b4 == b5 && b4 == b6){
winner = "Y";
strcat(out1, b4);
strcat(out1, win);
disablebuttons(hwnd);
MessageBoxA(hwnd,out1,"TicTacToe",MB_OK|MB_ICONINFORMATION);}
if (b7 == b8 && b7 == b9){
winner = "Y";
strcat(out1, b7);
strcat(out1, win);
disablebuttons(hwnd);
MessageBoxA(hwnd,out1,"TicTacToe",MB_OK|MB_ICONINFORMATION);}

if (b1 == b4 && b1 == b7){
winner = "Y";
strcat(out1, b1);
strcat(out1, win);
disablebuttons(hwnd);
MessageBoxA(hwnd,out1,"TicTacToe",MB_OK|MB_ICONINFORMATION);}
if (b2 == b5 && b2 == b8){
winner = "Y";
strcat(out1, b2);
strcat(out1, win);
disablebuttons(hwnd);
MessageBoxA(hwnd,out1,"TicTacToe",MB_OK|MB_ICONINFORMATION);}
if (b3 == b6 && b3 == b9){
winner = "Y";
strcat(out1, b3);
strcat(out1, win);
disablebuttons(hwnd);
MessageBoxA(hwnd,out1,"TicTacToe",MB_OK|MB_ICONINFORMATION);}
if (b1 == b5 && b1 == b9){
winner = "Y";
strcat(out1, b1);
strcat(out1, win);
disablebuttons(hwnd);
MessageBoxA(hwnd,out1,"TicTacToe",MB_OK|MB_ICONINFORMATION);}
if (b3 == b5 && b3 == b7){
winner = "Y";
strcat(out1, b3);
strcat(out1, win);
disablebuttons(hwnd);
MessageBoxA(hwnd,out1,"TicTacToe",MB_OK|MB_ICONINFORMATION);}
if (t1 == t2 && t3 == t4 && t5 == t6 && t7 == t8 && t7 == t9 && winner == "N"){

winner = "Y";
MessageBoxA(hwnd,"It is a Tie!!!","TicTacToe",MB_OK|MB_ICONINFORMATION);}


}
void computerturn(HWND hwnd){
int compturnstop = 0;
if (winner == "N"){

if (b1 == b2 && t3 != "U" && compturnstop == 0){
compturnstop = 3;
b3 = tic;
t3 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON3), false);
SetDlgItemText(hwnd, BUTTON3, tic);
checkwin(hwnd);
changetic();

}
if (b2 == b3 && t1 != "U" && compturnstop == 0){
compturnstop = 1;
b1 = tic;
t1 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON1), false);
SetDlgItemText(hwnd, BUTTON1, tic);
checkwin(hwnd);
changetic();

}
if (b4 == b5 && t6 != "U" && compturnstop == 0){
compturnstop = 6;
b6 = tic;
t6 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON6), false);
SetDlgItemText(hwnd, BUTTON6, tic);
checkwin(hwnd);
changetic();

}
if (b6 == b5 && t4 != "U" && compturnstop == 0){
compturnstop = 4;
b4 = tic;
t4 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON4), false);
SetDlgItemText(hwnd, BUTTON4, tic);
checkwin(hwnd);
changetic();

}
if (b6 == b8 && t9 != "U" && compturnstop == 0){
compturnstop = 9;
b9 = tic;
t9 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON9), false);
SetDlgItemText(hwnd, BUTTON9, tic);
checkwin(hwnd);
changetic();

}
if (b9 == b8 && t7 != "U" && compturnstop == 0){
compturnstop = 7;
b7 = tic;
t7 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON7), false);
SetDlgItemText(hwnd, BUTTON7, tic);
checkwin(hwnd);
changetic();

}
if (b1 == b4 && t7 != "U" && compturnstop == 0){
compturnstop = 7;
b7 = tic;
t7 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON7), false);
SetDlgItemText(hwnd, BUTTON7, tic);
checkwin(hwnd);
changetic();

}
if (b7 == b3 && t1 != "U" && compturnstop == 0){
compturnstop = 1;
b1 = tic;
t1 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON1), false);
SetDlgItemText(hwnd, BUTTON1, tic);
checkwin(hwnd);
changetic();

}

if (b2 == b5 && t8 != "U" && compturnstop == 0){
compturnstop = 8;
b8 = tic;
t8 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON8), false);
SetDlgItemText(hwnd, BUTTON8, tic);
checkwin(hwnd);
changetic();

}
if (b8 == b5 && t2 != "U" && compturnstop == 0){
compturnstop = 2;
b2 = tic;
t2 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON2), false);
SetDlgItemText(hwnd, BUTTON2, tic);
checkwin(hwnd);
changetic();

}
if (b3 == b6 && t9 != "U" && compturnstop == 0){
compturnstop = 9;
b9 = tic;
t9 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON9), false);
SetDlgItemText(hwnd, BUTTON9, tic);
checkwin(hwnd);
changetic();

}
if (b9 == b6 && t3 != "U" && compturnstop == 0){
compturnstop = 3;
b3 = tic;
t3 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON3), false);
SetDlgItemText(hwnd, BUTTON3, tic);
checkwin(hwnd);
changetic();

}
if (b1 == b3 && t2 != "U" && compturnstop == 0){
compturnstop = 2;
b2 = tic;
t2 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON2), false);
SetDlgItemText(hwnd, BUTTON2, tic);
checkwin(hwnd);
changetic();

}
if (b4 == b6 && t5 != "U" && compturnstop == 0){
compturnstop = 5;
b5 = tic;
t5 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON5), false);
SetDlgItemText(hwnd, BUTTON5, tic);
checkwin(hwnd);
changetic();

}
if (b7 == b9 && t8 != "U" && compturnstop == 0){
compturnstop = 8;
b8 = tic;
t8 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON8), false);
SetDlgItemText(hwnd, BUTTON8, tic);
checkwin(hwnd);
changetic();

}
if (b1 == b7 && t4 != "U" && compturnstop == 0){
compturnstop = 4;
b4 = tic;
t4 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON4), false);
SetDlgItemText(hwnd, BUTTON4, tic);
checkwin(hwnd);
changetic();

}
if (b2 == b8 && t5 != "U" && compturnstop == 0){
compturnstop = 5;
b5 = tic;
t5 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON5), false);
SetDlgItemText(hwnd, BUTTON5, tic);
checkwin(hwnd);
changetic();

}
if (b3 == b9 && t6 != "U" && compturnstop == 0){
compturnstop = 6;
b6 = tic;
t6 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON6), false);
SetDlgItemText(hwnd, BUTTON6, tic);
checkwin(hwnd);
changetic();

}
if (b3 == b5 && t7 != "U" && compturnstop == 0){
compturnstop = 6;
b7 = tic;
t7 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON7), false);
SetDlgItemText(hwnd, BUTTON7, tic);
checkwin(hwnd);
changetic();

}
if (b7 == b5 && t3 != "U" && compturnstop == 0){
compturnstop = 3;
b3 = tic;
t3 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON3), false);
SetDlgItemText(hwnd, BUTTON3, tic);
checkwin(hwnd);
changetic();

}
if (b1 == b5 && t9 != "U" && compturnstop == 0){
compturnstop = 9;
b9 = tic;
t9 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON9), false);
SetDlgItemText(hwnd, BUTTON9, tic);
checkwin(hwnd);
changetic();

}
if (b9 == b5 && t1 != "U" && compturnstop == 0){
compturnstop = 1;
b1 = tic;
t1 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON1), false);
SetDlgItemText(hwnd, BUTTON1, tic);
checkwin(hwnd);
changetic();

}

if (t5 == "5" && compturnstop == 0){
compturnstop = 5;
b5 = tic;
t5 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON5), false);
SetDlgItemText(hwnd, BUTTON5, tic);
checkwin(hwnd);
changetic();

}
if (t1 == "1" && compturnstop == 0){
compturnstop = 1;
b1 = tic;
t1 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON1), false);
SetDlgItemText(hwnd, BUTTON1, tic);
checkwin(hwnd);
changetic();

}
if (t3 == "3" && compturnstop == 0){
compturnstop = 3;
b3 = tic;
t3 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON3), false);
SetDlgItemText(hwnd, BUTTON3, tic);
checkwin(hwnd);
changetic();

}
if (t5 == "5" && compturnstop == 0){
compturnstop = 5;
b5 = tic;
t5 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON5), false);
SetDlgItemText(hwnd, BUTTON5, tic);
checkwin(hwnd);
changetic();

}
if (t7 == "7" && compturnstop == 0){
compturnstop = 7;
b7 = tic;
t7 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON7), false);
SetDlgItemText(hwnd, BUTTON7, tic);
checkwin(hwnd);
changetic();

}
if (t9 == "9" && compturnstop == 0){
compturnstop = 5;
b9 = tic;
t9 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON9), false);
SetDlgItemText(hwnd, BUTTON9, tic);
checkwin(hwnd);
changetic();

}
if (compturnstop == 0){
// MessageBoxA(hwnd,"Computer never took a turn","TicTacToe",MB_OK|MB_ICONINFORMATION);}

if (t1 != "U"){

compturnstop = 1;
b1 = tic;
t1 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON1), false);
SetDlgItemText(hwnd, BUTTON1, tic);
checkwin(hwnd);
changetic();
}
if (t2 != "U"){

compturnstop = 2;
b2 = tic;
t2 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON2), false);
SetDlgItemText(hwnd, BUTTON2, tic);
checkwin(hwnd);
changetic();
}
if (t3 != "U"){

compturnstop = 3;
b3 = tic;
t3 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON3), false);
SetDlgItemText(hwnd, BUTTON3, tic);
checkwin(hwnd);
changetic();
}
if (t4 != "U"){

compturnstop = 4;
b4 = tic;
t4 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON4), false);
SetDlgItemText(hwnd, BUTTON4, tic);
checkwin(hwnd);
changetic();
}
if (t5 != "U"){

compturnstop = 5;
b5 = tic;
t5 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON5), false);
SetDlgItemText(hwnd, BUTTON5, tic);
checkwin(hwnd);
changetic();
}
if (t6 != "U"){

compturnstop = 6;
b6 = tic;
t6 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON6), false);
SetDlgItemText(hwnd, BUTTON6, tic);
checkwin(hwnd);
changetic();
}
if (t6 != "U"){

compturnstop = 7;
b7 = tic;
t7 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON7), false);
SetDlgItemText(hwnd, BUTTON7, tic);
checkwin(hwnd);
changetic();
}
if (t6 != "U"){

compturnstop = 8;
b8 = tic;
t8 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON8), false);
SetDlgItemText(hwnd, BUTTON8, tic);
checkwin(hwnd);
changetic();
}
if (t9 != "U"){

compturnstop = 9;
b9 = tic;
t9 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON9), false);
SetDlgItemText(hwnd, BUTTON9, tic);
checkwin(hwnd);
changetic();
}
}

}
}
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[ ] = "WindowsApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(255,3,3));
//http://cboard.cprogramming.com/windows-programming/113200-window-background-color.html
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Tony's Amazing Tic Tac Toe", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
380, /* The programs width */
395, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
CreateWindow("button", "1", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 50, 10, 50, 50, hwnd, (HMENU)BUTTON1, GetModuleHandle (NULL), NULL);
CreateWindow("button", "2", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 150, 10, 50, 50, hwnd, (HMENU)BUTTON2, GetModuleHandle (NULL), NULL);
CreateWindow("button", "3", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 250, 10, 50, 50, hwnd, (HMENU)BUTTON3, GetModuleHandle (NULL), NULL);
CreateWindow("button", "4", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 50, 110, 50, 50, hwnd, (HMENU)BUTTON4, GetModuleHandle (NULL), NULL);
CreateWindow("button", "5", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 150, 110, 50, 50, hwnd, (HMENU)BUTTON5, GetModuleHandle (NULL), NULL);
CreateWindow("button", "6", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 250, 110, 50, 50, hwnd, (HMENU)BUTTON6, GetModuleHandle (NULL), NULL);
CreateWindow("button", "7", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 50, 210, 50, 50, hwnd, (HMENU)BUTTON7, GetModuleHandle (NULL), NULL);
CreateWindow("button", "8", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 150, 210, 50, 50, hwnd, (HMENU)BUTTON8, GetModuleHandle (NULL), NULL);
CreateWindow("button", "9", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 250, 210, 50, 50, hwnd, (HMENU)BUTTON9, GetModuleHandle (NULL), NULL);
CreateWindow("button","Start Game!", WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON, 130, 300, 100, 50, hwnd, (HMENU)BUTTON10, GetModuleHandle (NULL), NULL);
/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);
disablebuttons(hwnd);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
/* This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_COMMAND:
switch(LOWORD(wParam)) {
case BUTTON1:{
b1 = tic;
t1 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON1), false);
SetDlgItemText(hwnd, BUTTON1, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);

}


}


switch(LOWORD(wParam)) {
case BUTTON2:{
b2 = tic;
t2 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON2), false);

SetDlgItemText(hwnd, BUTTON2, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);
}

}

switch(LOWORD(wParam)) {
case BUTTON3:{
b3 = tic;
t3 = "U";

EnableWindow(GetDlgItem(hwnd, BUTTON3), false);
SetDlgItemText(hwnd, BUTTON3, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);
}

}

switch(LOWORD(wParam)) {
case BUTTON4:{
b4 = tic;
t4 = "U";

EnableWindow(GetDlgItem(hwnd, BUTTON4), false);
SetDlgItemText(hwnd, BUTTON4, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);
}

}

switch(LOWORD(wParam)) {
case BUTTON5:{
b5 = tic;
t5 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON5), false);
SetDlgItemText(hwnd, BUTTON5, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);
}

}
switch(LOWORD(wParam)) {
case BUTTON6:{
b6 = tic;
t6 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON6), false);
SetDlgItemText(hwnd, BUTTON6, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);
}

}

switch(LOWORD(wParam)) {
case BUTTON7:{
b7 = tic;
t7 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON7), false);
SetDlgItemText(hwnd, BUTTON7, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);
}

}

switch(LOWORD(wParam)) {
case BUTTON8:{
b8 = tic;
t8 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON8), false);
SetDlgItemText(hwnd, BUTTON8, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);
}

}
switch(LOWORD(wParam)) {
case BUTTON9:{
b9 = tic;
t9 = "U";
EnableWindow(GetDlgItem(hwnd, BUTTON9), false);
SetDlgItemText(hwnd, BUTTON9, tic);
checkwin(hwnd);
changetic();
computerturn(hwnd);
}


}
switch(LOWORD(wParam)) {
case BUTTON10:{
srand (time(NULL));
/* generate secret number between 1 and 10: */
v1 = rand() % 10 + 1;
enablebuttons(hwnd);
if (v1 <= 4){
MessageBoxA(hwnd,"computer goes first!","TicTacToe",MB_OK|MB_ICONINFORMATION);
computerturn(hwnd);
}

if (v1 >= 5){
MessageBoxA(hwnd,"Person goes first!","TicTacToe",MB_OK|MB_ICONINFORMATION);}

}
}




break;

case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
[/CODE]

13 answers to this question

Recommended Posts

  • 0

Congrats man! I do not know of a better way.. but congrats on getting that far :)

Thanks Id like to change the windows api and see if I can change it around to run on linux or maybe try Haiku first (beos clone)

  • 0

A lot of this code is repetitive, so you could at least make functions that take the parts that vary as parameters.

A tic-tac-toe AI is basically a function that takes a game position as a parameter and returns the best move. One way to do this is pre-encode all possible positions along with their respective best moves in some kind of map structure. This is easy to do by hand for a 3x3 tic-tac-toe, but quickly becomes impractical if the board gets larger (the number of possible positions increases exponentially). Implementing the AI is then as easy as a look up in a table.

If you want to code a real AI that actually finds the best move dynamically, I suggest looking into the minimax algorithm. This is the basis of AI engines for chess, checkers, reverso and all those turn-based positional games.

  • Like 2
  • 0

A lot of this code is repetitive, so you could at least make functions that take the parts that vary as parameters.

A tic-tac-toe AI is basically a function that takes a game position as a parameter and returns the best move. One way to do this is pre-encode all possible positions along with their respective best moves in some kind of map structure. This is easy to do by hand for a 3x3 tic-tac-toe, but quickly becomes impractical if the board gets larger (the number of possible positions increases exponentially). Implementing the AI is then as easy as a look up in a table.

If you want to code a real AI that actually finds the best move dynamically, I suggest looking into the minimax algorithm. This is the basis of AI engines for chess, checkers, reverso and all those turn-based positional games.

Yes your right we learned about minimax but wasn't sure how to do in c++

  • 0

Before you attempt to optimize the AI algorithm, definitely clean the code up first. I think you can reduce the amount of code to maybe a third of what it is now by making helper functions to eliminate the repetition as suggested. Less code, less potential bugs.

And if you are up for a redesign, consider going the OOP approach as that is the main strength of C++ over C.

  • 0

wow what a mess :p anyways im sure you'll work on cleaning up your code as you mature as a programmer. just something i noticed right off the bat,i dont think you're using switches correctly.

from your code

switch (message) /* handle the messages */

{

case WM_COMMAND:

switch(LOWORD(wParam)) {

case BUTTON1:{

b1 = tic;

t1 = "U";

EnableWindow(GetDlgItem(hwnd, BUTTON1), false);

SetDlgItemText(hwnd, BUTTON1, tic);

checkwin(hwnd);

changetic();

computerturn(hwnd);

}

}

switch(LOWORD(wParam)) {

case BUTTON2:{

b2 = tic;

t2 = "U";

EnableWindow(GetDlgItem(hwnd, BUTTON2), false);

SetDlgItemText(hwnd, BUTTON2, tic);

checkwin(hwnd);

changetic();

computerturn(hwnd);

}

}

why do you keep using switch(LOWORD(wParam)) for every check of a button?

it should be

switch(LOWORD(wParam))

{

case BUTTON1:

yadda yadda

break;

case BUTTON2:

yadda yadda

break;

case BUTTON3:

break;

case BUTTON4:

break;

}

  • 0

Before you attempt to optimize the AI algorithm, definitely clean the code up first. I think you can reduce the amount of code to maybe a third of what it is now by making helper functions to eliminate the repetition as suggested. Less code, less potential bugs.

And if you are up for a redesign, consider going the OOP approach as that is the main strength of C++ over C.

Thank you I know oop but isn't this only useful if your program is about keeping data?

wow what a mess :p anyways im sure you'll work on cleaning up your code as you mature as a programmer. just something i noticed right off the bat,i dont think you're using switches correctly.

from your code

why do you keep using switch(LOWORD(wParam)) for every check of a button?

it should be

switch(LOWORD(wParam))

{

case BUTTON1:

yadda yadda

break;

case BUTTON2:

yadda yadda

break;

case BUTTON3:

break;

case BUTTON4:

break;

}

I thought I tried that and it didn't work.... I'll try it again later thou thanks

If you understand the algorithm then it's just a matter of learning the language. That's a much easier problem thankfully. :)

I think minmax will require alot more code?

I'd look at refactoring a lot of your code into function(s) as a first step - remove the repetition.

Thanks

  • 0
I think minmax will require alot more code?
If you know what you're doing it's not that much code... I get the feeling you're pretty new to programming with a general-purpose language, so perhaps coding a minimax-based AI (which is a lot more than just the algorithm itself) is outside of your grasp for now. Brush up on your data structures and algorithms and it should be fairly obvious how to do this.
  • 0

I actually wrote a (console based) Tic Tac Toe game in C++ two days ago. For my AI player implementation I wanted to avoid "Googling it" and implementing an algorithm, but as an experiment I just threw together whatever came to mind. Please note I am very much not an AI person (did a module on Machine Learning at Uni, it sucked the life out of me). My AI player doesn't try to block the human player because I couldn't be especially bothered to write that, but it wouldn't be hard to implement a test against the human players last move following the same ideas as the current code (i.e, checking which line the player's trying to fill and blocking it). If you're interested this was my code for the AI decision...

(Where char map[] is a 1D array of each square on the board left-to-right top-to-bottom, and int size is the width/height of the board (i.e, standard game of 3x3, 9 cells, size = 3))


int AIPlayer::YourMove(char map[], int size){
int move;
cout << "Computer player's move!" << endl;
if (lastMove == -1){
move = ((size*size)-1) / 2;
if (isFree(map,move)){
map[move] = _thischar;
}else{
if (isFree(map, 0)){
move = 0;
}else if (isFree(map, size-1)){
move = size-1;
}else if (isFree(map, size * (size-1))){
move = size * (size-1);
}else if (isFree(map, (size*size)-1)){
move = (size*size)-1;
}
}
}else{
int tmp = lastMove;
int iters = 0;
while(true){
move = testNeighbours(tmp, size, map);
if (move == -1 && iters < 30){
tmp = (rand() % (size*size));
iters++;
}else if (iters >= 30){
move = 0;
while (!isFree(map, move)) move = (rand() % (size*size));
break;
}else break;
}
}
map[move] = _thischar;
lastMove = move;
return move;
}
int AIPlayer::testNeighbours(int target, int size, char map[]){
/*
So... the way we're going to run this...
Take the target, scale it back to the start of it's horiz, vert, and diag lines (if rlvnt)
and run a test with testSequence which will check each element. If the whole path is clear
it's worth trying to fill up, so go for it.
Otherwise return a -1 and wait for a different target value.
*/
int chosen;
int vert = target;
while (vert >= size) vert -= size;
chosen = testSequence(vert, size, size, map);
if (chosen != -1) return chosen;
int horiz = target;
while (horiz % size != 0) horiz -= 1;
chosen = testSequence(horiz, 1, size, map);
if (chosen != -1) return chosen;
int diag = target;
if (target % (size+1) == 0){ //top-left to btm-right
while (diag != 0) diag -= size+1;
chosen = testSequence(diag, size+1, size, map);
if (chosen != -1) return chosen;
}
diag = target;
if (target % (size-1) == 0){ //top-right to btm-left
while (diag != (size-1)) diag -= size-1;
chosen = testSequence(diag, size-1, size, map);
if (chosen != -1) return chosen;
}
return -1;
}
int AIPlayer::testSequence(int start, int step, int size, char map[]){
int lfree;
for (int i=start;i<start+(size*step);i+=step){
if ( isFree(map, i) ) {lfree=i;continue;}
if ( map[i] != _thischar ) return -1;
}
return lfree;
}
[/CODE]

And to quote my own readme...

On it's first move it merely checks the "highly desirable" squares in the middle and corners, taking the first available. Subsequently, it uses it's previous move to decide it's next by checking the vertical, horizontal and diagonal (if applicable) paths which cross through the previous move. If it finds an opponents piece in one of these paths it is discounted as being "unwinnable", and it moves on to the next checking direction. If all directions are obstructed it picks a random cell and starts again from there. It is therefore trivial to beat the AI by forming your own line parallel to the one it's creating - it all just depends who makes the first move!

You can download my full code here: http://nerdshack.info/?p=730

  • 0

You are doing a lot of potentially dodgy string comparisons in your code.


// This is bad
char const * a = "a";
char const * b = "a";
bool eq1 = a == b;

// Slightly better
bool eq1 = strcmp(a, b) == 0;

// This is much better
std::string a = "a", b = "a";
bool eq2 = a == b;
[/CODE]

The C string comparisons will work if your compiler stores duplicate C strings in the same location in memory (which MSVC does do).

However, you cannot rely on this behaviour. So either use std::string to store the strings and make use of its equality operator,

or use strncmp on the two character arrays.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Good think I still have SDRAM and FP RAM sitting around.
    • Fitbit Charge 6 fitness tracker with Google apps is now at its lowest price with 47% off by Fiza Ali Amazon is currently offering the Fitbit Charge 6 fitness tracker at its all-time low price with a 47% discount. The device features an AMOLED touchscreen display protected by Corning Gorilla Glass 3 that should offer improved scratch resistance and durability. The Charge 6 is equipped with a range of sensors including an optical heart rate sensor, a 3-axis accelerometer, built-in GPS with GLONASS support, red and infrared sensors for SpO2 monitoring, a skin temperature sensor, an ambient light sensor, a vibration motor, NFC, and multipurpose electrical sensors compatible with the ECG and EDA Scan apps. Heart rate is recorded every second during exercise tracking and every five seconds during normal daily use. The device requires the Google Health app for setup and synchronisation. Furthermore, Bluetooth provides wireless connectivity for syncing and communication with devices running Apple iOS 16.4 or later and Android 11.0 or later. The tracker stores up to 7 days of minute-by-minute activity data and retains daily activity totals for the previous 30 days. In terms of water resistance, the Fitbit Charge 6 has a 5 ATM rating that should make it suitable for swimming and water activities. The tracker operates in temperatures ranging from 14°F to 113°F and at altitudes of up to 28,000 feet. Moreover, the included Infinity band is made from a flexible silicone material and features a loop-and-peg fastening. The small band fits wrists measuring 5.1 to 6.7 inches, while the large band fits wrists measuring 6.7 to 8.3 inches. Both small and large bands are included in the box. When it comes to battery performance, the Fitbit Charge 6 should deliver up to 7 days of battery life under typical usage conditions. Features such as the Always-On Display, built-in GPS, and SpO2 monitoring increase power consumption and may require more frequent charging. The rechargeable lithium-polymer battery should take approximately two hours to charge from empty to full. Fitbit Charge 6 Fitness Tracker with Google Apps: $85.45 (Amazon US) - 47% off Good to know This Amazon deal is U.S. specific, and not available in other regions unless specified. We only use first-party seller links (at the time of article publishing); ensure that you purchase from a first-party seller link only. Check out Today's Deals on Amazon | or our recent tech deals. Become a Prime member (for Students or SNAP) via Neowin Get Prime Access - Prime for half price (for qualifying Medicaid, EBT, SNAP) Subscribe to Prime Video, Audible Plus, Music Unlimited or Kindle Unlimited via Neowin As an Amazon Associate, we earn from qualifying purchases.
    • google, meta, microsoft, true cancers of modern society
    • TeraCopy 4.0 Build 28 by Razvan Serea TeraCopy is a compact program designed to copy and move files at the maximum possible speed, also providing you with a lot of features. Copy files faster. TeraCopy uses dynamically adjusted buffers to reduce seek times. Asynchronous copy speeds up file transfer between two physical hard drives. Pause and resume transfers. Pause copy process at any time to free up system resources and continue with a single click. Error recovery. In case of copy error, TeraCopy will try several times and in the worse case just skips the file, not terminating the entire transfer. Interactive file list. TeraCopy shows failed file transfers and lets you fix the problem and recopy only problem files. Shell integration. TeraCopy can completely replace Explorer copy and move functions, allowing you work with files as usual. TeraCopy is free for non-commercial use only. For commercial use you need to buy a license. The paid version of the program includes the following features: Copy/move to your favorite folders. Save reports as HTML and CSV files. Select files with the same extension/folder. Remove the selected files from the copy queue. Features added since version 3.17: Enhanced speed graph. New multi-threaded copy engine. Support for copying to multiple targets. Queue system for managing multiple copy operations. Support for receiving files via the LocalSend protocol. TeraCopy entry in the modern Windows Explorer context menu. Integrated toolbar in the title bar. Why receive LocalSend transfers with TeraCopy? Handle file conflicts: Skip, overwrite, or rename files when a file with the same name already exists. LocalSend always creates another copy, which can waste time and disk space, especially when resuming an interrupted transfer. Filter unwanted files: Apply ignore lists or remove files manually before accepting a transfer, so unnecessary files are not downloaded. Better performance on fast networks: In tests over a 10 Gbps connection, TeraCopy received files several times faster than the standard LocalSend app on Windows. TeraCopy 4.0 Build 28 changelog: Fixed a bug where Overwrite behaved as Overwrite All during same-drive move operations. AdvancedInstaller fixed the installer’s security vulnerability: EXE Bootstrapper resolved the %appdata% location incorrectly for the System account. Download: TeraCopy 4.0 Build 28 | 14.6 MB (Freeware, paid upgrade available) View: TeraCopy Website | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • First exciting thing to come to Windows in a long time ! This is the kind of things they should focus on, instead of cramming as much AI as they can in everything.
  • Recent Achievements

    • Reacting Well
      NovaEdgeX earned a badge
      Reacting Well
    • Week One Done
      NovaEdgeX earned a badge
      Week One Done
    • One Year In
      BA the Curmudgeon earned a badge
      One Year In
    • Conversation Starter
      rosiecharles earned a badge
      Conversation Starter
    • First Post
      KMilenkoski1202 earned a badge
      First Post
  • Popular Contributors

    1. 1
      +primortal
      536
    2. 2
      +Edouard
      269
    3. 3
      PsYcHoKiLLa
      150
    4. 4
      Steven P.
      98
    5. 5
      macoman
      61
  • Tell a friend

    Love Neowin? Tell a friend!