Kotlin for Android Applications: Student Lab Workbook : Building the Object-oriented Card Game

Lab Exercise: Implementing a Card Game

### Objective In this lab, you will create an object-oriented Kotlin application to simulate a card game.
You will learn how to: - Define and use classes and objects.
How to connect classes to make an Object Oriented System - Implement method calls between objects: And pass parameters between the objects on the Method Calls - Use method handling approaches in OBJECTS:
Polymorphism : poly - Many + morph - shape.
Both overloading and overriding are polymorphic TYPE operations because they both change the shape of the method Calls.

method overloading:
A method has a signature: public methodName(int a, String b): The parameter signature in this case is (int a, String b) - called parametric because a and b are parameters on the method invocation. Changing the method signature is Method Overloading: an example of an Over-loaded Method here would be: methodName(float a, int b, bool c, String d)

method overriding:
In a sub-classed OBJECT, that sub class can change HOW the method is implemented.

How to connect classes to make an Object Oriented System:
A. Shared Field Composition
B. Method Calls

Table of Contents 1. Introduction 2. Lab Setup 3. Card Game Design 4. Implementing the Classes
Today we will introduce UML: Because Unified Modelling Language is the design language of Object-Oriented Systems Design and therefore creating IT Business Systems.
UML is our way of planning and implementing our Data Plumbing for our OBJECTS.
Think about OBJECTS as being the Applicances/Engines which convert and translate some input data into some output data: How that data is moved around between objects is something we plan and design with UML.
We will create UML Diagram to illustrate:
We will see how UML are our Design tool to inform us about how to deliver our 2 goals when we deliver an object-oriented System:
High Cohesion : One Class must focus on delivering only ONE ALGORITHM
Low Coupling : Coupling relates to method calls between OBJECTS: We would like to minimize our Method Calls between objects:
More method calls = More complexity in the System. We want to keep our complexity LOW to make our application more robust - less likely to fail - and more scalable - Easier to build up in the future.
High Cohesion and Low Coupling are pulling against each other.
- Card Class
- Deck Class
?? Might we also need a separate HAND class - a Hand being a collection of cards held by the player at any point in time.

- Player Class
- Game Class
5. Adding Functionality → Delivered as METHODS in our OBJECTS
- Drawing Cards
Putting Cards back into the DECK
- Playing the Game
6. Polymorphism and Overriding - Implementing a SpecialCard Class
7. Testing the Application
8. Conclusion
1. Introduction
In this lab, we will build a simple card game.
The game will involve creating a deck of cards
shuffling the deck
dealing cards to players
allowing players to draw and return cards to the deck.

2. Lab Setup 1. Open Android Studio. 2. Create a new Kotlin project. 3. Set up the project with an appropriate package structure.

3. Card Game Design Our card game will consist of the following classes: - `Card`: Represents a single card. - `Deck`: Represents a deck of cards. - `Player`: Represents a player in the game. - `Game`: Manages the overall game logic.

4. Implementing the Classes

#### Card Class

Class contains:

Define a class for a card that includes properties for the suit and rank.
enum class Rank(val value: Int) { TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT(8), NINE(9), TEN(10), JACK(11), QUEEN(12), KING(13), ACE(14) }
open class Card(val suit: Suit, val rank: Rank) { override fun toString(): String { return "${} of ${}" } }

class Deck { private val cards: MutableList<Card> = mutableListOf()
init { for (suit in Suit.values()) { for (rank in Rank.values()) { cards.add(Card(suit, rank)) } } }
fun shuffle() { cards.shuffle() }
fun draw(): Card? { return if (cards.isNotEmpty()) cards.removeAt(0) else null }
override fun toString(): String { return cards.joinToString(", ") } } ```
Player Class Define a class for the player that can hold cards.
```kotlin class Player(val name: String) { private val hand: MutableList<Card> = mutableListOf()
fun drawCard(deck: Deck) { val card = deck.draw() if (card != null) { hand.add(card) println("$name drew a ${card}") } else { println("No more cards in the deck.") } }
override fun toString(): String { return "$name's hand: ${hand.joinToString(", ")}" } } ```
Game Class Define a class to manage the game logic.
```kotlin class Game { private val deck: Deck = Deck() private val players: MutableList<Player> = mutableListOf()
init { deck.shuffle() }
fun addPlayer(player: Player) { players.add(player) }
fun start() { println("Starting the game...") for (player in players) { player.drawCard(deck) } }
fun showHands() { for (player in players) { println(player) } } } ```
Adding Functionality Add functionality to draw cards and play the game.
#### Drawing Cards ​Ensure each player can draw cards from the deck.
Playing the Game Initialize the game, add players, and simulate drawing cards.
*—- How to determine the Winner
*—- Add a betting pool

6. Polymorphism and Overriding
#### Implementing a SpecialCard Class ​Create a subclass of `Card` to represent special cards with additional properties.
```kotlin class SpecialCard(suit: Suit, rank: Rank, val specialEffect: String) : Card(suit, rank) { override fun toString(): String { return "${} of ${} with effect: $specialEffect" } } ```
#### Method Overloading Add overloaded methods to the `Player` class for different ways to draw cards.
```kotlin class Player(val name: String) { private val hand: MutableList<Card> = mutableListOf()
fun drawCard(deck: Deck) { val card = deck.draw() if (card != null) { hand.add(card) println("$name drew a $card") } else { println("No more cards in the deck.") } }
fun drawCard(deck: Deck, numberOfCards: Int) { repeat(numberOfCards) { drawCard(deck) } }
override fun toString(): String { return "$name's hand: ${hand.joinToString(", ")}" } } ```
### 7. Testing the Application ​Create a main function to test the card game.
```kotlin fun main() { val game = Game() val player1 = Player("Alice") val player2 = Player("Bob")
game.addPlayer(player1) game.addPlayer(player2)
game.start() game.showHands()
player1.drawCard(game.deck, 2) player2.drawCard(game.deck, 3)
game.showHands() } ```
### 8. Conclusion In this lab, you have implemented a simple card game using Kotlin,
demonstrating object-oriented programming principles
Encapsulation: Game Object contains and controls the Players and the Deck

such as classes, objects, method calls, polymorphism, method overloading, and method overriding.

This exercise should provide a solid foundation for building more complex Android applications using Kotlin.


Sample Output

Starting the game...
Alice drew a SIX of CLUBS
Bob drew a JACK of DIAMONDS
Alice's hand: SIX of CLUBS
Bob's hand: JACK of DIAMONDS
Alice drew a FOUR of DIAMONDS
Alice drew a NINE of SPADES
Bob drew a JACK of CLUBS
Bob drew a THREE of DIAMONDS
Bob drew a TWO of HEARTS
Alice's hand: SIX of CLUBS, FOUR of DIAMONDS, NINE of SPADES ( 19 points)
Bob's hand: JACK of DIAMONDS, JACK of CLUBS, THREE of DIAMONDS, TWO of HEARTS (25 points)

Some items to think about:
How can you make a method to determine the Value of Each Player’s Hand?
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
) instead.