Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #58 da revista programar. Faz já o download aqui!

vikcch

Duvida de Raciocinio - Movimento do Cavalo no Xadrez

Mensagens Recomendadas

vikcch    15
vikcch

Olá a todos,

Tive a ver uns sites de desafios de programação e deparei-me com este muito bom que nem é preciso registar para fazer os desafios, dá para fazer em 6 linguagens, js, python, ruby, php, java e c++.

Os desafios estão divididos em 3 niveis de dificuldade, fiz 2 ou 3 dos faceis, e fui ver os dificeis, vi lá um relacionado com xadrez e já que gosto de do jogo, tentei fazer o desafio..

link para o desafio em php

O desafio é saber o numero de movimento possíveis do cavalo tendo em conta o posição inicial dele..

parecia relativamente simples se apenas se usasse if's já que não seriam assim tantos, algo do tipo:

if initposx + 2 <= 8 && initposy + 1 <= 8

pode mover

tentei fazer com ciclos mas acho que ficou muito mais confuso... fica aqui a minha solução... gostava de ver a vossa e o que se pode fazer para melhor este codigo.

function KnightJumps($str) {  

 $init_pos = explode(' ', trim($str, '()'));	

 $num_possible_moves = 0;

 for ($i = 1; $i<=4; $i++){

if ($i < 3){
  $x = 2;
  $y = 1;
}else{
  $x = 1;
  $y = 2;
}

if ($i==2 || $i ==4)	
  $x = -$x;	

for ($i2 = 1; $i2<=2; $i2++){

  if ($i2 == 2)
	$y = -$y;

  $new_pos_x = $init_pos[0] + $x;
  $new_pos_y = $init_pos[1] + $y;

  //echo "x". $new_pos_x . "y" . $new_pos_y .  "|";	  

  if ($new_pos_x >=1 && $new_pos_x <=8 && $new_pos_y >=1 && $new_pos_y <=8)
	$num_possible_moves ++;
}
 }

 return $num_possible_moves;

}

Obrigado desde já!

Editado por vikcch

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1134
HappyHippyHippo

fui ver os dificeis

a sério ???

<?php 

function KnightJumps($str) {  
   sscanf($str, "(%d %d)", $x, $y);

   $xs = [2, 1, -1, -2, -2, -1, 1, 2];
   $ys = [1, 2, 2, 1, -1, -2, -2, -1];

   $count = 0;
   foreach ($xs as $i => $v)
       $count += ($x + $xs[$i] > 0) && ($x + $xs[$i] < 9) && ($y + $ys[$i] > 0) && ($y + $ys[$i] < 9);

   return $count;
}

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
vikcch    15
vikcch

obrigado por postares

a sério ???

a serio que não percebi...

wow muito mais simples este codigo....

que faz isto -> $i => $v na linha do foreach ? o $v não é usado em mais lado nenhum

esta linha sscanf($str, "(%d %d)", $x, $y); não funcionou comigo lá no site, mas se introduzindo logo os valores no $x e $y fica ok

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1134
HappyHippyHippo

a serio que não percebi...

porque o exercício é simples ...

que faz isto -> $i => $v na linha do foreach ? o $v não é usado em mais lado nenhum

pois não, mas alguma coisa tem de ser declarada ...

esta linha sscanf($str, "(%d %d)", $x, $y); não funcionou comigo lá no site, mas se introduzindo logo os valores no $x e $y fica ok

<?php
function KnightJumps($str) {  
preg_match_all("/\d{1}/", $str, $match);
list($x, $y) = $match[0];

$c = [1, 2, 2, 1, -1, -2, -2, -1, 1, 2];

$count = 0;
   for ($i = 0; $i < 8; ++$i)
    $count += ($x + $c[$i + 2] > 0) &&
			  ($x + $c[$i + 2] < 9) &&
			  ($y + $c[$i] > 0) &&
			  ($y + $c[$i] < 9);

return $count;
}

Editado por HappyHippyHippo

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
vikcch    15
vikcch

porque o exercício é simples ...

pois, não vi todos mas este deve ser o mais simples na categoria dos dificeis..

preg_match_all("/\d{1}/", $str, $match);

list($x, $y) = $match[0];

isto tambem não funciona lá no site... mas deixa estar... esta parte até me desenrasquei bem...

está lá outro relacionado com xadrez que vou tentar solucionar... se conseguir depois posto...

obrigado

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1134
HappyHippyHippo

isto tambem não funciona lá no site... mas deixa estar... esta parte até me desenrasquei bem...

mas que porcaria de site que não se pode fazer nada ....

ps : anda lá com com isso que já fiz o exercício ...

Editado por HappyHippyHippo

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
vikcch    15
vikcch

lol...

já li o enunciado 2 ou 3 vezes... até percebi bem o objectivo... e já pensei no assunto... mas não consigo fazer isso dum momento para o outro... se eu fosse bom não tava desempregado...

amanha ou depois posto o que consegui fazer...

Editado por vikcch

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1134
HappyHippyHippo

dica:

- desenha o tabuleiro num papel

- dá números de 1 a 8 para as linhas e para as colunas

- em cada célula escreve a soma do número da linha com o número da coluna

- desenha o mesmo tabuleiro ao lado

- agora em cada célula escreve a subtração do número da linha com o número da coluna

a ter em conta : não notas nada engraçado ???

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
vikcch    15
vikcch

que as diagonais tens todas o mesmo numero ? quando tou a somar são diagonais para a esquerda e quando tou o subtrair são as diagonais para a direita... é isso?

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1134
HappyHippyHippo

que as diagonais tens todas o mesmo numero ? quando tou a somar são diagonais para a esquerda e quando tou o subtrair são as diagonais para a direita... é isso?

yep ... só isso com o exercício anterior torna o código muito pequeno ...

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
vikcch    15
vikcch

Não consegui fazer em php, tava ter dificuldades em trabalhar com arrays, tenho pouca experiencia na linguagem e nem tenho aqui nada instalado que para rodar php...

fiz em c#... sempre me desenrasco melhor...

não percebi bem como usar esse metodo das diagonais, mas fiz tendo em conta a resolução que fizeste no exercicio do cavalo, usando 2 arrays que iram representar a direcção e multiplicar pela distancia...

link para o desafio

o codigo ficou um pouco grande mas pelos testes que fiz tá a funcionar bem...

using System;
using System.Collections.Generic;
namespace QueenCkeck
{
class Program
{
 public static void Main(string[] args)
 {

  QueenCheck();

  Console.Write("Press any key to continue . . . ");
  Console.ReadKey(true);
 }

 private static void QueenCheck() {
  Pos queen = new Pos(7, 7);
  Pos king = new Pos(6, 3);

  Console.WriteLine("Posições Inicias");
  Console.WriteLine("Rainha - x:" + queen.X + " y:" + queen.Y);
  Console.WriteLine("Rei	- x:" + king.X + " y:" + king.Y);
  Console.WriteLine();

  // sentido horario começando pelo "meio-dia"
  int[] xs = {0, 1, 1, 1, 0, -1, -1, -1};
  int[] ys = {1, 1, 0, -1, -1, -1, 0, 1};

  Console.WriteLine("Casas atacadas pelas rainha:");
  // popular list com casas de ataque da rainha
  List<Pos> queenAtack = new List<Pos>();
  for (int i = 0; i<8; i++){
for (int i2 = 1; i2<8; i2++){ // i2 começa em 1 para não adicionar a casa inicial
 if ((queen.X + xs[i]*i2 > 0) && (queen.X + xs[i]*i2 < 9) && (queen.Y + ys[i]*i2 > 0) && (queen.Y + ys[i]*i2 < 9)){

  int x = queen.X + xs[i]*i2;
  int y = queen.Y + ys[i]*i2;

  Console.Write("x" + x + " y" + y + " | ");

  queenAtack.Add(new Pos(x, y));
 }
}
Console.WriteLine();
  }  
  Console.WriteLine("Total: " + queenAtack.Count);
  Console.WriteLine();

  Console.WriteLine("Casas para onde o rei se pode mover:");
  // popular list com possiveis movimentos do rei para casas onde a rainha não ataca,
  // incluindo capturar a rainha porque a list 'queenAtack' não tem a posição da rainha
  List<Pos> kingMoves = new List<Pos>();
  for (int i = 0; i<8; i++)
  {
if ((king.X + xs[i] > 0) && (king.X + xs[i] < 9) && (king.Y + ys[i] > 0) && (king.Y + ys[i] < 9))
{
 int x = king.X + xs[i];
 int y = king.Y + ys[i];

 bool achou = false;
 foreach (Pos item in queenAtack)
 {	
  if (Pos.Igual(item, new Pos(x, y)))
  {
   achou = true;			
   break;
  }
 }
 if (!achou)
 {
  kingMoves.Add(new Pos(x, y));
  Console.Write("x" + x + " y" + y + " | ");
 }
}
  }  
  Console.WriteLine();
  Console.WriteLine("Total: " + kingMoves.Count);
  Console.WriteLine();
 }

 public class Pos {
  public int X {get; set;}
  public int Y {get; set;}

  public Pos(int x, int y)
  {
this.X = x;
this.Y = y;
  }
  public static bool Igual(Pos a, Pos b)
  {
if (a.X == b.X && a.Y == b.Y)
 return true;

return false;
  }
 }

}
}

gostava novamente de ouvir no que se pode melhorar ou ver a outra tecnica que falaste...

obrigado

Editado por vikcch

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1134
HappyHippyHippo
function QueenCheck($strArr) {  
   preg_match_all("/\d{1}/", $strArr[0], $match);                 // ler a posição da rainha
   list($qx, $qy) = $match[0];

   preg_match_all("/\d{1}/", $strArr[1], $match);                 // ler a posição do rei
   list($kx, $ky) = $match[0];

   $c = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1];                  // array de verificações

   $qd1 = $qx + $qy;                                              // valor da diagonal 1 da rainha
   $qd2 = $qx - $qy;                                              // valor da diagonal 2 da rainha

   if (($kx != $qx) &&                                            // verificar se o rei não se encontra na mesma linha que a rainha
       ($ky != $qy) &&                                            // verificar se o rei não se encontra na mesma coluna que a rainha
       ($kx + $ky != $qd1) &&                                     // verificar se o rei não se encontra na diagonal 1 da rainha
       ($kx - $ky != $qd2))                                       // verificar se o rei não se encontra na diagonal 2 da rainha
       return -1;

   $count = 0;
   for ($i = 0; $i < 8; ++$i) {                                   // ciclo de verificação de movimentos
       $count += ($kx + $c[$i + 2] > 0) &&                        // verificar se não sai do tabuleiro pela esquerda
                 ($kx + $c[$i + 2] < 9) &&                        // verificar se não sai do tabuleiro pela direita
                 ($ky + $c[$i] > 0) &&                            // verificar se não sai do tabuleiro pelo topo
                 ($ky + $c[$i] < 9) &&                            // verificar se não sai do tabuleiro pelo fundo
                 ($kx + $c[$i + 2] != $qy) &&                     // verificar se não fica na mesma linha que a rainha
                 ($ky + $c[$i] != $qx) &&                         // verificar se não fica na mesma coluna que a rainha
                 (($kx + $c[$i + 2]) + ($ky + $c[$i]) != $qd1) && // verificar se não fica na mesma diagonal 1 que a rainha
                 (($kx + $c[$i + 2]) - ($ky + $c[$i]) != $qd2);   // verificar se não fica na mesma diagonal 2 que a rainha
   }

   return $count;
}

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
vikcch    15
vikcch

Esqueci-me de fazer retornar -1, mas não é muito importante..

faz-me um bocado confusão ter tantas comparações na mesma linha...

se tivesses que escrever as casas atacadas pela rainha e quais as casas para onde o rei se podia mexer, não dava para encurtar muito mais o codigo do que o que fiz pois não??

diz lá qualquer coisa da maneira como eu pensei e resolvi..

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1134
HappyHippyHippo

não dava para encurtar muito mais o codigo do que o que fiz pois não??

Não testado, só de cabeça

using System;
using System.Collections.Generic;
namespace QueenCkeck
{
class Program
{
 public class Pos : IEquatable<Pos> {
   public int X {get; set;}
   public int Y {get; set;}

   public Pos(int x, int y) {
     this.X = x;
     this.Y = y;
   }
   public bool Equals(Pos pos) {
     return X == pos.X && Y == pos.Y;
   }
 }

 public static void Main(string[] args) {
   QueenCheck();

   Console.Write("Press any key to continue . . . ");
   Console.ReadKey(true);
 }

 private static void QueenCheck() {
   Pos queen = new Pos(7, 7);
   Pos king = new Pos(6, 3);

   Console.WriteLine("Posições Inicias");
   Console.WriteLine("Rainha - x:" + queen.X + " y:" + queen.Y);
   Console.WriteLine("Rei    - x:" + king.X + " y:" + king.Y);
   Console.WriteLine();

   // sentido horario começando pelo "meio-dia"
   int[] xs = {0, 1, 1, 1, 0, -1, -1, -1};
   int[] ys = {1, 1, 0, -1, -1, -1, 0, 1};

   int diag1 = queen.X + queen.Y;
   int diag2 = queen.X - queen.Y;

   Console.WriteLine("Casas atacadas pelas rainha:");
   // popular list com casas de ataque da rainha
   List<Pos> queenAtack = new List<Pos>();
   for (int column = 1; column <= 8; ++column) {
     for (int row = 1; row <= 8; ++row) {
       if (column == queen.X || row == queen.Y || column + row == diag1 || column - row == diag2)
         Console.Write("x" + column + " y" + row + " | ");
         queenAtack.Add(new Pos(column, row));
       }
     }
     Console.WriteLine();
   }

   Console.WriteLine("Casas para onde o rei se pode mover:");
   // popular list com possiveis movimentos do rei para casas onde a rainha não ataca,
   // incluindo capturar a rainha porque a list 'queenAtack' não tem a posição da rainha
   List<Pos> kingMoves = new List<Pos>();
   for (int i = 0; i<8; i++) {
     int x = king.X + xs[i];
     int y = king.Y + ys[i];
     if ((x > 0) && (x < 9) && (y > 0) && (y < 9)) {

       if (!queenAtack.contains(Pos(x, y))) {
         kingMoves.Add(new Pos(x, y));
         Console.Write("x" + x + " y" + y + " | ");
       }
     }
   }

   Console.WriteLine();
   Console.WriteLine("Total: " + kingMoves.Count);
   Console.WriteLine();
 }
}

Editado por HappyHippyHippo

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
vikcch    15
vikcch

faltava umas chavetas e no "queenAtack.Contains" tem se passar uma instância né?

if (!queenAtack.Contains(new Pos(x, y))) {
         kingMoves.Add(new Pos(x, y));
         Console.Write("x" + x + " y" + y + " | ");
       }

mas tá a adicionar todos, mesmo quando já existe na lista "queenAtack"...

tb esta a dicionar a posição da rainha nas list 'queenAtack'... mas não tem grande importâcia

não sabia que ++variavel tambem funcionava

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
vikcch    15
vikcch

alteraste a class Pos ?

tás a perguntar se tem lá o metodo "Equals", se sim, tem, mas no debugger não entra lá sequer (nem sabia que o metodo "Contains" ia chamar esse "Equals" se é o que é suposto fazer)

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1134
HappyHippyHippo
public class Pos : IEquatable<Pos> { // <----------
   public int X {get; set;}
   public int Y {get; set;}

   public Pos(int x, int y) {
     this.X = x;
     this.Y = y;
   }
   public bool Equals(Pos pos) {
     return X == pos.X && Y == pos.Y;
   }
 }

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora


×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade