Você está na página 1de 21

Crear un juego de tres en línea en red para Android

Construir un juego de tres en línea de multijugador en red con PHP, XML y


el kit de desarrollo de Android

Jack D. Herrington 09-04-2012


Senior Software Engineer
Leverage Software Inc.

Construya el fondo de un juego de tres en línea de multijugador y habilitado para la red con una
aplicación frontal de Android en este artículo.

Juego de tres en línea de multijugador en red


Acrónimos de uso frecuente
• API: Interfaz de programación de aplicaciones
• HTTP: Protocolo de Transferencia de Hipertexto
• IP: Protocolo Internet
• SDK: Kit de desarrollo de software
• SQL: Lenguaje de Consulta Estructurado
• IU: Interfaz de Usuario
• XML: Extensible Markup Language

Los juegos casuales son extremadamente populares y muy lucrativos, y es fácil saber por qué. No todas las
personas de todos los grupos de edades están interesadas en jugar online videojuegos de disparos en primera
persona contra hordas de adolescentes con reflejos tan rápidos como la velocidad de la luz. Algunas veces,
es más interesante jugar videojuegos donde tiene tiempo para pensar y realizar una estrategia o donde la
meta es cooperar unos con otros para ganar el juego.

Lo genial sobre los videojuegos casuales desde la perspectiva de los desarrolladores es que son mucho más
fáciles de construir que los videojuegos intensivos en gráficos de disparos en primera persona o de deportes.
Así que es más fácil para un solo desarrollador, o para un grupo de desarrolladores, producir una primera
versión de un nuevo videojuego original.

En este artículo, pasamos a través de las bases para crear un juego de línea de tres casual de multijugador en
red. El servidor del videojuego es una aplicación web basada en MySQL y PHP con una interfaz XML. La
parte frontal es una aplicación nativa de Android que funciona en teléfonos de Android.

© Copyright IBM Corporation 2012 Marcas


Crear un juego de tres en línea en red para Android Pagina 1 de 21
developerWorks® ibm.com/developerWorks/ssa/

Construyendo el fondo
El fondo inicia con una base de datos simple de MySQL que tiene dos tablas. El Listado 1 muestra el
esquema para la base de datos.

Listado 1. db.sql
DROP TABLE IF EXISTS games;
CREATE TABLE games(
id INT NOT NULL AUTO_INCREMENT,
primary key ( id ) );

DROP TABLE IF EXISTS moves;


CREATE TABLE moves(
id INT NOT NULL AUTO_INCREMENT,
game INT NOT NULL,
x INT NOT NULL,
y INT NOT NULL,
color INT NOT NULL,
primary key ( id ) );

La primera de las dos tablas es la tabla de los juegos, que sólo tiene el ID exclusivo del juego. En una
aplicación de producción, probablemente tenga una tabla de usuarios, y la tabla de juegos incluye los IDs de
usuario de ambos jugadores. Para hacerlo simple, sin embargo, renunciaré a este enfoque para concentrarme
en las bases de almacenar los datos del juego, la comunicación entre el cliente y el servidor y la construcción
de la parte frontal.

La segunda tabla es la tabla de movimientos, que incluye los movimientos individuales para el juego dado,
así que tiene cinco columnas. La primera columna es el ID exclusivo del movimiento. La segunda columna
es el ID del juego al que aplica este movimiento. Después vienen las posiciones 'x' y 'y' del movimiento.
Estos valores deben estar entre 0 y 2 para 'x' y 'y', ya que cuenta con una red de tres por tres. El último
campo es el "color" del movimiento, que es un entero que indica X u O.

Para construir la base de datos, primero use mysqladmin para crearla y después use el comando mysql para
ejecutar el script db.sql como se muestra aquí:

% mysqladmin --user=root --password=foo create ttt


% mysql --user=root --password=foo ttt < db.sql

Esta etapa crea una nueva base de datos llamada "ttt", que tiene el esquema del juego de tres en línea.

ahora que tiene el esquema, necesita crear una forma de iniciar un juego. Para esto, usted cuenta con un
script llamado start.php, como en el Listado 2.

Crear un juego de tres en línea en red para Android Pagina 2 de 21


ibm.com/developerWorks/ssa/ developerWorks®

Listado 2. start.php
<?php
header( 'Content-Type:text/xml' );

$dd = new PDO('mysql:host=localhost;dbname=ttt', 'root', '');


$sql = 'INSERT INTO games VALUES ( 0 )';
$sth = $dd->prepare($sql);
$sth->execute( array() );
$qid = $dd->lastInsertId();

$doc = new DOMDocument();


$r = $doc->createElement( "game" );
$r->setAttribute( 'id', $qid );
$doc->appendChild( $r );

print $doc->saveXML();
?>

El script comienza por conectarse a la base de datos. Después ejecuta una sentencia INSERT en la tabla de
juegos y recupera el ID que fue generado. Desde ahí crea un documento XML, añade el ID a una etiqueta de
juego y exporta el XML.

Necesita ejecutar este script para poner un juego en la base de datos, ya que la simple aplicación de Android
no tiene una interfaz para crear juegos. Este es el código:

$ php start.php
<?xml version="1.0"?>
<game id="1"/>
$

Ahora ya tiene su primer juego. Para ver la lista de juegos, use el script games.php que está en el Listado 3.

Listado 3. games.php
<?php
header( 'Content-Type:text/xml' );

$dbh = new PDO('mysql:host=localhost;dbname=ttt', 'root', '');

$sql = 'SELECT * FROM games';

$q = $dbh->prepare( $sql );
$q->execute( array() );

$doc = new DOMDocument();


$r = $doc->createElement( "games" );
$doc->appendChild( $r );

foreach ( $q->fetchAll() as $row) {


$e = $doc->createElement( "game" );
$e->setAttribute( 'id', $row['id'] );
$r->appendChild( $e );
}

print $doc->saveXML();
?>

Crear un juego de tres en línea en red para Android Pagina 3 de 21


developerWorks® ibm.com/developerWorks/ssa/

Este script, igual que el script.php, comienza por conectarse a la base de datos. Después de eso, consulta la
tabla de juegos para ver qué está disponible. Y desde ahí crea un nuevo documento XML, añade una etiqueta
de juegos, después añade etiquetas de juego para cada uno de los juegos disponibles.

Cuando ejecuta este script desde la línea de comandos, ve algo como esto:

$ php games.php
<?xml version="1.0"?>
<games><game id="1"/></games>
$

También puede ejecutar este script desde el navegador web para ver la misma salida.

¡Excelente! Con la API de juegos fuera del camino, es momento de escribir el código de servidor para
manejar los movimientos. Este código inicia con la construcción de un script ayudante llamado show_moves
que obtiene los movimientos actuales para un juego dado y los exporta como XML. El Listado 4 muestra el
código PHP para esta función de ayudante.

Listado 4. show_moves.php
<?php
function show_moves( $dbh, $game ) {
$sql = 'SELECT * FROM moves WHERE game=?';

$q = $dbh->prepare( $sql );
$q->execute( array( $game ) );

$doc = new DOMDocument();


$r = $doc->createElement( "moves" );
$doc->appendChild( $r );

foreach ( $q->fetchAll() as $row) {


$e = $doc->createElement( "move" );
$e->setAttribute( 'x', $row['x'] );
$e->setAttribute( 'y', $row['y'] );
$e->setAttribute( 'color', $row['color'] );
$r->appendChild( $e );
}

print $doc->saveXML();
}
?>

El script toma un manejador de base de datos y el ID de juego. Desde ahí ejecuta el SQL para obtener la lista
de movimientos. Después crea un documento XML con los movimientos para el juego dado.

Usted creó esta función de ayudante porque hay dos scripts que la usan; el primero es un script moves.php
que retorna los movimientos actuales para el juego especificado. El Listado 5 muestra este script.

Crear un juego de tres en línea en red para Android Pagina 4 de 21


ibm.com/developerWorks/ssa/ developerWorks®

Listado 5. moves.php
<?php
require_once( 'show_moves.php' );

header( 'Content-Type:text/xml' );

$dbh = new PDO('mysql:host=localhost;dbname=ttt', 'root', '');

show_moves( $dbh, $_REQUEST['game'] );


?>

Este simple script incluye el código de la función de ayudante, se conecta a la base de datos y después
invoca la función show_moves con el ID del juego especificado. Para probar este código, use el comando
curl para invocar el script en el servidor desde la línea de comandos:

$ curl "http://localhost/ttt/moves.php?game=1"
<?xml version="1.0"?>
<moves/>
$

Desgraciadamente, aún no ha hecho ningún movimiento, así que no es una salida particularmente
interesante. Para remediar eso necesita añadir el script final a la API del servidor. El Listado 6 muestra el
script move.php.

Listado 6. move.php
<?php
require_once( 'show_moves.php' );

header( 'Content-Type:text/xml' );

$dbh = new PDO('mysql:host=localhost;dbname=ttt', 'root', '');


$sql = 'DELETE FROM moves WHERE game=? AND x=? AND y=?';
$sth = $dbh->prepare($sql);
$sth->execute( array(
$_REQUEST['game'],
$_REQUEST['x'],
$_REQUEST['y']
) );

$sql = 'INSERT INTO moves VALUES ( 0, ?, ?, ?, ? )';


$sth = $dbh->prepare($sql);
$sth->execute( array(
$_REQUEST['game'],
$_REQUEST['x'],
$_REQUEST['y'],
$_REQUEST['color']
) );

show_moves( $dbh, $_REQUEST['game'] );


?>

Este script comienza por incluir la función de ayudante y conectarse a la base de datos. Después ejecuta
dos sentencias SQL. La primera elimina cualquier movimiento que pueda chocar con la que está siendo
enviada. La segunda inserta una nueva fila en la tabla de movimientos para el movimiento especificado. El
script después retorna la lista de movimientos al cliente. Esta etapa salva al cliente de tener que hacer dos
solicitudes cada vez que hace un movimiento. El ancho de banda no es barato, así que siempre que pueda
conglomerar solicitudes debe hacerlo.

Crear un juego de tres en línea en red para Android Pagina 5 de 21


developerWorks® ibm.com/developerWorks/ssa/

Para probar que todo esto funciona, puede hacer un movimiento:

$ curl "http://localhost/ttt/move.php?game=1&x=1&y=2&color=1"
<?xml version="1.0"?>
<moves><move x="1" y="2" color="1"/></moves>

Con el código del servidor del juego completo, puede construir la parte frontal de Android para este juego en
red de multijugador.

Construyendo la parte frontal de Android


Primero, instale el SDK de Android, así como algunas versiones de la plataforma de Android, y después
finalmente Eclipse y el plug-in de Eclipse de Android. Para nuestra suerte, todo esto está bien documentado
en el sitio de Android (vea Recursos para obtener enlaces). Una cobertura a profundidad sobre cómo
configurar su entorno de desarrollo requeriría todo este artículo y más.

Después de que configure el entorno de desarrollo, lance Eclipse e inicie un nuevo proyecto de Android.
Debe ver algo similar a la Figura 1.

Crear un juego de tres en línea en red para Android Pagina 6 de 21


ibm.com/developerWorks/ssa/ developerWorks®

Figura 1. Creando la aplicación de Android en Eclipse

La Figura 1 muestra el asistente de proyecto para aplicaciones de Android. Ingrese el nombre de un


proyecto, seleccione el botón de selección Create new project in workspace y especifique la ubicación
para el código con los elementos de UI. En la lista de comprobación Build Target, seleccione una plataforma
de Android. Para este código, yo uso Android 2.3.1. El código es muy simple, así que puede usar cualquier
versión que prefiera. Si no ve ninguna plataforma listada, entonces necesita descargar e instalar las
plataformas como se indica en las instrucciones de configuración del SDK de Android. Tenga en cuenta que
descargar todas estas plataformas requiere mucho, mucho tiempo.

Crear un juego de tres en línea en red para Android Pagina 7 de 21


developerWorks® ibm.com/developerWorks/ssa/

En la sección Properties , llene el nombre de la aplicación y el nombre del paquete. Yo usé "Tic Tac
Toe" y "com.jherrington.tictactoe" en los campos respectivos. Después, marque el recuadro de selección
Create Activity e ingrese un nombre para la actividad. Yo usé "TicTacToeActivity" como el nombre de la
actividad.

Haga clic en Finish para ver un nuevo proyecto que se parece a la Figura 2.

Figura 2. Los archivos del proyecto TicTacToe

La Figura 2 muestra los directorios de alto nivel y los archivos para una aplicación de Android
(los directorios son src, gen, Android 2.3.1 y res y los archivos son assets, AndroidManifest.xml,
default.properties y proguard.cfg). Los elementos importantes son:

• El directorio res, que contiene recursos


• El directorio src, que tiene el origen de Java™
• El archivo manifest, que contiene la información biográfica sobre la aplicación

Su primera edición es en el archivo manifest. La mayoría del archivo ya está correcto, pero necesita añadir el
permiso de Internet, de forma que la aplicación pueda hacer solicitudes en Internet. El Listado 7 muestra el
archivo manifest completado.

Listado 7. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0" package="com.jherrington.tictactoe">

<uses-permission
android:name="android.permission.INTERNET" />

<uses-sdk android:minSdkVersion="5" />

<application android:icon="@drawable/icon" android:label="@string/app_name">


<activity android:name="TicTacToeActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
</manifest>

El único cambio fue añadir la etiqueta uses-permission en la parte superior del archivo.

Crear un juego de tres en línea en red para Android Pagina 8 de 21


ibm.com/developerWorks/ssa/ developerWorks®

Su siguiente tarea es diseñar la IU. Para esto, ajuste el archivo layout.xml, que está contenido en el directorio
res/layout. El Listado 8 muestra el nuevo contenido para este archivo.

Listado 8. layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/linearLayout1">
<Button android:text="Play X" android:id="@+id/playx"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
<Button android:text="Play O" android:id="@+id/playo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
</LinearLayout>
<com.jherrington.tictactoe.BoardView android:id="@+id/bview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
></com.jherrington.tictactoe.BoardView>
</LinearLayout>

Este es un diseño sencillo. La parte superior es un conjunto de dos botones envueltos en un diseño lineal con
una orientación horizontal. Estos dos botones son los botones X y O que el usuario usa para especificar qué
color está jugando.

El resto del código está llenado con una clase BoardView, que muestra el tablero de tres en línea con el
juego actual. El código para la clase BoardView está en el Listado 11.

Con el diseño a la mano, es momento de escribir algo de código de Java para la aplicación. Esta codificación
comienza con la clase TicTacToeActivity en el Listado 9. Las actividades son los componentes básicos de
aplicaciones de Android. Cada aplicación tiene una o más actividades que representan los diversos estados
de la aplicación. A medida que navega a través de la aplicación construye una pila de actividades que puede
después sacar al usar el botón de retroceso en el teléfono. La aplicación TicTacToe tiene una sola actividad.

Listado 9. TicTacToeActivity.java
package com.jherrington.tictactoe;

import java.util.Timer;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.Gallery;
import android.widget.LinearLayout;

public class TicTacToeActivity extends Activity implements OnClickListener {


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Crear un juego de tres en línea en red para Android Pagina 9 de 21


developerWorks® ibm.com/developerWorks/ssa/

Button playx = (Button)this.findViewById(R.id.playx);


playx.setOnClickListener( this );

Button playo = (Button)this.findViewById(R.id.playo);


playo.setOnClickListener( this );

Timer timer = new Timer();


UpdateTimer ut = new UpdateTimer();
ut.boardView = (BoardView)this.findViewById(R.id.bview);
timer.schedule( ut, 200, 200 );
}

public void onClick(View v) {


BoardView board = (BoardView)this.findViewById(R.id.bview);
if ( v.getId() == R.id.playx ) {
board.setColor( 2 );
}
if ( v.getId() == R.id.playo ) {
board.setColor( 1 );
}
}
}

La actividad tiene dos métodos. El primero es el método onCreate, que construye la interfaz de usuario,
conecta al manejador onClick a los botones X y O e inicia el temporizador de actualización. El temporizador
de actualización es usado para renovar el estado del juego cada 200 milisegundos. Este dispositivo permite a
ambos jugadores ver cuando el otro jugador se mueve.

El manejador onClick establece el color actual del tablero con base en si el usuario hace clic en el botón X o
en el botón O.

La clase GameService, en el Listado 10, es una clase singleton que representa el servidor del juego y el
estado actual del juego dado.

Listado 10. GameService.java


package com.jherrington.tictactoe;

import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.util.Log;

public class GameService {


private static GameService _instance = new GameService();

public int[][] positions = new int[][] {


{ 0, 0, 0 },

Crear un juego de tres en línea en red para Android Pagina 10 de 21


ibm.com/developerWorks/ssa/ developerWorks®

{ 0, 0, 0 },
{ 0, 0, 0 }
};

public static GameService getInstance() {


return _instance;
}

private void updatePositions( Document doc ) {


for( int x = 0; x < 3; x++ ) {
for( int y = 0; y < 3; y++ ) {
positions[x][y] = 0;
}
}
doc.getDocumentElement().normalize();
NodeList items = doc.getElementsByTagName("move");
for (int i=0;i<items.getLength();i++){
Element me = (Element)items.item(i);
int x = Integer.parseInt( me.getAttribute("x") );
int y = Integer.parseInt( me.getAttribute("y") );
int color = Integer.parseInt( me.getAttribute("color") );
positions[x][y] = color;
}
}

public void startGame( int game ) {


HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://10.0.2.2/ttt/moves.php");

try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("game", Integer.toString(game)));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

HttpResponse response = httpclient.execute(httppost);


DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
updatePositions( db.parse(response.getEntity().getContent()) );
} catch (Exception e) {
Log.v("ioexception", e.toString());
}
}

public void setPosition( int game, int x, int y, int color ) {


HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://10.0.2.2/ttt/move.php");

positions[x][y] = color;

try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("game", Integer.toString(game)));
nameValuePairs.add(new BasicNameValuePair("x", Integer.toString(x)));
nameValuePairs.add(new BasicNameValuePair("y", Integer.toString(y)));
nameValuePairs.add(new BasicNameValuePair("color", Integer.toString(color)));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

HttpResponse response = httpclient.execute(httppost);


DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
updatePositions( db.parse(response.getEntity().getContent()) );
} catch (Exception e) {
Log.v("ioexception", e.toString());
}
}
}

Crear un juego de tres en línea en red para Android Pagina 11 de 21


developerWorks® ibm.com/developerWorks/ssa/

Este código es algo del código más interesante en la aplicación. Primero, tiene el método updatePositions,
que toma el XML retornado del servidor y busca los elementos de movimiento, después actualiza la matriz
de posiciones con el conjunto de movimientos actual. La matriz de posiciones tiene un valor para cada
posición en el tablero; cero indica un espacio vacío, 1 representa "O" y 2 es para "X".

Las otras dos funciones, startGame y setPosition, son la forma en que se comunica con el servidor. El
método startGame solicita el conjunto de movimientos actual del servidor y actualiza la lista de posiciones.
El método setPosition publica el movimiento en el servidor al crear una solicitud de publicación HTTP y
configurar los datos para la publicación usando una matriz de pares de valores de nombre, los cuales son
después son codificados para transporte. Después analiza el XML de respuesta para actualizar la lista de
posiciones.

Si observa detenidamente, el IP usado para conectarse al servidor es realmente interesante. No es "localhost"


o "127.0.0.1"; es "10.0.2.2", que es un alias para la máquina en la que se ejecuta el emulador. Ya que
el teléfono de Android es en sí mismo un sistema de UNIX® , tiene sus propios servicios en localhost.
Fascinante, ¿verdad? No es frecuente que sea tan claro que el teléfono no es en realidad un teléfono per
se, sino una computadora en toda regla que se ajusta a la palma de su mano y sucede que tiene un teléfono
integrado en él.

Entonces, ¿dónde estamos? Usted tiene la actividad, que es el componente principal para la aplicación; tiene
la configuración del diseño de IU; tiene el código de Java para conectarse al servidor. Ahora necesita dibujar
el tablero del juego. Esto es realizado por la clase BoardView en el Listado 11.

Listado 11. BoardView.java


package com.jherrington.tictactoe;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class BoardView extends View {


private int _color = 1;

public void setColor( int c ) {


_color = c;
}

public BoardView(Context context) {


super(context);
GameService.getInstance().startGame(0);
}

public BoardView(Context context, AttributeSet attrs) {


super(context,attrs);
GameService.getInstance().startGame(0);
}

public BoardView(Context context, AttributeSet attrs, int defStyle) {


super(context,attrs,defStyle);
GameService.getInstance().startGame(0);
}

Crear un juego de tres en línea en red para Android Pagina 12 de 21


ibm.com/developerWorks/ssa/ developerWorks®

public boolean onTouchEvent( MotionEvent event ) {


if ( event.getAction() != MotionEvent.ACTION_UP )
return true;
int offsetX = getOffsetX();
int offsetY = getOffsetY();
int lineSize = getLineSize();
for( int x = 0; x < 3; x++ ) {
for( int y = 0; y < 3; y++ ) {
Rect r = new Rect( ( offsetX + ( x * lineSize ) ),
( offsetY + ( y * lineSize ) ),
( ( offsetX + ( x * lineSize ) ) + lineSize ),
( ( offsetY + ( y * lineSize ) ) + lineSize ) );
if ( r.contains( (int)event.getX(), (int)event.getY() ) ) {
GameService.getInstance().setPosition(0, x, y, _color);
invalidate();
return true;
}
}
}
return true;
}

private int getSize() {


return (int) ( (float)
( ( getWidth() < getHeight() ) ? getWidth() : getHeight() ) * 0.8 );
}

private int getOffsetX() {


return ( getWidth() / 2 ) - ( getSize( ) / 2 );
}

private int getOffsetY() {


return ( getHeight() / 2 ) - ( getSize() / 2 );
}

private int getLineSize() {


return ( getSize() / 3 );
}

protected void onDraw(Canvas canvas) {


Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
canvas.drawRect(0,0,canvas.getWidth(),canvas.getHeight(), paint);

int size = getSize();


int offsetX = getOffsetX();
int offsetY = getOffsetY();
int lineSize = getLineSize();

paint.setColor(Color.DKGRAY);
paint.setStrokeWidth( 5 );
for( int col = 0; col < 2; col++ ) {
int cx = offsetX + ( ( col + 1 ) * lineSize );
canvas.drawLine(cx, offsetY, cx, offsetY + size, paint);
}
for( int row = 0; row < 2; row++ ) {
int cy = offsetY + ( ( row + 1 ) * lineSize );
canvas.drawLine(offsetX, cy, offsetX + size, cy, paint);
}
int inset = (int) ( (float)lineSize * 0.1 );

paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth( 10 );
for( int x = 0; x < 3; x++ ) {

Crear un juego de tres en línea en red para Android Pagina 13 de 21


developerWorks® ibm.com/developerWorks/ssa/

for( int y = 0; y < 3; y++ ) {


Rect r = new Rect( ( offsetX + ( x * lineSize ) ) + inset,
( offsetY + ( y * lineSize ) ) + inset,
( ( offsetX + ( x * lineSize ) ) + lineSize ) - inset,
( ( offsetY + ( y * lineSize ) ) + lineSize ) - inset );
if ( GameService.getInstance().positions[ x ][ y ] == 1 ) {
canvas.drawCircle( ( r.right + r.left ) / 2,
( r.bottom + r.top ) / 2,
( r.right - r.left ) / 2, paint);
}
if ( GameService.getInstance().positions[ x ][ y ] == 2 ) {
canvas.drawLine( r.left, r.top, r.right, r.bottom, paint);
canvas.drawLine( r.left, r.bottom, r.right, r.top, paint);
}
}
}
}

La mayoría del trabajo aquí es realizado en el método onTouch, que responde al usuario tocando una célula
particular en el tablero del juego, y el método onDraw, que pinta el tablero del juego usando el mecanismo
de pintura de Android.

El método onTouch usa las funciones de tamaño para definir un rectángulo para cada posición de célula.
Después usa el método contains en el rectángulo para ver si el usuario hizo clic dentro de la célula. Si lo
hizo, ejecuta una solicitud al servicio del juego para que haga un movimiento.

La función onDraw usa las funciones de tamaño para dibujar las líneas del tablero y para dibujar cualquier
X u O jugada. El singleton GameServer es usado para su matriz de posiciones, que tiene el estado actual de
cada cuadro en el tablero del juego.

La última clase que necesita es UpdateTimer, que usa el servicio del juego para actualizar las posiciones del
tablero con sus últimos valores. El Listado 12 muestra el código para el temporizador.

Listado 12. UpdateTimer.java


package com.jherrington.tictactoe;

import java.util.TimerTask;

public class UpdateTimer extends TimerTask {


public BoardView boardView;

@Override
public void run() {
GameService.getInstance().startGame( 0 );
boardView.post(new Runnable(){ public void run(){ boardView.invalidate(); } });
}
}

El temporizador es iniciado por la clase TicTacToeActivity cuando la aplicación se inicia. Este temporizador
es un mecanismo de sondeo. Esta no es la forma más eficiente para la comunicación entre el cliente y el
servidor, pero es la más simple y confiable. La forma más eficiente es usar la versión 1.1 del protocolo de
HTTP para mantener la conexión abierta y para que el servidor envíe actualizaciones al cliente cuando se
hagan los movimientos. Este enfoque es mucho más complejo; requiere que el cliente y el servidor soporten
el protocolo 1.1 y tiene problemas de escalabilidad con el número de conexiones. Ese enfoque está fuera del

Crear un juego de tres en línea en red para Android Pagina 14 de 21


ibm.com/developerWorks/ssa/ developerWorks®

ámbito de este artículo. Para juegos simples de demostración como este, un mecanismo de sondeo funciona
bien.

Con el código hecho, puede probar la aplicación. Eso significa iniciar el emulador. Debe ver algo como la
Figura 3 después de inicializar.

Figura 3. Lanzando el emulador de Android

Este es el emulador cargando una fantástica interfaz "A N D R O I D". Después de ser cargada, ve la pantalla
power-on en la Figura 4.

Crear un juego de tres en línea en red para Android Pagina 15 de 21


developerWorks® ibm.com/developerWorks/ssa/

Figura 4. El emulador lanzado y listo para usarse

Para entrar al teléfono, deslice el icono de bloqueo hacia la derecha. Esa acción lo lleva a la pantalla de
inicio y generalmente lanza la aplicación que está depurando. En este caso, esta acción muestra la pantalla
del juego en la Figura 5.

Crear un juego de tres en línea en red para Android Pagina 16 de 21


ibm.com/developerWorks/ssa/ developerWorks®

Figura 5. El juego antes de que se hagan movimientos

Dependiendo del estado de su servidor, puede ver o no ningún movimiento. En este caso, el juego estaba
vacío. Los botones Play X y Play O están en la parte superior con el tablero del juego de línea de tres en el
centro de la visualización. A continuación, haga clic en Play X, después haga clic en el cuadro del centro
para ver algo como la Figura 6.

Crear un juego de tres en línea en red para Android Pagina 17 de 21


developerWorks® ibm.com/developerWorks/ssa/

Figura 6. X toma el cuadro del centro, por supuesto

La Figura 6 muestra la visualización del tablero del juego con una X ahora llenando el cuadro del centro.
Para verificar que el servidor estaba conectado, puede ejecutar el comando curl en el script moves.php en el
servidor para obtener la lista más reciente de movimientos del juego.

Para probar que funcionen las Os, haga clic en Play O y seleccione el cuadro de una esquina como en la
Figura 7.

Crear un juego de tres en línea en red para Android Pagina 18 de 21


ibm.com/developerWorks/ssa/ developerWorks®

Figura 7. O toma el cuadro de una esquina

Puede jugar con Xs y Os. La aplicación se conecta al servidor para alojar el estado del juego en una
ubicación compartida. Y debido al temporizador de actualización, cada usuario puede ver los movimientos
realizados por el otro.

Conclusión
¿Es este un juego completo? No realmente. No hay verificación de condición de victoria, los jugadores
pueden sobrescribir posiciones y no hay verificación de turno. Pero las piezas de tecnología básicas están
presentes: un servidor de juego con el estado almacenado compartido entre los jugadores y una aplicación
gráfica nativa en un dispositivo móvil que se conecta al servidor del juego para proporcionar un interfaz para

Crear un juego de tres en línea en red para Android Pagina 19 de 21


developerWorks® ibm.com/developerWorks/ssa/

el juego. Puede usar este juego como un punto de partida para su propio juego y construirlo como desee.
Sólo recuerde mantenerlo casual y divertido, y tal vez sea el creador del siguiente Words With Friends o
multijugador de Angry Birds.

Crear un juego de tres en línea en red para Android Pagina 20 de 21


ibm.com/developerWorks/ssa/ developerWorks®

Sobre el autor
Jack D. Herrington

Jack Herrington es un ingeniero, autor y presentador que vive y trabaja en el Área de la Bahía.
Puede mantenerse al tanto de su trabajo y sus escritos en http://jackherrington.com.

© Copyright IBM Corporation 2012


(www.ibm.com/legal/copytrade.shtml)
Marcas
(www.ibm.com/developerworks/ssa/ibm/trademarks/)

Crear un juego de tres en línea en red para Android Pagina 21 de 21

Você também pode gostar