While loop still runs when I don't want it to?

Even though I have it set so Playerturn is false after one press it still runs the loops. I only want it to be able to press one key once, but instead I can press all the keys.

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
 int main()
{
    bool UpdateMove;
    bool Gamestarted = false;
    bool WindowOpen = true;
    bool Menu = true;
    bool Menu2;
    bool PlayerTurn = false;
    bool Player2 = false;
    bool AiTurn = false;
    bool OBarray[9] = {false};
    bool XBarray[9] = {false};
    bool TurnArray[5] = {false};
    bool firstturn = false;
    int AiMove;
    bool Ocycle;
    bool Xcycle;
    int x;
    int z = 0;
    char AiMark = 'O';
    char Amove[9] =  {' ',' ',' ',' ',' ',' ',' ',' ',' ',};
    srand(time(0));

    while(WindowOpen)
    {
        if(Menu)
        {
            std::cout << "1-9 to mark position, press enter to begin." << std::endl;
            UpdateMove = false;
            while(Menu2)
            {
                if(GetAsyncKeyState(VK_RETURN))
                {
                    Menu = false;
                    UpdateMove = true;
                    Menu2 = false;
                    Gamestarted = true;
                    AiTurn = true;
                    firstturn = true;
                    x = 0;
                }
            }
        }
        while(Gamestarted)
        {
            if(UpdateMove == true)
            {
                system("cls");
                std::cout << "|" << Amove[0] << "|" << Amove[1] << "|" << Amove[2] << "|\n-------\n|" << Amove[3] << "|" << Amove[4] << "|" << Amove[5] << "|\n-------\n|" << Amove[6] << "|" << Amove[7] << "|" << Amove[8] << "|\n-------" << std::endl;
                UpdateMove = false;
            }

            for(x = 0; x !=9; x++)
            {
                if(Amove[x] == 'O')
                {
                    OBarray[x] = true;
                }

            }
            x = 0;
            for(x = 0; x !=9; x++)
            {
                if(Amove[x] == 'X')
                {
                    XBarray[x] = true;
                }
            }
            x = 0;

            while(PlayerTurn)
            {
                if(GetAsyncKeyState('1'))
                {
                        Amove[0] = 'X';
                        UpdateMove = true;
                        PlayerTurn = false;
                        AiTurn = true;
                }
                if(GetAsyncKeyState('2'))
                {
                        Amove[1] = 'X';
                        UpdateMove = true;
                        PlayerTurn = false;
                        AiTurn = true;
                }
                if(GetAsyncKeyState('3'))
                {
                        Amove[2] = 'X';
                        UpdateMove = true;
                        PlayerTurn = false;
                        AiTurn = true;
                }
            }

        while(AiTurn)
        {
            TurnArray[z] = true;
            z++;

            if(TurnArray[0])
            {

                while((AiMove != 0) && (AiMove != 2) && (AiMove != 6) && (AiMove != 8))
                {
                    AiMove = (rand() %9);
                }
                Amove[AiMove] = AiMark;
                AiTurn = false;
                PlayerTurn = true;
                UpdateMove = true;
            }
            if(TurnArray[1])
            {
                if((XBarray[0] == false) && (XBarray[2] == false) && (XBarray[6] == false) && (XBarray[8] == false))
                {
                    if(OBarray[0])
                    {
                        OBarray[8] = 'O';
                        AiTurn = false;
                        PlayerTurn = true;
                        UpdateMove = true;
                    }
                    if(OBarray[8])
                    {
                        OBarray[0] = 'O';
                        AiTurn = false;
                        PlayerTurn = true;
                        UpdateMove = true;
                        Player2 = true;
                    }
                    if(OBarray[2])
                    {
                        OBarray[6] = 'O';
                        AiTurn = false;
                        PlayerTurn = true;
                        UpdateMove = true;
                        Player2 = true;
                    }
                    if(OBarray[6])
                    {
                        OBarray[2] = 'O';
                        AiTurn = false;
                        PlayerTurn = true;
                        UpdateMove = true;
                        Player2 = true;
                    }

                }
            }

        }
        }
    }



    return 0;
}


What I thought this did was if the statement was true run the while loop in it until it finds one of those numbers, set the spot on the board, end the Ai Turn, and the player turn, then Update the board. But does it instead somehow keep setting PlayerTurn to true?
Last edited on
I thought I might have spotted the problem, but it would be helpful if you posted more code, showing where your while(PlayerTurn) loop is called in relation to your while(AiTurn) loop. Are they in the same function?
I have it all in one, which I know I shouldn't do, but I'm not used to coding with functions because I never saw I point in it. I'm going to start coding that way after I finish this because I really don't want to have to redo everything. Anyway I posted the full code if that helps.
Still haven't figured it out, anyone know?
it wont go anywhere because everytime you press 1 or 2 or 3 in playerturn it will go to aiturn then go back to playerturn you need to end the game to stop
Still haven't fixed this so instead of reposting I'm just going to bump this post. I'm not sure what wwwiii meant, to clarify what the problem is instead of being able to press just 1 key 1 time I can press all the keys. I tried to push this problem aside and just keep working on what I was trying to make, but it's causing more problems because of the fact every time a key is pressed Aiturn is set back to true. Anyway, if anyone knows the problem and can help me that would be great.
One thing I noticed immediately is that at line 32, on the first iteration of your outer while loop, you're using the value of Menu2 without having first initialised it. This means that you have undefined behaviour - Menu2 could contain a random value, or one that is compiler-dependent.

I'm surprised your compiler didn't warn you about this.

Also, it would help to see the flow of control and logic in your code if you indented your lines consistently. Lines 97 - 153 are inside your while (GameStarted) loop, but that's not immediately obvious because you've indented them as if they weren't inside it.

I don't quite understand your explanation of the problem. Here's how your code behaves right now:

- Every time the player presses 1, 2 or 3, you set PlayerTurn to false and AiTurn to true

- This makes the while (playerTurn) loop exit, and the while(AiTurn) loop start.

- Then, whenever you set AiTurn to false, you set PlayerTurn to true.

- This means that you exit the while(AiTurn) loop. But you're still inside the while(Gamestarted) loop, so you begin the next iteration of that loop.

- When you hit while(PlayerTurn) again, PlayerTurn is true - because you set it to true the last time you changed AiTurn to false, so the while(PlayerTurn) loop runs again

- and so on, and so on, and so on.

You never set GameStarted to false, so the while(Gamestarted) loop never exits.

You would probably find all this easier to see yourself if you started to break the code up into functions. That would allow you to abstract things a little bit, making it easier to see the bigger picture of how the overall logic flows.

Also, it would help you avoid repeated code, like lines 76 - 79 being repeated at 83 - 86, and again at 90 - 93.

EDIT: And one other thing. You said:

I'm going to start coding that way after I finish this because I really don't want to have to redo everything.

Refactoring your code to improve it is never a bad thing to do. It can be a very helpful learning exercise, because you already know how the code works and what it's doing. It allows you to focus on finding a better way do to the thing you're doing, rather than trying to solve a new problem and at the same time learning a new way to do something.

Also, it can make the rest of your work on this project easier.

Last edited on
but I'm not used to coding with functions because I never saw I point in it


Well, main() is a function, so you're already programming with functions, and since you're using other functions (GetAsyncKeyState(), system()); I think you have an idea what the point is by now.

Also, for added emphasis, I think what @MikeyBoy said about refactoring is excellent advice.
Thanks for the responses, I'll do as you said and redo the code the reason I didn't want to is because I was originally just making this for fun to see if I could make a basic AI before I started studying again. Also, the wrong indenting is just because when I copied the code it turned out weirdly so I had to space it myself, but thanks for letting me know, I checked my code just to make sure I hadn't done it wrong, it would bug me if I had :x. Anyway, I'm still not sure what's causing the problem still even though I'm going to redo it I want to avoid this in the future. Since I still haven't made it very clear what the problem is, I'll write what it shows when I run the code and if I press all the keys.

When I run the code I want it so, I can only press one key for that turn, so I might only 1 move and then the Ai goes. But instead I can press all the keys, so if I press 1-9 it would look like:

|X|X|X|
|X|X|X|
|X|X|X|

It would be like if you were playing Tic Tac Toe in real life and your partner goes one time then you go, but instead of drawing one X you just draw them in all the spots instead.

Hope that makes it easier to understand, I don't know how else to explain it. ;/

One more thing I wanted to say, what did you mean by
You never set GameStarted to false, so the while(Gamestarted) loop never exits.
I have it set at the top. Or did you mean I never set it to false to end the loop? If so, the reason why I haven't done that yet is because I haven't finished what I'm working on yet. Maybe I'm just misunderstanding what you mean, wwwiii mentioned that also.
Last edited on
When I run the code I want it so, I can only press one key for that turn, so I might only 1 move and then the Ai goes. But instead I can press all the keys, so if I press 1-9 it would look like:

|X|X|X|
|X|X|X|
|X|X|X|

It would be like if you were playing Tic Tac Toe in real life and your partner goes one time then you go, but instead of drawing one X you just draw them in all the spots instead.

Oh, OK, I see what you mean now. So the problem is that the AI doesn't appear to take a turn between player turns.

If the code is adding 'X' to the array, then it's obviously correctly getting the player's choice, it must be entering a conditional block that sets PlayerTurn to false and AiTurn to true. So, the while (playerTurn) loop must be exitting, and the while (AiTurn) loop must be entering.

(By the way, I don't see any code for processing numbers 4 - 9. Did you edit those out of what you posted to keep it shorter? Are you certain that you're setting PlayerTurn and AiTurn correctly in every single one of those sections?)

My guess is that, somehow, the code is getting through the while (AiTurn) loop setting AiTurn to false without actually recording the move.

Either that, or for some reason the part of your code that displays the updated grid isn't being executed, so it only looks as though there's been no computer turn.

I notice that, in the player turn, there's nothing that checks whether there's already a symbol in the space the player tries to play in. So if the AI puts an 'O' in space 2, and then the player selects space 2, then the software allows the player to simply overwrite the 'O' with an 'X'. So it might just look as though the AI isn't taking a turn, when it fact it is, but the player is then overwriting the AI's moves.

EDIT:

My recommendation is to use a debugger to step through your code. You can see exactly which lines are being executed and which are not, and you can see how the values of your variables change as it does. That should give you an idea of what's really happening.

One more thing I wanted to say, what did you mean by
You never set GameStarted to false, so the while(Gamestarted) loop never exits.
I have it set at the top. Or did you mean I never set it to false to end the loop? If so, the reason why I haven't done that yet is because I haven't finished what I'm working on yet. Maybe I'm just misunderstanding what you mean, wwwiii mentioned that also.

Yes, that's what I meant. You initialise it to false, but once you've set it true and entered the loop, nothing ever sets it to false, so the loop runs for ever.
Last edited on
OMG I FIXED IT. I thought of how to fix it last night, but only tried it now. I had to set the TurnArray in AiTurn to false after I make the Ai move. I'm still not sure why this was the problem though, but I'm really glad I finally figured it out.
Last edited on
Topic archived. No new replies allowed.