Friday, May 28, 2021

[Java Source Code] Blackjack Game

Here's a sample code to create a Blackjack game in Java.


Blackjack's rule is pretty simple so I think it's a good start for developing card games :)


Screenshots from the game:



The game screen 1


The game screen 2


The game screen 3


Title screen




I used some free images for the title screen and the playing cards. You don't really need the image for the title screen but please prepare playing card images and put them in the res folder.

I got the playing card image from here:

https://chicodeza.com/freeitems/torannpu-illust.html

You can also get images from websites such as pixabay: 
https://pixabay.com/ja/illustrations/search/playing%20cards/



Here's the video preview:



Code structure:





Here's the code:


Game.java
This class handles the gameplay.


import java.awt.Color;
import java.net.URL;
import java.util.Random;

import javax.swing.ImageIcon;

public class Game{
	
	// CLASS
	ActionHandler aHandler = new ActionHandler(this);
	UI ui = new UI(this);
	Cards cards = new Cards();
	Random random = new Random();
	AudioAsset aa = new AudioAsset();
	SE se = new SE();
	Music music = new Music();
	
	// CARD STUFF
	int pickedCardNum;	
	int playerHas = 0;
	int dealerHas = 0;
	int playerCardNum[] = new int[6];
	int dealerCardNum[] = new int[6];	
	int playerCardValue[] = new int[6];
	int dealerCardValue[] = new int[6];	
	int playerTotalValue;
	int dealerTotalValue;	
	
	// OTHERS
	String situation = "";
	ImageIcon dealerSecondCard;
	

	public static void main(String[] args) {
		
		new Game();
	}	
	public void titleToGame() {
		
		ui.titlePanel.setVisible(false);
		ui.startB.setVisible(false);
		ui.exitB.setVisible(false);
		ui.table.setVisible(true);
		ui.dealerPanel.setVisible(true);
		ui.playerPanel.setVisible(true);
		ui.messageText.setVisible(true);
		ui.buttonPanel.setVisible(true);
		ui.getContentPane().setBackground(Color.black);
		
		playMusic(aa.bgm);
		
		startGame();
	}
	public void gameToTitle() {
				
		ui.titlePanel.setVisible(true);
		ui.table.setVisible(false);
		ui.dealerPanel.setVisible(false);
		ui.playerPanel.setVisible(false);
		ui.messageText.setVisible(false);
		ui.buttonPanel.setVisible(false);
		ui.getContentPane().setBackground(new Color(0,81,0));
		
		ui.titlePanel.alphaValue = 0f;
		ui.titlePanel.timer.start();
		
		stopMusic(aa.bgm);
	}
	public void startGame() {
				
		dealerDraw();
		playerDraw();
		dealerDraw();				
		ui.dealerCardLabel[2].setIcon(cards.front);
		ui.dealerScore.setText("Dealer: ?");
		playerTurn();		
	}
	public void dealerDraw() {

		playSE(aa.cardSound01);
		dealerHas++;
		
		ImageIcon pickedCard = pickRandomCard(); // pickRandomCard: return an ImageIcon
		if(dealerHas==2) {
			dealerSecondCard = pickedCard; // Save the second card for revealing it later
		}
		
		dealerCardNum[dealerHas] = pickedCardNum; // Register what card the dealer got		
		dealerCardValue[dealerHas] = checkCardValue();	// Register the card value. If it's from Jack to King, it returns 10
		
		ui.dealerCardLabel[dealerHas].setVisible(true);	
		ui.dealerCardLabel[dealerHas].setIcon(pickedCard);	// Display the card
		
		dealerTotalValue = dealerTotalValue();
		ui.dealerScore.setText("Dealer: " + dealerTotalValue);	
	}
	public void playerDraw() {

		playSE(aa.cardSound01);
		playerHas++;
		
		ImageIcon pickedCard = pickRandomCard();
				
		playerCardNum[playerHas] = pickedCardNum;		
		playerCardValue[playerHas] = checkCardValue();	
		
		ui.playerCardLabel[playerHas].setVisible(true);
		ui.playerCardLabel[playerHas].setIcon(pickedCard);
		
		playerTotalValue = playerTotalValue();	// Count total player card value	
		ui.playerScore.setText("You: " + playerTotalValue);
	}	
	public void playerTurn() {
		
		situation = "playerTurn";

		playerDraw(); // Hit a card
								
		if(playerTotalValue > 21) { // If the total value surpassed 21, the game is over
			dealerOpen();
		}
		else if(playerTotalValue == 21 && playerHas == 2) {
			playerNatural();
		}
		else {					
			if(playerHas > 1 && playerHas < 5) { // If the total value is less than 22 and has 4 or less cards, you can still hit
				ui.messageText.setTextPlus("Do you want to hit one more card?");
				ui.button[1].setVisible(true);
				ui.button[1].setText("Hit");
				ui.button[2].setVisible(true);
				ui.button[2].setText("Stand");	
			}
			if(playerHas == 5) { // If the player has 5 cards, the player's turn is over
				dealerOpen();
			}
		}		
	}
	public void playerNatural() {
		
		situation = "playerNatural";
		
		ui.messageText.setTextPlus("You got natural. Let's open the dealer's card.");
		ui.button[1].setVisible(true);
		ui.button[1].setText("Continue");
	}
	public void dealerOpen() {
		
		playSE(aa.cardSound01);
		ui.dealerCardLabel[2].setIcon(dealerSecondCard); // Reveal the second card	
		ui.dealerScore.setText("Dealer: " + dealerTotalValue);	
		
		if(playerHas == 2 && playerTotalValue == 21) { // If player got natural
			checkResult();
		}
		else if(dealerTotalValue < 17 && playerTotalValue <= 21) {
			dealerTurnContinue();
		}
		else {
			checkResult();
		}	
	}
	public void dealerTurn() {
						
		if(dealerTotalValue < 17) { // If it's less than 17, the dealer must hit one more card
			
			dealerDraw();
			
			if(dealerHas == 5 || dealerTotalValue >= 17) { // If the player has 5 cards, the player's turn is over
				checkResult();
			}
			else {
				dealerTurnContinue();
			}
		}	
		else {
			checkResult();
		}		
	}	
	public void dealerTurnContinue() {
		
		situation = "dealerTurnContinue";
		
		ui.messageText.setTextPlus("The dealer is going to hit another card.");
		ui.button[1].setVisible(true);
		ui.button[1].setText("Continue");
	}
	public void checkResult() {
		
		situation = "checkResult";		
		
		if(playerTotalValue > 21) {
			playSE(aa.youlost);
			ui.messageText.setTextPlus("You lost!");	
			gameFinished();
		}
		else {		
			if(playerTotalValue == 21 && dealerHas == 2) { // If player is natural
				if(dealerTotalValue == 21) {
					playSE(aa.draw);
					ui.messageText.setTextPlus("Draw!");	
					gameFinished();
				}
				else {
					playSE(aa.youwon);
					ui.messageText.setTextPlus("You won!");	
					gameFinished();
				}
			}
			else { 
				if(dealerTotalValue < 22 && dealerTotalValue > playerTotalValue) {
					playSE(aa.youlost);
					ui.messageText.setTextPlus("You lost!");	
					gameFinished();
				}
				else if(dealerTotalValue == playerTotalValue) {
					playSE(aa.draw);
					ui.messageText.setTextPlus("Draw!");	
					gameFinished();
				}
				else {
					playSE(aa.youwon);
					ui.messageText.setTextPlus("You won!");	
					gameFinished();
				}						
			}
		}
	}
	public void gameFinished() {

		situation = "gameFinished";		
		ui.button[1].setVisible(true);
		ui.button[1].setText("Play Again");
		ui.button[2].setVisible(true);		
		ui.button[2].setText("Quit");
	}
	public void resetEverything() {

		for(int i=1; i < 6; i++ ){
			ui.playerCardLabel[i].setVisible(false);
			ui.dealerCardLabel[i].setVisible(false);			
		}					
		for(int i=1; i < 6; i++) {
			playerCardNum[i]=0;
			playerCardValue[i]=0;
			dealerCardNum[i]=0;
			dealerCardValue[i]=0;
		}
		playerHas=0;		
		dealerHas=0;
		
		removeButtons();			
		startGame();
	}
	public int playerTotalValue() {
		
		playerTotalValue = playerCardValue[1] + playerCardValue[2] + playerCardValue[3] + playerCardValue[4] + playerCardValue[5];
		
		if(playerTotalValue > 21) {
			adjustPlayerAceValue();
		}
		playerTotalValue = playerCardValue[1] + playerCardValue[2] + playerCardValue[3] + playerCardValue[4] + playerCardValue[5];	
		return playerTotalValue;
	}
	public int dealerTotalValue() {
		
		dealerTotalValue = dealerCardValue[1] + dealerCardValue[2] + dealerCardValue[3] + dealerCardValue[4] + dealerCardValue[5];
		
		if(dealerTotalValue > 21) {
			adjustDealerAceValue();
		}
		dealerTotalValue = dealerCardValue[1] + dealerCardValue[2] + dealerCardValue[3] + dealerCardValue[4] + dealerCardValue[5];	
		return dealerTotalValue;
	}
	public void adjustPlayerAceValue() {
		
		for(int i=1; i<6; i++) {
			if(playerCardNum[i]==1) {
				playerCardValue[i]=1;	
				playerTotalValue = playerCardValue[1] + playerCardValue[2] + playerCardValue[3] + playerCardValue[4] + playerCardValue[5];
				if(playerTotalValue < 21) {
					break;
				}
			}
		}
	}
	public void adjustDealerAceValue() {
		
		for(int i=1; i<6; i++) {
			if(dealerCardNum[i]==1) {
				dealerCardValue[i]=1;	
				dealerTotalValue = dealerCardValue[1] + dealerCardValue[2] + dealerCardValue[3] + dealerCardValue[4] + dealerCardValue[5];
				if(dealerTotalValue < 21) {
					break;
				}
			}
		}
	}

	public ImageIcon pickRandomCard() {
		
		ImageIcon pickedCard = null;
		
		pickedCardNum = random.nextInt(13)+1;
		int pickedMark = random.nextInt(4)+1;
		
		switch(pickedMark) {
		case 1: pickedCard = cards.spade[pickedCardNum]; break;
		case 2: pickedCard = cards.heart[pickedCardNum]; break;
		case 3: pickedCard = cards.club[pickedCardNum]; break;
		case 4: pickedCard = cards.diamond[pickedCardNum]; break;
		}			
		return pickedCard;				
	}
	public int checkCardValue() {
		
		int cardValue = pickedCardNum;
		if(pickedCardNum==1) {
			cardValue=11;
		}
		if(pickedCardNum>10) {
			cardValue=10;
		}
		return cardValue;		
	}
	public void removeButtons() {
		
		ui.button[1].setVisible(false);
		ui.button[2].setVisible(false);
		ui.button[3].setVisible(false);
		ui.button[4].setVisible(false);
		ui.button[5].setVisible(false);
	}
	public void playSE(URL url) {
		
		se.setFile(url);
		se.play(url);
	}
	public void playMusic(URL url) {
		
		music.setFile(url);
		music.play(url);
		music.loop(url);
	}
	public void stopMusic(URL url) {
		
		music.stop(url);
	}
}



Cards.java
This class imports all the card images.

import javax.swing.ImageIcon;

public class Cards {

	ImageIcon front = new ImageIcon();
	ImageIcon spade[] = new ImageIcon[14];
	ImageIcon heart[] = new ImageIcon[14];
	ImageIcon club[] = new ImageIcon[14];
	ImageIcon diamond[] = new ImageIcon[14];

	public Cards() {
		
		front = new ImageIcon(getClass().getClassLoader().getResource("front.png"));

		// SPADE
		for(int num=1; num<14; num++) {
			spade[num]  = new ImageIcon(getClass().getClassLoader().getResource(num + "S.png"));
		}
		
		// HEART
		for(int num=1; num<14; num++) {
			heart[num]  = new ImageIcon(getClass().getClassLoader().getResource(num + "H.png"));
		}
		
		// CLUB
		for(int num=1; num<14; num++) {
			club[num]  = new ImageIcon(getClass().getClassLoader().getResource(num + "C.png"));
		}
		
		// DIAMOND
		for(int num=1; num<14; num++) {
			diamond[num]  = new ImageIcon(getClass().getClassLoader().getResource(num + "D.png"));
		}					
	}
}


UI.java

This class handles all the UI elements.


import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class UI extends JFrame{
	
	// Title Screen UI
	PaintPanel titlePanel;
	JButton startB,exitB;
	
	// Table UI
	JPanel table;
	JPanel dealerPanel;
	JPanel playerPanel;
	JLabel playerCardLabel[] = new JLabel[6];
	JLabel dealerCardLabel[] = new JLabel[6];
	
	// Message UI
    JTextAreaPlus messageText;
	JPanel scorePanel;
	JLabel playerScore, dealerScore;
	JPanel buttonPanel = new JPanel();
	JButton button[] = new JButton[6];
	Game game;
	
	int cardWidth = 150;
	int cardHeight = 213;
	
	
	public UI(Game game) {
		
		this.game = game;
		
		this.setTitle("SUPER BlACKJACK");
		this.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("ui_glass.png")).getImage());
		this.setSize(1200,900);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLayout(null);
		this.getContentPane().setBackground(new Color(0,81,0));
		
		createTitleScreen();
		createTableUI();	
		createOtherUI();
		this.setVisible(true);
	}
	public void createTitleScreen() {
			
		titlePanel = new PaintPanel(this);
		titlePanel.setBounds(0,0,1200,600);
		titlePanel.setOpaque(false);
		this.add(titlePanel);
		
		startB = new JButton("START");
		startB.setBounds(500,700,200,50);
		startB.setBorder(null);
		startB.setBackground(null);
		startB.setFocusPainted(false);
		startB.setForeground(Color.white);
		startB.setFont(new Font("Book Antiqua", Font.PLAIN,36));
		startB.setVisible(false);
		startB.addActionListener(game.aHandler);
		startB.setActionCommand("start");
		startB.setContentAreaFilled(false);
		this.add(startB);
		
		exitB = new JButton("EXIT");
		exitB.setBounds(500,750,200,50);
		exitB.setBorder(null);
		exitB.setBackground(null);
		exitB.setFocusPainted(false);
		exitB.setForeground(Color.white);
		exitB.setFont(new Font("Book Antiqua", Font.PLAIN,36));
		exitB.setVisible(false);
		exitB.addActionListener(game.aHandler);
		exitB.setActionCommand("exit");
		exitB.setContentAreaFilled(false);
		this.add(exitB);
		
		titlePanel.timer.start();
	}
	public void createTableUI() {
		
		table = new JPanel();
		table.setBackground(new Color(0,81,0));
		table.setBounds(50,50,850,600);
		table.setLayout(null);
		table.setVisible(false);
		
		dealerPanel = new JPanel();
		dealerPanel.setBounds(100,120,cardWidth*5,cardHeight);
		dealerPanel.setBackground(null);
		dealerPanel.setOpaque(false);
		dealerPanel.setLayout(new GridLayout(1,5));
		dealerPanel.setVisible(false);
		this.add(dealerPanel);
				
		playerPanel = new JPanel();
		playerPanel.setBounds(100,370,cardWidth*5,cardHeight);
		playerPanel.setOpaque(false);
		playerPanel.setLayout(new GridLayout(1,5));
		playerPanel.setVisible(false);
		this.add(playerPanel);

		for(int i = 1; i < 6; i++) {
			playerCardLabel[i] = new JLabel();
			playerCardLabel[i].setVisible(false);
			playerPanel.add(playerCardLabel[i]);
		}
		for(int i = 1; i < 6; i++) {
			dealerCardLabel[i] = new JLabel();
			dealerCardLabel[i].setVisible(false);
			dealerPanel.add(dealerCardLabel[i]);
		}	
		
		dealerScore = new JLabel();
		dealerScore.setBounds(50,10,200,50);
		dealerScore.setForeground(Color.white);
		dealerScore.setFont(new Font("Times New Roman", Font.PLAIN, 42));
		table.add(dealerScore);
		
		playerScore = new JLabel();
		playerScore.setBounds(50,540,200,50);
		playerScore.setForeground(Color.white);
		playerScore.setFont(new Font("Times New Roman", Font.PLAIN, 42));
		table.add(playerScore);
	
		this.add(table);
	}
	public void createOtherUI() {
		
		messageText = new JTextAreaPlus();
		messageText.setBounds(230,680,720,100);
		messageText.setBackground(null);
		messageText.setForeground(Color.white);
		messageText.setFont(new Font("Times New Roman", Font.PLAIN, 40));
		messageText.setEditable(false);
		this.add(messageText);
		
		buttonPanel = new JPanel();
		buttonPanel.setBounds(920,340,200,300);
		buttonPanel.setBackground(null);
		buttonPanel.setLayout(new GridLayout(6,1));
		this.add(buttonPanel);
		
		for(int i = 1; i < 6; i++) {
			button[i] = new JButton();
			button[i].setBackground(null);
			button[i].setForeground(Color.white);
			button[i].setFocusPainted(false);
			button[i].setBorder(null);
			button[i].setFont(new Font("Times New Roman", Font.PLAIN, 42));
			button[i].addActionListener(game.aHandler);
			button[i].setActionCommand(""+i);
			button[i].setVisible(false);
			buttonPanel.add(button[i]);
		}		
	}
}




PaintPanel.java

This class handles the title screen animation


import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;

public class PaintPanel extends JPanel implements ActionListener{
	
	public Timer timer = new Timer(30,this);
	float alphaValue = 0f;
	BufferedImage titleImage;
	
	UI ui;
	
	public PaintPanel(UI ui) {
		
		this.ui = ui;
		
		try {
			titleImage = ImageIO.read(getClass().getClassLoader().getResource("titleimage.png"));
			
		}catch(IOException e) {			
		}		
	}

	public void paintComponent(Graphics g) {
		
		super.paintComponent(g);

		Graphics2D g2d = (Graphics2D)g;
		g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaValue));
		if(alphaValue < 0.99) {
			g2d.setColor(Color.white);
		}
		else {
			g2d.setColor(Color.yellow);
		}
		
		g2d.setFont(new Font("Book Antiqua", Font.PLAIN, 110));
		g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		
		String text = "SUPER BLACKJACK";
		
		int stringLength = (int)g.getFontMetrics().getStringBounds(text, g).getWidth();
		int start = this.getWidth()/2 - stringLength/2;
		
		g.drawString(text, start, 200);		
		g.drawImage(titleImage, 280,320,640,280,null);
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
				
		alphaValue = alphaValue +0.01f;
		
		if(alphaValue > 1) {
			alphaValue = 1;
			timer.stop();
			ui.startB.setVisible(true);
			ui.exitB.setVisible(true);
		}
		repaint();
	}
}



ActionHandler.java

This class handles the button actions


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ActionHandler implements ActionListener{
	
	Game game;
	
	public ActionHandler(Game game) {
		
		this.game = game;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		
		String command = e.getActionCommand();
				
		game.removeButtons();
		
		switch(command) {
		case "start":
			game.titleToGame();
			break;
		case "exit":
			System.exit(0);
			break;
		case "1": 
			if(game.situation.equals("playerTurn")) {
				game.playerTurn();
			}
			else if(game.situation.equals("playerNatural")) {
				game.dealerOpen();
			}
			else if(game.situation.equals("dealerTurnContinue")) {
				game.dealerTurn();
			}
			else if(game.situation.equals("gameFinished")) {
				game.resetEverything();
			}
			break;
		case "2": 
			if(game.situation.equals("playerTurn")) {
				game.dealerOpen();
			}
			else if(game.situation.contentEquals("gameFinished")) {
				game.gameToTitle();
			}
			break;
		}			
	}
}


JTextAreaPlus.java

This is a modified version of JTextArea which can display texts letter by letter.


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JTextArea;
import javax.swing.Timer;

public class JTextAreaPlus extends JTextArea implements ActionListener{
	
	int i=0;
	String text;
	
	Timer timer = new Timer(10, this);
	
	public JTextAreaPlus() {
		
	}
	
	public JTextAreaPlus(String text) {
		super(text);
	}
	
	public void setTextPlus(String text) {
		
		this.text = text;
		setText("");
		timer.start();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		
		char character[] = text.toCharArray();
		int arrayNum = character.length;		
		String s = String.valueOf(character[i]);
		append(s);		
		i++;

		if(i == arrayNum){
			i = 0;
			timer.stop();
		}
	}
}



(Optional) If you want to play SE and Music

AudioAsset.java

This class imports all the sound data


import java.net.URL;

public class AudioAsset {
	
	URL cardSound01 = getClass().getClassLoader().getResource("cardSound01.wav");
	URL youwon = getClass().getClassLoader().getResource("Ryan_youwon.wav");
	URL youlost = getClass().getClassLoader().getResource("Ryan_youlost.wav");
	URL draw = getClass().getClassLoader().getResource("Ryan_draw.wav");
	URL isee = getClass().getClassLoader().getResource("Ryan_isee.wav");
	URL ok = getClass().getClassLoader().getResource("Ryan_ok.wav");
	URL hitanother = getClass().getClassLoader().getResource("Ryan_hitanother.wav");
	URL bgm = getClass().getClassLoader().getResource("bensound-theelevatorbossanova.wav");
}


SE.java


import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

public class SE {
	
	Clip clip;
	
	public void setFile(URL name) {
		
		try {
			AudioInputStream sound = AudioSystem.getAudioInputStream(name);
			clip = AudioSystem.getClip();
			clip.open(sound);
		}
		catch(Exception e) {
			
		}
	}
	
	public void play(URL name) {
		
		clip.setFramePosition(0);
		clip.start();
	}
	
	public void loop(URL name) {
		
		clip.loop(Clip.LOOP_CONTINUOUSLY);
	}
	public void stop(URL name) {
		
		clip.stop();
	}
}


Music.java


import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

public class Music {
	
	Clip clip;

	public void setFile(URL name) {
		
		try {
			AudioInputStream sound = AudioSystem.getAudioInputStream(name);
			clip = AudioSystem.getClip();
			clip.open(sound);
		}
		catch(Exception e) {
			
		}
	}
	
	public void play(URL name) {
		
		clip.setFramePosition(0);
		clip.start();
	}
	
	public void loop(URL name) {
		
		clip.loop(Clip.LOOP_CONTINUOUSLY);
	}
	public void stop(URL name) {
		
		clip.stop();
	}
}


end



2 comments:

  1. question do i need to pick one card picture and rename it to "front" because i'm getting an error when running the program

    ReplyDelete