Merge pull request #10 from flixcoo/feature/3-100-point-rules

feature/3 100 point rules
This commit is contained in:
2025-04-30 01:11:31 +02:00
committed by GitHub
8 changed files with 269 additions and 233 deletions

View File

@@ -1,47 +1,41 @@
/// This class represents a game session for the Cabo game. import 'package:cabo_counter/data/round.dart';
/// [gameTitle] is the title of the game.
/// [players] is a string list of player names. /// This class represents a game session for Cabo game.
/// [pointLimit] is a boolean indicating if the game has the
/// default point limit of 101 points or not.
/// [createdAt] is the timestamp of when the game session was created. /// [createdAt] is the timestamp of when the game session was created.
/// [round] is the current round number. /// [gameTitle] is the title of the game.
/// [finished] is a boolean indicating if the game session is finished. /// [gameHasPointLimit] is a boolean indicating if the game has the default
/// point limit of 101 points or not.
/// [players] is a string list of player names.
/// [playerScores] is a list of the summed scores of all players.
/// [roundNumber] is the current round number.
/// [isGameFinished] is a boolean indicating if the game has ended yet.
/// [winner] is the name of the player who won the game. /// [winner] is the name of the player who won the game.
class GameSession { class GameSession {
final DateTime createdAt = DateTime.now(); final DateTime createdAt = DateTime.now();
final String gameTitle; final String gameTitle;
final bool pointLimit; final bool gameHasPointLimit;
final List<String> players; final List<String> players;
List<List<int>> playerScores = List.generate(5, (_) => [0, 0]); late List<int> playerScores;
int round = 1; List<Round> roundList = [];
bool finished = false; int roundNumber = 1;
bool isGameFinished = false;
String winner = ''; String winner = '';
GameSession({ GameSession({
required this.gameTitle, required this.gameTitle,
required this.gameHasPointLimit,
required this.players, required this.players,
required this.pointLimit, }) {
}); playerScores = List.filled(players.length, 0);
}
@override @override
String toString() { String toString() {
return ('GameSession: [gameTitle: $gameTitle, ' return ('GameSession: [createdAt: $createdAt, gameTitle: $gameTitle, '
'players: $players, ' 'gameHasPointLimit: $gameHasPointLimit, players: $players, '
'round: $round, pointLimit: $pointLimit, ' 'playerScores: $playerScores, roundList: $roundList, '
'playerScores: $playerScores]'); 'roundNumber: $roundNumber, isGameFinished: $isGameFinished, '
} 'winner: $winner]');
// FIXME Debug
/// Returns a string representation of the scores for a specific round.
/// The method takes a round number as a parameter and returns a string
/// containing the name of each player and their corressponding score in
/// the given round.
String printRoundScores(int round) {
String result = '';
for (int i = 0; i < players.length; i++) {
result += '${players[i]}: ${playerScores[i][round]}\n';
}
return result;
} }
/// Returns the length of all player names combined. /// Returns the length of all player names combined.
@@ -53,65 +47,199 @@ class GameSession {
return length; return length;
} }
/// Increases the round number by 1. /// Assigns 50 points to all players except the kamikaze player.
void increaseRound() { /// [kamikazePlayerIndex] is the index of the kamikaze player.
round++; void applyKamikaze(int roundNum, int kamikazePlayerIndex) {
List<int> roundScores = List.generate(players.length, (_) => 0);
List<int> scoreUpdates = List.generate(players.length, (_) => 0);
for (int i = 0; i < roundScores.length; i++) {
if (i != kamikazePlayerIndex) {
scoreUpdates[i] += 50;
}
}
addRoundScoresToList(
roundNum, roundScores, scoreUpdates, kamikazePlayerIndex);
} }
/// Expands the player score lists by adding a new score of 0 for each player. /// Checks the scores of the current round and assigns points to the players.
/// This method is called when a new round starts so the lists in the /// There are three possible outcomes of a round:
/// active game view expands ///
void expandPlayerScoreLists() { /// **Case 1**<br>
for (int i = 0; i < playerScores.length; i++) { /// The player who said CABO has the lowest score. They receive 0 points.
playerScores[i].add(0); /// Every other player gets their round score.
///
/// **Case 2**<br>
/// The player who said CABO does not have the lowest score.
/// They receive 5 extra points added to their round score.
/// Every player with the lowest score gets 0 points.
/// Every other player gets their round score.
void calculateScoredPoints(
int roundNum, List<int> roundScores, int caboPlayerIndex) {
print('Spieler: $players');
print('Punkte: $roundScores');
print('${players[caboPlayerIndex]} hat mit ${roundScores[caboPlayerIndex]} '
'Punkten CABO gesagt');
/// List of the index of the player(s) with the lowest score
List<int> lowestScoreIndex = _getLowestScoreIndex(roundScores);
print('Folgende Spieler haben die niedrigsten Punte:');
for (int i in lowestScoreIndex) {
print('${players[i]} (${roundScores[i]} Punkte)');
} }
// The player who said CABO is one of the players which have the
// fewest points.
if (lowestScoreIndex.contains(caboPlayerIndex)) {
print('${players[caboPlayerIndex]} hat CABO gesagt '
'und bekommt 0 Punkte');
print('Alle anderen Spieler bekommen ihre Punkte');
_assignPoints(roundNum, roundScores, [caboPlayerIndex]);
} else {
// A player other than the one who said CABO has the fewest points.
print('${players[caboPlayerIndex]} hat CABO gesagt, '
'jedoch nicht die wenigsten Punkte.');
print('Folgende:r Spieler haben die wenigsten Punkte:');
for (int i in lowestScoreIndex) {
print('${players[i]}: ${roundScores[i]} Punkte');
}
_assignPoints(roundNum, roundScores, lowestScoreIndex, caboPlayerIndex);
}
}
/// Returns the index of the player with the lowest score. If there are
/// multiple players with the same lowest score, all of them are returned.
/// [roundScores] is a list of the scores of all players in the current round.
List<int> _getLowestScoreIndex(List<int> roundScores) {
int lowestScore = roundScores[0];
List<int> lowestScoreIndex = [0];
for (int i = 1; i < roundScores.length; i++) {
if (roundScores[i] < lowestScore) {
lowestScore = roundScores[i];
lowestScoreIndex = [i];
} else if (roundScores[i] == lowestScore) {
lowestScoreIndex.add(i);
}
}
return lowestScoreIndex;
}
/// Assigns points to the players based on the scores of the current round.
/// [roundNum] is the number of the current round.
/// [roundScores] is the raw list of the scores of all players in the current round.
/// [winnerIndex] is the index of the player who receives 5 extra points
void _assignPoints(int roundNum, List<int> roundScores, List<int> winnerIndex,
[int loserIndex = -1]) {
/// List of the updates for every player score
List<int> scoreUpdates = [...roundScores];
print('Folgende Punkte wurden aus der Runde übernommen:');
for (int i = 0; i < scoreUpdates.length; i++) {
print('${players[i]}: ${scoreUpdates[i]}');
}
for (int i in winnerIndex) {
print('${players[i]} hat gewonnen und bekommt 0 Punkte');
scoreUpdates[i] = 0;
}
if (loserIndex != -1) {
print('${players[loserIndex]} bekommt 5 Fehlerpunkte');
scoreUpdates[loserIndex] += 5;
}
print('Aktualisierte Punkte:');
for (int i = 0; i < scoreUpdates.length; i++) {
print('${players[i]}: ${scoreUpdates[i]}');
}
print('scoreUpdates: $scoreUpdates, roundScores: $roundScores');
addRoundScoresToList(roundNum, roundScores, scoreUpdates);
} }
/// Sets the scores of the players for a specific round. /// Sets the scores of the players for a specific round.
/// This method takes a list of round scores and a round number as parameters. /// This method takes a list of round scores and a round number as parameters.
/// It then replaces the values for the given [roundNumber] in the /// It then replaces the values for the given [roundNum] in the
/// playerScores. Its important that each index of the [roundScores] list /// playerScores. Its important that each index of the [roundScores] list
/// corresponds to the index of the player in the [playerScores] list. /// corresponds to the index of the player in the [playerScores] list.
void addRoundScoresToScoreList(List<int> roundScores, int roundNumber) { void addRoundScoresToList(
print('addRoundScoresToScoreList: $roundScores'); int roundNum, List<int> roundScores, List<int> scoreUpdates,
for (int i = 0; i < roundScores.length; i++) { [int? kamikazePlayerIndex]) {
playerScores[i][roundNumber] = (roundScores[i]); Round newRound = Round(
roundNum: roundNum,
scores: roundScores,
scoreUpdates: scoreUpdates,
kamikazePlayerIndex: kamikazePlayerIndex,
);
if (roundNum > roundList.length) {
roundList.add(newRound);
} else {
roundList[roundNum - 1] = newRound;
} }
} }
/// This method updates the points of each player after a round.
/// It first uses the _sumPoints() method to calculate the total points of each player.
/// Then, it checks if any player has reached 100 points. If so, it marks
/// that player as having reached 100 points in that corresponding [Round] object.
/// If the game has the point limit activated, it first applies the
/// _subtractPointsForReachingHundred() method to subtract 50 points
/// for every time a player reached 100 points in the game.
/// It then checks if any player has exceeded 100 points. If so, it sets
/// isGameFinished to true and calls the _setWinner() method to determine
/// the winner.
void updatePoints() {
_sumPoints();
if (gameHasPointLimit) {
_checkHundredPointsReached();
for (int i = 0; i < playerScores.length; i++) {
if (playerScores[i] > 100) {
isGameFinished = true;
print('${players[i]} hat die 100 Punkte ueberschritten, '
'deswegen wurde das Spiel beendet');
_setWinner();
}
}
}
}
/// Sums up the points of all players and stores the result in the
/// playerScores list.
void _sumPoints() {
for (int i = 0; i < players.length; i++) {
playerScores[i] = 0;
for (int j = 0; j < roundList.length; j++) {
playerScores[i] += roundList[j].scoreUpdates[i];
}
}
}
/// Checks if a player has reached 100 points in the current round.
/// If so, it updates the [scoreUpdate] List by subtracting 50 points from
/// the corresponding round update.
void _checkHundredPointsReached() {
for (int i = 0; i < players.length; i++) {
if (playerScores[i] == 100) {
print('${players[i]} hat genau 100 Punkte erreicht und bekommt '
'deswegen 50 Punkte abgezogen');
roundList[roundNumber - 1].scoreUpdates[i] -= 50;
}
}
_sumPoints();
}
/// Determines the winner of the game session. /// Determines the winner of the game session.
/// It iterates through the player scores and finds the player /// It iterates through the player scores and finds the player
/// with the lowest score. /// with the lowest score.
void _determineWinner() { void _setWinner() {
int score = playerScores[0][0]; int score = playerScores[0];
String lowestPlayer = players[0]; String lowestPlayer = players[0];
for (int i = 0; i < players.length; i++) { for (int i = 0; i < players.length; i++) {
if (playerScores[i][0] < score) { if (playerScores[i] < score) {
score = playerScores[i][0]; score = playerScores[i];
lowestPlayer = players[i]; lowestPlayer = players[i];
} }
} }
winner = lowestPlayer; winner = lowestPlayer;
} }
/// Summarizes the points of all players in the first index of their /// Increases the round number by 1.
/// score list. The method clears the first index of each player score void increaseRound() {
/// list and then sums up the points from the second index to the last roundNumber++;
/// index. It then stores the result in the first index. This method is
/// used to update the total points of each player after a round.
/// If a player reaches the 101 points,
void sumPoints() {
for (int i = 0; i < playerScores.length; i++) {
playerScores[i][0] = 0;
for (int j = 1; j < playerScores[i].length; j++) {
playerScores[i][0] += playerScores[i][j];
}
if (pointLimit && playerScores[i][0] > 101) {
finished = true;
print('${players[i]} hat die 101 Punkte ueberschritten, '
'deswegen wurde das Spiel beendet');
_determineWinner();
}
}
} }
} }

19
lib/data/round.dart Normal file
View File

@@ -0,0 +1,19 @@
/// This class represents a single round in the game.
/// It is stored within the [GameSession] class.
/// [roundNum] is the number of the round its reppresenting.
/// [scores] is a list of the actual scores the players got.
/// [scoreUpdates] is a list of how the players scores updated this round.
/// [kamikazePlayerIndex] is the index of the player who got kamikaze. If no one got
/// kamikaze, this value is null.
class Round {
final int roundNum;
final List<int> scores;
final List<int> scoreUpdates;
final int? kamikazePlayerIndex;
Round(
{required this.roundNum,
required this.scores,
required this.scoreUpdates,
this.kamikazePlayerIndex});
}

View File

@@ -50,7 +50,7 @@ class _ActiveGameViewState extends State<ActiveGameView> {
trailing: Row( trailing: Row(
children: [ children: [
const SizedBox(width: 5), const SizedBox(width: 5),
Text('${widget.gameSession.playerScores[playerIndex][0]} ' Text('${widget.gameSession.playerScores[playerIndex]} '
'Punkte') 'Punkte')
], ],
), ),
@@ -66,7 +66,7 @@ class _ActiveGameViewState extends State<ActiveGameView> {
), ),
ListView.builder( ListView.builder(
shrinkWrap: true, shrinkWrap: true,
itemCount: widget.gameSession.round, itemCount: widget.gameSession.roundNumber,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Padding( return Padding(
padding: const EdgeInsets.all(1), padding: const EdgeInsets.all(1),
@@ -74,8 +74,8 @@ class _ActiveGameViewState extends State<ActiveGameView> {
title: Text( title: Text(
'Runde ${index + 1}', 'Runde ${index + 1}',
), ),
trailing: index + 1 != widget.gameSession.round || trailing: index + 1 != widget.gameSession.roundNumber ||
widget.gameSession.finished == true widget.gameSession.isGameFinished == true
? (const Text('\u{2705}', ? (const Text('\u{2705}',
style: TextStyle(fontSize: 22))) style: TextStyle(fontSize: 22)))
: const Text('\u{23F3}', : const Text('\u{23F3}',
@@ -109,8 +109,8 @@ class _ActiveGameViewState extends State<ActiveGameView> {
List<int>.generate(widget.gameSession.players.length, (index) => index); List<int>.generate(widget.gameSession.players.length, (index) => index);
// Sort the indices based on the summed points // Sort the indices based on the summed points
playerIndices.sort((a, b) { playerIndices.sort((a, b) {
int scoreA = widget.gameSession.playerScores[a][0]; int scoreA = widget.gameSession.playerScores[a];
int scoreB = widget.gameSession.playerScores[b][0]; int scoreB = widget.gameSession.playerScores[b];
return scoreA.compareTo(scoreB); return scoreA.compareTo(scoreB);
}); });
return playerIndices; return playerIndices;

View File

@@ -18,8 +18,12 @@ class _CreateGameState extends State<CreateGame> {
]; ];
final TextEditingController _gameTitleTextController = final TextEditingController _gameTitleTextController =
TextEditingController(); TextEditingController();
/// Maximum number of players allowed in the game.
final int maxPlayers = 5; final int maxPlayers = 5;
String? selectedMode; // Variable für den ausgewählten Spielmodus
/// Variable to store the selected game mode.
bool? selectedMode;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -45,7 +49,7 @@ class _CreateGameState extends State<CreateGame> {
padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
child: CupertinoTextField( child: CupertinoTextField(
decoration: const BoxDecoration(), decoration: const BoxDecoration(),
maxLength: 8, maxLength: 16,
prefix: const Text('Name'), prefix: const Text('Name'),
textAlign: TextAlign.right, textAlign: TextAlign.right,
placeholder: 'Titel des Spiels', placeholder: 'Titel des Spiels',
@@ -62,7 +66,9 @@ class _CreateGameState extends State<CreateGame> {
suffix: Row( suffix: Row(
children: [ children: [
Text( Text(
selectedMode ?? 'Wähle einen Modus', selectedMode == null
? 'Wähle einen Modus'
: (selectedMode! ? '101 Punkte' : 'Unbegrenzt'),
), ),
const SizedBox(width: 3), const SizedBox(width: 3),
const CupertinoListTileChevron(), const CupertinoListTileChevron(),
@@ -131,7 +137,8 @@ class _CreateGameState extends State<CreateGame> {
showCupertinoDialog( showCupertinoDialog(
context: context, context: context,
builder: (context) => CupertinoAlertDialog( builder: (context) => CupertinoAlertDialog(
title: const Text('Maximale Spielerzahl erreicht'), title:
const Text('Maximale Spielerzahl erreicht'),
content: const Text( content: const Text(
'Es können maximal 5 Spieler hinzugefügt ' 'Es können maximal 5 Spieler hinzugefügt '
'werden.'), 'werden.'),
@@ -276,9 +283,9 @@ class _CreateGameState extends State<CreateGame> {
GameSession gameSession = GameSession( GameSession gameSession = GameSession(
gameTitle: _gameTitleTextController.text, gameTitle: _gameTitleTextController.text,
players: players, players: players,
pointLimit: selectedMode == '101 Pkt.' ? true : false, gameHasPointLimit: selectedMode!,
); );
Navigator.push( Navigator.pushReplacement(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => builder: (context) =>

View File

@@ -18,36 +18,36 @@ class _MainMenuViewState extends State<MainMenuView> {
GameSession( GameSession(
gameTitle: 'Spiel am 27.02.2025', gameTitle: 'Spiel am 27.02.2025',
players: ['Clara', 'Tobias', 'Yannik', 'Lena', 'Lekaia'], players: ['Clara', 'Tobias', 'Yannik', 'Lena', 'Lekaia'],
pointLimit: true), gameHasPointLimit: true),
GameSession( GameSession(
gameTitle: 'Freundschaftsrunde', gameTitle: 'Freundschaftsrunde',
players: ['Felix', 'Jonas', 'Nils'], players: ['Felix', 'Jonas', 'Nils'],
pointLimit: false), gameHasPointLimit: false),
GameSession( GameSession(
gameTitle: 'Familienabend', gameTitle: 'Familienabend',
players: ['Mama', 'Papa', 'Lisa'], players: ['Mama', 'Papa', 'Lisa'],
pointLimit: true, gameHasPointLimit: true,
), ),
GameSession( GameSession(
gameTitle: 'Turnier 1. Runde', gameTitle: 'Turnier 1. Runde',
players: ['Tim', 'Max', 'Sophie', 'Lena'], players: ['Tim', 'Max', 'Sophie', 'Lena'],
pointLimit: false), gameHasPointLimit: false),
GameSession( GameSession(
gameTitle: '2 Namen max length', gameTitle: '2 Namen max length',
players: ['Heinrich', 'Johannes'], players: ['Heinrich', 'Johannes'],
pointLimit: true), gameHasPointLimit: true),
GameSession( GameSession(
gameTitle: '3 Namen max length', gameTitle: '3 Namen max length',
players: ['Benjamin', 'Stefanie', 'Wolfgang'], players: ['Benjamin', 'Stefanie', 'Wolfgang'],
pointLimit: false), gameHasPointLimit: false),
GameSession( GameSession(
gameTitle: '4 Namen max length', gameTitle: '4 Namen max length',
players: ['Leonhard', 'Mathilde', 'Bernhard', 'Gerlinde'], players: ['Leonhard', 'Mathilde', 'Bernhard', 'Gerlinde'],
pointLimit: true), gameHasPointLimit: true),
GameSession( GameSession(
gameTitle: '5 Namen max length', gameTitle: '5 Namen max length',
players: ['Hartmuth', 'Elisabet', 'Rosalind', 'Theresia', 'Karoline'], players: ['Hartmuth', 'Elisabet', 'Rosalind', 'Theresia', 'Karoline'],
pointLimit: false), gameHasPointLimit: false),
]; ];
@override @override
@@ -91,18 +91,18 @@ class _MainMenuViewState extends State<MainMenuView> {
padding: const EdgeInsets.symmetric(vertical: 10.0), padding: const EdgeInsets.symmetric(vertical: 10.0),
child: CupertinoListTile( child: CupertinoListTile(
title: Text(session.gameTitle), title: Text(session.gameTitle),
subtitle: session.finished == true subtitle: session.isGameFinished == true
? Text( ? Text(
'\u{1F947} ${session.winner}', '\u{1F947} ${session.winner}',
style: const TextStyle(fontSize: 14), style: const TextStyle(fontSize: 14),
) )
: Text( : Text(
'Modus: ${_translateGameMode(session.pointLimit)}', 'Modus: ${_translateGameMode(session.gameHasPointLimit)}',
style: const TextStyle(fontSize: 14), style: const TextStyle(fontSize: 14),
), ),
trailing: Row( trailing: Row(
children: [ children: [
Text('${session.round}'), Text('${session.roundNumber}'),
const SizedBox(width: 3), const SizedBox(width: 3),
const Icon( const Icon(
CupertinoIcons.arrow_2_circlepath_circle_fill), CupertinoIcons.arrow_2_circlepath_circle_fill),

View File

@@ -18,13 +18,12 @@ class ModeSelectionMenu extends StatelessWidget {
child: CupertinoListTile( child: CupertinoListTile(
title: Text('101 Punkte', style: Styles.modeTitle), title: Text('101 Punkte', style: Styles.modeTitle),
subtitle: const Text( subtitle: const Text(
'Es wird solange gespielt, bis einer Spieler die 101 Punkte ' 'Es wird solange gespielt, bis einer Spieler mehr als 100 Punkte erreicht',
'genau erreicht oder überschreitet.',
style: Styles.modeDescription, style: Styles.modeDescription,
maxLines: 3, maxLines: 3,
), ),
onTap: () { onTap: () {
Navigator.pop(context, '101 Punkte'); Navigator.pop(context, true);
}, },
), ),
), ),
@@ -34,12 +33,12 @@ class ModeSelectionMenu extends StatelessWidget {
title: Text('Unbegrenzt', style: theme.modeTitle), title: Text('Unbegrenzt', style: theme.modeTitle),
subtitle: const Text( subtitle: const Text(
'Dem Spiel sind keine Grenzen gesetzt. Es wird so lange ' 'Dem Spiel sind keine Grenzen gesetzt. Es wird so lange '
'gespielt, bis die Spieler keine Lust mehr haben.', 'gespielt, bis Ihr keine Lust mehr habt.',
style: Styles.modeDescription, style: Styles.modeDescription,
maxLines: 3, maxLines: 3,
), ),
onTap: () { onTap: () {
Navigator.pop(context, 'Unbegrenzt'); Navigator.pop(context, false);
}, },
), ),
), ),

View File

@@ -41,17 +41,19 @@ class _RoundViewState extends State<RoundView> {
@override @override
void initState() { void initState() {
print('=== Runde ${widget.roundNumber} geöffnet ==='); print('=== Runde ${widget.roundNumber} geöffnet ===');
if (widget.roundNumber < widget.gameSession.round || if (widget.roundNumber < widget.gameSession.roundNumber ||
widget.gameSession.finished == true) { widget.gameSession.isGameFinished == true) {
print('Die Runde ${widget.roundNumber} wurde bereits gespielt, deshalb ' print(
'werden die alten Punktestaende angezeigt'); 'Diese wurde bereits gespielt, deshalb werden die alten Punktestaende angezeigt');
// If the current round has already been played, the text fields // If the current round has already been played, the text fields
// are filled with the scores from this round // are filled with the scores from this round
for (int i = 0; i < _scoreControllerList.length; i++) { for (int i = 0; i < _scoreControllerList.length; i++) {
_scoreControllerList[i].text = _scoreControllerList[i].text =
gameSession.playerScores[i][widget.roundNumber].toString(); gameSession.roundList[widget.roundNumber - 1].scores[i].toString();
} }
_kamikazePlayerIndex =
gameSession.roundList[widget.roundNumber - 1].kamikazePlayerIndex;
} }
super.initState(); super.initState();
} }
@@ -179,7 +181,7 @@ class _RoundViewState extends State<RoundView> {
backgroundColor: CupertinoColors.secondaryLabel, backgroundColor: CupertinoColors.secondaryLabel,
title: Row(children: [Text(name)]), title: Row(children: [Text(name)]),
subtitle: Text( subtitle: Text(
'${widget.gameSession.playerScores[index][0]}' '${widget.gameSession.playerScores[index]}'
' Punkte'), ' Punkte'),
trailing: Row( trailing: Row(
children: [ children: [
@@ -282,7 +284,7 @@ class _RoundViewState extends State<RoundView> {
onPressed: _areRoundInputsValid() onPressed: _areRoundInputsValid()
? () { ? () {
_finishRound(); _finishRound();
if (widget.gameSession.finished == true) { if (widget.gameSession.isGameFinished == true) {
Navigator.pop(context, widget.gameSession); Navigator.pop(context, widget.gameSession);
} else { } else {
Navigator.pushReplacement( Navigator.pushReplacement(
@@ -343,7 +345,7 @@ class _RoundViewState extends State<RoundView> {
} }
/// Finishes the current round. /// Finishes the current round.
/// Calls the [_calculateScoredPoints()] method to calculate the points for /// It first determines, ifCalls the [_calculateScoredPoints()] method to calculate the points for
/// every player. If the round is the highest round played in this game, /// every player. If the round is the highest round played in this game,
/// it expands the player score lists. At the end it updates the score /// it expands the player score lists. At the end it updates the score
/// array for the game. /// array for the game.
@@ -351,149 +353,30 @@ class _RoundViewState extends State<RoundView> {
print('===================================='); print('====================================');
print('Runde ${widget.roundNumber} beendet'); print('Runde ${widget.roundNumber} beendet');
// The shown round is smaller than the newest round // The shown round is smaller than the newest round
if (widget.gameSession.round < widget.gameSession.playerScores[0].length) { if (widget.roundNumber < widget.gameSession.roundNumber) {
print('Da diese Runde bereits gespielt wurde, werden die alten ' print('Da diese Runde bereits gespielt wurde, werden die alten '
'Punktestaende ueberschrieben'); 'Punktestaende ueberschrieben');
print('Alte Punktestaende:');
print(gameSession.printRoundScores(widget.roundNumber));
} }
_calculateScoredPoints();
widget.gameSession.sumPoints();
if (widget.gameSession.finished == true) {
print('Das Spiel ist beendet');
} else {
if (widget.roundNumber >= widget.gameSession.playerScores[0].length - 1) {
gameSession.expandPlayerScoreLists();
print('Das Punkte-Array wurde erweitert');
}
widget.gameSession.increaseRound();
}
print('Die Punktesummen wurden aktualisiert');
}
/// Checks the scores of the current round and assigns points to the players.
/// There are three possible outcomes of a round:
///
/// **Case 1**<br>
/// One player has Kamikaze. This player receives 0 points. Every other player
/// receives 50 points.
///
/// **Case 2**<br>
/// The player who said CABO has the lowest score. They receive 0 points.
/// Every other player gets their round score.
///
/// **Case 3**<br>
/// The player who said CABO does not have the lowest score.
/// They receive 5 extra points added to their round score.
/// Every player with the lowest score gets 0 points.
/// Every other player gets their round score.
void _calculateScoredPoints() {
print('Spieler: ${gameSession.players}');
// A player has Kamikaze
if (_kamikazePlayerIndex != null) { if (_kamikazePlayerIndex != null) {
print('${widget.gameSession.players[_kamikazePlayerIndex!]} hat Kamikaze ' print('${widget.gameSession.players[_kamikazePlayerIndex!]} hat Kamikaze '
'und bekommt 0 Punkte'); 'und bekommt 0 Punkte');
print('Alle anderen Spieler bekommen 50 Punkte'); print('Alle anderen Spieler bekommen 50 Punkte');
_applyKamikaze(_kamikazePlayerIndex!, widget.gameSession
List.generate(widget.gameSession.players.length, (index) => 0)); .applyKamikaze(widget.roundNumber, _kamikazePlayerIndex!);
} else { } else {
// List of the scores of the current round
List<int> roundScores = []; List<int> roundScores = [];
for (TextEditingController c in _scoreControllerList) { for (TextEditingController c in _scoreControllerList) {
if (c.text.isNotEmpty) roundScores.add(int.parse(c.text)); if (c.text.isNotEmpty) roundScores.add(int.parse(c.text));
} }
widget.gameSession.calculateScoredPoints(
print('Punkte: $roundScores'); widget.roundNumber, roundScores, _caboPlayerIndex);
print('${gameSession.players[_caboPlayerIndex]} hat CABO gesagt');
print('${gameSession.players[_caboPlayerIndex]} hat '
'${roundScores[_caboPlayerIndex]} Punkte');
/// List of the index of the player(s) with the lowest score
List<int> lowestScoreIndex = _getLowestScoreIndex(roundScores);
print('Folgende Spieler haben die niedrigsten Punte:');
for (int i in lowestScoreIndex) {
print('${widget.gameSession.players[i]} (${roundScores[i]} Punkte)');
}
// The player who said CABO is one of the players which have the
// fewest points.
if (lowestScoreIndex.contains(_caboPlayerIndex)) {
print('${widget.gameSession.players[_caboPlayerIndex]} hat CABO gesagt '
'und bekommt 0 Punkte');
print('Alle anderen Spieler bekommen ihre Punkte');
_assignPoints([_caboPlayerIndex], -1, roundScores);
} else {
// A player other than the one who said CABO has the fewest points.
print(
'${widget.gameSession.players[_caboPlayerIndex]} hat CABO gesagt, '
'jedoch nicht die wenigsten Punkte.');
print('Folgende:r Spieler haben die wenigsten Punkte:');
for (int i in lowestScoreIndex) {
print('${widget.gameSession.players[i]}: ${roundScores[i]} Punkte');
}
_assignPoints(lowestScoreIndex, _caboPlayerIndex, roundScores);
}
} }
} widget.gameSession.updatePoints();
if (widget.gameSession.isGameFinished == true) {
/// Returns the index of the player with the lowest score. If there are print('Das Spiel ist beendet');
/// multiple players with the same lowest score, all of them are returned. } else if (widget.roundNumber == widget.gameSession.roundNumber) {
/// [roundScores] is a list of the scores of all players in the current round. widget.gameSession.increaseRound();
List<int> _getLowestScoreIndex(List<int> roundScores) {
int lowestScore = roundScores[0];
List<int> lowestScoreIndex = [0];
for (int i = 1; i < roundScores.length; i++) {
if (roundScores[i] < lowestScore) {
lowestScore = roundScores[i];
lowestScoreIndex = [i];
} else if (roundScores[i] == lowestScore) {
lowestScoreIndex.add(i);
}
} }
return lowestScoreIndex;
}
/// Assigns 50 points to all players except the kamikaze player.
/// [kamikazePlayerIndex] is the index of the kamikaze player.
/// [roundScores] is the list of the scores of all players in the
/// current round.
void _applyKamikaze(int kamikazePlayerIndex, List<int> roundScores) {
for (int i = 0; i < widget.gameSession.players.length; i++) {
if (i != kamikazePlayerIndex) {
roundScores[i] += 50;
}
}
gameSession.addRoundScoresToScoreList(roundScores, widget.roundNumber);
}
/// Assigns points to the players based on the scores of the current round.
/// [winnerIndex] is the index of the player(s) who receive 0 points
/// [loserIndex] is the index of the player who receives 5 extra points
/// [roundScores] is the raw list of the scores of all players in the
/// current round.
void _assignPoints(
List<int> winnnerIndex, int loserIndex, List<int> roundScores) {
print('Folgende Punkte wurden aus der Runde übernommen:');
for (int i = 0; i < roundScores.length; i++) {
print('${widget.gameSession.players[i]}: ${roundScores[i]}');
}
for (int i in winnnerIndex) {
print(
'${widget.gameSession.players[i]} hat gewonnen und bekommt 0 Punkte');
roundScores[i] = 0;
}
if (loserIndex != -1) {
print('${widget.gameSession.players[loserIndex]} bekommt 5 Fehlerpunkte');
roundScores[loserIndex] += 5;
}
print('Aktualisierte Punkte:');
for (int i = 0; i < roundScores.length; i++) {
print('${widget.gameSession.players[i]}: ${roundScores[i]}');
}
gameSession.addRoundScoresToScoreList(roundScores, widget.roundNumber);
} }
@override @override

View File

@@ -2,7 +2,7 @@ name: cabo_counter
description: "Mobile app for the card game Cabo" description: "Mobile app for the card game Cabo"
publish_to: 'none' publish_to: 'none'
version: 0.1.3+60 version: 0.1.3+65
environment: environment:
sdk: ^3.5.4 sdk: ^3.5.4