Jump to content

Recommended Posts

Posted (edited)

Boa tarde pessoal, é meu primeiro post, estou começando na programação, no segundo ano de faculdade, porém nunca tive contato com programação, e tenho encontrado muita dificuldade, estamos no fechamento do semestre o professor passou-nos um trabalho com o código de um jogo da velha ja esta pronto, é para nós fatorarmos, diminuir o código, são 9 botões do tipo TButton cada um deles recebe o seguinte código:

NumeroVezes:=NumeroVezes + 1;
Button1,Caption:= 'X';
Verificar;

Como é o mesmo código para os nove só mudando o "nome do botão" pensei em criar um ActionlList com um Action que recebe o código acima e utilizá-lo associando aos 9 botões, porém feito isso não execução não funciona aonde deveria aparecer X fica em branco. Por favor me ajudem a achar o meu erro, minha inexperiência pode me levar a reprovar na faculdade.

Grato

Edited by thoga31
Tags code + GeSHi
Posted (edited)

Calma, não será por um exercício que reprovarias... 🙂

Pela descrição que dizes, eu não iria para uma Action, mas sim para um único handler para os 9 botões.

Pelo que consegui perceber, o NumeroVezes é só um contador do numero de jogadas, e presumo que o "Verificar" seja para ver se o utilizador ganhou.

Precisas portanto de um handler que, ao clicar num dos 9 botões, escreva X ou O, conforme o jogador activo, é isso?

Imagina o seguinte handler:

procedure BotaoJogo(Sender: TObject);
begin

end;

Este é um handler típico para o Evento onclick do TButton. Reparaste no parâmetro Sender? Esse parâmetro trás com ele a indicação do botão que foi carregado para chegar ao handler.

Vem como TObject, a classe raíz, pelo que ter de fazer um TypeCasting (converter) para obteres o TButton:

procedure BotaoJogo(Sender: TObject);
var
  Botao:TButton;
begin
  Botao := Sender AS TButton; // A partir deste momento, tudo o que fizeres com o "Botao", estarás a fazer ao botão que foi clicado no tabuleiro do jogo.

  // Por exemplo, se quiseres por a Caption do botão clicado com um 'X', fazes:
  Botao.Caption := 'X';

  // Não interessa qual foi clicado, desde que adiciones este handler aos TButtons todos do jogo, isto irá funcionar. 
end;

Claro que não te basta meter o X. Tens de saber várias coisas para o processo ser correcto.

Por exemplo, precisas saber o nome do botão, para saberes a posição dele:

Botao.Name // Terá o nome do botão clicado

E qual o jogador que está a jogar no momento:

NumeroVezes  // Pode indicar-te quem está a jogar, conforme seja par ou impar

Estás a seguir?

Dúvida até aqui?

Edited by nunopicado
  • Vote 1

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Posted (edited)

Bom dia nunopicado esse foi o código apresentado para nós fazermos a refatoração, diminuirmos o código, mas eu não sei como fazer isso, se puder ajudar agradeço.

Grato. Vinicius

unit UFrmJogoDaVelha;
interface
uses
 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
 Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ActnList;
type
 TPainel = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   Button4: TButton;
   Button5: TButton;
   Button6: TButton;
   Button7: TButton;
   Button8: TButton;
   Button9: TButton;
   ActionList1: TActionList;
   procedure JogoNovo;
   procedure Verificar;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
   procedure Button4Click(Sender: TObject);
   procedure Button5Click(Sender: TObject);
   procedure Button6Click(Sender: TObject);
   procedure Button7Click(Sender: TObject);
   procedure Button8Click(Sender: TObject);
   procedure Button9Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;
var
 Painel: TPainel;
 Botao: array[1..9] of TButton;
implementation
var
NumeroVezes: Integer;
{$R *.dfm}
procedure TPainel.JogoNovo();
var
M: Real;
i: Integer;
begin
 for i:=1 to 9 do
  Botao[i].Caption:='';
 M:=Int(Random * 10);
 i:=StrToInt(FloatToStr(M));
 Botao[i].Caption:='0';
 NumeroVezes:=0;
end;
procedure TPainel.Verificar;
label 1,2;
var i: Integer;
Resposta: Integer;
begin
 if (Button1.Caption='X') and (Button2.Caption='X')
 and (Button3.Caption='X') then goto 1;
 if (Button4.Caption='X') and (Button5.Caption='X')
 and (Button6.Caption='X') then goto 1;
 if (Button7.Caption='X') and (Button8.Caption='X')
 and (Button9.Caption='X') then goto 1;
 if (Button1.Caption='X') and (Button4.Caption='X')
 and (Button7.Caption='X') then goto 1;
 if (Button2.Caption='X') and (Button5.Caption='X')
 and (Button8.Caption='X') then goto 1;
if (Button3.Caption='X') and (Button6.Caption='X')
and (Button9.Caption='X') then goto 1;
if (Button1.Caption='X') and (Button5.Caption='X')
and (Button9.Caption='X') then goto 1;
if (Button3.Caption='X') and (Button5.Caption='X')
and (Button7.Caption='X') then goto 1;
repeat i:=StrtoInt(FloattoStr(Int (Random *10))) until
Botao[i].Caption='' ;
Botao[i].Caption:='0';
if (Button1.Caption='0') and (Button2.Caption='0')
and (Button3.Caption='0') then goto 2;
if (Button4.Caption='0') and (Button5.Caption='0')
and (Button6.Caption='0') then goto 2;
if (Button7.Caption='0') and (Button8.Caption='0')
and (Button9.Caption='0') then goto 2;
if (Button1.Caption='0') and (Button4.Caption='0')
and (Button7.Caption='0') then goto 2;
if (Button2.Caption='0') and (Button5.Caption='0')
and (Button8.Caption='0') then goto 2;
if (Button3.Caption='0') and (Button6.Caption='0')
and (Button9.Caption='0') then goto 2;
if (Button1.Caption='0') and (Button5.Caption='0')
and (Button9.Caption='0') then goto 2;
if (Button3.Caption='0') and (Button5.Caption='0')
and (Button7.Caption='0') then goto 2;
if NumeroVezes= 4 then
Begin
ShowMessage ('Partida Empatada');
JogoNovo;
Exit;
End;
Exit;
1:
Begin
Resposta:=Application.MessageBox
('Você ganhou, quer Jogar Novamente?','Vencedor',36);
if Resposta = 7 then Close;
JogoNovo;
Exit;
End;
2:
Begin
Resposta:=Application.MessageBox
('Eu ganhei, quer Jogar Novamente?','Vencedor',36);
if Resposta = 7 then Close;
JogoNovo;
Exit;
End;
end;
procedure TPainel.Button1Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button1.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button2Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button2.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button3Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button3.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button4Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button4.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button5Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button5.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button6Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button6.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button7Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button7.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button8Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button8.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button9Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button9.Caption:= 'X';
 Verificar;
end;
procedure TPainel.FormCreate(Sender: TObject);
begin
Randomize;
Botao[1] :=Button1;
Botao[2] :=Button2;
Botao[3] :=Button3;
Botao[4] :=Button4;
Botao[5] :=Button5;
Botao[6] :=Button6;
Botao[7] :=Button7;
Botao[8] :=Button8;
Botao[9] :=Button9;
JogoNovo;
end;
end.
Edited by nunopicado
GeShi
Posted (edited)

Bem, a primeira coisa que te posso sugerir é que indentes correctamente o teu código...

A indentação não é só uma questão de estética. Estando bem feita, facilita a leitura do código e a detecção de erros, o que ajuda tanto a ti a fazer o código, como ao professor ao lê-lo.

Tenho a certeza que não queres que o professor tenha como primeiro impacto um amontoado de caracteres, em vez de um código bem estruturado.

Garanto-te que a tua nota também vai depender disso. E o que é melhor, não custa nada fazer!

Sobre o código propriamente dito, há aí tanto para mexer que temos de ir por fases.

Começo por aquilo que já te tinha dito: O Handler dos botões.

Tu tens:

procedure TPainel.Button1Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button1.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button2Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button2.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button3Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button3.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button4Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button4.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button5Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button5.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button6Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button6.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button7Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button7.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button8Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button8.Caption:= 'X';
 Verificar;
end;
procedure TPainel.Button9Click(Sender: TObject);
begin
 NumeroVezes:=NumeroVezes + 1;
 Button9.Caption:= 'X';
 Verificar;
end;

Nove botões, nove handlers, e todos praticamente iguais. Só muda o botão que o chamou.

Volta ao que te tinha dito no post anterior, e conseguirás converter estes nove handlers em apenas um, usando o (Sender AS TButton) em vez do nome do botão.

Avisa quando estiver.

PS: Só para teres uma ideia, só neste passo reduzes cerca de 62 linhas de código...

Edited by nunopicado

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Posted

Bom dia nunopicado

Consegui implementar o método como você me explicou, um método para os nove botões, como eu faço agora para excluir os 9 métodos que agora ja não preciso mais? amanhã é a entrega do trabalho e a ultima prova, sua ajuda foi muito útil, vou procurar entrar para ver a resposta antes da faculdade que começa as 19hrs horario de Brasilia nós estamos com o fuso-horário de 4hrs de diferença dai para cá.

Muito Obrigado

Posted (edited)

Os métodos a mais basta eliminar do código (não esquecer as declarações dos métodos na definição da classe).

Há muito mais a optimizar aí... Pena o prazo ser curto.

- Podes remover a actionlist que não estás a usar

- Onde usas o Random, basta usar Random(9)+1 que já recebes um número inteiro de 1 a 9, sem precisares de todas aquelas conversões

- O array de botões é completamente inútil. Podes fazer os ciclos directamente nos botões usando o método FindComponent que te devolve um objecto com o nome que lhe passes por parâmetro

- O teu algoritmo de verificação com todos aqueles ifs e gotos é possivelmente a parte do teu programa que mais precisa ser optimizada. Basta um if para cada jogador, dentro de um ciclo que percorra as possibilidades de vitória, que podem ser guardadas por exemplo num array de constantes string:

Const
  cWins:array [1..8] of string=('123','456','789','147','258','369','159','357');

Se percorreres com um ciclo este array, e para cada uma destas posições somares as captions dos botões correspondentes (exemplo, botao1.caption + botao2.caption + botao3.caption, mais uma vez o FindComponent é precioso para isto) e verificares se é igual a 'OOO' ou 'XXX', encontras o teu vencedor.

Se não for igual a nenhum destes, é porque ninguém ganhou ainda.

Edited by nunopicado

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.