• Post Reply Bookmark Topic Watch Topic
  • New Topic

NIM with abstract class  RSS feed

 
Nils Anton
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello!

As a school exercise I've created a Nim game. The exercise is supposed to teach me about abstract classes, inheritance, and interfaces. Therefore I decided to have an abstract Player-class that the human and computer player inherit methods and instance variables from.

I would love to get some feedback on the code - especially the Player-, HumanPlayer-, and ComputerPlayer-class.

Also, I think that I understand abstract classes, and inheritance - yet I don't think I understand interfaces - more than that they're abstract classes. I've read some articles about them, yet I still don't feel that I know when to use an interface. Could you help me by giving me an example of when you should use an interface?

And answering this question as well: when initializing a variable in a constructor, is it better to have the constructor call a set-method, i.e.:


or have the constructor initialize the variables:

?


Link to java files:
https://www.dropbox.com/sh/9m5n64vqmmw5o8w/AACl_h1eO6seW42TULZ-jZGha?dl=0

"GameTestDrive.java" is used to run the game.

Your help is appreciated .

CODE:










 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nils Anton wrote:Hello!
As a school exercise I've created a Nim game. The exercise is supposed to teach me about abstract classes, inheritance, and interfaces. Therefore I decided to have an abstract Player-class that the human and computer player inherit methods and instance variables from.

Hi Nils, and welcome to JavaRanch.

Sounds like a fun exercise; and I'd say that what you've stated above sounds like a good place to start.

However, while I see a HumanPlayer, I don't see any ComputerPlayer class. What are the differences between them?
Try to explain it to us IN ENGLISH, not in "Java-speak".

Another thing: Consider adding a Board class that simply represents the "pyramid" of the game - ie, rows of 1, 3, 5, 7... matchsticks, that allows ANY Player to remove them, and prevents illegal moves.

Note that this is NOT the game itself, simply the "playing area"; and many games - including Chess, Go, Connect4/5, Mastermind, etc - have one. It's also the thing that you're likely to want to display (however you do that).

Also: DON'T include underscores ('_') in your variable names. It's regarded as "Python-esque", and generally frowned on in the Java community. You can find proper naming conventions here; and I advise you to memorise them as quickly as possible.

HIH

Winston
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
(Setting the tone: read this with a tone of but in mind, ok?)

Let's start with names.

Read this variable name out loud: playerNr_

Did hear yourself? Was it intelligible? When I read it out loud, I sound like I've had a few too many drinks. "Player what?"

This is what I call the "abbreviation slur". To what end are you abbreviating the name? To save keystrokes? If you're using an IDE, use the code completion shortcut feature! Most modern IDEs like Eclipse and IntelliJ IDEA have it. Avoid abbreviations, spell words out. It makes your programs easier to read and it reduces the cognitive load on the reader.

Next, look for unnecessary duplication:

I added a few things to highlight the problem but sorry, but how many times do you need to remind yourself that you're dealing with a Player here? Don't be redundant. It only adds to the cognitive weight of your program.

Next, the trailing underscore on the field names may be an common convention in other languages but it's not in Java. There may be some teams who carry this convention over to their projects but in general, I don't see this very much. This is just a matter of style but know that it's not a very common style and some people, like myself, even frown upon it.

 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
(Use same tone as before )

In Game.setPlayers, the first two lines are redundant. The effects of these two lines is to set the references to the objects referenced by p1 and p2, respectively. Yet, in the following statement, you overwrite those values. This forces the astute reader to pause and wonder why you did that: "Wait, why did he do that?" and interrupts his train of thought. Your code should help guide the reader through, building up an understanding of what was on your mind when you were writing it. Unnecessary operations like this disrupts that flow and reveals a lack of clarity of thought on your part -- or just a rookie misunderstanding, in this case.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
(You should know by now... )

Overall, this code strongly hints at someone who has experience writing programs in another language. I doubt this is your first rodeo, right Cowboy?

In a program this small, mixing concerns is not much of a big deal. In larger programs, however, you should think about separation of concerns, particularly the concerns of doing calculations vs input/display.

Using inheritance and polymorphism to simplify the decision to prompt or not prompt for input works in this case but experienced hands will detect a slight smell there and will keep a wary eye on it. Mixed responsibilities tend to make for code that is more difficult to maintain.

As for using interfaces vs abstract classes, my rule of thumb is to use an interface when you know there will be a definite need to have an unknown number of different implementations. Also, when the idea represented is along or crosses application layer boundaries (View, Control, Data, Service, Model, etc.), prefer interfaces as they have the least amount of coupling.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
2 seconds is an awfully long time to simulate a computer trying to make a decision. Are you trying to make the computer look stupid or what? ;)
 
Nils Anton
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Winston Gutkowski: thank you for the welcome .

However, while I see a HumanPlayer, I don't see any ComputerPlayer class. What are the differences between them?
Try to explain it to us IN ENGLISH, not in "Java-speak".


The human has to pick at least 1 stick, and can pick up to half of the sticks left - rounded down, i.e. if there's 21 sticks left she can take 10 sticks.

The computer randomly takes a number of sticks - while following the above rules.

Note that this is NOT the game itself, simply the "playing area"; and many games - including Chess, Go, Connect4/5, Mastermind, etc - have one. It's also the thing that you're likely to want to display (however you do that).


Sounds like a fun thing to add - I haven't done any "graphics" yet - yet I'm sure there's good guides on the net for how to do it .

Also: DON'T include underscores ('_') in your variable names. It's regarded as "Python-esque", and generally frowned on in the Java community. You can find proper naming conventions here; and I advise you to memorise them as quickly as possible.


I'll stay away from the underscores, and I've already bookmarked the link : ).


@Junily Lacar: loads of great feedback

One unnecessarily short name: playerNr_ (it does sound stupid when I read it out loud ), one unnecessarily long: playerNumber, playerName, etc.

I've got no excuse for the lines:


I'll be sure to stay away from underscore naming.

Overall, this code strongly hints at someone who has experience writing programs in another language. I doubt this is your first rodeo, right Cowboy?

I've before played around some in C#, UnityScript, Python, and done some visual scripting in Kismet and Hammer. Yet I recently started studying programming at school, so I feel I don't quite get what:

In a program this small, mixing concerns is not much of a big deal. In larger programs, however, you should think about separation of concerns, particularly the concerns of doing calculations vs input/display.

Using inheritance and polymorphism to simplify the decision to prompt or not prompt for input works in this case but experienced hands will detect a slight smell there and will keep a wary eye on it. Mixed responsibilities tend to make for code that is more difficult to maintain.

As for using interfaces vs abstract classes, my rule of thumb is to use an interface when you know there will be a definite need to have an unknown number of different implementations. Also, when the idea represented is along or crosses application layer boundaries (View, Control, Data, Service, Model, etc.), prefer interfaces as they have the least amount of coupling.


Yet I appreciate your attempt to explain it to me : ).

2 seconds is an awfully long time to simulate a computer trying to make a decision. Are you trying to make the computer look stupid or what? ;)


I wouldn't want to look stupid when I'm playing against it ;).


Thank you both for taking time out of your Friday to help me! : ).

 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This:

is more idiomatically written as:

Note the other things I changed as well.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nils Anton wrote:... I recently started studying programming at school, so I feel I don't quite get what:
In a program this small, mixing concerns is not much of a big deal. In larger programs, however, you should think about separation of concerns, particularly the concerns of doing calculations vs input/display.

Yet I appreciate your attempt to explain it to me : ).

That's fine. Just remember this: Your methods should do one thing and only one thing well. If it's calculating things, avoid mixing in input and/or display. If it's display, avoid mixing in lots of calculations and/or input. Those things that you want to mix in, that's what return values and parameters are for. So, main calls a method to get user input, then passes the input on the method that does calculations, then passes the results to another method that displays them.

Thank you both for taking time out of your Friday to help me! : ).

You're welcome
 
Fred Kleinschmidt
Bartender
Posts: 572
9
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Note that a constructor should never call any public or protected methods that are not specified as "final". If any subclass of your Player class happens to override that non-final method you will encounter problems that are very difficult to debug.

 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Fred Kleinschmidt wrote:Note that a constructor should never call any public or protected methods that are not specified as final.

And that deserves a cow. (I hope you don't mind my highlighting)

@Nils; DO NOT FORGET Fred's post, even if you don't understand it (yet).
It's perhaps the biggest source of "leaks" in Object-Oriented programs written in languages like Java.

Winston
 
Nils Anton
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
All the formatting tips are great - they make sense - so I'll be sure to use them in the future .

That's fine. Just remember this: Your methods should do one thing and only one thing well. If it's calculating things, avoid mixing in input and/or display. If it's display, avoid mixing in lots of calculations and/or input. Those things that you want to mix in, that's what return values and parameters are for. So, main calls a method to get user input, then passes the input on the method that does calculations, then passes the results to another method that displays them.


I like this way of thinking, since it makes it easier to decide what a method should contain.

Note that a constructor should never call any public or protected methods that are not specified as "final". If any subclass of your Player class happens to override that non-final method you will encounter problems that are very difficult to debug.


I'll try to keep this in mind.


Thank you all for the help .
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nils Anton wrote:The computer randomly takes a number of sticks - while following the above rules...

Hmmm. Really?

NIM is one of the oldest computer games there is, and the reason is that it has a very simple winning strategy.

In fact, I remember going to an exhibition at Kensington Olympia when I was about 7 (which would have been 1964) and getting 30 seconds of fame on national TV because I worked out how to "beat the computer" at a NIM game with either 13 or 15 matchsticks on the bottom row.

So you might want to look up the way to win rather than just having the computer take sticks at random.

Winston
 
Nils Anton
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hmmm. Really?

NIM is one of the oldest computer games there is, and the reason is that it has a very simple winning strategy.

In fact, I remember going to an exhibition at Kensington Olympia when I was about 7 (which would have been 1964) and getting 30 seconds of fame on national TV because I worked out how to "beat the computer" at a NIM game with either 13 or 15 matchsticks on the bottom row.

So you might want to look up the way to win rather than just having the computer take sticks at random.


It's time for me to do some investigation .
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!