Aplicacions amb Flutter, Dart i Flame

Tutorial Flutter Flame Projectes   Recursos CITCEA
Exemples Dart Dades pràctiques     Inici

Afegim l'opció d'un sol jugador

Ara modificarem el programa perquè també es pugui jugar contra l'aplicació. En aquesta versió, l'aplicació posarà la seva fitxa en qualsevol posició lliure, escollida aleatòriament. La persona serà sempre el jugador 1 i el jugador 2 serà automàtic.

Crearem una variable per emmagatzemar el nombre de jugadors de la partida. Aquesta variable valdrà 0 fins que no s'hagi triat una de les dues opcions. Modificarem el botó de la versió anterior i en posarem un altre similar; aquests serviran per triar el mode de joc. Atès que els dos botons fan coses molt similars, hem creat la funció inici, per no haver-ho de repetir dos cops. Mentre duri la partida, el botó del mode triat es mantindrà en color; però no farà res.

La funció tirAuto és la que posarà les fitxes de manera automàtica. Comptarà quantes caselles buides hi ha, generarà un nombre aleatori i posarà la fitxa en la posició que correspongui.

pant_principal.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:tres_linia/components/boto.dart';
import 'package:tres_linia/components/casella.dart';
import 'package:tres_linia/components/fitxa.dart';
import 'package:tres_linia/core/estils.dart';
class PantPral extends StatefulWidget {
  const PantPral({super.key});

  @override
  State<PantPral> createState() => _PantPralState();
}

class _PantPralState extends State<PantPral> {
  List<List<int>> estatCaselles = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
  int numJugadors = 0;  // Cal esperar que es premi un botó
  int jugadorActual = 0;  // No hi ha jugador fins que es prem un botó
  int quiGuanya = 0;  // De moment, no hi ha guanyador
  String notificacio = "Tira:";
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          height: 20,
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Boto(textBoto: "1 jugador", enUs: numJugadors != 2, accio: () {
              setState(() {
                inici(1);
              });
            },),
            SizedBox(
              width: 20,
            ),
            Boto(textBoto: "2 jugadors", enUs: numJugadors != 1, accio: () {
              setState(() {
                inici(2);
              });
            },)
          ],
        ),
        SizedBox(
          height: 20,
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Text(
              notificacio,
              style: Estils.estilTextInfo
            ),
            SizedBox(
              width: 20,
            ),
            Fitxa(estatAct: jugadorActual, mida: 25)
          ],
        ),
        for(int i = 0; i < 3; i++) filera(i),
        Expanded(child: Text(" "))
      ],
    );
  }

  Row filera(int pY) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      crossAxisAlignment: CrossAxisAlignment.end,
      children: [
        for(int i = 0; i < 3; i++) Casella(posX: i, posY: pY, estAct: estatCaselles[pY][i],
          posaFitxa: () {
            setState(() {
              // L'acció de picar la casella només es fa si la partida està en curs
              if((quiGuanya == 0) && (numJugadors > 0)){
                if(estatCaselles[pY][i] == 0) {
                  estatCaselles[pY][i] = jugadorActual;
                  if(jugadorActual == 1) {
                      jugadorActual = 2;
                  } else {
                    jugadorActual = 1;
                  }
                }
                // Després de cada tirada, mirem si hi ha guanyador
                quiGuanya = guanyador();
                // Si només hi ha un jugador, l'altre es tira automàticament
                if((quiGuanya == 0) && (numJugadors == 1)){
                  tirAuto(jugadorActual);
                  if(jugadorActual == 1) {
                      jugadorActual = 2;
                  } else {
                    jugadorActual = 1;
                  }
                  quiGuanya = guanyador();
                }
              }
            });
          },
        ),
      ],
    );
  }

  void inici(int numJug){
    if(numJugadors == 0){
      numJugadors = numJug;
      estatCaselles = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
      jugadorActual = 1;  // Comença el jugador 1
      quiGuanya = 0;  // De moment, no hi ha guanyador
      notificacio = "Tira:";
    }
  }

  void tirAuto(int jug){
    int opcions = comptaCaselles(0);
    int pos = Random().nextInt(opcions);
    int posAct = 0;
    for(int i = 0; i < 3; i++){
      for(int j = 0; j < 3; j++){
        if(estatCaselles[i][j] == 0){
          if(posAct == pos){
            estatCaselles[i][j] = jug;
          }
          posAct++;
        }
      }
    }
  }

  int comptaCaselles(int val){
    // Compta les caselles que tenen un determinat valor
    int total = 0;
    for(int i = 0; i < 3; i++){
      for(int j = 0; j < 3; j++){
        if(estatCaselles[i][j] == val){
          total++;
        }
      }
    }
    return total;
  }

  int guanyador(){
    int guanya = 0;
    // Atès que només s'afegeix una fitxa cada cop, només hi pot haver un guanyador
    // Primer mirem les diagonals
    if((estatCaselles[0][0] != 0) && (estatCaselles[0][0] == estatCaselles[1][1]) 
      && (estatCaselles[0][0] == estatCaselles[2][2])){
      guanya = estatCaselles[0][0];
    }
    if((estatCaselles[0][2] != 0) && (estatCaselles[0][2] == estatCaselles[1][1]) 
      && (estatCaselles[0][2] == estatCaselles[2][0])){
      guanya = estatCaselles[0][2];
    }
    // Mirem fileres i columnes
    for(int i = 0; i < 3; i++){
      if((estatCaselles[i][0] != 0) && (estatCaselles[i][0] == estatCaselles[i][1]) 
        && (estatCaselles[i][0] == estatCaselles[i][2])){
        guanya = estatCaselles[i][0];
      }
    }
    for(int i = 0; i < 3; i++){
      if((estatCaselles[0][i] != 0) && (estatCaselles[0][i] == estatCaselles[1][i]) 
        && (estatCaselles[0][i] == estatCaselles[2][i])){
        guanya = estatCaselles[0][i];
      }
    }
    // Si no hi ha guanyador, mirem si el taulell ja és ple
    // Si ho és, hi ha empat
    if((guanya == 0) && (comptaCaselles(0) == 0)){
      guanya = 3;
    }
    // S'acaba la partida si hi ha guanyador o no hi ha caselles
    // Es posa com a jugador al guanyador, per mostrar-lo
    // En cas d'empat, es deixa buit
    if(guanya > 0){
      numJugadors = 0;
      if(guanya == 3){
        notificacio = "Empat!";
        jugadorActual = 0;
      } else {
        notificacio = "Guanya:";
        jugadorActual = guanya;
      }
    }
    return guanya;
  }
}

Si el sistema automàtic fa una tirada aleatòria, és fàcil guanyar-lo. En la propera versió farem servir un algorisme que intenta guanyar.

 

 

 

 

 

 

 

 

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.