weird behavior of tic-tac-toe game

I wrote a tic-tac-toe program, when i run it, i get some weird behavior. Refer to the output below. The program output the winner when there is actually no winner. In my program, player 1 uses 'X' while player 2 uses 'O'.

+-+-+-+
|X|O| |
+-+-+-+
| | | |
+-+-+-+
| | | |
+-+-+-+

The winner is player 1.


The code of my main program.
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
  1 #include <iostream>
  2 #include <string>
  3 #include "myGrid.cpp"
  4 using namespace std;
  5
  6 int main(){
  7     int playerMarker = 1;
  8     myGrid grid;
  9     int row, col;
 10
 11     while (grid.winner() == 0 && !grid.full()){
 12         cout << "Player " << playerMarker << endl;
 13         cout << "Row => ";
 14         cin >> row;
 15         cout << "Column => ";
 16         cin >> col;
 17         if (!grid.add(row, col, playerMarker)){
 18             cout << "Location already filled." << endl << endl;
 19         } else {
 20             cout << grid.toString() << endl;
 21             playerMarker ^= 0x03;                  //toggle players
 22         }
 23     }
 24
 25     if (grid.full())
 26         cout << "Tie. Nobody wins." << endl;
 27     else
 28         cout << "The winner is player " << grid.winner() << ".\n";
 29
 30     return 0;
 31 }

The code for myGrid.cpp, myGrid.h is omitted.
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
  1 #include <sstream>
  2 #include <iostream>
  3 #include "myGrid.h"
  4 using namespace std;
  5
  6 myGrid::myGrid(){
  7     for (int i = 0; i < ODR; i++)
  8         for (int j = 0; j < ODR; j++)
  9             _grid[i][j] = 0;
 10 }
 11
 12 int myGrid::findState(int sum, int prod){
 13     int state;
 14
 15     if (prod != 0){
 16         if (sum == ODR * 1)
 17             state = 1;
 18         else if (sum == ODR * 2)
 19             state = 2;
 20         else
 21             state = 0;
 22     } else{
 23         state = 0;
 24     }
 25
 26     return state;
 27 }
 28
 29 bool myGrid::add(int userR, int userC, int playerMarker){
 30     int idxR = userR - 1;
 31     int idxC = userC - 1;
 32
 33     if (userR > ODR || userC > ODR || _grid[idxR][idxC] != 0)
 34         return false;
 35
 36     _grid[idxR][idxC] = playerMarker;
 37     return true;
 38 }
 39
 40 bool myGrid::full(){
 41     for (int i = 0; i < ODR; i++)
 42         for (int j = 0; j < ODR; j++)
 43             if (_grid[i][j] == 0)
 44                 return false;
 45
 46     return true;
 47 }
 48
 49 int myGrid::winner(){
 50     int state = 0;
 51     int sum, prod;
 52
 53     // check rows
 54     for (int i = 0; i < ODR; i++){
 55         sum = 0;
 56         prod = 1;
 57         for (int j = 0; j < ODR; j++){
 58             sum += _grid[i][j];
 59             prod *= _grid[i][j];
 60             if (state == 0)
 61                 state = findState(sum, prod);
 62         }
 63     }
 64
 65     // check cols
 66     for (int i = 0; i < ODR; i++){
 67         sum = 0;
 68         prod = 1;
 69         for (int j = 0; j < ODR; j++){
 70             sum += _grid[j][i];
 71             prod *= _grid[j][i];
 72             if (state == 0)
 73                 state = findState(sum, prod);
 74         }
 75     }
 76
 77     // check major diagonal
 78     sum = 0;
 79     prod = 1;
 80     for (int i = 0; i < ODR; i++){
 81         sum += _grid[i][i];
 82         prod *= _grid[i][i];
 83     }
 84     if (state == 0)
 85         state = findState(sum, prod);
 86
 87     // check minor diagonal
 88     sum = 0;
 89     prod = 1;
 90     for (int i = 0; i < ODR; i++){
 91         sum += _grid[i][ODR - 1 - i];
 92         prod *= _grid[i][ODR -1 - i];
 93     }
 94     if (state == 0)
 95         state = findState(sum, prod);
 96
 97     return state;
 98 }
 99
100 string myGrid::toString(){
101     ostringstream os;
102
103     os << "+-+-+-+" << endl;
104     for (int i = 0; i < ODR; i++){
105         for (int j = 0; j < ODR; j++)
106             os << '|' << transToSymbol(_grid[i][j]);
107         os << '|' << endl;
108         os << "+-+-+-+" << endl;
109     }
110
111     return os.str();
112 }
113
114 char myGrid::transToSymbol(int val){
115     char ch;
116
117     if (val == 0){
118         ch = ' ';
119     } else if (val == 1){
120         ch = 'X';
121     } else{
122         ch = 'O';
123     }
124
125     return ch;
126 }

I suspect the problem lies in the member method winner() and findState(); but i cannot find any logic error. Can anyone explain the peculiar behavior of my program?
Thanks a lot.
In function myGrid::winner() you are checking partial rows and partial columns. The call to findState() needs to be moved outside the inner for-loop.
53
54
55
56
57
58
59
60
61
62
63
    // check rows
    for (int i = 0; i < ODR; i++){
        sum = 0;
        prod = 1;
        for (int j = 0; j < ODR; j++){
            sum += _grid[i][j];
            prod *= _grid[i][j];
        }
        if (state == 0)
            state = findState(sum, prod);
    }

and similarly with the column check.

p.s. it was fun recreating the .h file and guessing the value of ODR.
Last edited on
Topic archived. No new replies allowed.