I have documented this restriction but should I be throwing an exception instead? Or can this be handled in the UI?Campbell Ritchie wrote:don't use size > 46340!
I think this check should happen in a method(checkWinner()?) in the Game class. Is this correct?Campbell Ritchie wrote:Work out whether you will decide that the Game has finished in an object of this class or somewhere else.
I considered a few options, but an array of arrays seems the best option to me considering the kindCampbell Ritchie wrote:Think whether there are other ways to organise the Squares than an array.
Prasanna Raman wrote:
46340 is (int)√2147483647!Prasanna Raman wrote:
I have documented this restriction . . .Campbell Ritchie wrote:don't use size > 46340!
Work it out. If you call such a method, what will it return? Does that mean the method must be called after every single move? What if you reach move 9 and nobody has won? What will that method return?Prasanna Raman wrote:
I think this check should happen in a method(checkWinner()?) in the Game class. Is this correct?Campbell Ritchie wrote:Work out whether you will decide that the Game has finished in an object of this class or somewhere else.
I presume you mean array because you haven't used an array of arrays. I would not use a List myself, and I think an array or an array of arrays each just as good as the other. But that is only my opinion.Prasanna Raman wrote:
I considered a few options, but an array of arrays seems the best option to me considering the kindCampbell Ritchie wrote:Think whether there are other ways to organise the Squares than an array.
of operations that need to be performed.
I am still working on this one.Campbell Ritchie wrote:Work it out. If you call such a method, what will it return? Does that mean the method must be called after every single move? What if you reach move 9 and nobody has won? What will that method return?
More important: can you think of any other ways to do it? I am not here to tell you how to do it but to make you think
Have you used these lines of code to show that returning the board might be dangerous because its state could be tampered with?Campbell Ritchie wrote:
Yes. I presume you have tried it. It is always worth knowing when you are returning something which might allow the state of an object to be altered unexpectedly.Prasanna Raman wrote: . . . Have you used these lines of code to show that returning the board might be dangerous because its state could be tampered with?
Yes, I did try this but am very confusedCampbell Ritchie wrote:Yes. I presume you have tried it. It is always worth knowing when you are returning something which might allow the state of an object to be altered unexpectedly.
Sorry, does this mean you will not be helping anymore?Campbell Ritchie wrote:And goodbye nice number of posts
Don't worry! At this rate, you should reach 44444 very soonCampbell Ritchie wrote:No, it means it will be a long time before my number of posts reads as a nice number
I think the method should return a String (or an enum) indicating whether X/O has won, or if it's a tie, or if the game is in progress. The method will be called only if the occupied square count is >=2*size-1.Campbell Ritchie wrote:Work it out. If you call such a method, what will it return? Does that mean the method must be called after every single move? What if you reach move 9 and nobody has won? What will that method return?
I feel it's appropriate to have this check done in the Game class, but I am not able to think of other ways to do this.Campbell Ritchie wrote:can you think of any other ways to do it? I am not here to tell you how to do it but to make you think
Why do you need to check whether you have passed 2*size-1? When you get a complete row, you have completed the game. The constraints on passing O/X and taking turns should ensure that anyway.Prasanna Raman wrote: . . . I think the method should return a String (or an enum) indicating whether X/O has won, or if it's a tie, or if the game is in progress. The method will be called only if the occupied square count is >=2*size-1.
. . . I feel it's appropriate to have this check done in the Game class, but I am not able to think of other ways to do this.
The minimum number of occupied squares needed for any player to win is 2n-1. So I thought I'd check that first before calling checkWinner() so we avoid calling checkWinner() from the first move.Campbell Ritchie wrote:Why do you need to check whether you have passed 2*size-1?
The other way I can think of is by using an enum called Result with 4 states - X,O,TIE,IN_PROGRESS. The checkWinner() method can return one of the 4 states.Campbell Ritchie wrote:I am sure you can think of other ways to signal game completion.
In my view, it is not the responsibility of the Board class to signal completion by applying the rules of the game. The game class is like the rule book, which should determine the result of the game.Campbell Ritchie wrote:Why does the Game class have to signal completion? Why can't you do it in the Board class?
I am very confused with this one. I realize in this instance that returning Square[][] is dangerous because the individual squares could be modified. Does it mean that an object can never be returned? Or the object can't be returned in some instances where its state is modifiable? I am not able to visualise when an object can or can't be returned.Campbell Ritchie wrote:If you return a Symbol[][] from Board#getBoard, that would have no links to the original object, and no outside code could damage it.
Can we avoid this interference by placing the Game class in a different package?Campbell Ritchie wrote:There are several other ways to secure that class from illegitimate interference.
What is wrong with checking from the first move? Obviously the first 4 turns you will always get false. I think it is simpler code, but it is your app, so you will have to decide. But consider several solutions before you decide.Prasanna Raman wrote: . . . So I thought I'd check that first before calling checkWinner() so we avoid calling checkWinner() from the first move.
You mentioned a different way to signal completion about 28000 posts ago, in this very thread.. . .The other way I can think of is by using an enum called Result with 4 states - X,O,TIE,IN_PROGRESS. The checkWinner() method can return one of the 4 states.
Agreed, then.. . . In my view, it is not the responsibility of the Board class to signal completion by applying the rules of the game. The game class is like the rule book, which should determine the result of the game.
Can we avoid this interference by placing the Game class in a different package?Probably. I would have put all the classes you have at present into one package. Then you can restrict access to the other classes by giving them package‑private access. You will probably have to give Game and Symbol public access.. . .
Design problem: the implementation which relies on a mutable object. Like this version of my Kettle class. The minFill field represents the smallest amount of water required to cover the element.What you are doing is passing a mutable object in. This mutable object becomes part of the implementation of Kettle, but because of bad design in the fill method, you now have two references to the same object. So when you set the w object to freezing, the kettle cools off. Later on you are returning the same object, so you now have three references to it: w, ww and one inside the Kettle object. When you change the volume of the ww object, you enlarge the object inside the Kettle so it would cause it to overflow. At least you would have cold water all over the floor, not boiling water running over your hands.Prasanna Raman wrote: . . . I realize in this instance that returning Square[][] is dangerous because the individual squares could be modified. . . .
You're welcomePrasanna Raman wrote:Thank you . . .
Opinions would differ. If you can seal your package and are sure there is no naughty code around, then you will be all right. That is one opinion.As a rule, should I just refrain from passing mutable objects from any method, or may there be instances when you do pass mutable objects safe in the knowledge that it's not going to be accessed from within the same package? . . .
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime. |