Tic Tac Toe Help!!

Hello all!! I have a quick question I am making a tic-tac-toe console game and it somewhat works the only thing that doesn't is checking vertical wins. I think my logic is wrong. Thanks for helping!!

Here is my code.

Game.h

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
//My Game.h File

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

const char PLAYER = 'X';
const char COMPUTER = 'O';
const char EMPTY = '*';

const int PLAYING = -1;
const int PLAYER_WINS = 0;
const int COMPUTER_WINS = 1;
const int DRAW = 2;

const int MAP_WIDTH = 3;
const int MAP_HEIGHT = 3;

typedef struct        //Struct containing winning info
{
    int iState;
    char chWho;
}Win;

class Game
{
    char Map [MAP_WIDTH][MAP_HEIGHT];      //Tic-Tac-Toe Map
public:
    Game ();                                                          //Constructor
    
    void drawMap ();                                             //Draws map to console
    void clearMap ();                                             //Clears the map to an EMPTY value
    void playerMove ();                                         //Asks user for X and Y points
    void computerMove ();                                    //Generates a computer X and Y points.

    Win gameState ();                                           //Get current game state
    
};


Game.cpp

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
//My Game.cpp File

Game::Game ()
{
    this->clearMap ();
}

//Init the map to EMPTY

void Game::clearMap ()
{
    int i = 0 , j = 0;
    for (i = 0 ; i < MAP_WIDTH ; i++)
    {
	for (j = 0 ; j < MAP_HEIGHT ; j++)
	{
	    this->Map [i][j] = EMPTY;
	}
    }
}

//Draw the map

void Game::drawMap ()
{
    int i = 0 , j = 0;
    for (i = 0; i < MAP_WIDTH ; i++)
    {
	for (j = 0; j < MAP_HEIGHT ; j++)
	{
	    cout << this->Map [i][j] << " ";
	}
	cout << endl;
    }
}

//Get player X and Y points

void Game::playerMove ()
{
    int iPlayerX = 0 , iPlayerY = 0;
    do
    {
	cout << "Please enter a Y value." << endl;
	cout << "Y >> : ";
	cin >> iPlayerX;
	while (cin.fail ())
	{
	    cout << "Please enter a number." << endl;
	    cout << "Y >> : ";
	    cin.clear ();
	    cin.ignore (256 , '\n');
	    cin >> iPlayerX;
	}
	cout << "Please enter a X value." << endl;
	cout << "X >> : ";
	cin >> iPlayerY;
	while (cin.fail ())
	{
	    cout << "Please enter a number." << endl;
	    cout << "X >> : ";
	    cin.clear ();
	    cin.ignore (256 , '\n');
	    cin >> iPlayerY;
	}
    }while (this->Map [iPlayerX][iPlayerY] != EMPTY);
    this->Map [iPlayerX][iPlayerY] = PLAYER;
}

//Generate computer X and Y

void Game::computerMove ()
{
    int iComputerX = 0 , iComputerY = 0;
    do
    {
	if (this->gameState ().iState == DRAW)
	{
	    break;
	}
	iComputerX = rand () % MAP_WIDTH;
	iComputerY = rand () % MAP_HEIGHT;
    }while (this->Map [iComputerX][iComputerY] != EMPTY);
    this->Map [iComputerX][iComputerY] = COMPUTER; 
}

//This is were I have my problems

Win Game::gameState ()
{
    //State to be returned at the end of checking.
    Win State = {PLAYING , '?'};
    int i = 0 , j = 0;   //Temp integers
    int iCounter = 0;    //Temp counter
    for (i = 0 ; i < MAP_WIDTH ; i++)  //This is suppose to check vertical wins
    {
	for (j = 0 ; j < MAP_HEIGHT ; j++)
	{
	    if (j + 1 < MAP_HEIGHT)  //To check for array out of bounds
	    {
		if (this->Map [i][j] == PLAYER || this->Map [i][j] == COMPUTER)  //If the spot is used
		{
                    /*If one point is the same as the next then increment the iCounter and make the      player on that spot the winner*/
		    if (this->Map [i][j] == this->Map [i][j + 1])    
		    {
			iCounter++;
			State.chWho = this->Map [i][j];
		    }
		}
	    }
	}
	if (iCounter == MAP_HEIGHT - 1) /*If all the spots were the same then determine who won*/
	{
	    if (State.chWho == COMPUTER)
	    {
		State.iState = COMPUTER_WINS;
		return State;
	    }
	    else
	    {
		State.iState = PLAYER_WINS;
		return State;
	    }
	}
	else
	{
	    iCounter = 0;
	}
    }
    iCounter = 0;

    //This checks horizontal wins 

    for (i = 0 ; i < MAP_HEIGHT ; i++)
    {
	for (j = 0 ; j < MAP_WIDTH ; j++)
	{
	    if (j + 1 < MAP_WIDTH)
	    {
                //Same logic as before if the spot is used then compare this and next
		if (this->Map [i][j] == COMPUTER || this->Map [i][j] == PLAYER)
		{
		    if (this->Map [i][j] == this->Map [i][j + 1])
		    {
			iCounter++;
			State.chWho = this->Map [i][j];
		    }
		}
	    }
	}
	if (iCounter == MAP_WIDTH - 1)
	{
	    if (State.chWho == COMPUTER)
	    {
		State.iState = COMPUTER_WINS;
		return State;
	    }
	    else
	    {
		State.iState = PLAYER_WINS;
		return State;
	    }
	}
	else
	{
	    iCounter = 0;
	}
    }
    iCounter = 0;

    //Checks for a draw (every space is used)
    for (i = 0 ; i < MAP_WIDTH ; i++)
    {
	for (j = 0 ; j < MAP_HEIGHT ; j++)
	{
	    if (this->Map [i][j] == COMPUTER || this->Map [i][j] == PLAYER)
	    {
		iCounter++;
	    }
	}
    }
    if (iCounter == MAP_WIDTH * MAP_HEIGHT) 
    {
	State.iState = DRAW;
	State.chWho = 'D';
	return State;
    }
    //None of the loops found anything therefore we must be playing
    State.iState = PLAYING;
    State.chWho = '?';
    return State;
}


main.cpp

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
//My main.cpp File

#include <iostream>

#include "Game.h"

using namespace std;

int main(int argc , char* argv[])
{
    srand ((unsigned) time (NULL));   //Seeding

    Game cGame;                               //Current game

    Win MyState = {PLAYING , '?'};              //Current game state

    do
    {
       	cGame.drawMap ();                           //Draw map
	cGame.playerMove ();                       //Get player's move
	cGame.computerMove ();                  //Generate computer's move
	MyState = cGame.gameState ();       //Get the current state
    
    }while (MyState.iState == PLAYING);    //Check if we are playing

    cout << "Player : " << MyState.chWho << " won!!" << endl;    //Declare the winner
    cout << "State Value : " << MyState.iState << endl;      //Debugging purposes ignore

    return 0;
}


Makefile


##My Makefile

CC = g++   ##Compiler 
CFLAGS = -Wall -g -c     ##Compiler options 
LFLAGS =                        ##Linker options
SRC = main.cpp Game.cpp     ##Sources
OBJS = $(SRC:.cpp=.o)          ##Objects
BIN = Tic-Tac-Toe                   ##Final program

all: $(SRC) $(BIN)

$(BIN): $(OBJS)
	$(CC) $(LFLAGS) $(OBJS) -o $@

%.o: %.cpp
	$(CC) $(CFLAGS) $< -o $@

clean:
	rm $(OBJS) $(BIN)


Again thanks for your time.
Last edited on
It helps if you tell us kind of where the issue is. Reading through a couple hundred lines of code to find a hidden error is kind of a pain.
No comments also really hurts. Create comments showing exactly which section is supposed to be checking for the vertical win.
Sorry guys for the late reply I'll edit the code right away.
Also in the vertical check loop does not work. Again thanks for your time very much appreciated.
Well, check the line 104 and 143. They're the same but that can't be right. The horizontal advancing cannot be done in the same dimension like the vertical. It's somewhat confusing that you're using i and j similar but for completly different directions
@coder777 Oh I see I am using i and j twice. For the vertical check I'll use i instead of j. I'll report back my results. By the way congrats on your 1200th post.

@Code Assassin Lol
Last edited on
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
    for (i = 0 ; i < MAP_HEIGHT ; i++)
    {
	for (j = 0 ; j < MAP_WIDTH ; j++)
	{
	    if (i + 1 < MAP_HEIGHT)
	    {
		if (this->Map [i][j] == PLAYER || this->Map [i][j] == COMPUTER)
		{
		    if (this->Map [i][j] == this->Map [i + 1][j])
		    {
			iCounter++;
			State.chWho = this->Map [i][j];
		    }
		}
	    }
	}
	if (iCounter == MAP_HEIGHT - 1)
	{
	    if (State.chWho == COMPUTER)
	    {
		State.iState = COMPUTER_WINS;
		return State;
	    }
	    else
	    {
		State.iState = PLAYER_WINS;
		return State;
	    }
	}
	else
	{
	    iCounter = 0;
	}
    }

I still have the same problem, :(
By the way congrats on your 1200th post.
Oh, thanks, I didn't realize.

I still have the same problem
Yes, it's the order of the loops. Can you imagine why?
@coder777 I switched loops and it works but I am still slumped as why it works. I have some sort of concept forming but I can't explain it.
Last edited on
When you code a loop always consider the second cycle. Mostly it suffice

From that above
The inner loop the second time you check the following:

oxo
oxo
ooo

while you want to check

ooo
xoo
xoo

The reason is that the inner loop goes horizontally

So the outer loop the second time you have already checked:

xxx
xxx

ooo

Do you see what I mean?
@coder777 Thank you!!! I finally understand what you mean. Oh my goodness thanks X 1000000000000!!!!
Topic archived. No new replies allowed.