Gerando dezenas para jogos em PHP

Galera, estou tentando criar um programinha em PHP que gere numeros para jogos de loteria como Mega Sena, Quina etc. Criei o seguinte código:

<?php
$Servidor = "localhost";
$Banco = "megasena";
$Usuario = "root";
$Senha = "";

if($_POST)
$Numjogos = $_POST["jogos"];
$Qtydezenas = $_POST["dezenas"];
$Valormin = $_POST["de"];
$Valormax = $_POST["ate"];
$tmp=[];
$arr = [];

//* for que gera combinações conforme escolhido no campo NumerodeJogos
  
                for($j=0; $j<$Numjogos;$j++){
                  
               echo "Combinação #" . ($j+1) . "{";
        
   //  for que gera os quantas dezenas conforme campo Quantidade //
     
                             for($k=0; $k<$Qtydezenas; $k++){
               
     //* o while se repete enquanto o numero gerado for repetido//
        
                             while(true){
            
            //gera numero aleatorio entre Valormin e Valormax digitados nos campos
         
                   $tmp = str_pad(rand($Valormin, $Valormax), 2, '0',STR_PAD_LEFT);
                         // verificar se a sequencia gerada ja existe no array $arr
                                   if (!array_search(($tmp), $arr)) { 
            	                       array_push($arr, ($tmp));
                         //sai do laço
                break;
            }
        }
        //exibe o numero gerado
      // echo " Dezena :" .is_array($tmp);
  
       var_dump($tmp);
            
    }
  
}    

try{

    $Conn = new PDO("mysql:host=$Servidor;dbname=$Banco", $Usuario, $Senha);
    $sql = "SELECT * FROM sorteio";
    $stmt = $Conn->query($sql);
    $resultado = $stmt->fetchAll();
   // echo "<pre>";
  //  print_r($resultado);

}catch(PDOException $erro){
    echo "Não foi possível conectar ao Banco de Dados: " . $erro->GetMessage();
}
?>

<html lang="en">
<head>
   <title>teste</title>
</head>
<body>

<form method="POST"> 
Numero de Jogos: <input type="text" size="10" name="jogos"> <br>
 Quantidade de Dezenas em cada jogo: <input type="text" size="10" name="dezenas"> <br>
 Iniciando em: <input type="text" size="5" name="de"> indo até:<input type="text" size="5" name="ate"> <br><br><br>
<input type="submit" name="BTEnvia" value="Enviar">  <input type="reset" name="BTApaga" value="Apagar">
       
<?php

?>
    
</body>
</html>

Bem, quando executo e dou um var_dump na variavel $tmp vejo que o programa gerou as cobinações certinho, conforme escolhido nos campos do formulário. Mas quando dou um eco na mesma variavel, o resultado não vem correto. Aparece sempre Dezena :string(2) repetido antes do que o var_dump ta imprimindo.
Eu que gostaria que cada combinação gerada fosse mostrada em uma linha abaixo da outra.
Outra coisa que eu gostaria de implementar é o seguinte: primeiro ordenar as dezenas geradas da menor para maior. Depois jogar no banco de dados que criei com os campos: Dez1, Dez2, Dez3, Dez4, Dez5 e Dez6, mas só poderia armazenar se a sequencia ainda nao existisse.
Alguem poderia me ajudar ??

Depende, como vc guarda esses valores no banco? É um campo varchar contendo as dezenas, tipo 1,5,10,25,43,51? Ou tem uma coluna para cada dezena?

Enfim, vou assumir que é o primeiro caso, mas aí se não for, vc adapta.

Para gerar números aleatórios sem repetição, eu já respondi aqui. Não precisa fazer um loop e toda hora verificar se o número já existe. Basta criar um array contendo todos os números, embaralhá-lo e pegar os 6 primeiros.

Só precisa de um loop para ficar gerando um novo jogo até que ele não esteja no array de jogos. Ficaria assim:

$Numjogos = $_POST["jogos"];
$Qtydezenas = $_POST["dezenas"];
$Valormin = $_POST["de"];
$Valormax = $_POST["ate"];
$jogos = [];

// array contendo todos os números, formatados com o zero à esquerda
$numeros = array_map(function($n) { return sprintf("%02d", $n); }, range($Valormin, $Valormax));

for($i = 1; $i <= $Numjogos; $i++) {
    echo "Combinação #$i: ";
    while (true) {
        // embaralha
        shuffle($numeros);
        // pega os 6 primeiros e ordena
        $sorteio = array_slice($numeros, 0, $Qtydezenas);
        sort($sorteio);
        // se não é jogo repetido, adiciona
        if (! in_array($sorteio, $jogos)) {
            $jogos[] = $sorteio;
            echo implode(', ', $sorteio). "\n";
            break;
        }
    }
}

// para verificar no banco, converta cada jogo para o formato usado
// abaixo estou assumindo que os valores ficam em uma única string, separados por vírgula (ex: "02,08,12,45,47,55")
foreach ($jogos as $jogo) {
    $formato_para_salvar_no_banco = implode(',', $jogo);
    // verifica se já existe, salva no banco, etc
}
2 curtidas

Perdoe-me a ignorância mas ainda fiquei confuso.
Ponto 1 - Meu banco de dados tem a tabela sorteio que tem os seguintes campos:
Cod_jogo (corresponde ao numero de cada sorteio e é auto incremento), Dez_1, Dez_2, Dez_3, Dez_4, Dez_5 e Dez_6. Assim sendo eu gostaria de, após serem geradas as dezenas, embaralhadas e escolhidas as 6, que verificasse no Banco de dados se aquela sequencia em especifico ja existe. Se existisse, o sistema geraria e salvaria. Depois disso imprimiria todas as combinações geradas na tela.
Mas essa parte com banco eu realmente nao sei fazer. Nem mesmo em que parte do código encaixa-la.

As colunas Dez_1, Dez_2, Dez_3, Dez_4, Dez_5 e Dez_6 estão ordenadas? Por exemplo, se os números forem 10, 12, 23, 34, 40 e 56, é garantido que Dez_1=10, Dez_2=12, Dez_3=23, Dez_4=34, Dez_5=40 e Dez_6=56?

Se for, basta fazer queries no banco verificando se já existe, e só inserir um novo caso não exista. Não uso PDO com frequência, mas seria algo assim:

// verifica se o jogo já existe no banco
function ja_existe($jogo, $stmt) {
    $stmt->execute($jogo);
    return $stmt->fetchColumn() > 0;
}

$Numjogos = $_POST["jogos"];
$Qtydezenas = $_POST["dezenas"];
$Valormin = $_POST["de"];
$Valormax = $_POST["ate"];
$jogos = [];
$numeros = array_map(function($n) { return sprintf("%02d", $n); }, range($Valormin, $Valormax));

$Conn = // criar conexão
$stmt = $Conn->prepare('select count(*) from NomeDaTabela where Dez_1=? AND Dez_2=? AND Dez_3=? AND Dez_4=? AND Dez_5=? AND Dez_6=?');
for ($i = 1; $i <= $Numjogos; $i++) {
    while (true) {
        // embaralha
        shuffle($numeros);
        // pega os 6 primeiros e ordena
        $sorteio = array_slice($numeros, 0, $Qtydezenas);
        sort($sorteio);
        // se não é jogo repetido, adiciona
        if (! ja_existe($sorteio, $Conn)) {
            $jogos[] = $sorteio;
            break;
        }
    }
}

Não. Nao estao ordenadas. Como existe o recurso de ordenar ainda enquanto array, sugerido por voce, pensei nao ser necessário

Aí complica, né. Eu sugiro que tente atualizar para deixá-las ordenadas, pois aí fica mais fácil verificar se um jogo já existe.

Claro que também dá para fazer um select que traz as colunas, aí vc coloca-as em um array e ordena, e depois compara com o que foi gerado, mas é mais trabalhoso (o ideal seria deixar ordenado no banco, pois aí dá pra fazer somente com count como eu fiz acima).

Vou tentar. Muito obrigado
obs: se não conseguir te falo
Valeu

Nessa função que voce criou voce declara dois parametros:

um deles é $jogo, correto ? Só não entendi bem o que jogo está recebendo e de onde, pois não o vi em outra parte do código.

Ops, o código deveria ser:

// verifica se o jogo já existe no banco
function ja_existe($jogo, $stmt) {
    $stmt->execute($jogo);
    return $stmt->fetchColumn() > 0;
}

$Numjogos = $_POST["jogos"];
$Qtydezenas = $_POST["dezenas"];
$Valormin = $_POST["de"];
$Valormax = $_POST["ate"];
$jogos = [];
$numeros = array_map(function($n) { return sprintf("%02d", $n); }, range($Valormin, $Valormax));

$Conn = // criar conexão
$stmt = $Conn->prepare('select count(*) from NomeDaTabela where Dez_1=? AND Dez_2=? AND Dez_3=? AND Dez_4=? AND Dez_5=? AND Dez_6=?');
for ($i = 1; $i <= $Numjogos; $i++) {
    while (true) {
        // embaralha
        shuffle($numeros);
        // pega os 6 primeiros e ordena
        $sorteio = array_slice($numeros, 0, $Qtydezenas);
        sort($sorteio);
        // se não é jogo repetido, adiciona
        if (! ja_existe($sorteio, $Conn)) {
            $jogos[] = $sorteio;
            break;
        }
    }
}

Antes estava if (! ja_existe($jogo, $Conn)) {, corrigi para if (! ja_existe($sorteio, $Conn)) { - já corrigi acima também

Cara, vou precisar de sua ajuda. Poderia me passar um email ou whatsapp. Nem sei se isso é normal mas nao estou conseguindo

Coloquei o código completo e coloquei a parte da conexão que faltava. Quando atualizei a pagina recebi o seguinte erro:

Notice : Undefined index: jogos in C:\xampp\htdocs\Mega\sorteia.php on line 13

Notice : Undefined index: dezenas in C:\xampp\htdocs\Mega\sorteia.php on line 14

Notice : Undefined index: de in C:\xampp\htdocs\Mega\sorteia.php on line 15

Notice : Undefined index: ate in C:\xampp\htdocs\Mega\sorteia.php on line 16

Veja o meu código inteiro,

<?php

$Servidor = "localhost";
$Banco = "megasena";
$Usuario = "root";
$Senha = "";

function ja_existe($jogo, $stmt) {
    $stmt->execute($jogo);
    return $stmt->fetchColumn() > 0;
}

$Numjogos = $_POST["jogos"];
$Qtydezenas = $_POST["dezenas"];
$Valormin = $_POST["de"];
$Valormax = $_POST["ate"];
$jogos = [];
$numeros = array_map(function($n) { return sprintf("%02d", $n); }, range($Valormin, $Valormax));

try{

    $Conn = new PDO("mysql:host=$Servidor;dbname=$Banco", $Usuario, $Senha);
    $sql = "SELECT * FROM sorteio";
    $statmt = $Conn->query($sql);
    $resultado = $statmt->fetchAll();
   // echo "<pre>";
  //  print_r($resultado);


}catch(PDOException $erro){
    echo "Não foi possível conectar ao Banco de Dados: " . $erro->GetMessage();

}


$stmt = $Conn->prepare('select count(*) from sorteio where Dez_1=? AND Dez_2=? AND Dez_3=? AND Dez_4=? AND Dez_5=? AND Dez_6=?');
for ($i = 1; $i <= $Numjogos; $i++) {
    while (true) {
        // embaralha
        shuffle($numeros);
        // pega os 6 primeiros e ordena
        $sorteio = array_slice($numeros, 0, $Qtydezenas);
        sort($sorteio);
        // se não é jogo repetido, adiciona
        if (! ja_existe($sorteio, $Conn)) {
            $jogos[] = $sorteio;
            break;
        }
    }
}

   

    ?>

<html lang="en">
<head>
<title>Sorteia</title>
</head>
<body>

<form method="POST"> 

Numero de Jogos: <input type="text" size="10" name="jogos"> <br>
 
Quantidade de Dezenas em cada jogo: <input type="text" size="10" name="dezenas"> <br>
 
Iniciando em: <input type="text" size="5" name="de"> indo até:<input type="text" size="5" name="ate"> <br><br><br>
<input type="submit" name="BTEnvia" value="Enviar">  <input type="reset" name="BTApaga" value="Apagar">

</body>
</html>

Na verdade acho que deveria ser if (! ja_existe($sorteio, $stmt)) - vc passa a prepared query, e não a conexão.

Mas como eu já disse antes, isso só funcionaria se as dezenas estivessem ordenadas no banco. Se não estiverem, aí fica mais complicado: precisaria consultar todos os jogos, e para cada um criar um array com as dezenas, ordenar e comparar com o $sorteio criado.

É como se ele não tivesse reconhecendo os campos do formulario. Não entendi

Na primeira vez que carrega a página, não vai ter nada preenchido, então não vai ter os campos.

Deveria ter algo como:

if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
    // código que gera os jogos
}

Coloquei o IF para verificar se havia ou não algo nos campos.
IF($_POST)
$Numjogos = $_POST[“jogos”];
$Qtydezenas = $_POST[“dezenas”];
$Valormin = $_POST[“de”];
$Valormax = $_POST[“ate”];
$jogos = [];
$numeros = array_map(function($n) { return sprintf(“%02d”, $n); }, range($Valormin, $Valormax));

Depois tentei preenchendo os campos e pressionei enviar e recebi o seguinte erro:

Fatal error : Uncaught Error: Call to undefined method PDO::execute() in C:\xampp\htdocs\Mega\sorteia.php:17 Stack trace: #0 C:\xampp\htdocs\Mega\sorteia.php(48): ja_existe(Array, Object(PDO)) #1 {main} thrown in C:\xampp\htdocs\Mega\sorteia.php on line 17

16 function ja_existe($jogo, $stmt) {
17 $stmt->execute($jogo); ------ > Ta dando erro aqui
18 return $stmt->fetchColumn() > 0;
}

Fiz um teste rápido aqui e funcionou:

// verifica se o jogo já existe no banco
function ja_existe($jogo, $stmt) {
    $stmt->execute($jogo);
    return $stmt->fetchColumn() > 0;
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $Numjogos = $_POST["jogos"];
    $Qtydezenas = $_POST["dezenas"];
    $Valormin = $_POST["de"];
    $Valormax = $_POST["ate"];
    $jogos = [];
    $numeros = array_map(function($n) { return sprintf("%02d", $n); }, range($Valormin, $Valormax));

    $Conn = new PDO("mysql:host, etc...");
    $stmt = $Conn->prepare('select count(*) from sorteio where Dez_1=? AND Dez_2=? AND Dez_3=? AND Dez_4=? AND Dez_5=? AND Dez_6=?');
    for ($i = 1; $i <= $Numjogos; $i++) {
        while (true) {
            shuffle($numeros);
            $sorteio = array_slice($numeros, 0, $Qtydezenas);
            sort($sorteio);
            // se não é jogo repetido, adiciona
            if (! ja_existe($sorteio, $stmt)) {
                $jogos[] = $sorteio;
                break;
            }
        }
    }

    foreach ($jogos as $jogo) {
        // aqui vc pode imprimir os jogos, inserir no banco, etc
        echo implode(', ', $jogo). "<br>\n";
    }
}

Mas como eu já disse, só vai funcionar se as colunas Dez_1, Dez_2, etc estiverem ordenadas. Porque eu comparo o primeiro elemento do array $sorteio com a coluna Dez_1, o segundo elemento com Dez_2 e assim por diante (por isso que eu ordeno o array).

Mas se as colunas não estiverem ordenadas no banco, aí tem que mudar a estratégia: precisaria fazer um SELECT de todos os jogos, e para cada um, jogar as colunas em um array, ordená-lo e comparar com $sorteio. Bem mais demorado e trabalhoso.


Agora, mudando de assunto, se vc está usando MySQL, pra que usar PDO?

Existe esse “mito da troca do banco de dados” (que é uma das justificativas mais comuns para escolherem PDO), mas na prática isso é algo que acontece tão pouco que acaba caindo no princípio YAGNI.

Outra desvantagem é que o PDO só simula prepared statements, que é algo que eu uso no código acima. A ideia é não recriar a query a cada iteração do for, por isso eu a preparo antes, fazendo com que ela seja reaproveitada a cada execução. Nativamente isso é feito do lado do servidor do banco, mas o PDO elimina este ganho por apenas simular a preparação.

Enfim, por que não usar as funções do MySQL diretamente? Vc elimina o overhead do PDO (já que a suposta “vantagem” de mudar de banco no futuro é algo que ocorre menos do que as pessoas pensam) e ainda ganha a vantagem do prepared statement (que é reaproveitar o trabalho do query planner em operações repetitivas).

// verifica se o jogo já existe no banco
function ja_existe($jogo, $stmt) {
    $stmt->bind_param('iiiiii', ...$jogo);
    $stmt->execute();
    $stmt->bind_result($count);
    $stmt->fetch();
    return $count > 0;
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $Numjogos = $_POST["jogos"];
    $Qtydezenas = $_POST["dezenas"];
    $Valormin = $_POST["de"];
    $Valormax = $_POST["ate"];
    $jogos = [];

    $numeros = array_map(function($n) { return sprintf("%02d", $n); }, range($Valormin, $Valormax));

    $Conn = new mysqli('host', 'usuario', 'senha', 'nome do banco');
    $stmt = $Conn->prepare('select count(*) from sorteio where Dez_1=? AND Dez_2=? AND Dez_3=? AND Dez_4=? AND Dez_5=? AND Dez_6=?');
    for ($i = 1; $i <= $Numjogos; $i++) {
        while (true) {
            shuffle($numeros);
            $sorteio = array_slice($numeros, 0, $Qtydezenas);
            sort($sorteio);
            // se não é jogo repetido, adiciona
            if (! ja_existe($sorteio, $stmt)) {
                $jogos[] = $sorteio;
                break;
            }
        }
    }

    foreach ($jogos as $jogo) {
        // aqui vc pode imprimir os jogos, inserir no banco, etc
        echo implode(', ', $jogo). "<br>\n";
    }
}

Lembrando que usei as funções mysqli (com esse “i” no final). Também existem as funções mysql (sem o “i”), que estão obsoletas, então atenção aí :slight_smile:

Mais sobre PDO vs MySQLi em:

Amigo, deu certo aqui. Vou dar uma estudada no código e tentar compreender algumas coisas que ainda não conhecia. Muito obrigado.
Estou batendo cabeça para fazer o INSERT aqui. Vai da certo

Me explica uma coisa,
$stmt = $Conn->prepare(‘select count(*) from sorteio where Dez_1=? AND Dez_2=? AND Dez_3=? AND Dez_4=? AND Dez_5=? AND Dez_6=?’);

Aqui percebi que a clausula WHERE recebe um parametro representado por uma interrogação. Estava lendo que geralmente essa exclamação será substituida em outro ponto do código pela variavel que sera procurada no banco. Nesse codigo aqui nao vi.
Voce pode me explicar ?

Outra coisa que estou tentando entender é que testei a conexão, mudando o nome do BD ou da tabela e o sistema deu erro de conexão, porem, a tabela tem os campos dez1, dez2 etc, e nao Dez_1, Dez_2 e por em diante. Porque nao dá erro ?