下面我们再来看看ClientControl类,这个类代码量是最多的,这个类负责整体的游戏流程和游戏逻辑,由于写这个游戏的时候并没有很好的思考,所以代码可能会比较乱:(,希望大家不要介意
/*
* ClientControl.java
*
* Created on 2007年10月2日, 下午2:02
* 此类是客户端中的关键类,此类专门负责整个程序的
* 流程和表现,负责对外通讯
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package com.hadeslee.apple.client;
/**
*
* @author lbf
*/
import com.hadeslee.apple.common.Bet;
import com.hadeslee.apple.common.INFO;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JFrame;
import static com.hadeslee.apple.common.Constants.*;
public class ClientControl extends Thread implements KeyListener {
private ClientView cv; //表示视图的类
private ClientModel cm; //表示模型的类
private ExecutorService es; //表示一个线程池的对象
private AudioClip[] betAu; //表示下注时的一个音频对象
private AudioClip onceMore;
private AudioClip xiu;
private AudioClip loop;
private AudioClip runA;
private AudioClip runB;
private AudioClip win;
private AudioClip lose;
private Bet bet; //缓存的上一局的下注记录
private PP p = PP.p1;
private volatile boolean canBet = true;
private volatile boolean isRunning;
private volatile boolean isBetting;
private volatile boolean isBetted;
private volatile boolean canMove = true; //表示此时是否可以下注,是否正在附加赌
private Image[] pkA;
private Image[] pkB; //表示两个人物的图像数组
private int result; //表示PK的结果,定义在Constants类里面
private Control con; //处理控制的类
private int allBet = 1;
private int allWin = 1; //表示此人所有下注,所有赢的数,此数用于控制,不能赋0,除法会异常
private AudioClip temp; //中间变量,用于放歌用的
private volatile boolean go;
private volatile boolean showMoney;
private volatile boolean blinkRatio; //用以控制闪动线程的
private volatile boolean isFullScreen; //指示此时是否是全屏
private JFrame jf; //表示此游戏的窗口
/** Creates a new instance of ClientControl */
public ClientControl() {
}
public ClientControl(int id, int allMoney) {
cm = new ClientModel();
cv = new ClientView(cm);
cm.setId(id);
cm.setAllMoney(allMoney);
cm.setInfo(new INFO());
try {
cm.getInfo().setBigBonus(10000);
cm.getInfo().setSmallBonus(1000);
cm.getInfo().setTip("欢迎使用单机版!!谢谢!");
} catch (Exception exe) {
exe.printStackTrace();
}
initModel();
initWindow();
initOther();
doShowAllMoney();
}
//初始化其它东西,比如声音片断
private void initOther() {
con = new Control();
betAu = new AudioClip[10];
for (int i = 1; i < 10; i++) {
betAu[i] = Applet.newAudioClip(this.getClass().getResource("sound/bet/bet" + i + ".au"));
}
//初始化所有要使用的声音片段
loop = Applet.newAudioClip(this.getClass().getResource("sound/loop.au"));
runA = Applet.newAudioClip(this.getClass().getResource("sound/runA.au"));
runB = Applet.newAudioClip(this.getClass().getResource("sound/runB.au"));
onceMore = Applet.newAudioClip(this.getClass().getResource("sound/wu.au"));
xiu = Applet.newAudioClip(this.getClass().getResource("sound/oncemore.au"));
win = Applet.newAudioClip(this.getClass().getResource("sound/win/win.au"));
lose = Applet.newAudioClip(this.getClass().getResource("sound/win/lose.au"));
bet = new Bet();
}
//初始化全屏
private void initWindow() {
jf = new JFrame("苹果机");
jf.getContentPane().add(cv, BorderLayout.CENTER);
jf.setSize(800, 600);
jf.setUndecorated(true);
jf.setVisible(true);
jf.setAlwaysOnTop(true);
jf.setLocationRelativeTo(null);//一条简便的语句,设置窗口居中显示
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.addKeyListener(this);
}
//初始化模型
private void initModel() {
initImage();
initModelOther();
}
//初始化图像
private void initImage() {
MediaTracker mt = new MediaTracker(cv);
int index = 0;
Image[] number = new Image[10];
Image[] winNumber = new Image[10];
for (int i = 0; i < 10; i++) {
number[i] = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("pic/game/number1/" + i + ".png"));
winNumber[i] = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("pic/game/number2/" + i + ".png"));
mt.addImage(number[i], index++);
mt.addImage(winNumber[i], index++);
}
Image bg = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("pic/game/bg.jpg"));
Image table = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("pic/game/table.png"));
Image pkBg = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("pic/game/pk.jpg"));
mt.addImage(bg, index++);
mt.addImage(table, index++);
mt.addImage(pkBg, index++);
pkA = new Image[3];
pkB = new Image[3];
for (int i = 0; i < 3; i++) {
pkA[i] = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("pic/game/pk/A" + i + ".png"));
pkB[i] = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("pic/game/pk/B" + i + ".png"));
mt.addImage(pkA[i], index++);
mt.addImage(pkB[i], index++);
}
try {
mt.waitForAll();
} catch (Exception exe) {
exe.printStackTrace();
}
cm.setBg(bg);
cm.setNumber(number);
cm.setWinNumber(winNumber);
//cm.setRunA(PP.p1.other);
cm.setTable(table);
cm.setPkA(pkA[0]);
cm.setPkB(pkB[0]);
cm.setPKBG(pkBg);
}
//初始化模型其它部份
private void initModelOther() {
Bet bet = new Bet();
cm.setBet(bet);
cm.addP(PP.p1);
//初始化线程池
es = Executors.newCachedThreadPool();
}
//专门起一个线程用于更新余额的方法
private void doShowAllMoney() {
es.execute(new Runnable() {
public void run() {
showMoney = true;
while (showMoney) {
try {
Thread.sleep(80);
cv.repaint(10, 661, 73, 107, 65);
} catch (Exception exe) {
exe.printStackTrace();
}
}
}
});
}
//专门处理下注的方法
private synchronized void doBet(int i) {
if (!isBetted) {
isBetted = true;
canMove = false;
cm.getBet().clearWin();
//doShowAllMoney();
}
cm.setAllMoney(cm.getAllMoney() - 1);
int bet = cm.getBet().getBet(i);
cm.getBet().setBet(i, bet + 1);
betAu[i].play();
}
//专门用来设置赔率的方法
private void setRatio() {
int rad = (int) (Math.random()*100) + 1;
if (rad > 95) {
cm.setRatioA(40);
} else if (rad > 85) {
cm.setRatioA(30);
} else {
cm.setRatioA(20);
}
rad = (int) (Math.random()*100) + 1;
if (rad > 95) {
cm.setRatioB(20);
} else if (rad > 85) {
cm.setRatioB(15);
} else {
cm.setRatioB(10);
}
}
//专门处理开始跑的方法
private void doRun() {
try {
//此时先把赔率设置好
setRatio();
isRunning = true;
canBet = false;
canMove = false;
showMoney = false;
INFO inf = cm.getInfo();
inf.setBigBonus(cm.getBet().getTotal() / 50 + inf.getBigBonus());
inf.setSmallBonus(cm.getBet().getTotal() / 100 + inf.getSmallBonus());
cv.repaint();
es.execute(new Runnable() {
public void run() {
runRun();
}
});
} catch (Exception exe) {
exe.printStackTrace();
}
}
public void keyPressed(KeyEvent ke) {
int allMoney = cm.getAllMoney();
int code = ke.getKeyCode();
//先看看是不是CTRL+F,如果是的话,就表示全屏或者退出全屏了
if (KeyEvent.VK_F == code && (ke.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) == KeyEvent.CTRL_DOWN_MASK) {
if (isFullScreen) {
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
try {
gd.setFullScreenWindow(null);
isFullScreen=false;
} catch (Exception exe) {
exe.printStackTrace();
}
} else {
//得到图形设备,也就是显示器
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
try {
gd.setFullScreenWindow(jf);
gd.setDisplayMode(new DisplayMode(800, 600, 16, 60));
isFullScreen=true;
} catch (Exception exe) {
exe.printStackTrace();
}
}
return;
}
//如果可以下注并且余额大于0才处理键盘事件
if (allMoney > 0 && canBet) {
if (KeyEvent.VK_1 == code) {
doBet(1);
cv.repaint(24, 566, 64, 31);
} else if (KeyEvent.VK_2 == code) {
doBet(2);
cv.repaint(129, 566, 64, 31);
} else if (KeyEvent.VK_3 == code) {
doBet(3);
cv.repaint(197, 566, 64, 31);
} else if (KeyEvent.VK_4 == code) {
doBet(4);
cv.repaint(264, 566, 64, 31);
} else if (KeyEvent.VK_5 == code) {
doBet(5);
cv.repaint(369, 566, 64, 31);
} else if (KeyEvent.VK_6 == code) {
doBet(6);
cv.repaint(474, 566, 64, 31);
} else if (KeyEvent.VK_7 == code) {
doBet(7);
cv.repaint(542, 566, 64, 31);
} else if (KeyEvent.VK_8 == code) {
doBet(8);
cv.repaint(610, 566, 64, 31);
} else if (KeyEvent.VK_9 == code) {
doBet(9);
cv.repaint(712, 566, 64, 31);
}
}
if (KeyEvent.VK_LEFT == code && canMove) {
if (cm.getAllMoney() > 0) {
if (temp != null) {
temp.stop();
}
go = false;
canBet = false;
cm.setAllMoney(cm.getAllMoney() - 1);
cm.setWinMoney(cm.getWinMoney() + 1);
cv.repaint(30, 75, 107, 65);
}
} else if (KeyEvent.VK_RIGHT == code && canMove) {
if (cm.getWinMoney() > 0) {
if (temp != null) {
temp.stop();
}
go = false;
cm.setAllMoney(cm.getAllMoney() + 1);
cm.setWinMoney(cm.getWinMoney() - 1);
cv.repaint(30, 75, 107, 65);
if (cm.getWinMoney() == 0) {
canBet = true;
cm.setBet(new Bet());
cm.setBetting(false);
isBetting = false;
cv.repaint(0, 30, 800, 600);
}
}
}
}
public void keyTyped(KeyEvent ke) {
}
public void keyReleased(KeyEvent ke) {
int code = ke.getKeyCode();
if (KeyEvent.VK_ESCAPE == code) {
System.exit(0);
}
//如果是回车键则分为几种可能,只分两种可能,有分和没分,有分就下分,没分就跑
if (KeyEvent.VK_ENTER == code) {
if (isRunning) {
ke.consume();
} else {
doEnter();
}
} else if (KeyEvent.VK_NUMPAD1 == code || KeyEvent.VK_Q == code) {
if (cm.getWinMoney() > 0 && isBetting) {
isBetting = false;
result = A_WIN;
}
} else if (KeyEvent.VK_NUMPAD3 == code || KeyEvent.VK_P == code) {
if (cm.getWinMoney() > 0 && isBetting) {
isBetting = false;
result = B_WIN;
}
}
//要按键能出来PK界面,必须赢的钱要大于0,否则赌的没意义
if (KeyEvent.VK_B == code) {
if (cm.isBetting()) {
//如果此时在PK,则无条件不显示
cm.setBetting(false);
isBetting = false;
cv.repaint(0, 30, 800, 600);
} else if (cm.getWinMoney() > 0 && canMove) {
//设置为可以PK
if (temp != null) {
temp.stop();
}
go = false;
cm.setBetting(true);
doPK();
cv.repaint(0, 30, 800, 600);
}
}
}
//定义一个同步方法以防止两个线程共同起动跑
private synchronized void doEnter() {
//当前的可用分为0时,按回车就跑
result = 0;
cm.setBetting(false);
isBetting = false;
go = false;
if (temp != null) {
temp.stop();
}
if (cm.getWinMoney() == 0) {
cm.clearP();
resetPP(); //无论怎么样,都要在开始把PP的记录重置
//如果已下注了,那就取下注的为准
if (canBet) {
if (isBetted) {
bet = cm.getBet();
doRun();
isBetted = false;
} else {
if (cm.getAllMoney() >= bet.getTotal() && bet.getTotal() > 0) {
bet.clearWin();
cm.setBet(bet);
cm.setAllMoney(cm.getAllMoney() - bet.getTotal());
doRun();
}
}
cv.repaint(0, 30, 800, 600);
}
} else {
allWin += cm.getWinMoney();
allBet += cm.getBet().getTotal();
cm.setAllMoney(cm.getAllMoney() + cm.getWinMoney());
cm.setWinMoney(0);
cm.setBet(new Bet());
canBet = true;
cv.repaint(0, 30, 800, 600);
}
}
//起PK线程,并且设置相当的布尔量
//使之可以PK
private void doPK() {
isBetting = true; //此时才可以将这个设为真,因为不会再跑了,所以可以押大小了
//doShowAllMoney();
cm.setBetting(true);
es.execute(new Runnable() {
public void run() {
pkRun();
}
});
}
//处理PK的线程体
private void pkRun() {
int indexA = 0;
int indexB = 0;
while (isBetting) {
try {
Thread.sleep(80);
int rand = (int) (Math.random()*100);
if (rand % 2 == 0) {
if (indexA < pkA.length - 1) {
cm.setPkA(pkA[++indexA]);
} else {
indexA = 0;
cm.setPkA(pkA[0]);
}
} else {
if (indexB < pkB.length - 1) {
cm.setPkB(pkB[++indexB]);
} else {
indexB = 0;
cm.setPkB(pkB[0]);
}
}
cv.repaint(269, 274, 254, 132);
} catch (Exception exe) {
exe.printStackTrace();
}
}
if (Math.random() * 10 > 1) {
while (indexA == indexB) {
indexA = (int) (Math.random()*3);
}
}
cm.setPkA(pkA[indexA]);
cm.setPkB(pkB[indexB]);
cv.repaint(238, 258, 330, 152);
handleResult(indexA, indexB);
}
//处理结果的一个方法,针对传进来的A和B的下标,判断谁赢谁输
private void handleResult(int a, int b) {
int current = 0;
//当A为布时
if (a == 0) {
if (b == 0) {
current = AB_TIE;
} else if (b == 1) {
current = A_WIN;
} else if (b == 2) {
current = B_WIN;
}
} else if (a == 1) {
if (b == 0) {
current = B_WIN;
} else if (b == 1) {
current = AB_TIE;
} else if (b == 2) {
current = A_WIN;
}
} else if (a == 2) {
if (b == 0) {
current = A_WIN;
} else if (b == 1) {
current = B_WIN;
} else if (b == 2) {
current = AB_TIE;
}
}
//当两者相等,则说明猜中了
if (result == current || current == AB_TIE) {
win.play();
cm.setWinMoney(cm.getWinMoney() * 2);
cv.repaint(30, 75, 107, 65);
try {
Thread.sleep(1000);
isBetting = true;
result = 0;
pkRun();
} catch (Exception exe) {
exe.printStackTrace();
}
} else if (result == 0) { //如果此时等于0,则说明没有猜拳
//showMoney=false;
} else {
canBet = true;
lose.play();
cm.setWinMoney(0);
//showMoney=false;
try {
Thread.sleep(1000);
cm.setBetting(false);
isBetting = false;
cm.setBet(new Bet());
cv.repaint(0, 30, 800, 600);
} catch (Exception exe) {
exe.printStackTrace();
}
}
result = 0;
}
//计算当前的路径出发总共跑SUM步得到的结果
private PP fromIndex(PP from, int sum, boolean isRun) {
if (isRun) {
int all = sum;
PP[] ps = PP.values();
int index = (all + p.ordinal()) % 26;
return ps[index];
} else {
int all = 5 + 7 + sum;
PP[] ps = PP.values();
int index = (all + p.ordinal()) % 26;
return ps[index];
}
}
private PP fromIndex(PP from, int sum) {
int all = 5 + 7 + sum;
PP[] ps = PP.values();
int index = (all + p.ordinal()) % 26;
return ps[index];
}
//跑大四喜的实现
private void doDaSiXi() {
es.execute(new Runnable() {
public void run() {
runDaSiXi();
}
});
}
//跑大四喜的方法体实现
private void runDaSiXi() {
}
//随机跑的时间用到的线程执行体
private void runRun() {
doBlinkRatio();
RatioA ra = RatioA.A_20;
RatioB rb = RatioB.B_10;
int total = con.getSteps(AUTO_CONTROL);
int sum = 0; //表示已经跑的数
//PP p=PP.p1;//初始开始跑的位置
cm.setRunning(true); //把模型设为正在跑的模式
cm.setP(p);
//p.setImage(yellow);
int sleepTime = 100;
try {
//先跑五个点做为起步
runA.play();
for (int i = 1; i < 6; i++) {
Thread.sleep(200);
p = p.next();
ra = ra.next();
rb = rb.next();
cm.setRa(ra);
cm.setRb(rb);
cm.setP(p);
//p.setImage(yellow);
//cv.repaint(178,50,465,413);
cv.repaint(p.x - 100, p.y - 100, 230, 230);
}
loop.loop();
while (sum++ < total) {
Thread.sleep(20);
p = p.next();
cm.setP(p);
ra = ra.next();
rb = rb.next();
cm.setRa(ra);
cm.setRb(rb);
//p.setImage(yellow);
//cv.repaint(178,50,465,413);
cv.repaint(p.x - 100, p.y - 100, 230, 230);
}
loop.stop();
runB.play();
//后面七个点为停步
for (int i = 0; i < 7; i++) {
p = p.next();
cm.setP(p);
//p.setImage(yellow);
Thread.sleep(sleepTime);
sleepTime += 10;
ra = ra.next();
rb = rb.next();
cm.setRa(ra);
cm.setRb(rb);
//cv.repaint(178,50,465,413);
cv.repaint(p.x - 100, p.y - 100, 230, 230);
}
PP pps = p;
//doBlinkRun(pps);
doRunOver(p);
} catch (Exception exe) {
exe.printStackTrace();
}
}
//根据赔率得到当前的位置
private RatioA getRa(int ratio) {
RatioA[] ras = RatioA.values();
for (RatioA rs : ras) {
if (rs.ratio == ratio) {
return rs;
}
}
return null;
}
private RatioB getRb(int ratio) {
RatioB[] rbs = RatioB.values();
for (RatioB rs : rbs) {
if (rs.ratio == ratio) {
return rs;
}
}
return null;
}
//处理根据国数得到当前的统一陪率
private int getRatio(int country) {
if (COUNTRY_A == country) {
return cm.getRatioA();
} else if (COUNTRY_B == country) {
return cm.getRatioB();
} else {
throw new RuntimeException("出了个不该出的错误!");
}
}
//确实是否亮赔率的灯
private void doCheckBlinkRatio() {
if (cm.isAWin()) {
cm.setRa(getRa(cm.getRatioA()));
} else {
cm.setRa(null);
}
if (cm.isBWin()) {
cm.setRb(getRb(cm.getRatioB()));
} else {
cm.setRb(null);
}
cv.repaint(0, 30, 800, 600);
}
//处理跑完的场景,根据中得不同的下标,比如,跑火车,中彩金等
private void doRunOver(PP p) throws Exception {
doShowAllMoney();
//如果下标大于0,则表示中了正规的注
if (p.getIndex() > 0) {
canMove = true;
doBlinkRun(p);
doCheckBlinkRatio();
cm.getBet().setWin(p.getIndex(), true);
int winMoney = 0;
if (p.country > 0) {
winMoney = bet.getBet(p.getIndex()) * p.country;
} else {
winMoney = bet.getBet(p.getIndex()) * getRatio(p.country);
}
cm.setWinMoney(winMoney);
cv.repaint(30, 75, 107, 65);
isRunning = false;
p.audio.play();
Thread.sleep(800);
if (cm.getWinMoney() > 0) {
playMusic();
//doPK();
} else {
if (!isRunning) {
cm.setBet(new Bet());
canBet = true;
}
}
cv.repaint(0, 30, 800, 600);
} else {
//如果下标等于ONCE_MORE,则表示开火车
if (p.getIndex() == ONCE_MORE) {
doOnceMore();
} else if (p.getIndex() == SONG_DENG) {
cm.setRa(getRa(cm.getRatioA()));
cm.setRb(getRb(cm.getRatioB()));
p.audio.play();
Thread.sleep(1000);
onceMore.play();
Thread.sleep(1500);
doSongDeng(p);
} else if (p.getIndex() == SMALL_BONUS) {
p.audio.play();
Thread.sleep(1000);
cm.getInfo().setSmallBonus(0);
cv.repaint();
} else if (p.getIndex() == BIG_BONUS) {
p.audio.play();
Thread.sleep(1000);
cm.getInfo().setBigBonus(0);
cv.repaint();
}
//下面的语句是为了调试程序而用的
//isBetting=true;
}
}
//专门用来播声音的方法
private void playMusic() {
int NO = (int) (Math.random()*10) + 1;
if (isBetting) {
} else {
if (temp != null) {
temp.stop();
}
temp = Applet.newAudioClip(this.getClass().getResource("sound/music/music" + NO + ".au"));
temp.loop();
}
}
//专起一个线程用于更新赔率的闪灯
private void doBlinkRatio() {
es.execute(new Runnable() {
public void run() {
blinkRatio = true;
while (!canMove) {
try {
Thread.sleep(40);
cv.repaint(141, 496, 518, 32);
if (!blinkRatio) {
break;
}
} catch (Exception exe) {
exe.printStackTrace();
}
}
}
});
}
//专门用以跑开火车的方法
private void doOnceMore() throws Exception {
//doBlinkRatio();
// blinkRatio=false;
p.audio.play();
PP startP = p;
RatioA ra = RatioA.A_20;
RatioB rb = RatioB.B_10;
int total = (int) (Math.random()*3) + 3; //随机产生火车的节数
final AudioClip wu = Applet.newAudioClip(this.getClass().getResource("sound/oncemore/wu.au"));
final AudioClip run = Applet.newAudioClip(this.getClass().getResource("sound/oncemore/run.au"));
final AudioClip stop = Applet.newAudioClip(this.getClass().getResource("sound/oncemore/stop.au"));
//先处理一个一个的出来
for (int i = 0; i < total; i++) {
Thread.sleep(1000);
stop.play();
cm.addP(startP = startP.next());
cv.repaint(178, 50, 465, 413);
}
es.execute(new Runnable() {
public void run() {
try {
wu.play();
Thread.sleep(3500);
run.loop();
} catch (Exception exe) {
exe.printStackTrace();
}
}
});
int steps = (int) (Math.random()*26) + 60;
int stepAll = steps;
//在此控制火车的头尾,也就是说不能中到50-100倍的那个灯
PP pto = fromIndex(p, steps + total, true);
PP pwe = fromIndex(p, steps, true);
//当总长度大于15时,必须会一头一尾的溢出
if (total > 15) {
while (!(pto.ordinal() < 15 && pwe.ordinal() > 17)) {
steps++;
pto = fromIndex(p, steps + total, true);
pwe = fromIndex(p, steps, true);
}
} else {
while (!(pto.ordinal() < 15 || pwe.ordinal() > 17)) {
steps++;
pto = fromIndex(p, steps + total, true);
pwe = fromIndex(p, steps, true);
}
}
while (steps > 0) {
//p.setImage(yellow);
Thread.sleep(200);
Vector<PP> v = cm.getP();
cm.clearP();
ra = ra.next();
rb = rb.next();
cm.setRa(ra);
cm.setRb(rb);
if (stepAll / 2 == steps) {
wu.play();
}
for (int i = 0; i < v.size(); i++) {
cm.addP(v.get(i).next());
}
steps--;
cv.repaint(178, 50, 465, 413);
}
blinkRatio = false;
cm.setRa(getRa(cm.getRatioA()));
cm.setRb(getRb(cm.getRatioB()));
cv.repaint(141, 496, 518, 32);
run.stop();
//先只留一个车头,然后一个一个地出来
Vector<PP> v = cm.getP();
cm.clearP();
for (int i = v.size() - 1; i >= 0; i--) {
PP p = v.get(i);
if (p.index > 0) {
cm.getBet().setWin(p.index, true);
stop.play();
int winMoney = 0;
if (p.country > 0) {
winMoney = bet.getBet(p.getIndex()) * p.country;
} else {
winMoney = bet.getBet(p.getIndex()) * getRatio(p.country);
}
cm.setWinMoney(winMoney + cm.getWinMoney());
}
cm.addP(p);
//doBlinkRun(p);
//doCheckBlinkRatio();
cv.repaint(0, 30, 800, 600);
Thread.sleep(1000);
}
for (PP pp : v) {
doBlinkRun(pp);
}
p = v.get(v.size() - 1);
canMove = true;
if (cm.getWinMoney() > 0) {
playMusic();
//doPK();
} else {
cm.setBet(new Bet());
canBet = true;
cv.repaint(0, 30, 800, 600);
}
isRunning = false;
}
//专门用以跑送灯的方法
private void doSongDeng(PP ps) {
p = ps;
blinkRatio = false;
//即使中到火车也不一定跑,跑的概率有70%
if (Math.random() * 100 > 30) {
int total = (int) (Math.random()*3) + 2;
while (total > 0) {
try {
int steps = (int) (Math.random()*20) + 20;
xiu.play();
for (int i = 0; i < steps; i++) {
Thread.sleep(20);
p = p.next();
cm.setP(p);
cv.repaint(p.x - 100, p.y - 100, 230, 230);
}
//如果是已经中过的,或者大奖,或者彩金等等,皆不中
while (p.isWin() || p.index < 0 || p.index == 5) {
steps++;
Thread.sleep(20);
p = p.next();
cm.setP(p);
cv.repaint(p.x - 100, p.y - 100, 230, 230);
}
final PP pps = p;
//doBlinkRun(pps);
cm.addP(p);
p.setWin(true);
if (p.index > 0) {
cm.getBet().setWin(p.index, true);
p.audio.play();
int winMoney = 0;
if (p.country > 0) {
winMoney = bet.getBet(p.getIndex()) * p.country;
} else {
winMoney = bet.getBet(p.getIndex()) * getRatio(p.country);
}
cm.setWinMoney(winMoney + cm.getWinMoney());
cv.repaint(0, 30, 800, 600);
}
total--;
Thread.sleep(1500);
} catch (Exception exe) {
exe.printStackTrace();
}
}
for (PP pp : cm.getP()) {
doBlinkRun(pp);
}
//doCheckBlinkRatio();
if (cm.getWinMoney() > 0) {
playMusic();
//doPK();
} else {
cm.setBet(new Bet());
canBet = true;
cv.repaint(0, 30, 800, 600);
}
} else {
cm.setBet(new Bet());
canBet = true;
cv.repaint(0, 30, 800, 600);
}
canMove = true;
isRunning = false;
}
//把PP里面的元素全部还原
private void resetPP() {
PP[] ps = PP.values();
for (PP p : ps) {
p.setWin(false);
p.setImage(p.other);
}
}
//闪动的线程方法实现
private void doBlinkRun(final PP p) {
es.execute(new Runnable() {
public void run() {
blinkRun(p);
}
});
}
//终点闪动的线程体
private void blinkRun(PP p) {
int total = 0;
go = true;
while (go) {
try {
Thread.sleep(300);
total++;
p.setImage(total % 2 == 0 ? null : p.other);
cv.repaint(p.x, p.y, 60, 60);
} catch (Exception exe) {
exe.printStackTrace();
}
}
p.setImage(p.other);
cv.repaint(0, 30, 800, 600);
}
//专门定义一个类来,把一些控制的机制封装在里面
private class Control {
public Control() {
}
//通过传入参数的值得到该返回多少步
//此方法是对外的统一接口
public int getSteps(int style) {
if (COMMON == style) {
return getCommon();
} else if (WIN_MIN == style) {
return getWinMin();
} else if (WIN_MAX == style) {
return getWinMax();
} else if (OPEN_MAX == style) {
return getOpenMax();
} else if (OPEN_MIN == style) {
return getOpenMin();
} else if (OPEN_BIG_BONUS == style) {
return getOpenBigBonus();
} else if (OPEN_SMALL_BONUS == style) {
return getOpenSmallBonus();
} else if (OPEN_SONG_DENG == style) {
return getOpenSongDeng();
} else if (OPEN_ONCE_MORE == style) {
return getOpenOnceMore();
} else if (AUTO_CONTROL == style) {
return getAutoControl();
} else if (OPEN_LOSE == style) {
return getOpenLose();
} else {
return (int) (Math.random()*26) + 10;
}
}
//内部方法,实现普通跑的步数
private int getCommon() {
int total = (int) (Math.random()*26) + 50;
//如果此时随机跑中得是大奖,则不一定给
if (fromIndex(p, total).index == 5) {
if (Math.random() * 100 > 1) {
total += 3;
}
}
//如果此时中了大小彩金,则也不一定给
if (fromIndex(p, total).index == BIG_BONUS || fromIndex(p, total).index == SMALL_BONUS) {
//if(Math.random()*10000>1){
total++;
// }
}
return total;
}
//实现取赢最小的方案
private int getWinMin() {
Bet bet = cm.getBet();
int index = 0;
int win = Integer.MAX_VALUE;
int[] wins = new int[10];
for (int i = 1; i < 10; i++) {
PP p = PP.p1;
while (p.index != i) {
p = p.next();
}
if (p.country > 0) {
wins[i] = bet.getBet(p.getIndex()) * p.country;
} else {
wins[i] = bet.getBet(p.getIndex()) * getRatio(p.country);
}
if (wins[i] <= win) {
if (wins[i] == win) {
if (Math.random() * 10 > 5) {
win = wins[i];
index = i;
}
} else {
win = wins[i];
index = i;
}
}
}
return getTotal(p, index);
}
//实现赢得最多方案
private int getWinMax() {
Bet bet = cm.getBet();
int index = 0;
int win = Integer.MIN_VALUE;
int[] wins = new int[10];
for (int i = 1; i < 10; i++) {
PP p = PP.p1;
while (p.index != i) {
p = p.next();
}
if (p.country > 0) {
wins[i] = bet.getBet(p.getIndex()) * p.country;
} else {
wins[i] = bet.getBet(p.getIndex()) * getRatio(p.country);
}
if (wins[i] > win) {
win = wins[i];
index = i;
}
}
return getTotal(p, index);
}
//实现开最大的那个方案(50或100倍)
private int getOpenMax() {
return getTotal(p, 5);
}
//实现开最小的那个方案(2或5倍)
private int getOpenMin() {
int rad = (int) (Math.random()*10);
if (rad > 5) {
return getTotal(p, 1);
} else {
return getTotal(p, 9);
}
}
//实现只要让玩家输即可,不一定让玩得输最多
public int getOpenLose() {
int betAll = cm.getBet().getTotal();
//用一个哈希表来存储输的下标和输的金额
EnumMap<PP, Integer> lose = new EnumMap<PP, Integer>(PP.class);
for (int i = 1; i < 10; i++) {
int wins = 0;
PP p = PP.p1;
while (p.index != i) {
p = p.next();
}
if (p.country > 0) {
wins = bet.getBet(p.getIndex()) * p.country;
} else {
wins = bet.getBet(p.getIndex()) * getRatio(p.country);
}
if (wins < betAll) {
//如果赢的小于下注的,则输的个数加1
lose.put(p, betAll - wins);
}
}
PP last = PP.p1; //最后要得到的位置
Set<PP> keys = lose.keySet();
System.out.println("会输的PP的个数是:" + keys.size());
//分三种方式去取想要的位置
int MyRad = (int) (Math.random()*100) + 1;
if (MyRad > 85) {
//第一种方式用权重去取到底开什么
System.out.println("用权重去取开什么牌了");
double value = 0;
Iterator<PP> it = keys.iterator();
while (it.hasNext()) {
PP now = it.next();
double myValue = lose.get(now) * 1.0 / now.random;
if (myValue >= value) {
value = myValue;
last = now;
}
}
} else if (MyRad > 30) {
//第二种是概率去取到底开什么
System.out.println("用概率去取什么牌了");
int rand = (int) (Math.random()*100) + 1; //产生一个1-100的随机数
System.out.println("产生的随机数是:" + rand);
//然后把要开的位置按概率从小到大排,尽量满足概率小的开
PP[] ps = keys.toArray(new PP[keys.size()]);
for (int i = 0; i < keys.size(); i++) {
for (int j = i + 1; j < keys.size(); j++) {
if (ps[i].random > ps[j].random) {
PP temp = ps[i];
ps[i] = ps[j];
ps[j] = temp;
}
}
}
System.out.println("排列前的顺序是:" + keys);
System.out.println("排列后的顺序是:");
for (PP now : ps) {
System.out.print(now + ",");
}
System.out.println();
//双重循环,已经把概率小的排在前面了
boolean isFind = false; //一个布尔量,看有没有当前随机数匹配的
for (PP now : ps) {
if (now.random > rand) {
System.out.println("匹配到的是:" + now + "它的概率是:" + now.random * 2);
last = now;
isFind = true;
break;
}
}
if (!isFind) {
System.out.println("没有匹配到,随机找一个");
int index = (int) (Math.random()*keys.size());
last = ps[index];
}
} else {
//第三种是直接以概率来取
System.out.println("直接取概率");
PP[] ps = keys.toArray(new PP[keys.size()]);
int index = (int) (Math.random()*keys.size());
last = ps[index];
}
System.out.println("===============================================");
return getTotal(p, last.index);
}
//表示开大彩金的实现
private int getOpenBigBonus() {
return getTotal(p, BIG_BONUS);
}
//表示开小彩金的实现
private int getOpenSmallBonus() {
return getTotal(p, SMALL_BONUS);
}
//表示开出送灯的实现
private int getOpenSongDeng() {
return getTotal(p, SONG_DENG);
}
//表示开出跑火车的实现
private int getOpenOnceMore() {
return getTotal(p, ONCE_MORE);
}
//实现到传入的位置,应该全速跑的数量total
private int getTotal(PP from, int index) {
int sum = (int) (Math.random()+26) + 30;
while (fromIndex(from, sum).index != index) {
sum++;
}
return sum;
}
//实现智能自动控
private int getAutoControl() {
System.out.println("总下注是:" + allBet);
System.out.println("总赢 是:" + allWin);
int rad = (int) (Math.random()*100);
System.out.println("随机数是:" + rad);
//输了九成了,这个时候送个大的
if (allBet / allWin > 10) {
System.out.println("输了九成了");
if (rad > 95) {
return getSteps(WIN_MAX);
} else if (rad > 90) {
return getSteps(OPEN_SONG_DENG);
} else if (rad > 80) {
return getSteps(OPEN_ONCE_MORE);
} else if (rad > 30) {
return getSteps(COMMON);
} else {
return getSteps(OPEN_LOSE);
}
} else if (allBet / allWin > 5) {
System.out.println("输了八成了");
if (rad > 98) {
return getSteps(WIN_MAX);
} else if (rad > 95) {
return getSteps(OPEN_SONG_DENG);
} else if (rad > 90) {
return getSteps(OPEN_ONCE_MORE);
} else if (rad > 30) {
return getSteps(COMMON);
} else {
return getSteps(OPEN_LOSE);
}
} else if (allBet > allWin) {
System.out.println("输了。。。。。。");
if (rad > 98) {
return getSteps(WIN_MAX);
} else if (rad > 95) {
return getSteps(OPEN_SONG_DENG);
} else if (rad > 90) {
return getSteps(OPEN_ONCE_MORE);
} else if (rad > 10) {
return getSteps(COMMON);
} else {
return getSteps(OPEN_LOSE);
}
} else if (allBet < allWin) {
System.out.println("赢了。。。。。。");
if (rad > 50) {
return getSteps(OPEN_LOSE);
} else {
return getSteps(COMMON);
}
} else {
System.out.println("出鬼了。。。。");
return getSteps(COMMON);
}
}
}
}
尽管千里冰封
依然拥有晴空
你我共同品味JAVA的浓香.
posted on 2007-11-13 09:06
千里冰封 阅读(2695)
评论(0) 编辑 收藏 所属分类:
JAVASE