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:
Data
Methods
Define a class for a card that includes properties for the suit and rank.
enum class Suit {
HEARTS, DIAMONDS, CLUBS, SPADES
}
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.")
}
}
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 "${rank.name} of ${suit.name} 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.")
}
}