Construindo um Simulador de Futebol com C#, LINQ e Distribuição de Poisson
Recentemente desenvolvi uma aplicação Console em C# com o objetivo de estudar estatística aplicada ao futebol utilizando a Distribuição de Poisson através da biblioteca Math.NET Numerics.

Embora seja um projeto simples, ele reúne diversos conceitos importantes da linguagem C#, como orientação a objetos, coleções, LINQ, encapsulamento, processamento estatístico e análise de probabilidades.
Objetivo
A proposta do projeto é estimar os placares mais prováveis de uma partida de futebol a partir das médias de gols marcados e sofridos por duas equipes.
O programa recebe:
- Nome do Time 1
- Nome do Time 2
- Média de gols feitos pelo Time 1
- Média de gols sofridos pelo Time 1
- Média de gols feitos pelo Time 2
- Média de gols sofridos pelo Time 2
A partir dessas informações, o sistema calcula uma expectativa de gols para cada equipe e gera todos os placares possíveis entre 0 e 6 gols.
Conceito Estatístico Utilizado
No futebol, um dos modelos mais utilizados para previsão de resultados é a Distribuição de Poisson.
Ela permite estimar a probabilidade de um determinado número de eventos ocorrer dentro de um intervalo conhecido.
No nosso caso:
- Evento = Gol
- Intervalo = Partida de futebol
A distribuição é representada por:
P(X=k)=\frac{\lambda^k e^{-\lambda}}{k!}
Onde:
- λ (lambda) representa a média esperada de gols.
- k representa a quantidade de gols desejada.
- P(X=k) representa a probabilidade daquele número de gols acontecer.
A biblioteca Math.NET já possui essa implementação pronta através do método:
Poisson.PMF(media, quantidade)
Classe XGol
A primeira classe criada foi a XGol.
Ela representa a probabilidade de uma equipe marcar uma quantidade específica de gols.
public class XGol
Cada objeto armazena:
- Nome da equipe
- Quantidade de gols
- Média de gols esperada
- Probabilidade calculada
Exemplo:
Brasil2 golsMédia: 1,80Probabilidade: 26,77%
Ao criar o objeto, a probabilidade é calculada automaticamente.
CalculaProbabilidade();
Essa abordagem centraliza toda a lógica estatística dentro da própria classe.
Classe Placar
A segunda classe representa um placar completo.
public class Placar
Ela recebe dois objetos XGol:
new Placar( new XGol(...), new XGol(...))
Exemplo:
Brasil = 2 golsArgentina = 1 gol
O placar gerado será:
2x1
Probabilidade do Placar
Assumindo independência entre os eventos das duas equipes, a probabilidade do placar é calculada multiplicando as probabilidades individuais.
Probalidade = XGolsTime1.Probabilidade * XGolsTime2.Probabilidade;
Por exemplo:
Brasil marcar 2 gols = 26%Argentina marcar 1 gol = 35%
Logo:
0,26 × 0,35 = 0,091
Resultado:
9,1%
Essa será a probabilidade do placar 2×1.
Determinação Automática do Resultado
A própria classe também determina o vencedor.
Resultado =(XGolsTime1.Quantidade == XGolsTime2.Quantidade)?"Empate":(XGolsTime1.Quantidade > XGolsTime2.Quantidade)?$"{XGolsTime1.Nome} Vence":$"{XGolsTime2.Nome} Vence";
Exemplos:
1x1 = Empate2x1 = Time 1 vence0x3 = Time 2 vence
Aqui temos um ótimo exemplo de utilização do operador ternário em C#.
Cálculo das Médias Esperadas
Antes de calcular as probabilidades, o programa gera uma média esperada para cada equipe.
MediaTime1 =(MediaGolsFeitosTime1 + MediaGolsSofridosTime2) / 2;MediaTime2 =(MediaGolsFeitosTime2 + MediaGolsSofridosTime1) / 2;
A ideia é simples:
- Ataque do Time A
- Defesa do Time B
e
- Ataque do Time B
- Defesa do Time A
A média dos dois valores gera uma expectativa inicial de gols.
Exemplo:
Brasil marca: 2,0Argentina sofre: 1,2
(2,0 + 1,2) / 2=1,6 gols esperados
Geração de Todos os Placares
O sistema utiliza dois laços for.
for (int i = 0; i <= 6; i++){ for (int j = 0; j <= 6; j++) { }}
O primeiro representa os gols do Time 1.
O segundo representa os gols do Time 2.
Isso gera:
0x00x10x2...6x6
Total:
49 combinações
Cada combinação é armazenada em:
List<Placar>
Utilização do LINQ
Depois que todos os placares são gerados, entra em cena um dos recursos mais poderosos do C#.
LINQ
Para encontrar os cinco resultados mais prováveis:
placars.OrderByDescending(x => x.Probalidade).Take(5).ToList();
O código:
- Ordena pela probabilidade.
- Do maior para o menor.
- Seleciona apenas os cinco primeiros.
É uma solução elegante e extremamente legível.
Exemplo de Saída
Supondo:
Brasil:2,0 gols feitos1,0 gol sofridoArgentina:1,5 gols feitos1,2 gol sofrido
O programa pode retornar algo semelhante a:
1x1 11,52%2x1 9,84%1x0 8,93%2x0 7,62%0x1 7,18%
Além disso, todos os 49 placares são exibidos em ordem de probabilidade.
Conceitos de C# Praticados
Este pequeno projeto permitiu trabalhar diversos conceitos importantes:
✅ Classes e Objetos
✅ Construtores
✅ Encapsulamento
✅ Métodos
✅ List
✅ LINQ
✅ Loops aninhados
✅ Operador ternário
✅ Formatação de números
✅ Integração com bibliotecas NuGet
✅ Probabilidade e Estatística
✅ Programação Orientada a Objetos
Próximos Passos
A evolução natural deste projeto é transformá-lo em uma aplicação WinUI 3.
Algumas melhorias possíveis:
- Exibição dos placares em DataGrid
- Ordenação dinâmica
- Filtros por probabilidade
- Gráficos estatísticos
- Comparação entre equipes
- Leitura de dados JSON
- Histórico de partidas
- Ajuste de fatores de ataque e defesa
- Simulações completas de campeonatos
O mais interessante é perceber como um projeto relativamente pequeno consegue unir matemática, estatística, futebol e desenvolvimento de software em um único laboratório de aprendizado.
Projetos como esse mostram que aprender C# não é apenas estudar sintaxe, mas construir soluções capazes de transformar dados em informação útil e apoiar processos de tomada de decisão. ⚽📊💻
#CSharp #DotNet #MathNet #Poisson #Estatistica #Futebol #Programacao #DesenvolvimentoDeSoftware #LINQ #ConsoleApp #WinUI #DataAnalysis #SoftwareEngineering
