Relay Race Game In Java With Threads

November 26th, 2009.
Filed under Games And Fun, Programming.

Make a relay race in Java with animated visuals. The original task was a school task that only needed to print team status and results in the Eclipse console. I liked it allot and made a really simple visual relay race. You have 5 teams with 4 contester running. Every contester is a thread working together as a team.

This is how the result page will look like, and while the contesters are running, the bars will increase in length. When one finishes you will see how many seconds he spent.

This game could have been programmed in many different ways, but I tried to make it this way with 4 classes working together.

The Contester class ( Thread )

/*
 *
 * Millad Dagdoni
 *
 */
import java.awt.Color;
import java.awt.Graphics;

public class Contester implements Runnable {

	private int teamNumber,
				contesterNumber,
				runLength;

	private double timeUsed;
	private Team team;
	private Graphics g;

	public Contester(){
		this(0,null,null);
	}

	public Contester(int runLength, Team team, Graphics g){
		setRunLength(runLength);
		setTeam(team);
		setGraphics(g);
	}
	public void run(){
		System.out.printf("\nContester %2d in team %2d is running!", contesterNumber, teamNumber );

		double startTime = System.currentTimeMillis();
		Color contesterColor = Color.red;

		int xPosition = 0;

		if(contesterNumber == 2){
			contesterColor = Color.blue;
			xPosition = 450;
		}
		if(contesterNumber == 3){
			contesterColor = new Color(110,59,58);
			xPosition = 450 * 2;
		}
		if(contesterNumber == 4){
			contesterColor = new Color(56,53,56);
			xPosition = 450 * 3;
		}
		g.setColor(Color.green);
		g.drawString("Contester: " + contesterNumber +" Team:" + teamNumber, ( xPosition / 3 ), ( teamNumber * 49 ));

		for(int i = 0; i < runLength; i++){
			try {
				g.setColor( contesterColor );
				g.drawRect( ( ( i + xPosition ) / 3 ), ( teamNumber * 50 ), 1, 30);

				int sleepTime = (int)( Math.random() * 50 );
				timeUsed += sleepTime;
				Thread.sleep( sleepTime );

			} catch (InterruptedException ie) {
				System.out.println("::: Thread sleep problem: " + ie);
			}
		}

		setTimeSpentByContester( startTime, System.currentTimeMillis() );

		g.setColor(Color.white);
		g.drawString( String.format("%2.2f sec", timeUsed) , ( ( xPosition + 6 ) / 3 ), ( teamNumber * 48 ) + 27 );
		System.out.printf("\nContester %2d on team %2d finished! Stage time: %2.2f", contesterNumber, teamNumber, timeUsed );

		team.addTimeUsed( timeUsed );

		if(team.getHowManyContesters() == contesterNumber)
			team.setTeamFinished(true);
		else
			team.setNestContesterToRun( contesterNumber + 1 );

	} // end run()

	// GET
	public int getContesterNumber() {
		return contesterNumber;
	}
	// SET
	public void setGraphics(Graphics g) {
		this.g = g;
	}
	public void setTeam(Team laget){
		this.team = laget;
	}
	public void setTimeSpentByContester(double startTime, double endTime){
		timeUsed = (endTime - startTime) / 1000;
	}
	public void setRunLength(int runLength) {
		this.runLength = runLength;
	}
	public void setTeamNumber(int newTeamNumber){
		this.teamNumber = newTeamNumber;
	}
	public void setContesterNumber(int newContesterNumber) {
		this.contesterNumber = newContesterNumber;
	}
}// end Class Contester

The Team class ( Holds many contesters )

/*
 *
 * Millad Dagdoni
 *
 */
import java.util.ArrayList;

public class Team implements Comparable< Team > {

	private int teamNumber;
	private float totalTimeUsed;
	private ArrayList< Contester > contesters;
	private boolean teamIsFinished;

	public Team(){
		this(0);
	}

	public Team(int teamNumber){
		setTeamNumber(teamNumber);
		contesters = new ArrayList< Contester >();
		setTeamFinished(false);
	}

	public void setNewContesterInList(Contester contester) {
		contester.setTeamNumber(teamNumber);
		contester.setContesterNumber(contesters.size() + 1 );
		this.contesters.add(contester);
	}
	// Starts the first guy
	public void runNow(){
		if(contesters.size() >= 1)
			new Thread(contesters.get(0)).start();
	}

	public void setNestContesterToRun(int contesterNumber){
		for(Contester contester: contesters)
			if(contester.getContesterNumber() == contesterNumber)
				new Thread(contester).start();
	}
	// SET
	public void setTeamNumber(int lagNummer) {
		this.teamNumber = lagNummer;
	}
	public void addTimeUsed(double tidBruktPerDeltager){
		this.totalTimeUsed += tidBruktPerDeltager;
	}
	public void setTimeUsed(float timeUsed) {
		this.totalTimeUsed = timeUsed;
	}
	public int getTeamNumber() {
		return teamNumber;
	}
	public float getTotalTimeUsed() {
		return totalTimeUsed;
	}
	public int getHowManyContesters(){
		return contesters.size();
	}

	public void setTeamFinished(boolean teamFinished) {
		this.teamIsFinished = teamFinished;
	}

	// GET
	public boolean getIsTeamFinished(){
		return teamIsFinished;
	}

	// Object
	public boolean equals(Object obj){
		if(!(obj instanceof Team)) return false;
		if(obj == this) return true;

		Team team = (Team)obj;
		if(team.getTeamNumber() == teamNumber
			&& team.getTotalTimeUsed() == totalTimeUsed
			&& team.getIsTeamFinished() == teamIsFinished )
			return true;

		return false;
	}
	public int compareTo(Team teamRef){
		float time = teamRef.getTotalTimeUsed();
		if(totalTimeUsed > time) return 1;
		if(totalTimeUsed < time ) return -1;
		return 0;
	}

}// end Team class

The RaceTimer which will hold the team(s) status time and progress.

/*
 *
 * Millad Dagdoni
 *
 */
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Collections;

public class RaceTimer {

	private float totalTimeUsed;
	private ArrayList< Team > teamsList;
	private Graphics graphic;

	public RaceTimer(Graphics g){
		setTotalTimeUsed(0);
		teamsList = new ArrayList< Team >();
		this.graphic = g;
	}

	public void startTheRace(){

		System.out.println("Race started!");

		for(Team lag: teamsList)
			lag.runNow();

		while(!getAreAllTeamsDone()){
			// Teams are running...
		}

		// Teams Done:
		Collections.sort(teamsList);
		writeResultsOnScreen();

	}// end startTheRace()

	public void setTotalTimeUsed(float totalTimeUsed) {
		this.totalTimeUsed = totalTimeUsed;
	}
	public void registerATeam(Team team){
		teamsList.add(team);
	}

	public boolean getAreAllTeamsDone(){
		boolean allAreDone = true;

		for(Team team: teamsList)
			if(!team.getIsTeamFinished())
				allAreDone = false;

		return allAreDone;
	}// end getAreAllTeamsDone()

	public void writeResultsOnScreen(){

		System.out.println("\n\nResults\n");

		graphic.setColor(Color.white);
		graphic.setFont(new Font("Arial",Font.BOLD,18));

		for(int i = 0; i < teamsList.size(); i++){

			int teamNumber = teamsList.get(i).getTeamNumber();
			float timeUsed = teamsList.get(i).getTotalTimeUsed();
			totalTimeUsed += timeUsed;

			graphic.drawString(String.format("%10d: Team %d ( %2.2f sec ) \n", ( i + 1 ), teamNumber, timeUsed ), 140,  ( i * 22 ) + 340 );
			System.out.printf("%10d: Team number %d: %2.2f \n", ( i + 1 ), teamNumber, timeUsed);
		}

		graphic.setFont(new Font("Arial", Font.BOLD,25) );
		graphic.drawString("Team " + teamsList.get(0).getTeamNumber() + " is the winner !!! ", 145, 480);
		System.out.printf("\nTotal time used: %2.2f sec",totalTimeUsed);

	}// end writeResultsOnScreen()

}// end RaceTimer class

The Client class ( Runs the program in a JFrame )

/*
 *
 * Millad Dagdoni
 * Java Innlevering 3
 *
 */
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.*;

public class Client extends JFrame {

	public Client(){
		super("Millad Dagdoni's Babylon Relay Race");
		setBackground(Color.black);
		setSize(600,500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setResizable(false);
		setLocationRelativeTo(null);
		setVisible(true);

		int raceLength = 400;

		// 5 teams with 4 contesters
		ArrayList< Team > teamList = new ArrayList< Team >();
		for(int i = 1; i < 6; i++)
			teamList.add( new Team( i ) );

		for(Team lag: teamList)
			for(int i = 0; i < 4; i++)
				lag.setNewContesterInList(new Contester(raceLength, lag, getGraphics()));

		RaceTimer raceTimer = new RaceTimer( getGraphics() );
		for(Team team: teamList)
			raceTimer.registerATeam(team);

		raceTimer.startTheRace();

	}// end Client()

	public void paint(Graphics g){
		/*
			 Black JFrame BG would not work
			 without paint(Graphics g)
		 */
	}// end paint()

	public static void main(String[] args) {
		new Client();
	} // end Main

}// end Client Class

Leave a Reply