Archive for the ‘Java’ Category

Reflection – Calling functions

Tuesday, June 1st, 2010

With c++ you can call functions as a reference instead of the actual name, as long as the reference is linked to the function itself (I did a post about it function pointers and also within csharp delegates)

To start with, we need to sort out what function we want to use to call, I am going to pick a function that returns a value and also passes parameters (kinder covers all aspects really), so this is going to be the function

public String addsTogether(String st1, String st2)

So to start off , lets build up the parameters to pass to the function, we have two string parameters, so we need to have a array of 2 strings.

String[] passingParameters = { new String("genux"), new String("was here")};

Now we need to setup a link to the function that we want to call, we setup a class instance with using the forName (which is the function name). Also because the function takes 2 String parameters we need to setup blank classes that are both Strings in types.

Class callingClass = Class.forName("CallMethodClass");
 
Class[] callingParameters = new Class[2];
callingParameters[0] = String.class;
callingParameters[1] = String.class;

this is the main part, this is the link, we create a Method (from the java.lang.reflect package) that links to the class function/method “addsTogether” (the function at the start of this post) and also the parameters type and length (2 strings).

Method callingMethod = callingClass.getMethod("addsTogether", callingParameters);

that is about it, all we need to do is to call the function now and that is it, so we use the Method link above variables invoke method, this takes the class that the function is wrapped within and also the parameters that we want to send to the function (method and function are kinder interchangeable) and that is about it. Since the returning value is a String (and we know this) we will need to case the returning type into that by using (String) otherwise it would be a type of Object (the base object type in java)

String result = (String)callingMethod.invoke(new CallMethodClass(), passingParameters);

Here is the source code in full (Save as CallMethodClass.java if you want to compile it up)

import java.lang.reflect.Method;
 
public class CallMethodClass {
 
	// adds together the two strings with inserting a space between them
	public String addsTogether(String st1, String st2)
	{
		return st1.concat(new String(" ").concat(st2));
	}
 
	public static void main(String[] args) {
		try
		{
			String[] passingParameters = { new String("genux"), new String("was here")};
			// setup the link to the class to call
			Class callingClass = Class.forName("CallMethodClass");
			// passing parameters to the callingClass, the method has two String parameters
			Class[] callingParameters = new Class[2];
			callingParameters[0] = String.class;
			callingParameters[1] = String.class;
			// and now setup the method to call
			Method callingMethod = callingClass.getMethod("addsTogether", callingParameters);
 
			// call the method and get the return (convert to a String)
			// pass in the parameters here, when calling (invoking) the method
			String returnValue = (String)callingMethod.invoke(new CallMethodClass(), passingParameters);
 
			// and now output the result
			System.out.println("OUTPUT : "+returnValue);
		} catch (Exception e)
		{
			System.out.println(e.getMessage());
		}
	}
}

here is the output of the program

OUTPUT : genux was here

CS106A – Assignment 6 – Adventure game

Friday, May 28th, 2010

This is assignment 6, Adventure Game, similar to Will Crowther’s pioneering Adventure game, this appears to be the last assignment from the Stanford CS106A course. The adventure game is textural based, but the main part of the assignment is pull data from files to build up the adventure environment so that nothing as such is hard coded apart from the main options like QUIT, HELP etc.

You have different parts of the adventure game to build up, reading in of the rooms that the user will move around, the adventure objects to pick up file to read in (and place within the rooms in the adventure game) and you are also able to pick up the items as well. To start with I am going to do the reading in of the files (if present)

Here is part of the room file, it starts with the room ID number, then the small name followed by the description (finishing with “—–”) and, last but not least, is the movement options and the room ID to move to, e.g WEST 2 means if you go WEST you will end up in room ID 2


1
Outside building
You are standing at the end of a road before a small brick
building. A small stream flows out of the building and
down a gully to the south. A road runs up a small hill
to the west.
-----
WEST 2
UP 2

here is how I am reading in the main room file, the readPassEmpty is another function that will read passed any empty lines and return the first non empty string from within the file, the readInLine will read just one line at a time (with all error checking). the returnRoom is what I am going to return back to the main adventure class that will add the rooms read into a ArrayList.

String st = readPassedEmpty(rd);
if (st== null) return null;
returnRoom.roomNumber = Integer.parseInt(st);
returnRoom.roomName = readInLine(rd);
String readIn;
while(true) {
	readIn = readInLine(rd);
	if (readIn.indexOf("-----")>=0) break;
	returnRoom.roomDescription.add(readIn);
}
while (true)
{
	readIn = readInLine(rd);
	if (readIn == null) break;
	if (readIn.equals("")) break;
	returnRoom.roomMotionTable.add(getMotionTable(readIn));
}

To break the movement roomID (/options) part of the file into parts, I used the split function within the String class, you pass in a regular expression, in this case [ ]+ which means any space [ ] and + means 1 or more times e.g. if there is one space between movement or 5 then it will classes as the same thing, and if there is any options attached to the roomID e.g. you needs to have KEYS

String[] split = st.split("[ ]+");
dir = split[0];
int indexOf =split[1].indexOf("/");

reading in the adventure room objects and also the synonyms is very similar in that I either break the synonym into a regular expression searching for the “=” and thus linking the left value to the right value within a ArrayList of synonyms. The adventure objects, I just read in there values and add the objects to the required room, for example the file looks like

KEYS
a set of keys
3

where the KEYS is the object, “a set of keys” is the long description, and 3 is the roomID to place the items into.

Movement around the adventure

To move around the adventure game, the user types in the direction (or there is some hidden options) and then the adventure game will move to that required place and the way that I thought about this was to get all of the movement options within that room, see if the player has requested any of these movement options and move that player to the next room, but if there is a option/requirement (e.g. KEYS) to access that room then see if the player has them within his user objects. Else if there is no movement that the user requested just output a error and return -1 (which means no update).

private int movePlayer(String player, int roomID)
{
	AdvMotionTableEntry[] moves = advRooms.get(roomID-1).getMotionTable();
	for (int i = 0; i < moves.length; i++)
	{
		if (moves[i].getDirection().equals(player))
		{
			String keyName =moves[i].getKeyName();
			if (keyName != null)
			{
				int objectPlace = getObjectIndexUsers(keyName);
				if (objectPlace >=0)
					return moves[i].getDestinationRoom();
			} else
				return moves[i].getDestinationRoom();
		}
	}
	println("There is no way to move in that direction.");
	return -1;
}

the getObjectIndexUsers is just a function that will scan though the users objects and search for the key, if one found return that key index, else return -1 as below.

private int getObjectIndexUsers(String keyName)
{
	for (int i =0; i < userObjects.size(); i++)
	{
		if (userObjects.get(i).getName().equals(keyName))
			return i;
	}
	return -1;
}

if you download the zip file you will notice that the most of game loop is within the mainGame function, what happens in there is to

  • whilst not finished
  • display the room – short or long description – if required
  • set the room to be classed as visited (for the short/long description to be displayed)
  • check for the room is FORCED – and thus to not request the users input and move
  • If not FORCED request the users input for the movement
  • With the users request, process the request to either TAKE/DROP MOVE QUIT etc options
  • If none of the standard requested, see if it was a movement request e.g. WEST/NORTH/DOWN etc.
  • Then if the roomID = 0, the game is finished, either win/lose
  • repeat

The rest of the code is very similar in nature to the above code, looping through arrays and checking for conditions, it was a interesting game assignment I thought, I am going to do the CS106B next, which is a course that you write code in C++ (but only on a MAC/Windows PC). Shall do some posts of there assignments.

I used ArrayList to store the rooms etc into, because they allow for good access to the data in. I have included the full source code of the assignment and also the assignment PDF file within the ZIP file attached.

CS106A – Assignment 5 – FacePamphlet – Extensions

Tuesday, May 25th, 2010

This is assignment 5, FacePamphlet, that is a very simple incarnation of facebook (social network of people), but linked to CS106A so that everyone is part of the main group of Stanford CS106A course. This is the extensions part, but after reading the extensions and one of them was converting from using the acm.graphics library to using the java.xswing library – (GCanvas – JPanel) then since the assignment 6 looks very interesting I am going to leave that one for another day because only had about 1 hour to do this extension.

The extensions

  • Search for some friends with key words e.g. part of the name
  • status line on 2-x lines
  • change the middle gcanvas to a jpanel – NOTE not going to do at present
  • friend finder – friends that you could link to from your friends already

Search for some friends with key words e.g. part of the name

To search for names that are already in the users list but you type in part of there name, then I have added in the search to the friends request button action and if no friend is found with that name then do a possible search of different names with the request as a search within each name. Of course do not want to add in the user that I am logged in as and any friends that the current user already has as friends, below is the java code that implements this

			Message = "Error : "+ ex.getMessage() + " Possible names : ";
			String[] possibleNames = repository.getUsers();
			for (int i =0; i < possibleNames.length; i++)
			{
				if (possibleNames[i].indexOf(requested) >= 0)
				{
					if (!possibleNames[i].equals(homeUserID))
					{
						// if not already my friend
						if (!repository.isMyFriend(possibleNames[i]))
							Message += possibleNames[i];
					}
				}
			}

status line on 2-x lines

How I implemented this was to create a array of GLabel which are an array length of the status line divided by the centre display texture width (CENTERTEXTWIDTH) e.g. so that if there is a status line of “genux is burping” then there would only be one array length but if the line was allot longer then there would be a X array length. Also since we do not want to break the word across two lines, I searched for the space after the centre display texture width and then cut the line there instead of in the middle of the word and then placed the rest of the sentence on the next line (that is where the endSpace integer value comes into play).

	if (statusCentre != null) 
		for (int i =0; i < statusCentre.length; i++)
		remove(statusCentre[i]);
	String theStatus = repository.getProperty(usersID + FILE_STATUS);
	if (theStatus != null)
	{
		theStatus = usersID + " is " + theStatus;
		int endSpace =0;
		int statusSize = (theStatus.length() / CENTERTEXTWIDTH)+1;
		statusCentre = new GLabel[statusSize];
		for (int i =0 ; i < statusSize; i++)
		{
			// endSpace = get the last space words and only output full words
			String outString = theStatus.substring((i * CENTERTEXTWIDTH) + endSpace);
			if (outString.length() > CENTERTEXTWIDTH)
			{
				// find the closet space
				int end = outString.indexOf(" ",CENTERTEXTWIDTH);
				outString = outString.substring(0,end); //CENTERTEXTWIDTH);
				endSpace += end-CENTERTEXTWIDTH;
			}
			statusCentre[i] = new GLabel(outString);
			statusCentre[i].setLocation(FPConstants.LEFT_MARGIN, FPConstants.STATUS_TOP+(i * statusCentre[i].getHeight()));
			statusCentre[i].setFont(FPConstants.STATUS_FONT);
			add(statusCentre[i]);
		}
	}

friend finder – friends that you could link to from your friends already

The friend finder, the way that I thought about this was everyone is a friend of the course CS106A, so using the repository getUsers it will return a array of users, so all I did was created a function that takes the current users friend array and also the friends of the course array and then just found the users that was in the course array list and not in current users list and returned that as a array (e.g. there could be more than one un-friended user), I did not implement any double click on the FPScrollableList because it will just be using the friend request method and as stated before I am looking at the assignment 6 and it is looking interesting :) .

Below is how I used the throw away users of the intersection of both arrays (my friends and the course friends)

	// return a string array of names that are within the main group courseF and not in my friends group
	// could do a random return of different similar names with X as the maximum to return
	// but since a simple example then probably not needed ?
	private String[] returnNames(String[] myF, String[] courseF)
	{
		String[] returnS;
		int diff = courseF.length - myF.length;
		// equals 1 because the courseF would include the userID name as well
		if (diff == 1)
			returnS = new String[0];
		else
		{
			returnS = new String[diff-1];
			int insertI =0;
			// find the names that are not in myF and then insert into the returnS
			for (int i=0; i < courseF.length; i++)
			{
				Boolean inI = true;
				for (int j =0; j < myF.length;j++)
				{
					if (courseF[i].equals(myF[j]))
					{
						inI = false;
						break;
					}
				}
				if (inI && (!courseF[i].equals(homeUserID))) 
					returnS[insertI++] = courseF[i]; 
			}
		}
		return returnS;
	}

I have included the source code in the zip file attached with also the assignment and running interface.

CS106A – Assignment 5 – FacePamphlet

Monday, May 24th, 2010

This is assignment 5, FacePamphlet, that is a very simple incarnation of facebook (social network of people), but linked to CS106A so that everyone is part of the main group of Stanford CS106A course. I am going to do the extensions of the assignment in the next post and also just some of the points of this FacePamphlet application.

There are some milestones that allow you to head towards, like a stepping stone to figure out the path to take to get the assignment done. Here are the milestones and also some code that will be linked into the milestones

Milestone 1: Create the west side panel

To create the panels with the data, then need to pull some data from the files that are present on the filesystem. Things like the name of the user is stored in a file and also friends, requests of friends etc, so to create for example below the list of friends that I would have, the repository class is already created and that “talks” to the filesystem to get the data in question (either locally in my case, and also in the testing phrasing of the assignment) but if you changed it to a network setup then it would get the data from a remote server. I have created a few private variables that will store the different parts of the graphics user interface so that I can “talk” to them with just referencing there name, which makes it allot more easier to update there details in the future.

Below the first code will get the full user name from the repository and add it to the WEST panel and then it will retrieve the list of names of friends into a String array and then cycle through to add them to the friends list on the WEST panel again.

		usersName = new JButton(repository.getProperty(userID + FILE_NAME));
		add(usersName, WEST);
 
		friendsList = new FPScrollableList();
		// add to the friends list
		myFriends = repository.getMyFriends();
		for (int i=0; i < myFriends.length; i++)
			friendsList.add(myFriends[i]);
		add(new JLabel("Friends:"), WEST);
		add(friendsList,WEST);

Milestone 2 – interactors

Interactors with the different parts of the GUI is nice and a good way is using the above code, e.g. using private variables that can be able to talk to when we get clicks from the GUI on buttons and want to find out which item was clicked, also since we are using some stanford custom code like FPScrollableList, FPScollableTextArea which you have to add the listens and also tell the called function what command (in string text) has been called.

		friendsList.addActionListener(this);
		friendsList.setActionCommand(VISIT);

the VISIT is a static final string so that encase any thing is altered just alter it once (it equals = “VISITS”)

Milestone 3: Create the center panel

The centre panel creates the basic information of the user, but also displays a graphical image and also error reporting with status updates as well. With the graphics object the graphics is saved within a string format, which using the FPTools has a graphics to string converter, but to rescale the image I am seeing if the height/width is beyond centre size then alter the image by the size that is available divided by the size of the graphical object.

		if (picCentre.getHeight() > FPConstants.MAX_IMAGE_HEIGHT)
		{
			double newHeight = FPConstants.MAX_IMAGE_HEIGHT / picCentre.getHeight();
			picCentre.scale(newHeight);
		}
		if (picCentre.getWidth() > CENTERWIDTH)
		{
			double newWidth = CENTERWIDTH/ picCentre.getWidth();
			picCentre.scale(newWidth);
		}
		picCentre.setLocation(FPConstants.LEFT_MARGIN, FPConstants.IMAGE_TOP);
		add(picCentre);

updating the error messages I am using a function that takes the message as string and then just output the message, I am removing object and then just re-creating it and placing on the area specified in the FPConstants class. (you could test to see if there is any message length and thus create the infoMessage object)

	private void updateErrorMessage(String message)
	{
		if (infoMessage !=null) remove(infoMessage);
		infoMessage = new GLabel(message);
		infoMessage.setFont(FPConstants.INFO_MESSAGE_FONT);
		infoMessage.setColor(FPConstants.INFO_MESSAGE_COLOR);
		infoMessage.setLocation(FPConstants.LEFT_MARGIN, FPConstants.APPLICATION_HEIGHT - FPConstants.BOTTOM_MARGIN);
		add(infoMessage);
	}

Milestone 4: Implement the interactors

Here is the interactor for when you click on requesting a friend, or press enter on the friends name text box (getActionCommand), to start with I am getting the text of the friends and seeing if there is any friends with the same name already in my friends list, else if not then send a request. I have include the error reporting and also the message string is the error string that is being sent back to inform the user what is being happening.

	if ((event.getSource() == friendRequestButton) || event.getActionCommand().equals(FRIENDREQUEST))
		{
			String requested = friendRequest.getText();
			if (requested.length() > 0)
			{
				try 
				{
					if (repository.isMyFriend(requested))
						Message = requested + " is already your friend";
					else
					{
						repository.requestFriend(requested);
						Message = "Requested friend : " + requested;
					}
					repository.setProperty(homeUserID + FILE_LOG , "Requested friend " + requested);
				}
				catch (NullPointerException ex)
				{
					Message = "Not sure of name ? "+ requested + " : error : "+ ex.getMessage();
				}
				catch (ErrorException ex)
				{
					Message = "Not sure of name ? "+ requested + " : error : "+ ex.getMessage();
				}
			}
			friendRequest.setText("");
		}

Milestone 5: Shift over to the networked repository

Since I am running on the local PC, then I cannot connect to the Stanford server to test with, so will just guess that it is working :) .

I also did implement a basic logging of the last actioned, in the users repository directory, and also if a user updates there pending friends request list and another user is viewing there FacePamphlet account and the friends list is updated then it will report the new friend in the status messages.

Going to implement in the extensions

  • Search for some friends with key words e.g. part of the name
  • status line on 2-x lines
  • change the middle gcanvas to a jpanel
  • friend finder – friends that you could link to from your friends already

Shall post extension next.

CS106A – Assignment 4 – Extensions

Wednesday, May 19th, 2010

This is assignment 4, Yahtzee, which is a dice game. This assignment comes once again from the Stanford CS106A course. Here is the extensions of the assignment, the previous Yahtzee post is for the standard course

And here are the Extensions

  • Add a high score feature. Save the top ten highest scores and names to a file and make it persistent between runs of the program. Read the file when you start and print out the hall of fame. If a player gets a score that preempts one of the early high scores, congratulate them and update the file before you quit so it is recorded for next time.
  • Incorporate the bonus scores for multiple Yahtzees in a game. As long as you have not entered a 0 in the Yahtzee box, the rules of the game give you a bonus chip worth 100 points for each additional Yahtzee you roll during the same game.
  • Beef up your Yahtzee to the variant called “Triple Yahtzee.” In this variant, each player manages three simultaneous scorecard columns, as if they were playing for three players at once. The player can assign a roll to any one of their three columns. All entries are scored normally with respect to categories and validity, but the values in the second column are doubled, and the third column values are tripled. The player’s score consists of the sum of all three columns. This would make for a three-dimensional
    array (an array of players who have any array of columns which are an array of score entries)—pretty tricky! Game play continues for 3 * 13 rounds, until all players have
    filled in all entries in all three columns. The player with the highest total score is the winner.

Top scores

The way that I approached, displaying and saving the top scores was to use a BufferedReader, which allows to read a line by line of a file, so once the file was opened I could read each line of the top 10 scores, with the scores and the name of the top person being separated by a comma e.g. 10,genux so whilst I was reading in the top scores I could find the comma and then find out the lowest value which I could pass back to the main game, here is the java code for that

System.out.println("Top 10 scores :");
while (reader.ready())
{
	scoresTop10 = reader.readLine();
	commaValue = scoresTop10.indexOf(",");
	lowestValue = Integer.parseInt(scoresTop10.substring(0,commaValue));
	System.out.println("score : " + lowestValue +" name : "+scoresTop10.substring(commaValue+1));
}
reader.close();

the reasons was so that once that game had finished I could see if the highest score was higher than the lowest score of the top 10 scores and if so update the scores file. To update the scores file I read in the scores into a two arrays, one being the score values and the other being the string of the names, but whilst reading in the scores, I inserted into the array where the new score and person name (that had played the game and scored a score that could be placed into the highest scores file), once done this then just wrote out to the file the new top 10 highest scores (by only writing out 10 of the array), this source code starts of with me inserting the new “score” and “username” into the scores/names array at the correct place, and the code below that uses the PrintWriter to out to the file.

...
	if (scoreChecker < score && !updated)
	{
		scores[insertNumber] = score;
	        names[insertNumber] = username;
		insertNumber++;
		updated = true;
	}
	scores[insertNumber] = scoreChecker;
	names[insertNumber] = scoresTop10.substring(commaNumber+1);
...
PrintWriter fileWriter = new PrintWriter(new FileWriter("top10.scores"));
for (int i =0; i < 10; i++)
	fileWriter.println(scores[i]+","+names[i]);
	fileWriter.close();
}

Bonus Yahtzee

The bonus of yahtzee for multiple yahtzees (100 points extra), I did by when I was updating the scores within the function I checked to see if the score was above 0 (which would mean that there was a score for this yahtzee) and also that the previous score was above 0 as well (e.g. there was a previous yathzee) then increase the score by 100).

here is the source code for that part

		else if (category == YahtzeeConstants.YAHTZEE && scoresUpdate[boardX][category] > 0 && score >0)
		{
			scoresUpdate[boardX][category] += (YAHTZEE_BONUS_CLIP*(boardX+1));
			score = scoresUpdate[boardX][category];
			return false;
		} else

Triple Yahtzee – x score cards

To allow for X amount of score cards ( did limit it to 3) but you could have 2 score cards and all that I did was to ask the user when they started the game to see how many score cards they wanted and then altered the scoring array to that amount. When it did come to adding the score to the board, I just questioned the user which score card to use, and then used that score card and times (*) the value accordingly. I did have to alter a couple of lines in functions to have the 3 dimensional array instead of 2 and also when updating the score cards had to alter it to place into the correct one, but could use most of the functions untouched due to how they was programmed.

I have included the score code in the zip file attached and also the PDF of the assignment requirements.

CS106A – Assignment 4 – Yahtzee

Tuesday, May 18th, 2010

This is assignment 4, Yahtzee, which is a dice game. This assignment comes once again from the Stanford CS106A course. I have included the basic assignment 4 code, here is the second post of the assignment. the next post I am going to do the extensions of the assignment.

Category 9 – Full house

Once again, I am going to bubble sort (bubble sort at the bottom of this post) the dice values, so that I can check to see if there are 3 of the same values and 2 of other values that are the same. This is very similar to counting how many values are the same with three/four of a kind, but this time need to make sure that there are only 3 / 2 split of different values, and for the scoring value we only need to return true/false since the value if it is a full house it is 25 points or 0 for nothing.

So, the way that I have done it, is with checking to see if values are the same within the array (whilst scanning from the start to end) and if they are increment the count (counting of similar values), if the values changes then check to see if the count is equal to 3 or 2 (which is the full house requirements) and if so set a boolean value to true and keep on checking. To get to return true, need to see if both the 3 and 2 boolean values are true then we know that we have a full house.

	// need to check for 3 of the same value and then 2 of the same value
	private Boolean checkFullHouse(int[] dice)
	{
		int count =1;
		Boolean found3 = false, found2 = false;
		for (int i=1; i < YahtzeeConstants.N_DICE;i++)
		{
			if (dice[i] == dice[i-1]) 
				count++;
			else
			{
				if (count == 3)
					found3 = true;
				else if (count == 2)
					found2 = true;
				count=1;
			}
		}
		if (count == 3)
			found3 = true;
		else if (count == 2)
			found2 = true;
		if (found3 && found2) return true;
		return false;
	}

Categories 10,11 – Small/Large straight

The last two are very similar and because once again I am using the bubble sort to organise the array into a order then we just need to check the array by going through it from start to finish checking to make sure that the value before is 1 minus the present value in the array ( e.g. array being 3,4,5, present value is the 4 and the previous value is 3 which is correct), then add up these correct placements within the array and if the consecutive values are either 4 (small straight) or 5 (large straight) return true or false accordingly.

	// consecutiveValues = how many in a straight line
	private Boolean checkStraight(int[] dice, int consecutiveValues)
	{
		int inLine =1;
		for (int i =1; i < YahtzeeConstants.N_DICE; i++)
		{
			if ((dice[i-1]+1) == dice[i]) inLine++;
		}
		if (inLine >= consecutiveValues) return true;
		return false;
	}

The main thing within the program is to make sure that you are always accounting for the difference with the categories numbers (which start from 1) and the scoring values (which start from 0) or the dice numbers (which start from 0 again), of course could make the size of those arrays 1 bigger.

To create the score array and also so we know what is a score value of 0 or not, then the score array is setup with all values of -1.

	/* setup the scores to a value of -1, default value */
	private void setupScores(int[][] scoresSetup, int playersNum, int totalValues)
	{
		for (int i=0; i < playersNum; i++)
			for (int j=0; j < totalValues;j++)
				scoresSetup[i][j] = -1;
	}

So that when you are selecting a category to place the score of your dice and you try to select a category already selected, then just need to check the score for -1 and if so we know it is a category not already used.

	private Boolean updateScore(int[] scoresUpdate, int category, int score)
	{
		// default is -1, since cannot get this score value
		if (scoresUpdate[category] == -1)
		{
			scoresUpdate[category] = score;
			return false;
		}
		else
		{
			display.printMessage("Category already selected, please select another");
			return true;
		}
	}

Also within the source code, I have included a cheat mode so that you can insert the values of the dice in runtime (when you are asked about the number of players type in -99 and the cheat mode is activated and there is only 1 player setup).

The next post is the extensions of this assignment.

CS106A – Assignment 4 – Yahtzee

Tuesday, May 18th, 2010

This is assignment 4, Yahtzee, which is a dice game. This assignment comes once again from the Stanford CS106A course. I have included the basic assignment 4 code, and over the next two posts going to explain about the thoughts behind working out the categories within the game, e.g. yahtzee, straight etc. And then in the 3rd post I am going to do the extensions of the assignment.

So to start with here are the different types of categories that the 5 dice can fall into with also there score associated value. ( the number at the start is the category that the dice would fall into)

  • 1. Ones. Any dice configuration is valid for this category. The score is equal to the sum of all of the 1’s showing on the dice, which is 0 if there are no 1’s showing.
  • 2–6. Twos, Threes, Fours, Fives, and Sixes. (same as above but for different values). Any dice configuration is valid for these categories. The score is equal to the sum of the 2’s, 3’s, 4’s, and so on, showing on the dice.
  • 7. Three of a Kind. At least three of the dice must show the same value. The score is equal to the sum of all of the values showing on the dice.
  • 8. Four of a Kind. At least four of the dice must show the same value. The score is equal to the sum of all of the values showing on the dice.
  • 9. Full House. The dice must show three of one value and two of another value. The score is 25 points.
  • 10. Small Straight. The dice must contain at least four consecutive values, such as the sequence 2-3-4-5. The score is 30 points.
  • 11. Large Straight. The dice must contain five consecutive values, such as the sequence 1-2-3-4-5. The score is 40 points.
  • 12. Yahtzee! All of the dice must show the same value.. The score is 50 points.
  • 13. Chance. Any dice configuration is valid for this category. The score is equal to the sum of all of the values showing on the dice.

There is a few hints within the assignment

  • There’s not much difference between determining the validity for Three of a Kind, Four of a Kind, Yahtzee, and Full House.
  • There’s not much difference between determining the validity for Small Straight and Large Straight.
  • Any dice configuration is valid for Ones, Twos, Threes, Fours, Fives, Sixes, and Chance.
  • A dice configuration assigned to a category where it doesn’t meet the requirements receives a score of 0.

which kinder give some basic help, on how to figure out the different categories.

Categories 1-6, counting single values

From the start I am going to figure out the first 6 categories, which means that if any of the values within the 5 dice are from 1-6 (each category) then add that dice value into that score. So, what we need to do is loop thought the dice’s and then sum up the dice that meet that requirement (e.g. either a 1 or 2 or 3 depending on that category), so a basic function would require the dice array and also the category (number) to check against and if any of the dice are in that category then add that value of the dice to the returning value. Also since the 13th category, (chance), adds up all of the values of the dice, then can use this function as well. Below is my java function to achieve these categories

	// add single categories e.g. 1,2,3,4,5 and only the dice that have those values
	private int addSingle(int[] dice, int category)
	{
		int sum =0;
		for (int i =0; i < YahtzeeConstants.N_DICE; i++) 
		{
			if (category == dice[i]) sum+=dice[i];
			if (category == YahtzeeConstants.CHANCE)sum+=dice[i]; 
		}
		return sum;
	}

Categories 7,8, 12 – Three/Four of a kind, and Yahtzee

Next, we are going to tackle the 3/4/5(Yahtzee) of a kind, e.g. to start with, I thought that if we had the array dice in a sorted array (e.g. 2,2,2,4,5 as such) then it would be easier to find the groups of dices that are the same, but I am using the sorting for other categories as well, so the sorting function is lower in this post. So once the dice are ordered, what we need to do is to count up the values of the dice (the sum value below) which is going to be return value if there is the correct amount of found dice in the dice array. Finding the correct amount (X being 3/4/5 of dice), we need to count up the number of dice that are of the same value, so we need to have a count value and also whilst going through the array check with the present dice with the previous value, if they are the same increment the count value, otherwise if they are not then re-set the counting value to 1 ONLY if we are below the categories check e.g. three of a kind (3), or four of a kind (4) or yahtzee (5), and then check at the end of the function if the count is above the X value (the categories value) and if so return the sum’d value of the dice array or return 0.

So here it is, the java code that will find out if there is 3 / 4 / 5 dice of the same value and return the sum of the dice.

	// X being the three / four / five (Yahtzee!!)
	private int checkXOfAKind(int[] dice, int X)
	{
		// if count = 3 then there is a three of a kind 
		int count =1, sum = dice[0];
		for (int i =1; i < YahtzeeConstants.N_DICE; i++)
		{
			// if the same value
			if (dice[i] == dice[i-1])
			{
				count++;
			}
			else
			{
				if (count < X) 
					count = 1; 
			}
			sum += dice[i];
		}
		if (count >= X) 
			return sum;
		else 
			return 0;
	}

Bubble sort

Here is am sorting the array of dice into a order, using the bubble sort algorithm, which makes it easier to find the groups of dice values, bubble sort will basically move (bubble) up the array if that value is the highest in the array or find the place where it would fit, for example if you had a array of 5 values

4 , 3 , 5 , 2 , 1

and the first time though the bubble you select the number 4 (since that is at the start of the array, and call the position in the array to be checked positionCheck) and check against the next value, 3 in this case and since 4 is greater than 3 then it will swap those values, so after the first check the new values would be

3, 4, 5, 2, 1

but in the second check on this first run, the next value is 4 (since we have moved one up in the array, and after the swap, it is 4 again and positionCheck is 2 now) but now the next value is 5 which is greater than 4 and so we do not need to swap them values, so positionCheck moves up one more (value of 3) and 5 is greater than 2, thus swap and then again since positionCheck would be 4 and this value is 5 (after the swapping of 5 and 2) which once again 5 is greater than 1, so swap .. so after the first run though we have found the highest number and moved that to the end, so the new array would be

3, 4, 2, 1, 5

so we would need to do the bubble of few more times (length of array amount of times minus 1, since the highest value is moved to the top at the start), but in the code I have not taken off the minus 1 since it just looks slightly better at times, not much of a waste of CPU cycles this time around since there is only 5 dice to check.

	// to find the values, first order the dice, thus able to create the straight and also if the dice are
	// sorted then can easily find the ones, twos etc.
	private void orderDice(int[] dice)
	{
		// use the bubble sort
		for (int i =0; i < YahtzeeConstants.N_DICE; i++)
		{
			for (int j =0; j < YahtzeeConstants.N_DICE; j++)
			{
				// swap if right value is greater than the left
				if (dice[i] < dice[j])
				{
					int temp = dice[i];
					dice[i] = dice[j];
					dice[j] = temp; 
				}
			}
		}
	}

the next post will include the other categories, and here is link to the second post about the yahtzee game.