Seemingly random behaviour in states and property changes
-
In order to learn some C++ and Qt I am looking at some of the examples and trying to replicate/change them. So far, so good, but... One of the things I'm trying is replacing the AI in the Tic Tac Toe example, and it's not working as expected.
I have a QML file where I define my ApplicationWindow, with a MenuBar, and a Canvas element as a view in which I draw the board. The board is divided into nine tiles, implemented via a Component element that includes an Item element with two states that change with the clicked signal, and a MouseArea that, when it's clicked, works all the game logic (via functions defined in a *.js file that I import in the QML file):
[snip]
And then a grid of tiles, for the actual board, using a Repeater:
[snip]
The thing is, in player vs. player mode, it works fine, all state transitions happen as they should, and the tiles show the cross or nought image depending on who the current player is and where they click. But when playing against the computer, only human player moves work well, and AI moves either don't set the cross or nought image as visible, or set the wrong image (even though the board has the right state for each tile, I've checked by printing out the full board after every move), and it detects wins that shouldn't be a win (for example, two crosses and a nought in the same row).
Any idea what I'm doing wrong? Thanks in advance. If you need more details or parts of the code that I didn't post, let me know.
-
[snip]
Example screenshot. Blue crosses are human player, there are three missing red circles at tiles 1, 5, and 8 (upper left corner is tile 0). There's an invisible blue cross at tile 6, placed there by the computer during it's last turn, which is a winning move for X, but it shows that O won.
Makes no sense.
-
Hi,
Yes there is but not necessarily able to answer your question.
Are you trying to implement the AI to play the game "from the outside" or within the GUI directly ?
-
@SGaist The AI is in a separate *.js file, which I import in the QML. It's rather long, but I shall post it in case it helps:
[snip]
I have also edited the initial post to include the part of the QML that I omitted, with all the calls to the game logic.
-
I am not aware of a limit.
I am by no mean an AI expert but I'm wondering if you are not "doing it wrong". If i've understand your code correctly you are trying to put your AI everywhere in the GUI rather than have it as a second player that has access to the game.
Shouldn't you rather have e.g. a model that represent the grid and game state and have your AI analyze and modify it (that would replace the click from the player) ? That way the GUI would be updated automatically and wouldn't depend on it. You could even have two AI playing one against the other.
-
@SGaist Thanks for your help. I sort of do that already, it's in the first post:
[snip]
Or would that not suffice as a model that does what you said?
Oh, and that I'm doing it wrong goes without saying... If I was doing it right, it would work :P
-
I've re-read the example just to be sure I didn't miss something but in fact I did. If you want to modify the AI you "only" need to modify the computerTurn method or add a new xxxAI method and call it from computerTurn.
There's no need to modify any other file.
-
@SGaist I don't think I understand... What computerTurn method? I don't have one in my code, at least by that name. Everything is in the onClicked, so that it'll react to the click, perform the necessary changes according to the user action, and then do the computer's move... Which is done in the same way as the human's move, so theoretically it should work.
But it's late and I'm tired, so maybe you said something very obvious and I just don't see it.
-
In the Tic-Tac-Toe example you linked in your first post, you have the AI implementation in tic-tac-toe.js which contains computerTurn that will call either smartAI or randomAI based on your settings. So if you want to add a new AI, you could implement it in a myMegaCoolAI method that you will call from computerTurn (again based on the settings of the application)
-
@SGaist But as I said I don't have a computerTurn method. If you look at my code instead of the example, you'll see I have several move methods (a random move, a slightly smarter move, and a minimax-based move) in my js file, and I call them from the onClicked after the player completes their move, thereby simulating the computer's turn. That should suffice, right? I'm just getting rid of a level of indirection.
-
Removing that "level of indirection" makes the code globally less clear. If you take the original, replacing the AI with your own is really just modifying the computerTurn part, you would even have to care about the UI part since it's already handled properly.
-
@SGaist "Less clear" is subjective, but either way it shouldn't be the cause of the strange behaviour I'm seeing.
As for taking the original and merely replacing the original... Well, that kind of defeats the purpose of learning Qt, which is why I'm implementing the example from scratch. Just changing the AI would at best teach me a bit of Javascript. Granted, that one is my fault because in the first comment of this topic I didn't properly word what I was actually doing.
-
We might then see the learning process a bit differently. I'd first implement the AI the way I want it based on what exist to ensure that part is working. Then on the next iteration, I'd modify another part of the code. That way you know more or less exactly what you broke when something start to misbehave. Changing several things at once will get you in trouble faster.
Since you want to learn QML, did you took a look at the qmlbook.org web site ?
-
Problem solved. The problem was between the chair and the keyboard. If anyone's curious, the part of my code that takes care of the computer's turn was outside the branch where the player's turn takes place, and it should be inside. And the same for the checking of whether it's a win or a draw after both players complete a turn. One of those things that is easy to overlook if one assumes the structure of the code is correct, and the bug is due to misusing a feature of the language/framework/whatever. Well, turns out sometimes the developer can use the tools properly and still be Doing It Wrong™.
-
All programming languages offer features to shoot yourself in the foot ;)
Glad you found out and thanks for sharing :)
Happy coding !