weird behavior of tic-tac-toe game

zhaorenbo (7)
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.
Chervil (1203)
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
Registered users can post here. Sign in or register to post.