[Resolvido] Desafio: jogo com PHP

Iniciado por Agarwaen, 25 de Setembro de 2016, 01:03

tópico anterior - próximo tópico

Agarwaen

Olá a todos!

Eu preciso implementar um simples jogo utilizando PHP e um pouco de HTML que consiste nisso:

  • Um jogo de adivinhação de um número entre 0 e 100 (que vai ser gerado aleatoriamente pelo programa);
  • A cada tentativa do usuário de adivinhar o número deverá ser a ele informado se ele acertou o número, se o número que ele chutou é menor ou maior do que o sorteado e a quantidade de tentativas dele de acertar o número.

Eu consegui implementar o jogo utilizando C e Python (seguem os códigos), no entanto, ao fazê-lo com PHP, por algum motivo o algoritmo está gerando um loop infinito e, ao executar esse loop infinito, o meu navegador simplesmente trava completamente, assim como todo o meu computador, que precisa ter o desligamento forçado.

O jogo em C:


#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <time.h>

void limpa_tela()
{
system("clear");
}

int main(void)
{
setlocale(LC_ALL, "Portuguese");
limpa_tela();
srand(time(NULL));

int x = rand() % 100;
int p = 0;
int t = 0;

do
{
printf("Dê um palpite: \n\n");
scanf("%d", &p);
limpa_tela();

t += 1;

if(p == x)
{
printf("Parabéns, você acertou! Placar: %d\n", t);
}

else
{
if(p > x)
{
printf("Tente algo menor...\n");
}

else
{
printf("Tente algo maior...\n");
}
}
} while(p != x);

printf("Fim do jogo\n\n");

return 0;

}


O jogo em Python:


from random import randint
import os

os.system("clear")

x = int(randint(0, 100))
p = 0;
t = 0;

while p != x:

p = int(input("Dê um palpite de 1 a 100:\n\n"))
os.system("clear")

t += 1

if p == x:

print("Parabéns, você acertou! Placar: %i" % t)

elif p < x:

print("Chute um valor maior...")

else:

print("Chute um valor menor...")

print("Fim do jogo")


O que eu consegui fazer em PHP até agora foi isso (que está travando o meu computador):


<?php		$p = 0;		$t = 0;		$x = rand(0, 100);					do		{			echo			"				<form action = '' method = 'post'>					<input type = 'number' name = 'p' />					<input type = 'submit' />				</form>							";							$p = $_POST["p"];			$t += 1;							if($p == $x)			{				echo "<br />Parabéns, você acertou! Placar $t";			}							else			{				if($p > $x)				{					echo "Tente algo menor...";				}									else				{					echo "Tente algo maior...";				}			} 		} while($p != $x);					echo "<br />Fim do jogo";?>



Obs: os programas que eu fiz em C e em Python não informam o placar (número de tentativas) a cada tentativa, isso só é feito ao final, quando o usuário já acertou o número.

Obrigado, desde já.

irtigor

#1
Faz uma cara que não mexo com isso mas não parece certo mesmo. Quando você cria um form sem um action ele vai se executar e no inicio você atribui 0 pra p e um número aleatório  pra x.  Eu usaria session ou um cookie e nada de loop.

------
Pra ficar tudo em uma página só você tem que atribuir os valores pra x e p só se o usuário já não enviou algum dado (ou seja ele acabou de abrir a pagina) e verificar o valor envidado quando a variável no post existir, então tem que cercar as coisas com ifs (if (!empty($_POST)) então dá um valor pra p e x... if (isset($_POST['p']) então olha se é o valor correto).
------
O loop já tá implícito porque toda vez que o usuário clica no submit o script é executado novamente.

Agarwaen

Cara, serei sincero: não consegui entender muita coisa do que tu explicou. Eu não entendo nada de sessões (ainda não cheguei nessa parte no meu cronograma de aulas), até tentei aprender um pouco pra tentar utilizar no programa, mas não mudou muita coisa. Retirei o laço do ... while, como tu recomendou, e tentei fazer novamente com o que eu consegui entender do que tu explicou. Vejamos:


<html>
<head>
<title>Jogo</title>
</head>
<body>
<form action = "" method = "post">
<input type = "number" name = "p" />
<input type = "submit" name = "botao" />
</form>

<?php			if(isset($_POST["botao"]))			{				srand(time(NULL));							$x = rand(0, 100);				$p = $_POST["p"];				$t = $t + 1;								if($p != "")				{					if($p == $x)					{						echo "Parabéns, você acertou! Placar: $t";						}										else					{						if($p > $x)						{							echo "Tente algo menor... Placar: $t";						}												else						{							echo "Tente algo maior... Placar: $t";						}						}				}								else				{					echo "Digite um valor";				}								//echo $x;			}						else			{											}					?>

</body>
</html>


O problema agora é (tu vai conseguir percebê-lo removendo o comando para transformar uma linha de código em uma linha de comentários em 'echo $x;'): o script está gerando um número aleatório sempre que o botão é acionado, enquanto deveria fazê-lo somente uma vez. Tentei resolver o problema semeando o gerador de números aleatórios com time(NULL) (assim como fiz no programa em C) e gerando o número aleatoriamente antes da validação do botão submit, mas, aparentemente, o buraco é mais fundo. Espero que tenha compreendido a minha ignorância o meu problema e que possa me ajudar, afinal preciso passar de ano concluir isso  ;D 

irtigor

Isso é o esperado, toda vez que você clica no botão o script (essa página já que não tem um action definido) é executado novamente, isso acontecia na primeira versão também. Então o que você tem que fazer é gerar o número somente se essa página acabou de ser aberta (é um if a parte) e depois em outro if ver se recebeu algo por post e comparar. Uma forma de ter esses dados entre as requisições de paginas é usando a variável global de sessão. Então em um if você verifica se uma sessão já existe, se não existe você cria e coloca o valor do número aleatório lá, ai dentro de outro if (quando receber algo por post) você compara o valor com o que tá na sessão.

Dá pra fazer mais ou menos do jeito que tinha feito antes, se largar o navegador e usar o php do terminal.

Agarwaen

Obrigado cara, consegui entender.

A quem ainda interessar:
Encontrei um exemplo semelhante resolvido em: http://www.sergiotoledo.com.br/tutoriais/programacao-php/jogos-php

O meu desafio agora é mostrar o placar a cada tentativa do usuário de acertar o número, e não somente ao final do jogo, tal como acontece neste programa em python:


from random import randint
import os

os.system("clear")

x = int(randint(1, 100))

#print(x)

p = 0;
t = 0;

while p != x:

p = int(input("Dê um palpite de 1 a 100:\n\n"))
os.system("clear")

t += 1

if p == x:

print("Parabéns, você acertou! Placar: %i" % t)

elif p < x:

print("Chute um valor maior... Placar: %i" % t)

else:

print("Chute um valor menor... Placar: %i" % t)

print("Fim do jogo")


Já tentei de diversas formas e ainda não consegui.

Aqui está o código completo do jogo semi finalizado:


<html>
<head>
<title>Jogo</title>
</head>
<body>

<?php					session_start(); // Inicia a sessão para salvar o número gerado pelo algoritmo						echo	                "			<form action = '' method = 'post'>				<label for = 'p'>Adivinhe o número sorteado de 0 a 100! Dê o seu palpite:</label>				<input type = 'text' name = 'p' />				<input type = 'submit' value = 'Continuarar' />			</form>						"; // Formulário					if(!isset($_SESSION["palpite"])) // Iniciando a contagem de tentativas e gerando o número			{				$_SESSION["palpite"] = 1;				$_SESSION["x"] = rand(0, 100);			}						if(isset($_POST["p"]) && $_POST["p"] != "A") // Caso o usuário tenha dado um palpite			{				$p = $_POST["p"]; // Recebendo o palpite e armazenando-o em uma variável								if($_SESSION["x"] == $p) // Caso o usuário acerte o número				{					echo "Parabéns, você acertou! O número era <b>" . $_SESSION['x'] . "</b><br />Você tentou <b>" .  $_SESSION['palpite'] . "</b> vezes<br />Para jogar novamente digite A";				}								else // Caso o usuário não acerte o número				{					if($p > $_SESSION["x"]) // Caso o palpite do usuário seja maior do que o número correto					{						echo "Tente um número menor...";					}										else					{						echo "Tente um número maior..."; // Caso o palpite do usuário seja menor do que o número correto					}					$_SESSION["palpite"] ++; // Incrementando o palpite (para poder realizar a contagem)				}			}						else // Caso o usuário tenha finalizado o jogo e queira começar novamente			{				if(isset($_POST["p"]) and $_POST["p"] == "A")				{					unset($_SESSION["x"]);					session_destroy(); // Destrói a variável da sessão que armazena o número sorteado (para recomeçar)				}			}				?>


</body>
</html>



A quem interessar, souber e quiser me ajudar, obrigado.

irtigor

#5
Você já tá contando, falta mostrar. Se é pra aparecer a cada tentativa ele não pode estar dentro do if que só alcançado quando o usuário acerta.

-----
Outra coisa, o correto é que o session_start() apareça antes de qualquer output pro navegador, do jeito que tá no seu você pode ter problemas.

Agarwaen

Obrigado mais uma vez, cara  ;)

Finalizei tudo:


<html>
<head>
<title>O jogo</title>
</head>
<body>

<?php					session_start(); // Inicia a sessão para salvar o número gerado pelo algoritmo						echo			"			<form action = '' method = 'post'>				<label for = 'p'><h3 align = 'center'>Adivinhe o número sorteado de 0 a 100!</h3><br /><p align = 'center'>Dê o seu palpite:</p></label>								<p align = 'center'>					<input type = 'text' name = 'p' />					<input type = 'submit' value = 'Continuar' />				</p>			</form>						"; // Formulário					if(!isset($_SESSION["palpite"])) // Iniciando a contagem de tentativas e gerando o número			{				$_SESSION["palpite"] = 1;				$_SESSION["x"] = rand(0, 100);			}						if(isset($_POST["p"]) && $_POST["p"] != "A") // Caso o usuário tenha dado um palpite			{				$p = $_POST["p"]; // Recebendo o palpite e armazenando-o em uma variável								if($_SESSION["x"] == $p) // Caso o usuário acerte o número				{					echo "<br /><p align = 'center'>Parabéns, você acertou! O número era <b>" . $_SESSION['x'] . "</b><br />Você tentou <b>" .  $_SESSION['palpite'] . "</b> vezes<br />Para jogar novamente digite <b>A</b></p>";					}								else // Caso o usuário não acerte o número				{					if($p > $_SESSION["x"]) // Caso o palpite do usuário seja maior do que o número correto					{						echo "<br /><p align = 'center'>Tente um número menor...</p>";						echo "<h2 align = \"center\">Placar: <font color = \"blue\" size = \"30\">" . $_SESSION['palpite'] . "</font></h2>";					}										else // Caso o palpite do usuário seja menor do que o número correto					{						echo "<br /><p align = 'center'>Tente um número maior...</p>";						echo "<h2 align = \"center\">Placar: <font color = \"blue\" size = \"30\">" . $_SESSION['palpite'] . "</font></h2>";					}										$_SESSION["palpite"] ++; // Incrementando o palpite (para poder realizar a contagem)				}			}						else // Caso o usuário tenha finalizado o jogo e queira começar novamente			{				if(isset($_POST["p"]) and $_POST["p"] == "A")				{					unset($_SESSION["x"]);					session_destroy(); // Destrói a variável da sessão que armazena o número sorteado (para recomeçar)				}			}


Só não compreendi o que tu disse sobre a função session_start() no meu código, porque nele a primeira coisa que é feita é a chamada dessa função. Você quis dizer que eu devo chamá-la antes mesmo das primieras tags HTML?


<html>
<head>
<title>Slide 5 - Questão 12</title>
</head>
<body>


Enfim, obrigado.  :)

irtigor

Isso o ideal é que ele seja a primeira coisa, então ficaria antes do cabeçalho html.