• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Bear Bibeault
  • Liutauras Vilda
  • Devaka Cooray
Sheriffs:
  • Knute Snortum
  • Junilu Lacar
  • Henry Wong
Saloon Keepers:
  • Ron McLeod
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
  • Tim Holloway
Bartenders:
  • salvin francis
  • Frits Walraven
  • Piet Souris

Array solution for Tennis Game

 
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello again.

I realised that I have little knowledge in counting, sorting and other array operations.
A challenge to become better is to solve a Tennis Game only making use of the array dat structure for part one.
Part 2 would be to use a Hash Map.
There are probably examples on the internet, but i realised that if I work my way out through comments is better for me.

Business Requirements:

The way a tennis game works:

0 points= Love
1 point = 15
2 points= 30
3 points= 40
Tied score= All
40-40 = Deuce
Scorer wins deuce point = Ad-In
Receiver wins deuce point = Ad-Out

In order to win the game, a player must win at least four points. So if you are up 40-30, 40-15 or 40-love, and win one more point, you win the game. If the score is tied in a game or set, you use the term “all”. For example, if you and your opponent have both won two points in the game, the score would be 30-all.

The only time this is different is when the score is 40-40, called deuce. When the score reaches deuce, one player or team will need to win at least two points in a row to win the game. If player A is serving and wins the deuce point, the score is Ad-In. If they win another point, they win the game, or else it goes back to deuce.


Implementation Requirements:

- make use of the array data structure
- it will be a tennis game played by 2 players, but designed to be easily expanded to 4 players
- the MVC structure should be implemented
- unit tests should be provided




Program doesn't work as expected for now
Would you please offer guidance on how to keep count in real time and condition the result depending on the player performance.
Improve my program.

I could have a temporary array ad push each player to it, but that would complicate things.

Thank you!
 
Ranch Hand
Posts: 116
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

Program doesn't work as expected for now


Could you be more specific about what is not working? What happens vs. what do you expect to happen?

Some general notes as I read through the code:
1) The class is called "AbstractPlayer", but it is not declared abstract (in fact, it's instantiated it in Main). It's recommended you either rename it to Player, or make it an abstract class and then have a Player class that extends it (the word abstract has a specific meaning in Java)

2) Inside the game logic, you don't want to be hardcoding things like the names of the players. It's a good idea (and specified by the requirements) to make it easily extensible to support 4 players. If you have to go an add if statements checking player names in order to add new players, then the code isn't extensible.

3) What is the GameLogic's keepScore method trying to accomplish? Is the purpose of this method to simulate one of the players scoring a point? If so, how do you know which player scored the point (is it supposed to be random?) And what is the purpose behind returning the 0th index of the Array every time? That seems to imply that the game would only ever be at 0-0.

4) What is the purpose of taking in "playerScore" in the constructor of an AbstractPlayer? Wouldn't all players start at 0-0 or is there a case where someone would start with more points?

5) In your Main, I recommend creating the players as variables, rather than inline with the keepScore method. This would allow you to call keepScore multiple times on the same player.

6) The name of the keepScore method doesn't really explain to me what it's trying to do. Is this called when a Player scores a point? If so, maybe scorePoint would be a better method name.

7) One concept that I feel is missing from the overall design is the concept of the Game itself. A Game contains multiple players, and has a state (such as in progress, player 1 won, player 2 won) right? How will you represent that logic in the current design? Maybe the GameLogic can handle that, but it doesn't right now. If there can be 4 players, does it make sense to also have a representation for a Team of players?

8) Minor issue: the naming of constant variables should be all upper case: GAME_SCORE_CHOICE (is there a more descriptive name for this variable?)

9) What is this syntax? Line 67-69


10) How are you implementing the mode/view/controller pattern?

11) Especially since unit tests are a requirement: try writing tests along with or before writing the code if possible. Describe the desired behavior of your project in plain English sentences and then try converting those into JUnit test cases. Tests are often considered something that is done after the implementation, but it doesn't have to be that way. Used correctly, unit tests can be a tool to help you write code. I think we're all guilty to some extent of looking at unit tests as a hassle, but if you get in the mindset of using unit tests to help you, they don't have to be that way.
 
Sheriff
Posts: 14990
250
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1. There is no such score as "Love 10" in tennis.

2. I didn't see anything in the requirements related to scoring of a set and yet you have "set" as one of your scores

3. I don't understand what that keepScore() method is supposed to be doing and hardcoding "bob" and "joe" in that method is definitely wrong.

4. Where are the unit tests?

5. How is MVC implemented here?
 
Lg Long
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Zachary Griggs,

Very good questions, thank you for taking the time to read through!

Program doesn't work as expected for now
Could you be more specific about what is not working? What happens vs. what do you expect to happen?




1) The class is called "AbstractPlayer", but it is not declared abstract (in fact, it's instantiated it in Main). It's recommended you either rename it to Player, or make it an abstract class and then have a Player class that extends it (the word abstract has a specific meaning in Java)



Naming it to player now, will make it abstract in refactoring. It is misleading, but that was my intention, to make it abstract in the future.

2) Inside the game logic, you don't want to be hardcoding things like the names of the players. It's a good idea (and specified by the requirements) to make it easily extensible to support 4 players. If you have to go an add if statements checking player names in order to add new players, then the code isn't extensible.



Right you are on this one, but this can be picked up on refactoring? An idea to stick to arrays would be, have an array list will the accepted names.
For not I will be having the BaseClassPlayer, and one field of type int, as I could use Player index to check for score?

3) What is the GameLogic's keepScore method trying to accomplish? Is the purpose of this method to simulate one of the players scoring a point? If so, how do you know which player scored the point (is it supposed to be random?) And what is the purpose behind returning the 0th index of the Array every time? That seems to imply that the game would only ever be at 0-0.



Good question. Should have commented above what the method is doing.
The method is supposed to keep the score for each of the 2 players as they advance. And apply the game rules. I think it might be pseudo code:
do{
   if(player == score[0]){
       player == '10';
   }
   if(player == score[1]){
       player == '15';
   }
   if(player == score[2]){
       player == '30';
   }
   // this is where I think I should use indexes for player1 and player 2 to assign the strings from score array??
   if(player = 1 and score(1) == '40' ||  player = 2 and score(1) == '40'){
       score(1) == 'Deuce';
       score(2) == 'Deuce';
   } else {
      score(layer) == '40';
   }
 
  if(player = 1 and score(1) == 'Advantage' ||  player = 2 and score(1) == 'Advantage'){
       score(1) == 'Deuce';
       score(2) == 'Deuce';
  } else{
     score(player) == 'Advantage';
  }

  if(score(player) == 'Advantage' || '40'){
     score(player) == 'GAME'
  }
   // keep it to GAME for now
}
while(!player == won);
}

4) What is the purpose of taking in "playerScore" in the constructor of an AbstractPlayer? Wouldn't all players start at 0-0 or is there a case where someone would start with more points?



Indeed they would start at 0. I might be missing what you are trying to say about the constructor.

5) In your Main, I recommend creating the players as variables, rather than inline with the keepScore method. This would allow you to call keepScore multiple times on the same player.



At the moment main if just to keep this going

6) The name of the keepScore method doesn't really explain to me what it's trying to do. Is this called when a Player scores a point? If so, maybe scorePoint would be a better method name.



It scores a point, but also keeps count of the scores. I guess it's a personal preference.

7) One concept that I feel is missing from the overall design is the concept of the Game itself. A Game contains multiple players, and has a state (such as in progress, player 1 won, player 2 won) right? How will you represent that logic in the current design? Maybe the GameLogic can handle that, but it doesn't right now. If there can be 4 players, does it make sense to also have a representation for a Team of players?



Indeed. This is what I thought I made obvious, apparently not. The GameLogic should hold the logic for the game to provide with details on the state of a player.

8) Minor issue: the naming of constant variables should be all upper case: GAME_SCORE_CHOICE (is there a more descriptive name for this variable?)



Noted, it's good enough.

9) What is this syntax? Line 67-69



It returns null if nothing has happened according to the conditions?
Not sure.

10) How are you implementing the mode/view/controller pattern?


I am implementing the MVC by having a Model - ClassPlayer(pojo), Controller - GameLogic(state-behaviour of the player-game), View - Interface(scanner class); EntryPoint - Main

11) Especially since unit tests are a requirement: try writing tests along with or before writing the code if possible. Describe the desired behavior of your project in plain English sentences and then try converting those into JUnit test cases. Tests are often considered something that is done after the implementation, but it doesn't have to be that way. Used correctly, unit tests can be a tool to help you write code. I think we're all guilty to some extent of looking at unit tests as a hassle, but if you get in the mindset of using unit tests to help you, they don't have to be that way.



I am aware of this situation, but I will choose to write unit tests after the code, although it is wrong. As a start. After I learn how to work with plain arrays and conditions better, I will.

I hope I put a bit more clarity on this.
 
Lg Long
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Junilu Lacar



1. There is no such score as "Love 10" in tennis.



Fair enough, you are right, there is "Love", "10", "15", "30", "40", "Deuce", "Advantage", "Game", "Set"(for now we will ignore solving the set problem)

2. I didn't see anything in the requirements related to scoring of a set and yet you have "set" as one of your scores



I will post the first post again updating that for the first iteration "set will not be considered", but should be taken in consideration for completion of the program

3. I don't understand what that keepScore() method is supposed to be doing and hardcoding "bob" and "joe" in that method is definitely wrong.



keepScore() method should be able to keep the score for a player, and provide with response according to game rulles

4. Where are the unit tests?



Good question, I will be writting the unit tests after I figure out my logic

5.  How is MVC implemented here?



I am implementing the MVC by having a Model - ClassPlayer(pojo), Controller - GameLogic(state-behaviour of the player-game), View - Interface(scanner class); EntryPoint - Main
 
Lg Long
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is weird. How do I delete a post, if I post something by mistake?
 
Marshal
Posts: 67939
258
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Lg Long wrote:. . .

1. There is no such score as "Love 10" in tennis.

. . .  "Love", "10", "15", "30", "40", "Deuce", "Advantage", "Game", "Set" . . .

No, it's  "Love", "15", "30", "40", "Deuce", "Advantage", "Game", "Set"
 
Campbell Ritchie
Marshal
Posts: 67939
258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Lg Long wrote:. . . . I think it might be pseudo code:
do{
   if(player == score[0]){
       player == '10';
   } . . .

That doesn't look right at first sight, I am afraid. Please explain more.

That also looks like non‑obect‑oriented code. What you want is a score field for each player, and an opponent field. That latter allows you to score a point when your opponent is at advantage and immediately take both players to deuce. It might be a good idea to concoct some sort of pseudo‑score for use when the opponent is at advantage.
 
Lg Long
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

 That doesn't look right at first sight, I am afraid. Please explain more.



Interface:
Options: Press 1 to add point to Player1 - > response: Player 1 has 'wateva score the player has, if he won or at deuce'
            Press 2 to add point to Player 2  - > response: Player 1 has 'wateva score the player has, if he won or at deuce'
            Press 3 to check score
            Press 4 to exit.

Acording to the interface:

I need to build a method to:

- assign index value to a player.
- check for 'deuce, advantage, deuce'
- print result

How can I split all that in different methods. To write tests more easily?

this is my model:

 
Junilu Lacar
Sheriff
Posts: 14990
250
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Lg Long wrote:

4. Where are the unit tests?


Good question, I will be writting the unit tests after I figure out my logic


That would be the wrong time to write them. Unit tests are a great design tool. Write them before you write any of your main (production) code. More specifically, write each unit test as an example of how you would use each piece of functionality that you build, as you build it. You mentioned "refactoring." Refactoring is done as part of this process. Unit tests are little experiments of how you want to design your program. Refactoring is done when you find that an experiment has revealed flaws in your design and you want to make small changes without starting all over again. Your existing unit tests provide safety in doing refactoring. Refactoring without unit tests that already pass is foolish and dangerous.

I am implementing the MVC by having a Model - ClassPlayer(pojo), Controller - GameLogic(state-behaviour of the player-game), View - Interface(scanner class); EntryPoint - Main


That's not quite what MVC is. I will comment more on this later.
 
Lg Long
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Forgot the toString() method

 
Campbell Ritchie
Marshal
Posts: 67939
258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can see two problems in that toString() method.
  • 1: You are still calling the class AbstractXXX.
  • 2: You are recording both players' scores twice.
  • Shouldn't the displayed order of scores change depending on who's serving?
     
    Lg Long
    Ranch Hand
    Posts: 79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Can someone please explain how I can do this:

    private final static String[] gameScoreChoice = {"Love", "15", "30", "40", "Deuce", "Advantage", "Game", "Set"};
    int player1;
    int player2;

    gameScoreChoice(player1) = "Love"

     
    Lg Long
    Ranch Hand
    Posts: 79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    I can see two problems in that toString() method.
    1: You are still calling the class AbstractXXX.
    2: You are recording both players' scores twice.
    Shouldn't the displayed order of scores change depending on who's serving?




    Overcomplicating at this stage.

    All I want is to have a very simple program, able to assign array values to 1 or the other player and validate according to tennis game rules.

    press 1, player 1 point
    press 2, player 2 point

    ------ Deuce, Advantage or Game.

    press 3, show score
    press 4, end program
     
    Lg Long
    Ranch Hand
    Posts: 79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Came up with this.
    Confused as I thought the int player1 should be assigned the index of the gameScoreChoice array.

    I guess I have to build a method to assign array values to players?


     
    Lg Long
    Ranch Hand
    Posts: 79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    This is what I wanted for starters.
    Might not have been explicit enough.
    Was I roasted or no one understood or thought of a starting point like this one?

    Suggestions from now on?

     
    Campbell Ritchie
    Marshal
    Posts: 67939
    258
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    A player isn't a String. You have a player class; use it.
    The scores aren't Strings. Nor are they ints. Something is only an int if you can do arithmetic with it. They might however be elements of an enum.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Overall, your problem is that you don't seem to have a clear idea of how you want to organize the bits and pieces that make up your program. I like to think of the process of writing a program as telling a story. In a story, you have characters and roles, scenes in which the characters interact with each other, and actions that characters perform to move the story along.

    If you think of it like this and use tests to kind of draw a sketch of each "scene" in your program, then it's easier to start organizing your thoughts. For example, how would a game start? What would the code look like? I might try drawing this sketch:

    Then I would ask myself "Is this a reasonable way to tell the story that a Game needs two players and the score starts with both players at Love?"

    If I think this looks reasonable, then I write the code so that my test passes. Then I go on to the next scene, maybe experimenting with how I might write the code that says a player won a point.

    Don't get caught up in details like implementing toString() and using arrays before you even have a clear idea of what the general flow of the program is. You'll just confuse yourself to no end and get nowhere fast.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Coming back to refactoring and that first sketch or experiment I showed. I would look at that and ask myself "Do I even need a Player class right now? What exactly does a Player do anyway besides provide its name? What if I only do this instead?" Then I'd try another experiment, simplifying the code:

    That certainly is simpler. Maybe I'd try implementing this instead.
     
    Sheriff
    Posts: 6801
    182
    Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Lg Long wrote:This is weird. How do I delete a post, if I post something by mistake?


    You can't.  Ask a mod to delete it, or edit it and say, "Please Delete!"  But most of the time you do not want to delete a post.  Instead, use the Preview button (to the left of the Submit button) before you post.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Lg Long wrote:I need to build a method to:

    - assign index value to a player.
    - check for 'deuce, advantage, deuce'
    - print result

    How can I split all that in different methods. To write tests more easily?


    This is exactly the problem you'll run into when you don't use tests to design code that is testable. Because you're writing your tests after the design, your design will most likely already be difficult or impossible to test at a unit level. If, however, you start by writing a test that suggests a design, you can implement that design and make the test pass. I know it may seem counterintuitive to start with a test but once you get on a roll with this approach, it's hard to do it any other way.

    Let me show you a test (i.e. experiment) for how to write one of those methods:

    That's it. While the "story" this test tells is that a new game is not at deuce, it also shows that to check for deuce, you would call the game.isDeuce() method.

    How might a game get to deuce? Well, I might try to sketch that story out with a test like this:

    This test is a bit unconventional in form but it at least tells the story of one way a game will get to deuce. That is, the server wins three points which puts their score at 40. Then the receiver wins two points. Now the score should be 40-30, not deuce, which is what we assert on line 12. Then the receiver gets another point to tie it up at 40 all or deuce. Line 16 asserts that fact.

    The above is an example of how you use tests as a design tool, to experiment and hash out what you want the flow of the program to look like. By doing this "outlining" you'll start to discover different ways you can design your classes, how you would interact with them and what kind of behavior you want to see and more importantly, test.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    I wrote:Because you're writing your tests after the design, your design will most likely already be difficult or impossible to test at a unit level.


    Case in point: look at this code that you wrote without tests:

    What unit test might you write for this code? What story would that test try to tell? What scenario would the keepScore() method return null? In a previous reply, you admitted that you weren't even sure. How can you write a program if you're not sure what its behavior should be? You might as well be saying "I want to write a program to play a game but I'm not really sure how that game should be played."

    By writing a test first, you're describing a small scenario in which your class will be involved and then asserting what its expected behavior should be. When you can write a test that tells that story clearly, it is much easier to write the code to carry that story out. If we went with the design you have created, here's what a test might look like:

    If you read that test code, it's very unclear, right? What might you do to clarify the intent here? Try to figure out what story you want to tell here.
     
    Lg Long
    Ranch Hand
    Posts: 79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Junilu Lacar wrote:Coming back to refactoring and that first sketch or experiment I showed. I would look at that and ask myself "Do I even need a Player class right now? What exactly does a Player do anyway besides provide its name? What if I only do this instead?" Then I'd try another experiment, simplifying the code:

    That certainly is simpler. Maybe I'd try implementing this instead.



    Hi Junilu Lacar,

    Thank you for taking the time to teach. I did needed your guidance and it made sense.

    You are right, I lack the ability to put order in my thought process and build a story from the requirements.
    Part of the reason I am doing assessments like this one.

    I dd solve the test and I might have an idea of how to build separate methods for points to be added separate, in this way it is easily testable.

    This is my code



    Will continue and hope you can review my code.
     
    Lg Long
    Ranch Hand
    Posts: 79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Campbell Ritchie wrote:A player isn't a String. You have a player class; use it.
    The scores aren't Strings. Nor are they ints. Something is only an int if you can do arithmetic with it. They might however be elements of an enum.



    Thank you for the comment, planning to use Enums as I move up the ladder, for now i want to do exercises with arrays.
    It doesn't feel right not to know how to use arrays to solve any problem.
    Ofcourse other solutions might be better, but I need to feel comfortable using arrays.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Lg Long wrote:I dd solve the test and I might have an idea of how to build separate methods for points to be added separate, in this way it is easily testable.

    This is my code ...


    Great effort! I can honestly say you've already exceeded my expectations.

    Now, let's work on making some small improvements.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Let's start with your test:

    So the name of the test method is like the scene name. It should summarize what this little story is about. Just naming it "setScore()" doesn't inform other people what the test's intent is. You want to communicate with your code, so be  expressive with your names, especially with test names.

    Another thing to remember is semantics or what the words you use mean. If I said "I'm going to the grocery to get my car fixed" would that make sense to you? Probably not. And you'd probably ask "Did you mean you're going to the shop to get your car fixed?"  By using the wrong word to express my intent, I created confusion.

    This is the same thing that happens when you use a method named setScore() and use it in a context where people would expect something like getScore() instead. Why did you think "setScore()"? My guess is that you were focused on what you were doing inside that method, which was setting the initial scores to "love".  That's the wrong perspective to take. Your class API, that is, the things a class will allow others to call on it, should be from the perspective of the caller.

    For example, if the caller wanted to get the current score, it makes more sense to call game.getScore() than it does to call game.setScore(), doesn't it?

    What story did you really want to tell with this little test? Let me help you refactor this (and refactoring can be as simple as renaming a method so that the code makes more sense when you read it):

    Read that carefully and think about the story that code tells. Now read your code and compare the story it tells. Which story is clearer and makes more sense?

    Notice also that the design this test suggests is much simpler than the design suggested by your test. Try to start with the simplest design possible.

    Here's the implementation that will make the above test pass:

    You may look at that and say, "Well, that's not right!" and you'd be absolutely correct. However, it's the bare minimum code we need to make the test pass and that's really all you're looking to do at this point. Your goal right now is to sketch out how you want to interact with the Game class. Don't worry about the details for now. Once we understand more about what this class should do, we can refactor the implementation to what it really should be.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You might also notice that I used "Game" instead of "GameLogic". Why? Because it makes the code read more naturally.

    Have you ever heard anybody say "I'm going to play ChessLogic!" Or even if you didn't know what specific game it was, would you say "I'm going to play a GameLogic!" or "I'm going to play a Game!"? The first statement sounds funny, especially when you say out loud.  Choose names such that when you read your code out loud, it's just like you were telling a story to someone who doesn't know how to program.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    So let's say we started with the simplified test I suggested and made the test pass. We could move forward from here in a few different ways. One way might be by saying "Well, we really want to be able to give the players' names and have the score include their names." If we decided this is where we want to go with the design then we might write a test to align more with what you had originally:


    Note that this a new test. We keep the one we had before. To make this new test pass, we might make the following change to the production code:

    This is actually more code than I'd want to add at one go but it's still just enough to make the new test pass without breaking the old test that was already passing. This is an important strategy when you're trying to refine your design. Keep your existing tests passing, write only one failing test at a time. This ensures that you're writing only enough code to make an increment of functionality and that you're not breaking any functionality that you've already made to pass its tests.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    So we wrote a test that failed (RED), then we wrote some code to make it pass (GREEN). We wrote another test that failed (RED) and then wrote some more code to make it pass (GREEN). We really should be refactoring as we go as well. Refactoring makes our code easier to read and work with. At this point, the code is still pretty easy to work with. But is it easy to read?

    Well, this may look like it's easy to read:

    but with a little refactoring, we can make its intent really jump out at the reader. So I'm going to Extract Method to make the code more expressive:

    Line 13 now reads very clearly; I don't have to work as hard to translate the "formula" of player1 == null && player2 == null because that code was extracted to a method with a name that clearly explained what the intent of the formula is. I could also do that with the other lines:


    Notice how I just moved code around and wrapped them in methods that explained their intent. This is one of the main uses of the Extract Method refactoring: it helps clarify your code's intent so that it's much easier to understand.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    That little refactoring exercise gave me another benefit besides making the code clearer and more expressive: it organized the logic into little "boxes". Now, if I want to move forward by saying "Well, let's just worry about the scoring logic without the players' names for now..." I know where I need to make most of the changes I'll need to make: in the plainScore() method. If I want to move forward by saying "Now I want to worry about showing the score with the player's names" then I know most of the changes will revolve around the scoreWithPlayerNames() method.

    The code is organized better so that I can quickly find where I need to make changes depending on what I want to do next. This allows me to make small tweaks to my design without having to dig around a whole mass of code. If I make any changes, the changes will be very surgical, with little chance of disturbing other sections of code that have nothing to do with whatever change I'm making.
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I'd encourage you to go through this exercise yourself. Do it very intentionally, thinking about each change you make, each test you write, always asking questions like:

    What story do I want to tell?
    Is this the way the story should be told?
    Is this clear? Is it expressive? Does it make sense?
    What can I do to make it clearer?
    Is there a different, maybe better way to tell this story?

    Also,
    Is this just enough code to make the test pass?
    Did I write too much code?
    Is all the code I just wrote needed to make the test pass?
    Is there any code that's not needed to make the test pass?
     
    Bartender
    Posts: 3747
    154
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Interesting topic!

    Not interfering with Junilu, but while reading this topic sofar, my thoughts went like:

    - how does a scoring board look? If I remember from Wimbledon, it is like this:
      set           1  2  3  4  5
      player1   .   6  4  -  -  -  A  
      player2       7  3  -  -  - 40


    so there is no use of words like 'all' or 'deuce' (assuming that deuce is represented as 40-40, can't remember exactly).

    - I would keep the score internally as 0-0, 1-0, ..., 6-6, and only when displaying, I would translate a score like 7-6 to 'A 40'. See above.

    - arrays that I need are player[2], set[3 or 5], currentGame[2], and these belonging to a class 'Match'. I would let a class 'GameLogic' determine whether a currentGame is won by player1 or player2, and I would have a variable that indicated who's to serve. That is not important for now, but when determining who wins a ralley, you might give the server a slight advantage.

    - a Match also needs to know whether it is 'best of 3' or 'best of 5'.

    - and it is easy scalable by having an array of 'Matches'

    Well, my 2 cents.

     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hold that thought, Piet. While what you're talking about is still further down the line, the foundation that can be established with a test-first approach will be more likely to accommodate those kinds of requirements. The important thing is to keep your code base tested and well-factored so that adapting it to new requirements doesn't require a complete rewrite and extensions and additions can be made intuitively and naturally.

    For now in this early stage of development/design we'll want to focus on the basic stories that we want to tell with the code.
     
    Piet Souris
    Bartender
    Posts: 3747
    154
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It just appeared to me that I had no clue what OP wanted to model, let alone what to show (especially all the terms like deuce and so, that reminded me of modelling an umpire), so I was giving it a shot. Well, anxious to know how this topic will evolve!
     
    Campbell Ritchie
    Marshal
    Posts: 67939
    258
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Lg Long wrote:. . . Thank you for the comment, planning to use Enums as I move up the ladder, for now i want to do exercises with arrays. . . .

    You are in a bit of a quandary there; you need to learn how arrays work, even though you know your app would be better if you use enums (not Enums). You will have that difficulty sometimes, not knowing whether to use the best solution or to try out a particular language feature.
     
    Lg Long
    Ranch Hand
    Posts: 79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thank you all for commenting: Piet, Cambell, especially Junilu as you seem to take a real interest in helping me not only solve this problem, but develop principles that I can apply to any situation.

    With the pandemic going on, I had to put a pause on the work, as I had to help a friend. Delivering chicken soup.
    Will read the comments tmrw and see where I head. Did not write any code yet.

    See you all tmrw!
     
    Campbell Ritchie
    Marshal
    Posts: 67939
    258
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Piet Souris wrote:. . . there is no use of words like 'all' or 'deuce' . . .

    I thought that whenever there is a number, they did use the term “all”. “Love‑all”, “15‑all”, “30‑all”, and “deuce” are valid scores. The board might however display that as “30‑30” etc.
     
    Lg Long
    Ranch Hand
    Posts: 79
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hello Junilu,

    I did the code to pass the first test, just because it was interesting. I thought I could just have an @Override toString() method to print the result as a string.
    It took me a bit to figure it out that I need a for loop.
    Is there another way? I think I did see some examples involving streams?
    Why do I need to use a forLoop and I can't use a toString. Wrong code:



    I understand why that is the bare minimum. It is because both player go from "Love-all" the both have that score on so it is only acceptable to have it.

    this is the code to pass that



    Next post will be to cover your later response
     
    Junilu Lacar
    Sheriff
    Posts: 14990
    250
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I want to (re)explain a few things here.

    I'm walking you through the test-first approach to programming to help you organize your thoughts and therefore your code better. Your code reflects your thinking. If your thinking is confused and disorganized, your code will reflect that. With that last attempt, your code suggests a great desire to use an array somehow. I think you're focusing too much on that and forcing the use of an array even when it isn't appropriate.

    If you follow this process I'm trying to explain, it will eventually become clearer to you where you need an array. But you have to lead up to that, not start with it. I like to think of it as "the code telling you what it wants to be/do." I discover what the code wants to be/do by experimenting with different options and seeing which one feels more natural and reads better. The option that reads the best and feels most natural is what I consider as "what the code wants to do."

    Right now, you're telling the code what YOU want. You desperately want to use an array somehow so you're doing that at the first opportunity you see. Granted, you're still a beginner and you may not recognize if something looks natural/intuitive or not but I can tell you that the declaration on line 2 of String[] initialScore = {"Love-all"}; is very unintuitive and unnatural. In other words, the code doesn't want to do that.

    The for-loop on lines 6-9 doesn't make sense either. It won't even get a chance to execute more than once. Line 9 will never get executed. That's not what the code wants to do either.

     
    Knute Snortum
    Sheriff
    Posts: 6801
    182
    Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Minor change: this code
    can be changed to this
    if you're only using i inside the for loop.
     
    Hoo hoo hoo! Looks like we got a live one! Here, wave this tiny ad at it:
    Java file APIs (DOC, XLS, PDF, and many more)
    https://products.aspose.com/total/java
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!