thegoodfellas/blogset-br huggingface dataset:
Sim, nos demos uma parada com o blog... mas nao, nao fiquem tristes!Em breve um novo blog... nao sei quando, nem como sera o blog... mas quando eu conseguir bolar um nome... irei cria-lo! Mas... como ainda estamos recebendo uma media de 150 visitas por dia... depois de tanto tempo desatualizado, apos a extreia da @bandacw7 no @TOP10MTV, descidimos divulga-los rumo ao 1o lugar, pois ele sao muito bons e merecem!!!Entao deixo voces novamente com o clipe concorrente "Sera Voce":Entao va ate o TOP 10 MTV e vote muuuito mesmo! Queremos a Banca CW7 em 1o lugar! - Adeus Restart e Justin Biba! < Revoltas anonimas Enviado por: Aline Tavares nao sei se e verdade ou MITOmais encontrei na Net. uma fato exclusivono dia 27 de Agosto de 2010 as 23:00 voces poderam ver MARTE a olho nu,tao grande quanto a lua cheia no universo.teremos duas Lua's no Ceuisso mesmo, tambem nao acreditei quando li .Temos muita sorte !!!por isso nao percamA proxima vez que Marte vai aparecer assim sera em 2687.OBS: Partilhe isso com seus amigos pois ninguem, hoje vivo, teraoportunidade de observar novamente o fato.GOSTO ? COMENTA VAI ! Pense em qualquer objeto e responda sinceramente as perguntas do site, em menos de 20 perguntas eles acertam exatamente o que voce estava pensando.Pelo menos comigo funcionou varias vezes e ainda vou testar mais algumas vezes, realmente muito bom.Para acessar o site clique na imagem abaixo (procure na lista que vai aparecer, pelo "Pense em Portugues")E incrivel... tudo bem que algumas perguntas voce nao sabe responder!Mas isso nao vem ao caso ja que voce pode escolher a opcao desconhecido!Fonte: A La Quatre (acesse clicando aqui) O 11 passou a ser um numero inquietante.Podem pensar que e uma casualidade forcada ou simplesmente uma tolice, mas o que esta claro e que ha coisas no minimo interessantes.Vejamos:1) New York City tem 11 letras.2) Afeganistao tem 11 letras.3) The Pentagon tem 11 letras.4) George W. Bush tem 11 letras.Ate aqui, meras coincidencias ou casualidades forcadas. Agora comeca o interessante.1) Nova Iorque e o estado No 11 dos EUA.2) O primeiro dos voos que embateu contra as Torres Gemeas era o No11.3) O voo No 11 levava a bordo 92 passageiros; somando os numerais da: 9+2=11.4) O outro voo que bateu contra as Torres, levava a bordo 65 passageiros, que somando os numerais da: 6+5=11.5) A tragedia teve lugar a 11 de Setembro, ou seja, 11 do 9, que somando os numerais da: 1+1+9=11.E agora o intrigante.1) As vitimas totais que faleceram nos avioes sao 254: 2+5+4=11.2) O dia 11 de Setembro, e o dia numero 254 do ano: 2+5+4=11.3) A partir do 11 de setembro sobram 111 dias ate ao fim de um ano.4) Nostradamus (11 letras) profetiza a destruiao de Nova Iorque na Centuria numero 11 dos seus versos.Mas o mais chocante de tudo e que, se pensarmos nas Torres Gemeas, damo-nos conta que tinham a forma de um gigantesco numero 11.E, como se nao bastasse, o atentado de Madrid aconteceu no dia 11.03.2004, que somando os numerais da: 1+1+0+3+2+0+0+4=11.Intrigante, nao acham??E se
esqueceram que o atentado de Madrid aconteceu 911 dias depois do de New York, que somando os numerais 9+1+1=11!!!!E AGORA o mais arrepiante:Corinthians, tem 11 letras, tem 11 jogadores e sua fundacao foi em 1910, que somando os numerais da 1+9+1+0=11.CONCLUSAO DE TUDO ISSO: Seria Bin Laden Corinthiano?? kkkkkkkkkkEnviado por: Jessica Torres
programa que converta musicas para .ogg no Baixaki. Existem varios.2 Depois abra o programa e converta as musicas.3 Envie as musicas convertidas para meus documentos/18wos haulin/musicas4 Abra o Jogo, aperte "R" e selecione a musica desejada.COMO EDITAR UM MAPA NO HAULIN Tutorial ensinando como editar mapas no Haulin'.OBS: tem que executar o jogo em modo window!!!! nao pode ser full screen!!!Para abrir em window, va em Iniciar, Programas, 18 w of steel haulin, configure graphics mode.. vai em Advanced e clica em In a Window.Download: http://www.4shared.com/file/31572022/edde08a4/COMO_EDITAR_UM_MAPA_NO_HAULIN.htmlComo instalar mods Vejo na comunidade todos os dias pessoas com dificuldade na instalacao de mods vou explicar rapidamente pois e muito facil..vamo la...quando vc baixa o mod ele vem zinpado e so usar o winRar para descompacta lo isso feito e so extrai os arquivos .SCS para a pasta C:\Documents and Settings\Usuario\Meus documentos\18 WoS Haulin\mod
g23 e g29) e esse desequilibrio pode levar a combinacoes ate entao nao exploradas, resultando em um novo salto em desempenho. Mas e quanto ao melhor agente, o que podemos dizer? Na proxima secao vamos olhar isso mais de perto.Resultados O melhor agente ocorre em g22, com um desempenho medio de 6248.7 linhas/game, e corresponde aos genes: 0.8775823, 0.109419234, 0.8726228, 0.5850601, 0.073843196, 0.21980879 e 0.19367324. Sabemos que esse resultado corresponde a media de 10 games, mas nao sabemos nada sobre a distribuicao de probabilidade desta variavel. Para investigar melhor esse comportamento, vamos testar o agente novamente: 10 runs de 100 games aleatorios cada. O grafico abaixo mostra os resultados: O valor medio obtido foi de 3261.871 linhas/game com desvio padrao de 3196.501 linhas. Observando a quantidade de outliers, esses valores nao sao uma surpresa. Considere o histograma abaixo, com bin = 500: Como o numero de linhas removidas e uma variavel discreta, os graficos acima nos sugerem uma distribuicao geometrica. Vamos modelar essa variavel, assumindo que a cada peca nova, existe uma probabilidade constante p de que o jogo ira terminar. Parece uma hipotese fraca, mas lembre-se de que o game-over so ocorre devido a uma sequencia ruim de pecas, que certamente ira ocorrer com probabilidade q, determinada pelo gerador aleatorio. Consequentemente, o historico passado de pecas nao tem influencia pratica na duracao do jogo: e impossivel distinguir uma grade com um milhao de linhas removidas, de uma outra que tenha acabado de iniciar. Essa falta de memoria e justamente uma das propriedades da distribuicao geometrica. Seja K a variavel aleatoria numero de lances ate o termino do jogo, p a probabilidade de game-over e k um numero de lances qualquer. Assumimos que Prob(K = k) = (1 - p)(k - 1) * p. Ou seja, a probabilidade do jogo terminar apos k lances e determinada pelo produto entre as probabilidades de sobrevivermos (k - 1) lances e a probabilidade de ocorrer game-over no proximo lance. Se E(K) e a media de K, temos que p = 1/E(K). Agora, seja X a variavel numero de linhas removidas ate o termino do jogo. Conforme o numero de lances ultrapassa 45, sabemos que as linhas devem ser removidas a uma taxa de 2.5 pecas/linha para evitar o termino do jogo. Isso ocorre porque o numero maximo de blocos na grade e 20 x 9 = 180, ou seja, e possivel que 180/4 = 45 pecas caiam sem nenhuma linha ser removida. Como K e X estao relacionados quando k >> 45, podemos concluir que possuem a mesma distribuicao de probabilidade. De acordo com a discussao acima, temos: E(X) = 3261.871 p = 1/E(X) = 0.000306572516203 σ2 = (1 - p)/p2 σ = 3261.371 Prob(X = x) = (1 - p)(x - 1) * p Para testar o modelo, obtemos uma nova amostra de 1000 games aleatorios e comparamos com os resultados previstos por Prob(X). O poligono de frequencias abaixo mostra os resultados: Nada mal, o modelo parece funcionar bem! Uma outra opcao seria modelar o desempenho medio do agente usando uma distribuicao exponencial, o
analogo continuo da distribuicao geometrica. Existem alteracoes interessantes que podem ser feitas na programa, por exemplo: alterar os metodos de mutacao e crossover Usar uma funcao nao-linear para avaliar as posicoes Usar uma GA de estado-estacionario Investigar o efeito do agente conhecer a proxima peca Investigar a distribuicao de probabilidade de outras variaveis (altura da grade, por exemplo) Acho que e isso pessoal! Essa foi uma aplicacao simples de GA, mas os conceitos valem para qualquersituacao. Como vimos o algoritmo pode levar um bom tempo para retornar uma solucao, que nem sempree a melhor. O importante e conhecer bem o problema e identificar quais os algoritmos que realmentevalem a pena aplicar. Ate a proxima!
blocksAboveHoles(int[][] board) { int blocks = 0; int cols = board[0].length; for(int c = 1; c < cols - 1; c++) { boolean swap = false; for (int r = board.length - 2; r >= 0; r--) { if (board[r][c] == 0) swap = true; else { if (swap) blocks++; } } } return blocks; } public static int countWells(int[][] board) { int cols = board[0].length; int wells = 0; //da segunda ate a penultima coluna for (int col = 2; col < cols - 2; col++) { for (int row = 0; row < board.length - 1; row++) { if ((board[row][col - 1] > 0) && (board[row][col + 1] > 0) && (board[row][col] == 0)) wells++; else if (board[row][col] > 0) break; } } //primeira coluna for (int row = 0; row < board.length - 1; row++) { if ((board[row][1] == 0) && (board[row][2] > 0)) wells++; else if (board[row][1] > 0) break; } //ultima coluna for (int row = 0; row < board.length - 1; row++) { if ((board[row][cols - 3] > 0) && (board[row][cols - 2] == 0)) wells++; else if (board[row][cols - 2] > 0) break; } return wells; } public static float bumpiness(int[][] board) { int cols = board[0].length; int[] heights = new int[cols - 2]; for(int x = 1; x < cols - 1; x++) { for(int y = 0; y < board.length - 1; y++) { if(board[y][x] != 0) { heights[x - 1] = board.length - 1 - y; break; } } } float bmp = 0.0f; for (int i = 0; i < cols - 3; i++) { float diff = Math.abs(heights[i] - heights[i + 1]); bmp += diff; } return bmp; }} //fim da classe BoardEvaluatorClasse TetrisMove Objetos dessa classe representam um lance que pode ser feito, dado determinada peca e board. Os campos position e rotation representam a posicao em que a peca sera encaixada e a rotacao, respectivamente. O campo eval representa a qualidade deste lance, de acordo com a avaliacao do agente. Segue a classe TetrisMove:public class TetrisMove{ Point position = new Point(0, 0); int rotation; float eval; public TetrisMove(){} public TetrisMove(Point p, int rot ) { this.position = p; this.rotation = rot; }}Classe MoveSearcher Outra classe com metodos estaticos, mas desta vez a ideia e listar todos os lances possiveis, retornando o melhor. O codigo de getValidMoves parece complicado, mas e bem simples: (i) movemos a peca o maximo possivel para a esquerda e (ii) fazemos um drop, adicionando o lance resultante na lista. (iii) Voltamos a peca verticalmente para o topo e movemos para a direita. Os processos (ii) e (iii) sao repetidos ate ser impossivel mover para direita, quando passamos para a proxima rotacao e repetimos a partir de (i). Repare que o agente e passado como argumento, e o metodo eval do objeto TetrisAgent e invocado. Outro detalhe importante e o metodo removePiece da classe TetrisBoard, quee utilizado para desfazer o lance, logo apos efetuar o drop. O metodo getBestMove simplesmente invoca getValidMoves e retorna o lance com maior eval. Segue a classe MoveSearcher:import java.util.ArrayList;public class
while (!gameOver) { if (board.canMoveDown(fallingPiece)) { TetrisMove bestMove = MoveSearcher.getBestMove(board, fallingPiece.clonePiece(), agent); fallingPiece.position = bestMove.position; fallingPiece.rotation = bestMove.rotation; board.updateBoard(fallingPiece); } else { board.updateBoard(fallingPiece); cleared +=board.checkCompleteRows(); addNewPiece(); } if (doSleep) { try { Thread.sleep(20L); } catch(InterruptedException ex){} } repaint(); } agent.clearedRowsArray.add(cleared); //acessado por varias threads! if (doneSignal != null) doneSignal.countDown(); } } //fim da classe AIGameTestando o agente Chegou a hora de testar a estrutura da AI, colocando um agente para jogar. Lembrando que o agente teve seus genes hard-coded na classe TetrisAgent, voce pode alterar esses valores manualmente ou simplesmente usar ai.agent = TetrisAgent.randomAgent(), e testar um agente randomico. Segue a classe TestAgent:import javax.swing.*;import java.awt.*;public class TestAgent{ public static void main (String[] args) { JFrame f = new JFrame(); int rows = 20, cols = 10, block = 32; boolean sleep = true; //para atualizar o panel AIGame ai = new AIGame(rows, cols, block, sleep); ai.setBackground(Color.black); f.add(ai); f.pack(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setResizable(false); f.setVisible(true); new Thread(ai).start(); }} No proximo post iremos implementar a GA e observar a evolucao dos agentes. Caso esteja curioso, substitua os genes por esses valores (na ordem): 0.95856917f, 0.08560386f, 0.9476838f, 0.58525276f,0.0291457f, 0.18112998f, 0.17345366f e execute o programa algumas vezes. Ate a proxima!
precisaria de argumentos, afinal rotacao e posicao sao variaveis de instancia. Porem, acompanhe o raciocinio abaixo: Ao mover ou rotacionar uma peca, podemos facilmente calcular a nova rotacao ou posicao, e chamar boardIndexes passando estes valores, obtendo assim os novos indices ocupados. Caso estes indices estejam livres o movimento e possivel, e as variaveis de instancia rotacao e posicao sao atualizadas. Caso contrario, a colisao e detectada e a peca nao se move. A logica para lidar com o movimento e colisao das pecas sera implementada na classe TetrisBoard. Objetos da classe TetrisPiece sabem se mover, mas a decisao de mover cabe a outro objeto.Segue a classe TetrisPiece:import java.awt.*;public class TetrisPiece{ int rotation; int kind; int blockSize = 20; Point position = new Point(0,0); //upper left static final int PIECE_SIZE = 5; static final int BLOCKS_PIECE = 4; static final Color[] COLORS = { new Color(255, 255, 0), //yellow new Color(0, 180, 0), //green new Color(255, 0, 0), //red new Color(255, 127, 0), //orange new Color(255, 0, 255), //purple new Color(0, 0, 255), //blue new Color(0, 255, 255) //cyan }; static final int [][][] TRANSLATIONS = { /* T */ { {-2, -3}, {-2, -3}, {-2, -3}, {-2, -2} }, /* I */ { {-2, -2}, {-2, -4}, {-2, -2}, {-2, -3} }, /* S */ { {-2, -3}, {-2, -3}, {-2, -3}, {-2, -2} }, /* Z */ { {-2, -3}, {-2, -3}, {-2, -3}, {-2, -2} }, /* O */ { {-2, -3}, {-2, -3}, {-2, -3}, {-2, -3} }, /* J */ { {-2, -3}, {-2, -2}, {-2, -3}, {-2, -3} }, /* L */ { {-2, -3}, {-2, -3}, {-2, -3}, {-2, -2} } }; static final int[][][][] PIECES = { //TPiece { { {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 1, 1, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} } }, //IPiece { { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 1}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {1, 1, 1, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 0, 0} } }, //SPiece { { {0, 0,
0, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 1, 1, 0}, {0, 1, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 1, 1, 0}, {0, 1, 1, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} } }, //ZPiece { { {0, 0, 0, 0, 0}, {0, 0, 0, 1, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 1, 1, 0, 0}, {0, 1, 0, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} } }, //OPiece { { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 0, 0} } }, //JPiece { { {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 1, 1, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 0, 0} } }, //LPiece { { {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 1, 1, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {0, 1, 0, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 0, 0}, {0,
0, 1, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 0, 0, 0}, {0, 0, 0, 1, 0}, {0, 1, 1, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} } } }; public void draw(Graphics g) { g.setColor(COLORS[this.kind]); for (int i = 0; i < PIECE_SIZE; i++) { for (int j = 0; j < PIECE_SIZE; j++) { if (PIECES[kind][rotation][i][j] == 1) { g.fillRect(position.x + j * blockSize, position.y + i * blockSize, blockSize, blockSize); } } } } public void moveLeft() { position.x -= blockSize; } public void moveRight() { position.x += blockSize; } public void moveDown() { position.y += blockSize; } public void rotateCW() { rotation++; if (rotation > 3) rotation = 0; } public void rotateCCW() { rotation--; if (rotation < 0) rotation = 3; } public Point[] boardIndexes(Point pos, int rot) { Point[] indexes = new Point[BLOCKS_PIECE]; int n = 0; for (int i = 0; i < PIECE_SIZE; i++) { for (int j = 0; j < PIECE_SIZE; j++) { if (PIECES[kind][rot][i][j] == 1) { int col = j + pos.x/blockSize; int row = i + pos.y/blockSize; indexes[n] = new Point(col, row); n++; } } } return indexes; } public TetrisPiece clonePiece() { TetrisPiece p = new TetrisPiece(); p.kind = this.kind; p.rotation = this.rotation; p.position = new Point(this.position.x, this.position.y); p.blockSize = this.blockSize; return p; }} //fim da classe TetrisPiece/* classe auxiliar */class Point{ int x; int y; public Point(int x, int y) { this.x = x; this.y = y; } public Point(){}}Classe TetrisBoard Essa classe representa a grade onde as pecas se movem, e a estrura e bem simples: no construtor sao passados o numero de linhas rows e colunas cols, usados para inicializar a array board. Reparem que board consiste de rows + 1 linhas e cols + 2 colunas, onde a linha extra sera usada para detectar colisao com o fundo da grade, e as duas colunas extras serao usadas para detectar colisao com as laterais. Obviamente apenas a parte interna da grade sera desenhada (rows linhas x cols colunas). O metodo removePiece remove uma peca da grade, obtendo os indices ocupados por essa peca (atraves do metodo boardIndexes do objeto TetrisPiece) e zerando os mesmos. Este metodo nao e utilizado na logica do game, mas sera util ao implementarmos a AI. Agora a parte mais interessante: colisoes. O metodo isColliding recebe uma array de indices e verifica se ao menos um desses indices esta ocupado, o que resultaria em colisao. Aqui devemos ter cuidado com duas coisas: indices de array negativos (causa RuntimeException) e um bug em potencial: pecas ficando presas nas bordas superiores da grade. Os 2 primeiros if's, dao conta disso. Os proximos metodos sao do tipo canMoveX e canRotateX. Ao receber input de movimento (do usuario ou da AI), estes metodos serao chamados para decidir se o movimento e possivel, como discutido no topico anterior. Os metodos willFitNext e pieceLandOffScreen detectam duas situacoes distintas de game-over: No primeiro caso, a proxima peca nao possui espaco, no segundo, a ultima peca encaixada ficou parcialmente fora
(int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { int block = board.board[i][j + 1]; if (block != 0) { g.setColor(TetrisPiece.COLORS[block - 1]); g.fillRect(j * blockSize, i * blockSize, blockSize, blockSize); } } } } protected void addNewPiece() { if (board.pieceLandOffScreen(fallingPiece)) { gameOver = true; fallingPiece = null; return; } TetrisPiece next = randomPiece(); if (board.willFitNext(next)) { fallingPiece = next; } else { fallingPiece = null; gameOver = true; } } protected TetrisPiece randomPiece() { int kind = random.nextInt(7); int rot = random.nextInt(4); TetrisPiece piece = new TetrisPiece(); piece.blockSize = this.blockSize; piece.kind = kind; piece.rotation = rot; int x = blockSize * (cols/2 + TetrisPiece.TRANSLATIONS[kind][rot][0]); int y = blockSize * TetrisPiece.TRANSLATIONS[kind][rot][1]; piece.position = new Point(x, y); return piece; } private void addKeyWatcher() { addKeyListener( new KeyAdapter() { public void keyPressed(KeyEvent e) { if (gameOver) { return; } int key = e.getKeyCode(); if (key == KeyEvent.VK_SPACE) { } else if (key == KeyEvent.VK_LEFT) { if (board.canMoveLeft(fallingPiece)) fallingPiece.moveLeft(); } else if (key == KeyEvent.VK_RIGHT) { if (board.canMoveRight(fallingPiece)) fallingPiece.moveRight(); } else if (key == KeyEvent.VK_UP || key == KeyEvent.VK_NUMPAD3) { if (board.canRotateCW(fallingPiece)) fallingPiece.rotateCW(); } else if (key == KeyEvent.VK_DOWN || key == KeyEvent.VK_NUMPAD1) { if (board.canRotateCCW(fallingPiece)) fallingPiece.rotateCCW(); } repaint(); } }); } // fim de addKeyWatcher()}Testando o cliente Agora, a parte mais facil: juntar tudo em um metodo main e testar nosso cliente Tetris. A ideia aqui e verificar se tudo funciona como devia, e nao implementar um game completo. Por exemplo, na classe TetrisPanel, a velocidade foi fixada com long step = 1000L/4, ou seja, a cada 0.25 segundos o loop sera executado. Na parte visual, desenhamos a peca como um bloco continuo, mas e facil desenhar as bordas utilizando drawRect em conjunto com fillRect, sem esquecer de setar as cores de fill e stroke. Use as setas do teclado para mover e rotacionar as pecas, e nao se esqueca de testar valores diferentes para rows, cols e blockSize. Vale lembrar que o JPanel se ajustara com largura = cols * blockSize e altura = rows * blockSize, independentemente do tamanho do seu monitor! Segue a classe TestTetris: import javax.swing.*;import java.awt.*;public class TestTetris{ public static void main(String[] args) { JFrame f = new JFrame("Tetris - GA"); int rows = 20; int cols = 10; int blockSize = 30; GamePanel gamePanel = new GamePanel(rows, cols, blockSize); gamePanel.setBackground(Color.gray) ; gamePanel.setBorder(BorderFactory.createLineBorder(Color.white)); f.add(gamePanel); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); f.setVisible(true); f.setResizable(false); gamePanel.startNewGame(); }}No proximo post iremos comecar a parte que realmente interessa, AI. Fique ligado!