3D Tic Tac Toe!

did this as an exercise, based loosely on the Carol Shaw Atari 2600 version.
i know the code's kinda cluttered. at first i didn't think anyone would ever read it but myself and i was just trying to get it to work. :)

feel free to point out anything i could do to make it more efficient, i'm sure there's plenty... i know for one thing i didn't have to pass an argument to the DISPLAY function, as i just could have accessed the global array directly... i don't even know which is the better way...



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <cstdlib>
#include <iostream>
#include <string>
#include <cstring>


using namespace std;

void DISPLAY (int *brd);
bool displayWINNER (int turn);
void resetARRAY ();
bool checkWINNER (int turn, int g, int r, int c);
int normalizeINPUT (string inp);

int turn, adj[6][6][6];


int main()
    {
         string inp;
         int g,r,c; 
         resetARRAY ();
         
    while (true) {
         turn++;
         DISPLAY (&adj[0][0][0]);
         if (turn%2==0) {cout<<"\nPlayer O, it's your turn!\n\n";}
             else {cout<<"\nPlayer X, it's your turn!\n\n";}
          cout<<"Enter grid number ('Q' to Quit) : ";
          getline (cin,inp);
          if ((inp[0]=='q')||(inp[0]=='Q')) break;
          g=normalizeINPUT(inp);
          if ((g<1)||(g>4)) {cout<<"\nInvalid selection.\n\n";            
                       system("PAUSE");turn--;continue;}
                       
          cout<<"Row number : ";
          getline (cin,inp);
          r=normalizeINPUT(inp);
          if ((r<1)||(r>4)) {cout<<"\nInvalid selection.\n\n";            
                       system("PAUSE");turn--;continue;}
                       
          cout<<"Column number : ";
          getline (cin,inp);
          c=normalizeINPUT(inp);
          if ((c<1)||(c>4)) {cout<<"\nInvalid selection.\n\n";            
                       system("PAUSE");turn--;continue;}
          if (adj[g][r][c]!=0) {cout<<"\nPlease select an unoccupied square!\n\n";
                       system("PAUSE");turn--;continue;}
          if (turn%2==0) {adj[g][r][c]=2;}
             else {adj[g][r][c]=1;}
          if (checkWINNER (turn,g,r,c)) {if(displayWINNER(turn)) break;}
         }
         cout<<"\n\n\n";
         return 0;
}


bool checkWINNER (int turn,int g,int r,int c) {
     int h=1;                   //sets 'h' to either
     if (turn%2==0) h=2;        //Xs or Os to check
     
     int x[4],y[4],z[4];        //variables to store winning coordinates
     x[0]=g;y[0]=r;z[0]=c;      //sets 0 of each to last move
     
     int ct;
     
     for (int a=1;a<14;a++){    //iterates through all possible directions
     
           ct=1;                      //each time resetting counter to one 
     
           int g2=g; int r2=r; int c2=c;
           
           for (int i=0;adj[g2][r2][c2]!=5;){

                 switch (a) {
                        case 1:g2--;break;                //////////////////////
                        case 2:g2--;r2--;c2--;break;      //  increments
                        case 3:g2--;r2--;break;           //  in each
                        case 4:g2--;r2--;c2++;break;      //  possible
                        case 5:g2--;c2--;break;           // direction
                        case 6:g2--;c2++;break;           //  until 
                        case 7:g2--;r2++;c2--;break;      // hitting
                        case 8:g2--;r2++;break;           //  a '5'
                        case 9:g2--;r2++;c2++;break;      //   
                        case 10:c2--;break;               //
                        case 11:r2--;c2--;break;          //   
                        case 12:r2--;break;               //  
                        case 13:r2--;c2++;break;          //////////////////////
                         }
                        
                 if (adj[g2][r2][c2]==h) {
                           x[ct]=g2;y[ct]=r2;z[ct]=c2;
                           ct++;}
                 
                 }
                 
                 
          g2=g;r2=r;c2=c;   //reset placeholder variables
         
         
          for (int i=0;adj[g2][r2][c2]!=5;) { 
              
              
                switch (a) {
                      case 1:g2++;break;                ///////////////////////
                      case 2:g2++;r2++;c2++;break;      //
                      case 3:g2++;r2++;break;           // and
                      case 4:g2++;r2++;c2--;break;      // then back
                      case 5:g2++;c2++;break;           //  in the
                      case 6:g2++;c2--;break;           //  opposite 
                      case 7:g2++;r2--;c2++;break;      //  direction
                      case 8:g2++;r2--;break;           //
                      case 9:g2++;r2--;c2--;break;      //
                      case 10:c2++;break;               //
                      case 11:r2++;c2++;break;          //
                      case 12:r2++;break;               //
                      case 13:r2++;c2--;break;          ///////////////////////
                      }
                                   
              if (adj[g2][r2][c2]==h) {
                      x[ct]=g2;y[ct]=r2;z[ct]=c2;
                      ct++;
                      }
               }
               if (ct>3) {for (int b=0;b<4;b++) {adj[x[b]][y[b]][z[b]]=4;} return 1;}
               }
     return 0;
}


     
int normalizeINPUT (string inp) {
    int i, q; 
    string n;
    for (int i=0;inp[i] != ' ';i++) n=n+inp[i];
    q=atoi(n.c_str());
    return q;
}

        
    

void DISPLAY(int *brd)
{
     system ("cls");
     cout <<"#1\t\t#2\t\t#3\t\t#4\n\n\n";
     int n;
     for (int y=1;y<5;y++) {
         for (int x=1;x<5;x++) {
             for (int z=1;z<5;z++) {
                 n=((x*36)+(y*6)+(z));
                 switch (*(brd+n)) {
                        case 0: cout<<" "; break;
                        case 1: cout<<"X"; break;
                        case 2: cout<<"O"; break;
                        case 4: cout<<(char)219;break;
                        }
                 if (z<4) cout<<(char)179;
                 }
             if (x<4) cout<<"\t\t";
             }
         if (y<4) {
                  cout<<"\n";
                  for (int m=1;m<32;m++) {
                       if (m%8==0) {cout<<"\t\t";}
                         else if (m%2==0) {cout<<(char)197;}
                           else cout<<(char)196;}
                            cout<<"\n";
                      }
                  
         }
     cout<<"\n\n\n\n";
     return;
     }
     
     
bool displayWINNER (int tn) {
     char yn[100];
     DISPLAY (&adj[0][0][0]);
     if (tn%2==0) {cout<<"\n\nO is the winner!!\n\n";}
        else cout<<"\n\nX is the winner!!\n\n";
     cout<<"Play again? (y/n) : ";
     cin>>yn;
     if (!strcmp(yn,"y")||!strcmp(yn,"Y")) {resetARRAY (); cin.ignore(1); turn=0; return 0;}
        else return 1;
}


void resetARRAY () {
     for (int x=0;x<6;x++) {
         for (int y=0;y<6;y++) {
             for (int z=0;z<6;z++) {
                 adj[x][y][z]=0;
                 }
             }
         }
     for (int i=0;i<6;i++) {
             for (int j=0;j<6;j++) {
                 adj[0][i][j]=5; adj[5][i][j]=5;
                 adj[i][j][0]=5; adj[i][j][5]=5;
                 adj[i][0][j]=5; adj[i][5][j]=5;}
                 }
         
     }
     
So Cool. I didn't realize that you could build a grid like that.

One suggestion:
In normalizeINPUT(), you require a [space] at the end of an input. It took me a few tries before I realized this. Otherwise I kept getting stack overflows during runtime.
To get around needing a space at the end of normalizeINPUT();, change for (int i=0;inp[i] != ' ';i++) n=n+inp[i]; to for (int i=0;inp[i] != '\0';i++) n=n+inp[i];
In normalizeINPUT(), you require a [space] at the end of an input. It took me a few tries before I realized this. Otherwise I kept getting stack overflows during runtime.


To get around needing a space at the end of normalizeINPUT();, change for (int i=0;inp[i] != ' ';i++) n=n+inp[i]; to for (int i=0;inp[i] != '\0';i++) n=n+inp[i];


thanks so much for checking it out!
thinking back, i have no idea why i just assumed the user would enter a whitespace somewhere, but somehow i managed to play a bunch of times without that being an issue.... but i also didn't do that much testing of the parser.

now at the risk of sounding like the noob i am, Stewbond, why does that stack overflow occur? don't all those variables go out of scope between function calls? i mean, i got it to crash just now after reading your post, but i had to enter a couple hundred random characters with no whitespace....

Last edited on
1
2
3
4
5
6
7
8
int normalizeINPUT (string inp) {
    int i, q; 
    string n;
    for (int i=0;inp[i] != '\0';i++) {n=n+inp[i];cout<<i;}
    q=atoi(n.c_str());
    cout<<"\ninp="<<inp<<"\tn="<<n<<"\tq="<<q<<"\ti="<<i<<"\n";
    return q;
}


i put a diagnostic cout into this function so i could track for myself what was happening with the variables. it spit out gobbledegoop for the value of n until i changed the loop's exit condition as whitenite1 suggested.

for some reason the final value of loop variable i is something ridiculous like 4439629. although it has no impact on the running of the program, i'm still not sure why this happens. i put another diagnostic cout inside the loop so i could track the value of i with each iteration. during runtime i entered a '3'. the cout inside the loop predictably output a single 0 for it's one iteration, but the final value of i in the last cout line was still 4439629. i don't get it.
Topic archived. No new replies allowed.