Golden Wheel 1.0 (simulazione Java del gioco

Esame di Fondamenti di informatica III
(Professor Hmeljak)
Espeleta Tomas (n°80700189)
[email protected]
Via Amendola 9, 31045 Motta di Livenza - TV
Golden Wheel 1.0 (simulazione Java del gioco della roulette)
INTRODUZIONE
GoldenWheel - la ruota dorata - e' un software per l'emulazione del gioco della roulette. Sviluppato per
l'esame di Fondamenti di Informatica III del corso di D.U. teledidattico in Ingegneria Informatica, consiste in
un sistema interamente scritto in Java che permette di visualizzare su un browser web l'ambiente di gioco di
una roulette francese.
Il sistema e' funzionante, ma per una eventuale diffusione questa distribuzione dovrebbe essere considerato
una "alfa"-release.
IL SERVER
Il server consiste in una applicazione stand-alone scritta in Java2 (gwServer.class), che va dunque avviato
con l'interprete.
Bisogna fare attenzione perche' questo utilizza due librerie presenti sulla cartella corrente del server,
pertanto la linea di comando per avviarlo e' la seguente:
java -cp %CLASSPATH%;tinySQL.jar;cup_runtime.jar gwServer
oppure
run.bat
L'applicazione gwServer, una volta avviata, ascolta sulla porta 8001, creando ad ogni chiamata un nuovo
thread (gwServerThread.class). Questo ascolta il socket, interpretando gli input tramite un protocollo
proprietario, implementato a parte nell'oggetto gwProtocol.
La logica del protocollo e' di fatto quella di una macchina a stati finiti: inizialmente si trova su uno stato di
"attesa". Una volta ricevuto la linea di input, questa viene interpretata e viene restituita una linea di output.
Ecco schematizzati gli stati del protocollo:
STATO0: Da' come benvenuto una riga di output con tutti i dati sul server.
STATO1: Aspetta che venga inserita una password tramite il comando:
PASSWD <utente> <cryptedpasswd>
STATO2: Raggiunto solo se il logon ha successo, interpreta i comandi BET, SPIN, QUIT.
STATO3: Chiamato "BETRCV", viene raggiunto se e' stato trovato il comando BET. In questo stato
vengono immessi i tre dati necessari a "compilare" una scommessa (SESSIONE, CODICE_PUNTATA,
CREDITI_PUNTATI).
I CREDITI
Ho chiamato "crediti" il numero adimensionale della valuta disponibile al giocatore per le puntate. Si e' liberi
di interpretarli come meglio si vuole... sarebbe pero' preferibile utilizzare una valuta "dai numeri brevi", che
rispetti cioe' il valore delle chip disponibili (1, 5, 10, 25).
Esempi: migliaia di lire, euro, dollari.
In questa versione non ho imposto alcun limite alle puntate.
LE PUNTATE
Le puntate cono codificate in un modo abbastanza semplice: un solo intero individua il tipo di puntata e i
numeri puntati: Se "00XX NNMM" e' la rappresentazione esadecimale dell'intero a 32 bit, queste sono le
varie puntate disponibili:
0001 00XX: Numero Pieno. XX e' il numero puntato (hex).
0002 YYXX: Cavallo. XX e YY sono i numeri puntati (hex).
0003 00XX: Terzina (trasversale). XX e' il numero "di testa" puntato: la
terzina e' formata cioe' da XX, XX+1, XX+2
0004 00XX: Quartina (angolo): XX e' ancora il n' di testa. Ad esempio:
XX=14 - Quartina=(20,21,23,24)
0005 0000: Primi quattro. In questa roulette a un solo 0, la puntata
consiste nei numeri: (0, 1, 2, 3)
0006 00XX: Sei numeri (due trasversali): XX e' il numero di testa. XX,
XX+1, ... , XX+5
0010 000X: Dozzina. X e' il numero della dozzina (1, 2, 3).
0011 000X: Colonna. X e' il numero della colonna (1, 2, 3).
(La prima colonna e' quella che contiene 1, 4, ..34)
0020
0021
0022
0023
0024
0025
0001
0001
0001
0001
0001
0001
:
:
:
:
:
:
Rosso
Nero
Pari
Dispari
1-18
19-36
Le scommesse vengono immagazzinate in un vettore ed in un database. Per verificare l'utente e
memorizzare le scommesse ho utilizzato un Database creato con un driver JDBC freeware: tinySQL. Si tratta
di un driver per file di testo e file DBF... non e' certamente il miglior sistema, ne' il piu' veloce... ma la scelta
di JDBC permette di mantenere pressoche' inalterato il codice quando si voglia cambiare driver e base di dati
(ODBC, MySQL, posGrep, etc..)
IL CLIENT
Il client consiste in due applet che interagiscono tra di loro (vedasi iac.txt per maggiori informazioni sulla
comunicazione fra gli applet).
tappeto: consiste in un tappeto verde di gioco, dove si fanno le puntate. Riconosce il tipo di puntata
appena appoggiata la chip (che si posiziona con "snap" solo in certe posizioni di una griglia
determinata), e mantiene un vettore delle chip presenti sul tappeto.
All'avvio della ruota (SPIN), il tappeto trasferisce all'applet della ruota (roulcli.class) tutte le scommesse
(metodo chips2bets).
roulcli: consiste nella ruota vera e propria. Ruota l'immagine con un algoritmo di rotazione, calcolando
ad ogni frame la nuova angolazione. Allo stesso tempo s'incarica della rotazione della pallina, del display
con l'ultimo numero uscito (Display.class). All'inizio si incarica anche del logon dell'utente.
Una volta uscito il numero, chiede a tappeto di rimuovere le chip perse dal giocatore, ed e'pronto per
una nuova tornata.
Ecco che oggetti utilizzano i due applet:
tappeto ---- Chip
+--- (Bet)
roulcli +--- PwdDisplay
+--- Display
+--- Pallina
+--- gwClient --- Bet
+--- Bet
LE CLASSI
Server
addUser.java
Applicazione stand-alone per creare un nuovo utente.
gwServer.java
Applicazione multithread che ascolta sulla porta 8001...
gwServerThread.java Server vero e proprio. Gestisce il socket di connessione.
gwProtocol.java (!) Classe per gestire il protocollo di connessione.
gwDBase.java
Classe che fornisce un'interfaccia al driver JDBC utilizzato.
Package "bet.manage" (gestione scommesse)
---------------------------------------------Bet.java
Oggetto "scommessa", contiene crediti e codice puntata.
BetEncoding.java
Fornisce un metodo statico per la decodifica dei codici puntata.
BetStore.java
Si occupa di memorizzare una scommessa nel DBase.
Package "bet.passwd" (gestione passwords)
-----------------------------------------Passwd.java
Fornisce un metodo che verifica la password passata nel DBase.
CryptPwd.java
Fornisce un metodo che cripta la password con l'algoritmo MD5.
Client
roulcli.java
(!) Applet principale: visualizza la routa,
gestisce la comunicazione C/S.
tappeto.java
(!) Applet tappeto: visualizza il tappeto di gioco e mantiene
una lista di scommesse.
Bet.java
Oggetto "scommessa", contiene crediti e codice puntata.
Chip.java
Oggetto "chip", contiene crediti, codice puntata e posizione.
Pallina.java
Oggetto "pallina": gestione pallina sulla ruota e relativi suoni.
Client.java
Apre un clentSocket sulla porta 8001 e fornisce due stream di I/O
gwClient.java
Client di rete: si collega al server e passa le scommesse.
Display.java
Oggetto che gestisce il display con i numeri usciti
PwdDisplay.java
Pannello iniziale per Logon.
MD5.java
Algoritmo MD5. Traduzione a java (c) 1998 by Michael Lecuyer.
SVILUPPI FUTURI
Ecco alcune idee per sviluppi futuri:
1) La gestione degli utenti e' attualmente limitata a un comando "addUser", che permette soltanto di
creare le tabelle e aggiungere un nuovo username/password. Si puo' estendere l'applicazione (che
dovrebbe usare JDBC), per cancellare un utente, sospenderlo, visualizzarne i crediti...
2) Gestire allo stesso modo un anagrafico del cliente.
3) Grazie a JBDC risulta facile creare una gestione delle puntate e degli utenti tramite WEB. Si puo' ad
esempio creare una serie di pagine amministrative protette da password in cui si fanno delle queries e
delle statistiche sui file di log, nonche' la stessa amministrazione utenti. Si possono utilizzare pagine JSP,
anche se per la gestione di log e' forse piu' adatto uno script Perl, o delle pagine PHP3.
4) Implementare alcuni tipi di scommessa che attualmente non vengono riconosciuti, come ad esempio i
numeri orfanelli e le serie.
5) Migliorare la grafica della pagina, facendo attenzione a rispettare i Tag degli applet. 6) Oscurare la
password in digitazione (PwdDisplay.java)
7) addUser.java deve avvisare se l'utente esiste gia', e chiedere conferma quando viene usdato lo switch '-n'
LISTATI
SERVER:
/**
*** -------------------------------------------------------*** GoldenWheel v0.01 (gwServer.java)
*** Emulazione di Roulette Francese.
*** Server Multigiocatore
*** ideato e creato da Espeleta Tomas. (c)2000
*** (c) 2000 by Espeleta Tomas.
*** Scritto per l'esame di "Fondamenti di informatica III"
*** Diploma teledidattico in Ingegneria informatica
***
email:
[email protected]
***
www:
http://balder.prohosting.com/espeleta
***
indirizzo: v. Amendola 9, 31045 Motta di Livenza - (TV)
***
*** -------------------------------------------------------***/
import java.net.*;
import java.io.*;
public class gwServer {
final static int SERVER_PORT = 8001;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(SERVER_PORT);
System.out.println ("Golden-Wheel Server v0.01, listening... (CTRL-C to
stop)");
} catch (IOException e) {
System.err.println("Could not listen on port: " +
Integer.toString(SERVER_PORT));
System.exit(-1);
}
// Qui accetta le chiamate, creando un nuovo THREAD per ognuna di esse.
while (listening) {
System.gc();
new gwServerThread(serverSocket.accept()).start();
}
serverSocket.close();
}
}
/** (gwServerThread.java)
*** -------------------------------------------------------*** GoldenWheel v0.01 (c)2000 by Espeleta Tomas
*** Emulazione di Roulette Francese.
*** Thread principale del Server. Memorizza e processa
*** le scommesse di un giocatore.
***
*** (c) 2000 by Espeleta Tomas.
*** Scritto per l'esame di "Fondamenti di informatica III"
*** Diploma teledidattico in Ingegneria informatica
***
email:
[email protected]
***
www:
http://balder.prohosting.com/espeleta
***
indirizzo: v. Amendola 9, 31045 Motta di Livenza - (TV)
*** -------------------------------------------------------***/
import java.net.*;
import java.io.*;
public class gwServerThread extends Thread {
private Socket socket = null;
public static int counter;
public gwServerThread(Socket socket) {
super("gwServerThread");
this.socket = socket;
counter++;
System.out.println("Thread has born: " + Integer.toString(counter));
}
public void run() {
try {
BufferedReader reader = new BufferedReader( new
InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
String inputLine, outputLine;
// Chiede la Hello-String del protocollo e la scrive...
gwProtocol gwp = new gwProtocol();
outputLine = gwp.processInput(null);
writer.println(outputLine);
// Legge l'input dal socket e lo processa
// Se il protocollo ritorna QUIT, esce dal thread
while ((inputLine = reader.readLine()) != null) {
outputLine = gwp.processInput(inputLine);
writer.println(outputLine);
if (outputLine.equalsIgnoreCase("QUIT"))
break;
}
writer.close();
reader.close();
socket.close();
} catch (Exception e) {
try {
socket.close();
} catch (Exception se) {
System.out.println("Socket error: " + se);
}
}
}
protected void finalize() {
counter -= (counter > 0) ? 1 : 0;
System.out.println("Thread has died: " + Integer.toString(counter));
}
}
/**
***
***
***
***
***
***
***
***
***
***
---------------------------------------------------------------- **
GoldenWheel v0.01 (c)2000 by Espeleta Tomas (gwProtocol.java)
Emulazione di Roulette Francese.
Protocollo di comunicazione (interpreta le richieste del client):
1) autentica l'utente
2) memorizza le scommesse,
3) fa "girare"la ruota,
4) calcola le vincite.
5) restituisce il numero uscito e un array delle vincite al client.
(c) 2000 by Espeleta Tomas.
*** Scritto per l'esame di "Fondamenti di informatica III"
*** Diploma teledidattico in Ingegneria informatica
***
email:
[email protected]
***
www:
http://balder.prohosting.com/espeleta
***
indirizzo: v. Amendola 9, 31045 Motta di Livenza - (TV)
***
*** ---------------------------------------------------------------- */
import
import
import
import
import
import
import
java.net.*;
java.io.*;
java.util.StringTokenizer;
bet.manage.Bet;
bet.manage.BetStore;
bet.manage.BetEncoding;
bet.passwd.*;
public class gwProtocol {
private
private
private
private
static
static
static
static
final
final
final
final
int
int
int
int
WAITING = 0;
PASSWDREQ = 1;
CMDRCV = 2;
BETRCV = 3;
private int state = WAITING;
private int betParam = 0;
private int number, j;
private
private
private
private
private
Bet mybet = null;
gwDBase myDB;
BetStore bets;
Passwd passwd;
int saldo = 0;
public gwProtocol() {
myDB = new gwDBase();
bets = new BetStore(myDB);
passwd = new Passwd(myDB);
}
public String processInput(String myInput) {
String myOutput = null;
int readNumber;
// STATO0: Welcome
if (state == WAITING) {
myOutput = "Welcome to GoldenWheel Server v0.01! Make your bet...";
state = PASSWDREQ;
// STATO1: Prima di tutto e' NECESSARIO inserire Username e Passwd
//
accetto solo il comando: PASSWD <username> <passwd>
} else if (state == PASSWDREQ) {
if (myInput.startsWith("PASSWD")) {
StringTokenizer st = new StringTokenizer(myInput);
if (st.countTokens() == 3) {
st.nextToken();
String username = st.nextToken();
String pwd = st.nextToken();
StringBuffer s = new StringBuffer();
if (passwd.verify(username, pwd, s)) {
state = CMDRCV;
myOutput = "OK, welcome " + username + ", " + s;
} else {
myDB.close();
myOutput = "QUIT";
}
// Memorizzo il saldo ottenuto nella variabile "saldo"
try {
saldo = Integer.parseInt(s.toString());
} catch (NumberFormatException e) {
saldo = 0;
}
} else {
state = PASSWDREQ;
myOutput = "ERROR: UID/PWD syntax was wrong.";
}
} else myOutput = "ERROR: Password required!";
// STATO2: Interpreta i comandi accettati
} else if (state == CMDRCV) {
if (myInput.startsWith("BET")) {
state = BETRCV;
myOutput = "OK";
} else if (myInput.equals("SPIN")) {
number = (int)Math.round(Math.random() * 36);
//
number = 17;
myOutput = Integer.toString(number) + ",";
if (bets.size() > 0) {
for (j = 0; j < bets.size() - 1; j++) {
myOutput += Integer.toString(BetEncoding.decode((Bet)bets.get(j),
number)) + ",";
}
myOutput += Integer.toString(BetEncoding.decode((Bet)bets.get(j),
number));
}
// Passando il saldo attuale, scrive le variazioni di saldo su DBase e sulla
variabile "saldo"
saldo = bets.writeIt(number, passwd.getUser(), saldo);
// Rimuove tutte le scommesse
bets.clear();
} else if (myInput.equalsIgnoreCase("QUIT")) {
myDB.close();
myOutput = "QUIT";
// Altrimenti.. restituisce un errore
} else {
myOutput = "ERROR: Commands accepted: BET, SPIN, QUIT.";
}
// STATO3: Riceve tre dati per ogni puntata: CLIENTE, CODICE_PUNTATA,CREDITI
} else if (state == BETRCV) {
try {
readNumber = Integer.parseInt(myInput);
if (Bet.needNewOne())
mybet = new Bet();
mybet.addvalue(readNumber);
myOutput = "OK";
} catch (NumberFormatException e) {
mybet.reset();
state = CMDRCV;
myOutput = "ERROR: Number format error.";
System.out.println(myOutput);
}
// Se ha terminato di "riempire" l'oggetto scommessa,
// lo mette via e torna allo stato "Command receive"
if (Bet.ready()) {
bets.add(mybet);
state = CMDRCV;
}
}
return myOutput;
}
}
/**
*** -------------------------------------------------------*** GoldenWheel v0.01
(gwDBase.java)
*** Emulazione di Roulette Francese.
*** Questo oggetto si occupa di aprire il DBase
*** fornisce i due metodi getRs e execute.
*** (c)2000 by Espeleta Tomas
*** -------------------------------------------------------***/
import java.util.*;
import java.sql.*;
public class gwDBase {
private Connection conn;
private Statement st;
public ResultSet rs;
private void getMyConnection() {
String Sistema = System.getProperty("os.name");
// Sotto Windows carico l'ODBC System-DataSource chiamato "mydb"
if (Sistema.startsWith("Win")) {
try {
//
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//
conn = DriverManager.getConnection("jdbc:odbc:mydb");
Class.forName("ORG.as220.tinySQL.textFileDriver").newInstance();
conn = DriverManager.getConnection("jdbc:tinySQL", "", "");
} catch (Exception e) {
System.out.println(e);
System.exit(1);
}
// Sotto Unix o altro, cerco di caricare MySql
} else {
try {
//
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
//
conn =
DriverManager.getConnection("jdbc:mysql://127.0.0.1/mydb?user=myusr&password=mypwd");
Class.forName("ORG.as220.tinySQL.textFileDriver").newInstance();
conn = DriverManager.getConnection("jdbc:tinySQL", "", "");
} catch (Exception e) {
System.out.println(e);
System.exit(1);
}
}
}
public gwDBase() {
getMyConnection();
try {
st = conn.createStatement();
} catch (SQLException e) {
System.out.println(e);
System.exit(1);
}
}
public ResultSet getRs(String sql) {
try {
rs = st.executeQuery(sql);
} catch (SQLException e) {
System.out.println(e);
}
return rs;
}
public boolean execute(String sql) {
boolean retval = false;
try {
retval = st.execute(sql);
} catch (SQLException e) {
System.out.println(e + "(" + sql + ")");
}
return retval;
}
public void close() {
try {
conn.close();
} catch (Exception ignored) {}
}
}
/* ---------------------------------------** Bet.java
** Oggetto 'scommessa': il protocollo si occupa di riempirlo
** con il dati passati man mano dal client:
** Codice Cliente, Codice Puntata, Crediti giocati.
** ---------------------------------------*/
package bet.manage;
public class Bet {
private static boolean betready = false;
private static boolean needNew = true;
private int i = 0;
public int CodCliente;
public int CodPuntata;
public int Credits;
public Bet() {
needNew = betready = false;
}
public void reset() {
i = 0;
betready = false;
needNew = true;
}
public void addvalue(int val) {
if (i == 0) {
CodCliente = val;
i++;
} else if (i == 1) {
CodPuntata = val;
i++;
} else if (i == 2) {
Credits = val;
i = 0;
betready = true;
needNew = true;
}
}
public static boolean needNewOne() {
return needNew;
}
public static boolean ready() {
return betready;
}
}
/*
**
**
**
**
**
**
**
**
**
*/
-----------------------------------------------------------------BetEncoding.java
Contiene il metodo decode(Bet b, int numero_uscito),
questo verifica che il numero sia contenuto nella puntata.
Restituisce:
-1
se non e' una scommessa valida.
moltiplicatore
se il numero uscito era stato scommesso in b.
0
se il numero uscito non e' stato scommesso.
------------------------------------------------------------------
package bet.manage;
public class BetEncoding {
static private final int ERROR = -1;
static private final int NOMATCH = 0;
static private int rossi[] = {1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27,
30, 32, 34, 36};
// numero: numero uscito!
// b: scommessa sotto esame
static public int decode(Bet b, int numero) {
int code = b.CodPuntata;
int which = (code / 0x10000);
// Prendo i 16 bit piu' significativi
int j, n, n1;
int retval = NOMATCH;
// Moltiplicatore della vincita
n = (code & 0x00ff);
// Trattiamo a parte lo zero...
if (n == 0 && which != 0x01 && which != 0x05) {
retval = ERROR;
// Puntate non valide
} else if (numero == 0) {
if (which == 0x05 && n == 0) {
// Primi 4 (0,1,2,3)
retval = 8;
} else if (which == 0x01 && n == 0) { // Pieno
retval = 35;
} else retval = NOMATCH;
// Importante! tutti gli altri casi sono NO match!
// Puntata non valida se il n>36 (ovvio!)
} else if (n > 36) {
retval = ERROR;
// Tutte le altre puntate...
} else {
switch (which) {
case 0x01: // Pieno
if (n == numero) retval = 35;
break;
case 0x02: // Cavallo
n1 = (code & 0xff00) >> 8;
if (n1 > 36) retval = ERROR;
if (n == numero || n1 == numero) retval = 17;
break;
case 0x03: // Terzina
if (((n+2) % 3) != 0) retval = ERROR;
if (n == numero || (n + 1) == numero || (n + 2) == numero) retval = 11;
break;
case 0x04: // Quartina
if (n > 32 || ((n % 3) == 0)) retval = ERROR;
if (numero == n || numero == (n + 1) || numero == (n + 3) || numero ==
(n + 4) )
retval = 8;
break;
case 0x05:
// Primi 4 (0,1,2,3)
retval = NOMATCH;
if (numero == 1 || numero == 2 || numero == 3)
retval = 8;
break;
case 0x06: // Due file
if (n > 31 || ((n+2) % 3) != 0) retval = ERROR;
for (j = 0; j < 6; j++)
if (numero == (n + j)) retval = 5;
break;
case 0x10: // Dozzina
if (numero <= 12 && n == 1) retval = 2;
if (numero > 12 && numero <= 24 && n == 2) retval = 2;
if (numero > 24 && numero <= 36 && n == 3) retval = 2;
break;
case 0x11: // Colonna
if ((numero % 3) == 1 && n == 1) retval = 2;
if ((numero % 3) == 2 && n == 2) retval = 2;
if ((numero % 3) == 0 && n == 3) retval = 2;
break;
case 0x20: // Rosso
for (j = 0; j < 18; j++)
if (numero == rossi[j]) retval = 1;
break;
case 0x21: // Nero
retval = 1;
for (j = 0; j < 18; j++)
if (numero == rossi[j]) retval = 0;
if (numero == 0) retval = 0;
break;
case 0x22: // Pari
if ((numero % 2) == 0) retval = 1;
break;
case 0x23: // Dispari
if ((numero % 2) == 1) retval = 1;
break;
case 0x24: // 1-18
if (numero < 19) retval = 1;
break;
case 0x25: // 19-36
if (numero > 18) retval = 1;
break;
default:
retval = -1;
}
}
return (retval * b.Credits);
// restituisco la vincita
}
}
/*
**
**
**
**
*/
---------------------------------------------------------BetStore.java
Estende la classe Vector: Mette via le scommesse su questo
vettore speciale che scrive anche sulla tabella di log.
----------------------------------------------------------
package bet.manage;
import java.util.Vector;
import java.util.Date;
import java.text.SimpleDateFormat;
import gwDBase;
public class BetStore extends Vector {
private gwDBase db;
public BetStore(gwDBase db) {
super();
this.db = db;
}
// Scrive sul dbase le variazioni al saldo attuale dell'utente
// funzione chiamata da
public int writeIt(int n, String username, int saldo) {
int
int
int
int
Bet
deltaSaldo = 0;
TotScommessa = 0;
TotVincita = 0;
won;
temp = null;
// deltaSaldo del casino
for (int j = 0; j < size(); j++) {
temp = (Bet)get(j);
won = BetEncoding.decode(temp, n);
//System.out.println("Scommessa : " + Integer.toString(temp.Credits) + ", won: " + won);
TotScommessa += temp.Credits;
TotVincita += won;
if (won == 0)
deltaSaldo -= temp.Credits;
// il casino vince
else deltaSaldo += won;
// il casino perde (saldo positivo)
}
saldo += deltaSaldo;
Date d = new Date(System.currentTimeMillis());
SimpleDateFormat f1 = new SimpleDateFormat ("dd/MM/yyyy");
SimpleDateFormat f2 = new SimpleDateFormat ("hh:mm:ss");
db.execute("INSERT INTO logtable (Data, Ora, username, TotScommessa, TotVincita,
deltaSaldo) VALUES ('" + f1.format(d) +"','"+ f2.format(d) +"','"+ username +"','"+
Integer.toString(TotScommessa) +"','"+ Integer.toString(TotVincita) +"','"+
Integer.toString(deltaSaldo) + "')");
db.execute("UPDATE passwd SET saldo = '" + Integer.toString(saldo) + "' WHERE
username = '" + username + "'");
return saldo;
}
}
/*
**
**
**
**
**
**
**
*/
---------------------------------------------------------Passwd.java
Oggetto 'password': controlla username e password passati
al protocollo dal client. Il costruttore richiede il
Dbase dove sono mantenuti i dati per l'autenticazione.
Una volta autenticati, mantiene una copia di Username.
fornisce i due metodi: verify e getUser.
----------------------------------------------------------
package bet.passwd;
import java.sql.*;
import gwDBase;
public class Passwd {
private String username;
private gwDBase db;
private ResultSet rs;
// ---------------------------------------------------------public String getUser() {
String retValue = this.username;
return retValue;
}
// ---------------------------------------------------------// verifica che username/password siano validi, scrive in "Saldo" il saldo di tale utente
public boolean verify(String username, String passwd, StringBuffer Saldo) {
rs = db.getRs("SELECT username, passwd, saldo FROM passwd WHERE username='" +
username + "'");
try {
if (!rs.next()) {
// Username non trovato!
this.username = null;
System.out.println("User not found!");
} else {
int i;
byte[] b1 = (new
CryptPwd()).crypt(rs.getString("passwd").trim()).getBytes();
byte[] b2 = passwd.getBytes();
for (i = 0; i < b1.length && b1[i] == b2[i]; i++);
if (b1.length == b2.length && b2.length == i) {
// Username OK!
this.username = username;
Saldo.append(rs.getString("saldo"));
}
}
} catch (SQLException e) {
System.out.println("---->"+e);
}
return (this.username != null);
}
// ---------------------------------------------------------public Passwd(gwDBase db) {
this.db = db;
}
}
// ---------------------------------------------------------/* -----------------------------------------------** CryptPwd.java
** Fornisce solo un metodo, che cripta la password
** con l'algoritmo standard SHA
** ulteriore livello di sicurezza potrebbe essere
** assicurato da un socket sicuro
** -----------------------------------------------*/
package bet.passwd;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class CryptPwd {
private MessageDigest md;
// -----------------------------------------------public CryptPwd() {
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
System.out.println(e.toString());
}
}
// -----------------------------------------------private final String digits = "0123456789ABCDEF";
public String crypt(String toBeCrypted) {
StringBuffer result = new StringBuffer();
md.update(toBeCrypted.getBytes());
byte b[] = md.digest();
// Rappresentazione esadecimale della password criptata
for (int j = 0; j < b.length; j++) {
result.append(digits.charAt((int)(b[j] >> 4) & 0xf));
result.append(digits.charAt((int)(b[j]) & 0xf));
}
return result.toString();
}
}
// ----------------// Add user/password
// ----------------import java.util.*;
import java.sql.*;
class addUser {
public static void main(String argv[]) {
boolean newtable = false;
// flag
//System.out.println(Integer.toString(argv.length));
if (argv.length != 3) {
if (argv.length == 4 && argv[0].equals("-n"))
newtable = true;
else {
System.out.println("Ohps, syntax error:\n
Use: java addUser [-n]
<username> <password> <credits>\n
-n: creates a new table, REMOVING OLD USERS!");
return;
}
}
try {
// Cerchiamo di registrare textFileDriver.
Class.forName("ORG.as220.tinySQL.textFileDriver").newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.err.println(
"I could not find the tinySQL classes. Did you install\n" +
"them as directed in the README file?");
e.printStackTrace();
}
try { // Stiamo attenti alle SQLExceptions!
// Colleghiamoci al tinySQL Driver.
Connection con = DriverManager.getConnection("jdbc:tinySQL", "", "");
// prendiamo un oggetto Statement dalla Connessione
Statement stmt = con.createStatement();
// Se c'e' lo switch -n, crea nuova tabella
int i = 0;
if (newtable) {
stmt.executeUpdate("CREATE TABLE passwd (username CHAR(10), passwd
CHAR(10), saldo NUMERIC(10))");
System.err.println("Created the passwd table.");
stmt.executeUpdate("CREATE TABLE logtable (Data CHAR(10), Ora CHAR(8),
username CHAR(10), TotScommessa NUMERIC(10), TotVincita NUMERIC(10), deltaSaldo
NUMERIC(10))");
System.err.println("Created the logtable table.");
i = 1;
}
// Insert new user
try {
stmt.executeUpdate("INSERT INTO passwd (username, passwd, saldo)
VALUES('" + argv[0+i] + "', '" + argv[1+i] + "', '" + argv[2+i] +"')");
System.out.println("User added!");
} catch (Exception e) {
System.out.println("Some problem adding user: " + e.getMessage());
}
stmt.close();
con.close();
} catch( Exception e ) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
CLIENT:
//
//
//
//
//
//
//
//
//
//
//
//
//
---------------------------------------------------------------Golden-Wheel applet.
(roulcli.java)
Simulazione della roulette francese. (c)2000 by Espeleta Tomas.
Funziona solo se in comunicazione con a pagina web attraverso
l'oggetto JSObject.
(c) 2000 by Espeleta Tomas.
Scritto per l'esame di "Fondamenti di informatica III"
Diploma teledidattico in Ingegneria informatica
email:
[email protected]
www:
http://balder.prohosting.com/espeleta
indirizzo: v. Amendola 9, 31045 Motta di Livenza - (TV)
----------------------------------------------------------------
import com.ms.security.*;
import
import
import
import
import
import
import
import
import
java.net.*;
java.awt.*;
java.awt.image.MemoryImageSource;
java.awt.image.PixelGrabber;
java.awt.Color;
java.applet.Applet;
java.applet.AppletContext;
java.util.Vector;
java.util.StringTokenizer;
public class roulcli extends Applet implements Runnable {
private final int DELAY = 54;
private Thread appletThread;
private Image image, ballImg;
private Image image2, backImage, tempImg;
private Graphics tempG;
private MemoryImageSource imgSrc;
private int buffer1[], buffer2[];
private int larghezza, altezza;
private int appletW, appletH;
private int wherex, wherey;
private int frame;
private int cosNorm[] = new int[360];
private int sinNorm[] = new int[360];
private double angolo, speed;
private boolean spinCmd = false;
private boolean firstremove = true; // flag per rimuovere una sola volta le chip
private String n;
// Numero uscito, settato da beginSpin, stampato da
aggiornaGraph
private Color bgColor;
private int winnerNum;
// Dati di risposta del server
private String wonString;
private
private
private
private
Pallina pallina;
Display display;
PwdDisplay pd;
gwClient gwc;
public Vector bets;
// ATTENZIONE! bets deve essere riempito da un altro applet!
// ---------------------------------------------------------------public void init() {
// Assicura il funzionamento della rete su IE
try {
if (Class.forName("com.ms.security.PolicyEngine") != null)
PolicyEngine.assertPermission(PermissionID.NETIO);
} catch (Throwable cnfe) {}
// Dimensioni dell'applet
appletW = size().width;
appletH = size().height;
// bgcolor e' il parametro dell'applet per il background
try {
bgColor = new Color(Integer.parseInt(getParameter("bgcolor"), 16));
} catch (Exception e) {
bgColor = Color.white;
}
// Coloriamo l'applet di bgColor (verde!)
Graphics g = getGraphics();
g.setColor(bgColor);
g.fillRect(0, 0, appletW, appletH);
// Inizializza i suoni della pallina
Pallina.initBallSounds(this);
// Calcola tabella dei seni e dei coseni
calcolaSinCos();
// Crea array delle scommesse e un client GoldenWheel
bets = new Vector(30);
gwc = new gwClient(getDocumentBase().getHost(), this);
// Creo la pallina
if ((ballImg = loadImage("images/pallina.gif")) == null)
showStatus("Errore nell\'immagine ");
// Carico le due immagini della roulette...
if ((backImage = loadImage("images/r.jpg")) == null)
showStatus("Errore nell\'immagine ");
if ((image = loadImage("images/r2.gif")) == null)
showStatus("Errore nell\'immagine ");
// ... e ne memorizzo le dimensioni
larghezza = image.getWidth(this);
altezza = image.getHeight(this);
// Creo un double-buffer (offscreen)
tempImg = createImage(appletW, appletH);
tempG = tempImg.getGraphics();
tempG.setColor(bgColor);
// Creo i display... quello delle password e' un panel.
this.setLayout(new BorderLayout());
display = new Display(tempG, (appletW - 120) / 2, (appletH +
backImage.getHeight(this) - 70) / 2, 120, 70);
pd = new PwdDisplay(bgColor, gwc);
this.add(BorderLayout.SOUTH, pd);
// deprecated
// Per le animazioni, creo due buffer. Li inizializzo con l'immagine della ruota.
buffer1 = new int[larghezza * altezza];
buffer2 = new int[larghezza * altezza];
capturePixels(image, buffer1);
imgSrc = new MemoryImageSource(larghezza, altezza, buffer2, 0, larghezza);
imgSrc.setAnimated(true);
image2 = createImage(imgSrc);
imgSrc.newPixels(0, 0, larghezza, altezza, true);
}
// ---------------------------------------------------------------public void start() {
appletThread = new Thread(this);
appletThread.setPriority(Thread.NORM_PRIORITY);
appletThread.start();
}
// ---------------------------------------------------------------public void run() {
showStatus("Welcome to GoldenWheel 1.0...");
System.gc();
// Disegno le due immagini della roulette
if (backImage != null && image != null) {
// (wherex, wherey) e' il centro della roulette
wherex = (backImage.getWidth(this) >> 1);
wherey = (backImage.getHeight(this) >> 1);
tempG.fillRect(0, 0, appletW, appletH);
tempG.drawImage(backImage, 0, 0, this);
tempG.drawImage(image, 33, 33, this);
// Non ci serve piu': la abbiamo in buffer1 ;-)
image = null;
}
// --------------------------------------------// CICLO PRINCIPALE DI ANIMAZIONE
// (tm serve a mantenere costante il framerate)
long tm = System.currentTimeMillis();
boolean once = true;
while (appletThread != null) {
// Quando c'e' lo spin, calcola un nuovo angolo
if (spinCmd) {
angolo = (angolo + speed) % 360;
ruota();
// notifica il cambiamento dei pixels...
imgSrc.newPixels(0, 0, larghezza, altezza, true);
// calcola la nuova posizione della pallina.
if (!(pallina.isready()))
pallina.nextpos();
// Inizia il suono di rotazione della pallina
pallina.changeSound(2);
}
// Se ci si e' loggati, mostra il display (una volta)...
if (gwc.pwdok() && once) {
display.paint();
once=false;
}
// Disegna il nuovo angolo
repaint();
// Aspetta il prossimo frame
tm += DELAY;
delay((int)Math.max(0, tm - System.currentTimeMillis()) );
frame++;
// La ruota pian piano si ferma: ogni 38 frame rallenta...
if ((speed -= ((frame % 38 == 0) ? 1 : 0)) <= 0) {
speed = 0;
spinCmd = false;
}
}
}
// ---------------------------------------------------------------public void stop() {
// Spegni tutti i suoni! 8-)
if (pallina != null)
pallina.changeSound(0);
// Chiudi il client...
if (gwc != null)
gwc.close();
// ...e annulla il thread.
if (appletThread != null) {
appletThread = null;
backImage = image2 = null;
}
}
// ---------------------------------------------------------------// la coppia paint() - update() permette di eliminare il farfallio
// ---------------------------------------------------------------public void paint(Graphics g) {
update(g);
}
public void update(Graphics g) {
aggiornaGraph(g);
}
// ---------------------------------------------------------------//
funzione di vero e proprio aggiornamento del tappeto
// ---------------------------------------------------------------void aggiornaGraph(Graphics g) {
if (spinCmd) { // se ancora c'e' spin...
// Disegna background
tempG.fillRect(0, 0, appletW, appletH);
tempG.drawImage(backImage, 0, 0, null);
tempG.drawImage(image2, wherex - (larghezza>>1)-1, wherey - (altezza>>1)-1,
null);
if (n != null && pallina.isarrived()) {
display.setString(n);
// Chiama una volta
if (firstremove) {
firstremove = false;
// la funzione di notifica in "tappeto"...
// tappeto.removeLostChips(wonString);
vedi IAC.TXT
getAppletContext().getApplet("sender").getParameter("%removeLostChips%" + wonString);
}
} else {
display.setString("");
}
// Disegna display
display.paint();
// Disegna pallina
if (pallina.isready())
pallina.disegna(tempG, (int)angolo);
else pallina.disegna(tempG, wherex, wherey, (int)angolo);
}
g.drawImage(tempImg, 0, 0, this);
}
//
//
//
//
---------------------------------------------------------------Calcolo la tabella dei seni e quella dei coseni:
Ottengo valori interi perche' li moltiplico per 255 ;-)
---------------------------------------------------------------void calcolaSinCos() {
final double SEX2RAD = (2 * Math.PI) / 360;
for (int i = 0; i < 360; i++) {
cosNorm[i] = (int)(Math.cos(SEX2RAD * (double)i) * 255D);
sinNorm[i] = (int)(Math.sin(SEX2RAD * (double)i) * 255D);
}
}
// ---------------------------------------------------------------Image loadImage(String s) {
showStatus("Loading images...");
MediaTracker mediatracker = new MediaTracker(this);
URL url = null;
Image image = null;
try {
url = new URL(getDocumentBase(), s);
} catch(MalformedURLException _ex) { }
try {
image = getImage(url);
mediatracker.addImage(image, 1);
mediatracker.waitForID(1);
} catch(InterruptedException _ex) {
image = null;
}
if (mediatracker.isErrorID(1))
image = null;
return image;
}
// ---------------------------------------------------------------// Esegue i calcoli su buffer2, ruotando di "angolo".
// ---------------------------------------------------------------void ruota() {
int cosalfa = cosNorm[359 - (int)angolo];
int sinalfa = sinNorm[359 - (int)angolo];
int lmezzi = larghezza >> 1;
int hmezzi = altezza >> 1;
// Applico la formula (x1, y1) = (cosalfa*x - sinalfa*y, sinalfa*x+cosalfa*y)
// PixelGrabber mette il punto (x,y) in buffer[
for (int y = -hmezzi; y < hmezzi; y++) {
int k1 = y * sinalfa >> 8;
int l1 = y * cosalfa >> 8;
int start = larghezza * (y + hmezzi);
for (int x = -lmezzi; x < lmezzi; x++) {
int x1 = (x * cosalfa >> 8) - k1;
int y1 = (x * sinalfa >> 8) + l1;
if (x1 >= -lmezzi && x1 < lmezzi && y1 >= -hmezzi && y1 < hmezzi)
buffer2[start + (x + lmezzi)] = buffer1[larghezza * (y1 + hmezzi) +
(x1 + lmezzi)];
}
}
}
// ---------------------------------------------------------------//
Copia l'immagine data nel buffer
// ---------------------------------------------------------------void capturePixels(Image img, int buff[]) {
PixelGrabber pg = new PixelGrabber(img, 0, 0, larghezza, altezza, buff, 0,
larghezza);
try {
if (!pg.grabPixels()) {
showStatus("Image error");
appletThread = null;
}
} catch (InterruptedException e) {
showStatus("Image error");
appletThread = null;
}
if ((pg.status() & 0x80) != 0) {
showStatus("Image error");
appletThread = null;
}
}
// ----------------------------------------------------------------//
Il seguente metodo viene chiamato da Javascript:
// (per funzionare su netscape devo fare un catch delle exceptions)
// ----------------------------------------------------------------public void beginSpin() {
// Non giro la ruota se la password non e' OK.
if (!gwc.pwdok())
return;
// Mi collego al server...
int risultato = -1;
String results[] = new String[1];
results[0] = "Error!";
// Creo un collegamento col server (se questo e' giu')
if (!gwc.isAlive()) {
gwc = new gwClient(getDocumentBase().getHost(), this);
}
// Passo le scommesse al client GWC e ottengo il risultato
if (gwc != null && bets != null) {
gwc.setBets(bets);
risultato = gwc.bet(results);
if (risultato == -1 || results[0].equals(""))
n = "Error, " + Integer.toString(risultato);
else n = Integer.toString(risultato);
}
// Memorizzo i risultati
winnerNum = risultato;
wonString = new String(results[0]);
firstremove = true;
// flag per rimuovere una sola volta le chip
// Creo una pallina che si fermi sul numero ottenuto! ;-)
if (risultato != -1) {
pallina = null;
System.gc();
speed = 10;
pallina = new Pallina(ballImg, cosNorm, sinNorm, risultato);
pallina.changeSound(1);
spinCmd = true;
}
}
// --------------------------------------------------------// Funzione per sapere da fuori (tappeto) se la password e' OK...
public boolean pwdok() {
return gwc.pwdok();
}
// --------------------------------------------------------void delay(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException ignored) {}
}
// --------------------------------------------------------public Insets getInsets() {
return new Insets(280,2,2,2);
}
// --------------------------------------------------------// getParameter: %comando%parametri%separati%da%percentuale
//
vedi iac.txt
public String getParameter(String cmd) {
StringTokenizer st = new StringTokenizer(cmd, "%");
if (!cmd.startsWith("%"))
return super.getParameter(cmd);
try {
String s = st.nextToken();
if (s.equals("removeAllElements")) {
bets.removeAllElements();
return null;
}
else
if (s.equals("addElement")) {
int code = Integer.parseInt(st.nextToken());
int value = Integer.parseInt(st.nextToken());
bets.addElement(new Bet(code, value));
return null;
}
if (s.equals("pwdok")) {
return (new Boolean(pwdok())).toString();
}
} catch (Exception ignored) {}
return null;
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
------------------------------------------------------GoldenWheel v1.0 (tappeto.class)
Oggetto “tappeto”
Applet che ricrea il magico tappeto verde 8-)
(c) 2000 by Espeleta Tomas.
Scritto per l'esame di "Fondamenti di informatica III"
Diploma teledidattico in Ingegneria informatica
email:
[email protected]
www:
http://balder.prohosting.com/espeleta
indirizzo: v. Amendola 9, 31045 Motta di Livenza - (TV)
-------------------------------------------------------
import
import
import
import
import
import
import
java.applet.Applet;
java.applet.AppletContext;
java.awt.*;
java.util.Random;
java.util.Vector;
java.util.StringTokenizer;
netscape.javascript.JSObject;
public class tappeto extends Applet implements Runnable {
private
private
private
private
private
private
private
private
e' nuova
private
private
private
scommesse
private
Dimension dimensioni;
// dimensioni dell'Applet
Thread myself;
// Thread
MediaTracker trk;
// per caricare le immagini
Graphics tempG;
// Doppio buffer
Image tappetoImg, tempImg; // Immagini
Image chip1Img, chip5Img, chip10Img, chip25Img;
boolean inizializzato;
// Flag di inizializzazione
boolean newbet;
// Flag: la chip appena rilasciata sul tappeto,
Font mainfont;
Color bgColor;
Vector Chips;
// Font dei messaggi
// Colore: impostare col parametro bgColor
// il vero e proprio tappeto... memorizza le
Chip newChip;
// Oggetto chip per le fiches temporanee
protected roulcli externo;
public JSObject win;
String pippo = "";
int xClick, yClick;
int newx, newy;
int chipidx = -1;
int CREDITI = 0;
//
Griglia di
int[] tabX
263, 282, 298,
int[] tabY
tutte le coordinate dei numeri e degli incroci possibili
= new int[] {40, 57, 75, 91, 109, 126, 144, 160, 178, 195, 213, 229, 247,
316, 332, 351, 367, 385, 401, 420, 436, 473, 20 };
= new int[] {21, 34, 52, 66, 82, 98, 114, 126, 152 };
static final int XCHIP1 = 180;
static final int XSTEP = 30;
static final int YCHIPS = 180;
// -------------------------------------------------public void init() {
super.init();
dimensioni = size();
trk = new MediaTracker(this);
// Inizializza bgColor
try {
//pippo = Integer.toHexString(Color.decode(getParameter("bgcolor")).getRGB());
bgColor = new Color(Integer.parseInt(getParameter("bgcolor"), 16));
} catch (Exception e) {
bgColor = Color.green;
}
setBackground(bgColor);
// Creo un double-buffer (offscreen)
tempImg = createImage(dimensioni.width, dimensioni.height);
tempG = tempImg.getGraphics();
tempG.setColor(bgColor);
// Oggetto per scrivere i crediti nella pag. HTML ;-)
win = JSObject.getWindow(this);
}
// -------------------------------------------------void delay(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException ignored) {}
}
// -------------------------------------------------public void run() {
start();
repaint();
while (myself != null) {
repaint();
delay(30);
}
}
// -------------------------------------------------public void start() {
// Trasforma l'applet in un thread
if (myself == null) {
myself = new Thread(this);
myself.start();
}
}
// -------------------------------------------------public void stop() {
if (myself != null)
myself = null;
}
// -------------------------------------------------// la coppia paint() - update()
// permette di eliminare il farfallio
public void update(Graphics g) {
aggiornaGraph(g);
}
public void paint(Graphics g) {
update(g);
}
// ---------------------------------------------------------------private void loadImages() {
tappetoImg = getImage(getCodeBase(), "images/tappeto.jpg");
trk.addImage(tappetoImg, 1);
chip1Img = getImage(getCodeBase(), "images/chip1.gif");
trk.addImage(chip1Img, 2);
chip5Img = getImage(getCodeBase(), "images/chip5.gif");
trk.addImage(chip5Img, 3);
chip10Img = getImage(getCodeBase(), "images/chip10.gif");
trk.addImage(chip10Img, 4);
chip25Img = getImage(getCodeBase(), "images/chip25.gif");
trk.addImage(chip25Img, 5);
try {
trk.waitForAll();
} catch(InterruptedException ignored) {}
inizializzato = true;
}
// -------------------------------------------------// Funzione che decide SE e DOVE piazzare la chip: (x,y) e'
// il punto dove viene rilasciata la chip. (newx, newy) il nuovo punto
public boolean place(int x, int y) {
int i, j;
// Due aree fuori dall'area di puntata valida
if (y > 170)
return false;
if (x < 40 && y > 124)
return false;
// Cerco a quale punto della griglia si avvicina di piu'
// la chip che voglio posizionare.
for (i = 1; i < 24 && x > tabX[i]; i++);
for (j = 1; j < 8 && y > tabY[j]; j++);
// Imposto le nuove coordinate (prendo la distanza minore)
newx = ((x - tabX[i-1]) < (tabX[i] - x)) ? i - 1 : i;
newy = ((y - tabY[j-1]) < (tabY[j] - y)) ? j - 1 : j;
// Non tutta la griglia e' valida!
if (newx == 24) {
// Colonne
if (newy == 0) newy = 1;
if (newy == 6) newy = 5;
if (newy > 6) return false;
} else if (newy == 7) {
// 1st, 2nd, 3rd
if (x < tabX[8]) { newx = 4; }
else if (x < tabX[16]) { newx = 12; }
else if (newx < 24) { newx = 20; }
} else if (newy == 8) {
// 1-18 Even red black Odd 19-36
if (x < tabX[4]) { newx = 2; }
else if (x < tabX[8]) { newx = 6; }
else if (x < tabX[12]) { newx = 10; }
else if (x < tabX[16]) { newx = 14; }
else if (x < tabX[20]) { newx = 18; }
else if (newx < 24) { newx = 22; }
} else if (newx == 0) {
if (newy > 0 && newy < 6) {
if (x < tabX[0]) {
// Zero
newx = 25;
newy = 3;
} else newx = 1;
// prima traversa
}
}
return true;
}
// -------------------------------------------------public void paintChip(Chip mychip, Graphics g) {
if (mychip.value == 1)
tempG.drawImage(chip1Img, mychip.xPos, mychip.yPos, null);
if (mychip.value == 5)
tempG.drawImage(chip5Img, mychip.xPos, mychip.yPos, null);
if (mychip.value == 10)
tempG.drawImage(chip10Img, mychip.xPos, mychip.yPos, null);
if (mychip.value == 25)
tempG.drawImage(chip25Img, mychip.xPos, mychip.yPos, null);
}
// -------------------------------------------------public void aggiornaGraph(Graphics g) {
if (!inizializzato) {
g.setFont(mainfont);
g.setColor(Color.white);
g.drawString("Sto caricando le immagini...", 15, dimensioni.height/2);
loadImages();
return;
}
tempG.setColor(bgColor);
tempG.fillRect(0, 0, dimensioni.width, dimensioni.height);
tempG.drawImage(tappetoImg, 0, 0, null);
tempG.drawImage(chip1Img, XCHIP1, YCHIPS, null);
tempG.drawImage(chip5Img, XCHIP1 + XSTEP, YCHIPS, null);
tempG.drawImage(chip10Img, XCHIP1 + XSTEP * 2, YCHIPS, null);
tempG.drawImage(chip25Img, XCHIP1 + XSTEP * 3, YCHIPS, null);
tempG.setColor(Color.white);
tempG.drawString(pippo, 20, 10);
/*
for (int i = 0; i < Chips.size(); i++) {
tempG.setColor(Color.white);
tempG.drawString(Integer.toString(((Chip)Chips.elementAt(i)).value), 20, 40+10*i);
}
*/
for (int i = 0; i < Chips.size(); i++)
paintChip((Chip)Chips.elementAt(i), tempG);
if (newChip != null)
paintChip(newChip, tempG);
g.drawImage(tempImg, 0, 0, this);
}
// --------------------------------------------------------// Rimuove le chip perse e ritorna i crediti aggiornati
// ** Funzione chiamata al momento giusto da roulcli.
public void removeLostChips(String risultati) {
int won, removed=0;
StringTokenizer st = new StringTokenizer(risultati, ",");
try {
for (int i = 0; st.hasMoreTokens(); i++) {
won = Integer.parseInt(st.nextToken());
if (won > 0) {
// Vinto!
CREDITI += won;
} else if (won == 0) {
// Perso!
Chips.removeElementAt(i-removed);
removed++;
}
}
} catch (Exception e) {
pippo = "Exception Removing chip!" + e.toString();
}
// ... e la funzione di notifica nella pag HTML
win.call("updatebank", null);
}
// --------------------------------------------------------// ** Funzione chiamata da Javascript per sapere se c'e' qualche chip scommessa
public boolean anyBet() {
chips2bets();
// riempio il Vector di scommesse
return (Chips.size() > 0);
}
// --------------------------------------------------------public void chips2bets() {
// Inizializza l'applet getApplet(), non faccio un cast a roulcli
// perche' getApplet su Netscape non ritorna un oggetto corretto...
// si vedano le note sulla comunicazione fra applet (iac.txt)
Applet roulApplet = getAppletContext().getApplet("receiver");
// IMPORTANTE: riempio il vector bets dell'applet "roulcli"
Chip mychip;
// Rimuove tutte le scommesse: VEDI IAC.TXT
// roulApplet.bets.removeAllElements();
roulApplet.getParameter("%removeAllElements%");
for (int i = 0; i < Chips.size(); i++) {
mychip = (Chip)Chips.elementAt(i);
// roulApplet.bets.addElement(new Bet(mychip.code, mychip.value));
roulApplet.getParameter("%addElement%" + Integer.toString(mychip.code) + "%"
+ Integer.toString(mychip.value));
}
}
// --------------------------------------------------------// setCredits: chiamata da gwClient per impostare i crediti dell'utente
public void setCredits(int credits) {
CREDITI = credits;
win.call("updatebank", null);
}
// ------------------------------------------------------------//
Il seguente metodo viene chiamato da Javascript:
// ------------------------------------------------------------public String getCredits() {
return Integer.toString(CREDITI);
}
// -------------------------------------------------//
CONTROLLO DEL DRAG AND DROP
// --------------------------------------------------
public boolean mouseDown(Event event, int i, int j) {
newbet = false;
xClick = i;
yClick = j;
// Inizializza l'applet roulcli x comunicazioni fre i due applet
Applet roulApplet = getAppletContext().getApplet("receiver");
if (roulApplet.getParameter("%pwdok%").equals("false")) {
return true;
}
if (yClick > YCHIPS && yClick < YCHIPS + 20) {
if (newChip == null)
newChip = new Chip();
newChip.xPos = xClick - 10;
newChip.yPos = yClick - 10;
if (xClick > XCHIP1 && xClick < XCHIP1 + 20) {
newChip.value = 1;
} else if (xClick > XCHIP1 + XSTEP && xClick < XCHIP1 + XSTEP + 20) {
newChip.value = 5;
} else if (xClick > XCHIP1 + XSTEP * 2 && xClick < XCHIP1 + XSTEP * 2 + 20) {
newChip.value = 10;
} else if (xClick > XCHIP1 + XSTEP * 3 && xClick < XCHIP1 + XSTEP * 3 + 20) {
newChip.value = 25;
} else newChip = null;
if (newChip != null)
newbet = true;
}
// Controlla se viene premuto su qualche chip
// gia' presente sul tavolo
for (int k = 0; k < Chips.size(); k++) {
Chip myChip = (Chip)Chips.elementAt(k);
if (xClick > myChip.xPos && xClick < myChip.xPos + 20)
if (yClick > myChip.yPos && yClick < myChip.yPos + 20) {
newChip = myChip; // Copia il puntatore e...
chipidx = k;
// memorizza l'indice della chip presa
}
}
repaint();
return true;
}
// -------------------------------------------------public boolean mouseDrag(Event event, int i, int j) {
if (newChip == null)
return true;
if (newChip.value > 0) { // chip presa!
newChip.xPos = i - 10;
newChip.yPos = j - 10;
}
repaint();
return true;
}
// -------------------------------------------------public boolean mouseUp(Event event, int i, int j) {
try {
if (newChip != null) {
// Se la chip viene piazzata con successo
if (place(i, j)) {
//showStatus(Integer.toString(newx)+ "," + Integer.toString(newy));
//pippo = Integer.toString(newChip.code);
newChip.xPos = tabX[newx] - 10;
newChip.yPos = tabY[newy] - 10;
newChip.code = codifica(newx, newy);
if (chipidx == -1) {
// ADD CHIP (SE NON GIA' MEMORIZZATA)
Chips.addElement(newChip);
}
// rimuove il valore della chip dai CREDITI
if (newbet)
CREDITI -= newChip.value;
// Altrimenti se era gia' memorizzata, la cancello dal Vector...
// e riaggiunge il valore della chip ai CREDITI
} else if (chipidx != -1) {
CREDITI += newChip.value;
Chips.removeElementAt(chipidx);
}
}
win.call("updatebank", null);
// Aggiorna tabellone CREDITI
chipidx = -1;
newChip = null;
} catch (Exception e) {pippo = e.toString();
}
repaint();
return true;
}
// -------------------------------------------------public tappeto() {
inizializzato = false;
mainfont = new Font("Helvetica", 1, 16);
Chips = new Vector();
}
// -------------------------------------------------public int codifica(int x, int y) {
int n = 0;
// X Dispari: spazi vuoti
if ((x % 2) == 1) {
// Numeri
if ((y % 2) == 1) { // y dispari
n = 2+(3*x-y)/2;
n = (0x1 << 16) + n;
}
// Cavalli sulle righe orizz.
if (y == 2 || y == 4) { // y = 2 o 4
n = (3+3*x-y)/2;
n = (0x2 << 16) + (n<<8) + (n+1);
}
// Traverse
if (y == 0 || y == 6) { // x dispari, y = 0,6
n = (3*(x-1))/2 + 1;
n = (0x3 << 16) + n;
}
// X Pari: linee
} else {
// Cavalli sulle righe vert.
if (y == 1 || y == 3 || y == 5) { // x pari, y =1,3,5
n = (1+3*x-y)/2;
n = (0x2 << 16) + (n<<8) + (n+3);
}
// Angoli
if (y == 2 || y == 4) { // x pari, y = 2 o 4
n = (3*x-y)/2;
n = (0x4 << 16) + n;
}
// Traverse Doppie
if (y == 0 || y == 6) { // x pari, y = 0,6
n = (3*(x-1))/2;
n = (0x6 << 16) + n;
}
}
// Colonne
if (x == 24) {
if ((y % 2) == 1) { // x=24, y dispari
n = 3 - (y-1)/2;
n = (0x11 << 16) + n;
}
}
// Primi quattro numeri
if (x == 0)
n = (0x5 << 16);
// Zero
if (x == 25)
n = (0x1 << 16);
//
Scommesse in basso:
if (y == 7) {
// 1st dozen
if (x == 4) {
n = (0x10 << 16) + 1;
// 2nd dozen
} else if (x == 12) {
n = (0x10 << 16) + 2;
// 3rd dozen
} else if (x == 20) {
n = (0x10 << 16) + 3;
}
} else if (y == 8) {
// 1-18
if (x == 2) {
n = (0x24 << 16) +
// Pari
} else if (x == 6) {
n = (0x22 << 16) +
// Rosso
} else if (x == 10) {
n = (0x20 << 16) +
// Nero
} else if (x == 14) {
n = (0x21 << 16) +
// Dispari
} else if (x == 18) {
n = (0x23 << 16) +
// 19-36
} else if (x == 22) {
n = (0x25 << 16) +
}
}
1;
1;
1;
1;
1;
1;
return n;
}
// -------------------------------------------------// getParameter: %comando%parametri%separati%da%percentuale
//
vedi iac.txt
public String getParameter(String cmd) {
StringTokenizer st = new StringTokenizer(cmd, "%");
if (!cmd.startsWith("%"))
return super.getParameter(cmd);
try {
String s = st.nextToken();
if (s.equals("removeLostChips")) {
removeLostChips(st.nextToken());
return null;
}
else
if (s.equals("setCredits")) {
setCredits(Integer.parseInt(st.nextToken()));
return null;
}
} catch (Exception e) {
pippo = "Exception executing command!" + e.toString();
}
return null;
}
}
//
//
//
//
//
//
//
//
---------------------------------------------------------------PwdDisplay.java
Display dove viene richiesto username e password.
Si tratta di un'estensione dell'oggetto Panel.
Su una griglia 3x2 vengono poste due label, due TextField, un bottone.
c'e' uun overload di processActionEvent per gestire il
bottone 'OK'.
----------------------------------------------------------------
import
import
import
import
java.awt.*;
java.awt.event.*;
java.applet.Applet;
java.applet.AppletContext;
class PwdDisplay extends Panel {
private
private
private
private
Font myFont;
Color bgColor, backupCol;
Label lb1, lb2, lb3;
myButton bt3;
protected TextField tf1, tf2;
public PwdDisplay(Color bgc, gwClient gwc) {
GridLayout g = new GridLayout(3,2);
setLayout(g);
setForeground(Color.white);
setBackground(bgc);
lb1 = new Label("Username:");
lb2 = new Label("Password:");
lb3 = new Label("");
tf1 = new TextField("", 10);
tf2 = new TextField("", 10);
bt3 = new myButton(" OK ", gwc, this);
add(lb1);
add(tf1);
add(lb2);
add(tf2);
add(lb3);
add(bt3);
show();
// deprecated
reshape(40, 270, 200, 80); // deprecated
}
}
// Il bottone e' di tipo "selfbutton", gestisce cioe' in modo
// autonomo l'evento ActionEvent.
class myButton extends Button {
private gwClient client;
private TextField u, p;
private PwdDisplay owner;
public myButton (String label, gwClient client, PwdDisplay owner) {
super(label);
//enableEvents(AWTEvent.ACTION_EVENT_MASK);
this.owner = owner;
this.client = client;
this.u = owner.tf1;
this.p = owner.tf2;
}
public boolean action(Event e, Object what) {
// super.processActionEvent(e);
if (client.isAlive()) {
if (client.logon(u.getText(), p.getText())) {
try {
Applet t =
((Applet)getParent().getParent()).getAppletContext().getApplet("sender");
owner.hide(); // Nascondi
// vedi IAC.TXT
t.getParameter("%setCredits%" + Integer.toString(client.getSaldo()));
} catch (Exception ex) { setLabel("ARGH"); }
}
}
return true;
}
}
//
//
//
//
---------------------------------------------------------------Pallina.java
Questo oggetto crea, disegna e cambia i suoni della pallina
----------------------------------------------------------------
import
import
import
import
java.awt.Color;
java.awt.Image;
java.awt.Graphics;
java.applet.AudioClip;
class Pallina extends Object {
private
private
private
private
private
private
final
final
final
final
final
final
double NUMBER_ANGLE = 360D/37;
int MAX_RADIUS = 104;
int MIN_RADIUS = 24;
int FINAL_RADIUS = 64;
int TEMPO = 3000;
int SPEED = 21;
//
//
//
//
//
//
Angolo di un numero sulla ruota
Raggio massimo (quello di partenza)
Raggio minimo
Raggio delle caselle dei numeri
gradi dopo cui calare velocita'
velocita' pallina (gradi/frame)
private Image palla;
private int x, y, w, h, cx, cy;
private int t, alfa, r;
private int myspeed;
private boolean ready;
private boolean arrived;
private boolean endSoundStarted;
private int numbers[] = new int[]
{17,25,2,21,4,19,15,32,0,26,3,35,12,28,7,29,18,22,9,31,14,20,1,33,16,24,5,10,23,8,30,11,3
6,13,27,6,34,17,25};
public static AudioClip rotSound, endSound;
// Numero che deve uscire! ;-)
private int n;
// Puntatori locali alle tabelle sinNorm e cosNorm
private int coseni[], seni[];
// -------------------------------------------------------------
//
//
//
//
I due seguenti metodi servono a disegnare la pallina su Graphics g
A seconda che la pallina stia girando o sia "pronta" a cadere sul
numero giusto, l'applet chiama il primo o il secondo metodo.
------------------------------------------------------------public void disegna(Graphics g, int centerx, int centery, int angolo) {
cx = centerx;
cy = centery;
g.drawImage(palla, cx + x, cy + y, null);
}
// ----------------------------------------------public void disegna(Graphics g, int angolo) {
int newx, newy;
double a = 6D;
// Calcola newx e newy, coordinate del numero uscito!
for (int i = 0; i < 37 && n != numbers[i]; i++)
a += NUMBER_ANGLE;
newx = ((FINAL_RADIUS * coseni[(angolo + 359 - (int)a) % 360]) >> 8) - w;
newy = ((FINAL_RADIUS * seni[(angolo + 359 - (int)a) % 360]) >> 8) - h;
if (arrived || distance(x, y, newx, newy) < 12) {
arrived = true;
x = newx;
y = newy;
changeSound(3);
} else {
myspeed = 2;
nextpos();
}
g.drawImage(palla, cx + x, cy + y, null);
}
// ------------------------------------------------------------public boolean isready() {
return ready;
}
// ------------------------------------------------------------public boolean isarrived() {
return arrived;
}
// ------------------------------------------------------------public void nextpos() {
t += myspeed;
alfa = (alfa + myspeed) % 360;
x = ((r * coseni[359-alfa]) >> 8) - w;
y = ((r * seni[359-alfa]) >> 8) - h;
if (t > TEMPO && r > FINAL_RADIUS) {
// Dopo 8 giri, cala il raggio e la
velocita'
int decremento1 = ((t % 3) == 0) ? 2 : 0;
int decremento2 = ((t % 10) == 0) ? 2 : 0;
r -= decremento1;
if (myspeed > 4)
myspeed -= decremento2;
}
if (r <= FINAL_RADIUS)
ready = true;
}
// ------------------------------------------------------------public void changeSound(int status) {
if (status == 0) {
// Stop!
rotSound.stop();
endSound.stop();
} else if (status == 1) {
// At the beginning...
rotSound.stop();
rotSound.loop();
} else if (status == 2) {
// While looping...
if (r < FINAL_RADIUS + 8) {
rotSound.stop();
if (!endSoundStarted) {
endSound.loop();
endSoundStarted = true;
}
}
} else if (status == 3) {
// Ball stops.
endSound.stop();
}
}
// ------------------------------------------------------------private int distance(int x1, int y1, int x2, int y2) {
return (int)(Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
// ------------------------------------------------------------public Pallina(Image p, int[] c, int[] s, int n) {
super();
this.n = n;
this.palla = p;
this.coseni = c;
this.seni = s;
this.w = (p.getWidth(null) >> 1);
this.h = (p.getHeight(null) >> 1);
this.r = MAX_RADIUS;
this.myspeed = SPEED;
this.ready = false;
this.arrived = false;
this.endSoundStarted = false;
}
// ------------------------------------------------------------// ***** Metodo Statico che carica i suoni della pallina *****
// ------------------------------------------------------------public static void initBallSounds(roulcli owner) {
rotSound = owner.getAudioClip(owner.getCodeBase(), "audio/bspin.au");
endSound = owner.getAudioClip(owner.getCodeBase(), "audio/bstop.au");
}
// ------------------------------------------------------------}
//
//
//
//
//
//
//
//
//
//
--------------------------------------------------------------------GoldenWheel Client
(c)2000 by Espeleta Tomas
(gwClient.java)
Oggetto che si occupa della comunicazione con il server, alla
creazione si occupa di attivare un socket tramite la classe "Client"
fornisce vari metodi:
logon:
permette l'autenticazione dell'utente
setBets: imposta un riferimento locale al vettore di scommesse
bet:
comunica la scommessa al server.
pwdok:
restituisce true se ci si e' loggati con successo.
---------------------------------------------------------------------
import
import
import
import
import
java.io.*;
java.net.*;
java.util.Vector;
java.awt.Color;
java.awt.Graphics;
public class gwClient {
private final int OK = 1;
private final int ERROR = 2;
private
private
private
private
private
private
private
private
private
private
private
roulcli caller;
Vector bets;
Client client;
BufferedReader reader;
PrintWriter writer;
String welcome;
String response;
String servername;
int numero, vincita;
boolean logged;
boolean alive;
private String username, passwd;
private String ID;
private int saldo;
// ---------------------------------------------------------------private void delay(int ms) {
try {
Thread.sleep(ms);
} catch (Exception ignored) {}
}
// ---------------------------------------------------------------private void myError(String message) {
caller.showStatus(message);
}
// ---------------------------------------------------------------private void makeConnection() {
client = new Client(servername, 8001);
try {
reader = new BufferedReader (new InputStreamReader (client.in));
writer = new PrintWriter (new OutputStreamWriter (client.out), true);
// WriteServer welcome string
welcome = reader.readLine();
alive = true;
} catch (IOException e) {
myError("Error initializing connection...");
alive = false;
}
logged = false;
}
// ---------------------------------------------------------------// Funzione unidirezionale per crittografare la password: MD5
static private final String digits = "0123456789ABCDEF";
static private String crypt(String s) {
MD5 md = new MD5();
StringBuffer result = new StringBuffer();
md.update(s.getBytes());
byte[] b = md.digest();
// Rappresentazione esadecimale della password criptata
for (int j = 0; j < b.length; j++) {
result.append(digits.charAt((int)(b[j] >> 4) & 0xf));
result.append(digits.charAt((int)(b[j]) & 0xf));
}
return result.toString();
}
// ---------------------------------------------------------------public gwClient(String servername, roulcli caller) {
this.caller = caller;
this.servername = servername;
makeConnection();
username = "";
passwd = "";
// Inizializzo un ID casuale, che servira' ad identificare la sessione
ID = Integer.toString((int)(Math.random()*100)+100);
}
// ---------------------------------------------------------------public void setBets(Vector bets) {
this.bets = bets;
}
// ---------------------------------------------------------------// Registra la scommessa e lancia la pallina.
// Restituisce il numero uscito e in risultati i moltiplicatori delle vincite.
public int bet(String[] risultato) {
int status = OK;
int retval = -1;
int k = -1;
try {
for (int i = 0; i < bets.size() && status != ERROR; i++) {
// Sends command BET
if (status == OK) {
writer.println("BET");
response = reader.readLine();
if (!response.startsWith("OK")) status = ERROR;
delay(5);
}
// Sends ID
if (status == OK) {
writer.println(ID);
response = reader.readLine();
if (!response.startsWith("OK")) status = ERROR;
delay(5);
}
// Sends bet code
if (status == OK) {
writer.println(Integer.toString(((Bet)(bets.elementAt(i))).code)); // Rouge
response = reader.readLine();
if (!response.startsWith("OK")) status = ERROR;
delay(5);
}
// Sends bet credits amount
if (status == OK) {
writer.println(Integer.toString(((Bet)(bets.elementAt(i))).credits));
response = reader.readLine();
if (!response.startsWith("OK")) status = ERROR;
delay(5);
}
}
if (status != OK) {
myError("Error sending your bets...");
close();
} else {
// Sending command SPIN
writer.println("SPIN");
response = reader.readLine();
}
} catch (Exception e) {
myError("Exception detected while sending bets." + e);
response = null;
}
if (response != null)
k = response.indexOf(',');
if (k != -1) {
retval = Integer.parseInt(response.substring(0, k));
risultato[0] = new String(response.substring(k+1, response.length()));
} else {
retval = -1;
risultato[0] = "Error!";
}
return retval;
}
// ---------------------------------------------------------------public void close() {
try {
client.kill();
alive = false;
} catch (Throwable ignored) {}
}
// ---------------------------------------------------------------public boolean isAlive() {
return alive;
}
// ---------------------------------------------------------------public boolean logon(String usr, String pwd) {
username = usr;
passwd = crypt(pwd);
try {
if (!logged) {
writer.println("PASSWD " + username + " " + passwd);
response = reader.readLine();
if (response.startsWith("OK")) {
logged = true;
try {
saldo =
Integer.parseInt(response.substring(response.lastIndexOf(',')+2, response.length()));
} catch (NumberFormatException e) {
saldo = 0;
}
myError("User " + usr + ": Welcome! ");
} else {
// Il server butta giu' la connessione!!
myError("User " + usr + " not accepted...");
// ... quindi la ripristino
makeConnection();
}
delay(5);
}
} catch (Exception e) {
myError("Exception detected while sending password." + passwd);
response = null;
}
return logged;
}
// ---------------------------------------------------------------public boolean pwdok() {
return logged;
}
// ---------------------------------------------------------------public int getSaldo() {
return saldo;
}
// ----------------------------------------------------------------
}
//------------------------------------------------------------------// Client.java
// usato da gwClient, semplicemente APRE il socket e fornisce
// due stream di I/O (“in” e “out”)
//------------------------------------------------------------------import java.io.*;
import java.net.*;
//------------------------------------------------------------------public class Client {
public InputStream in;
public OutputStream out;
// Il socket rimane privato...
private Socket client;
//------------------------------------------------------------------public Client(String host, int port) {
try {
client = new Socket(host, port);
in = client.getInputStream();
out = client.getOutputStream();
} catch (Exception e) {
System.out.println("IOExc : " + e);
}
}
//------------------------------------------------------------------public void kill() throws Throwable {
try {
client.close();
super.finalize();
} catch (Exception ignored) {
}
}
}
//
//
//
//
//
//
//
//
---------------------------------------------------------------Display.java
Display dove viene visualizzato il numero uscito
Ha bisogno dell' oggetto Graphics su cui scrivere... fornisce
i seguenti metodi:
setString: Imposta la stringa da visualizzare
paint: Disegna il display, nero con bordo giallo.
----------------------------------------------------------------
import
import
import
import
java.awt.Graphics;
java.awt.Color;
java.awt.Font;
java.awt.FontMetrics;
class Display {
static private int rossi[] = {1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30,
32, 34, 36};
private
private
private
private
private
private
String contenuto;
Color bgColor, fgColor, backupCol;
Graphics g;
Font myFont;
FontMetrics misura;
int left, top, w, h, sw;
// ---------------------------------------------------------------public Display(Graphics myG, int left, int top, int w, int h) {
bgColor = Color.black;
fgColor = Color.white;
backupCol = myG.getColor();
myFont = new Font("SansSerif", Font.BOLD, h/5);
myG.setFont(myFont);
misura = myG.getFontMetrics();
setString("Make your bet!");
this.g = myG;
this.left = left;
this.top = top;
this.w = w;
this.h = h;
}
// ---------------------------------------------------------------public void setString(String s) {
int num;
contenuto = s;
fgColor = Color.white;
try {
num = Integer.parseInt(s);
if (num == 0)
fgColor = Color.green;
for (int i = 0; i < rossi.length; i++)
if (num == rossi[i])
fgColor = Color.red;
if (myFont.getSize() < h/2) {
myFont = new Font("SansSerif", Font.BOLD, h/2);
g.setFont(myFont);
misura = g.getFontMetrics();
}
} catch (NumberFormatException ignored) {}
sw = misura.stringWidth(s);
}
// ---------------------------------------------------------------public void paint() {
g.setColor(bgColor);
g.fillRect(left, top, w, h);
// Costruisco un bordo giallo oro.
g.setColor(new Color(0xa0a030));
for (int b = 0; b < 3; b++)
g.drawRect(left + b, top + b, w - b*2, h - b*2);
// Scritta
g.setColor(fgColor);
g.drawString(contenuto, left + (w - sw) / 2, top + h/2 + misura.getHeight()/3);
g.setColor(backupCol);
}
}
//
//
//
//
---------------------------------------------------------------Chip.java (chiamata da tappeto.java)
Implementa una fiche come immagine con una POSIZIONE e un VALORE
----------------------------------------------------------------
public class Chip {
public
public
public
public
int
int
int
int
Chip() {}
}
xPos;
yPos;
code;
value;
// Posizione sul tappeto
// Codice scommessa di questa chip
// Valore in crediti ($, dollari o migliaia di lire...)
// ---------------------------------------------------------------public class Bet {
public int code;
public int credits;
public Bet(int code, int credits) {
this.code = code;
this.credits = credits;
}
public Bet() {
}
}
// ----------------------------------------------------------------