闲着无事,写个小程序玩玩。随便复习下多线程的东东,黑马的视频断断续续的看,快1个月只有利用周末看看,平时上班太忙了唉,还好用6天时间就看了视频的18天内容。强行灌输了不少东西,几天没看。现在又快忘记光了,特别写个小日志来复习了。呵呵。
先想功能需求分析:
需求分析:
1, 可生成一个随机的扑克牌,用三个线程或多个线程去猜。猜对后,打印奖励100元。
2, 每个线程可有三次机会去猜,中途猜中的,打印100元,并不再参与猜了。
3, 没有猜对的线程最后统一告诉答案,但必须是所有线程都猜完后,再打印最后答案。
4, 扑克牌可以排除大小王两张牌,剩余的52张牌进行随机抽一张牌作为答案,让三个线程去猜。
-------------------------------代码-------------------------
/**
先想功能需求分析:
需求分析:
1, 可生成一个随机的扑克牌,用三个线程或多个线程去猜。猜对后,打印奖励100元。
2, 每个线程可有三次机会去猜,中途猜中的,打印100元,并不再参与猜了。
3, 没有猜对的线程最后统一告诉答案,但必须是所有线程都猜完后,再打印最后答案。
4, 扑克牌可以排除大小王两张牌,剩余的52张牌进行随机抽一张牌作为答案,让三个线程去猜。
实现思想:
1, 扑克牌 有四种花色,每种花色共有13个。(不考虑大王及小王)
2, 扑克牌 抽到的四种花色是随机,且牌面数也是随机的。
3, 可以用数组来维护两个表,一个表放花色,一个表放牌面数。
系统分别产生两个随机数是 两表的大小减1之内的数。
4. 根据产生的两个随机数,取出表中元素。可将花色与面数 封装成一对象的数据,扑克。
5. 系统在控制台中,输入字符串匹配答案。三次机会应该是循环三次,猜对就不再参与,循环可break。
6. 三次猜错了,要告诉三次猜奖机会用完了,但答案要等所有线程跑完猜完,所以肯定要wait。
*/
import java.util.*;
public class ScannerTest{
public static final String[] COLORS = {"红桃","黑桃","方块","梅花"};
public static final String[] NUMS = {"A","2","3","4","5","6","7","8","9"
,"10","J","Q","K"};
public static void main(String[] args){
Random round = new Random();
int colorInt = round.nextInt(COLORS.length);
int numInt = round.nextInt(NUMS.length);
Card corCard = new Card(COLORS[colorInt],NUMS[numInt]); //随机产生的扑克牌
//System.out.println(corCard);
ArrayList<GuessCard> al = new ArrayList<GuessCard>();
for(int i=0;i<3;i++){ //搞三个线程来跑猜游戏
GuessCard gc = new GuessCard(corCard,3);
al.add(gc);
new Thread(gc,"第"+(i+1)+"个人线程").start();
}
GuessOver go = new GuessOver(corCard,al); //专门一线程查看是否所有线程都跑完了。
new Thread(go).start();
}
}
class GuessOver implements Runnable{
private Card corCard ; //正确的答案,也就是那把同步的锁
private ArrayList<GuessCard> al; //所有正在猜的线程对象
public GuessOver(Card corCard,ArrayList<GuessCard> al){
this.corCard = corCard;
this.al = al;
}
public void run(){
boolean flag = false;
//遍历所有线程查看是否都猜完了,若未猜完就一直查下去。至到查到所有线程都猜完了。
while(!flag){
flag = true; //默认猜完了?,猜完了就不遍历了,进同步块唤醒wait的线程。
Iterator<GuessCard> it = al.iterator();
while(it.hasNext()){
GuessCard gc = it.next();
if(gc.getTime()!=-1){
flag =false; //遍历到只要有一个线程没猜完,就直接再遍历循环查是否猜完了。
break;
}
}
}
//所有的线程次数都用完了,且都是-1,证明都在wait中了或都猜中了或部分猜中部分wait了。接下来我们来唤醒所有wait的线程即可。
synchronized(corCard){
corCard.notifyAll();
}
}
}
class GuessCard implements Runnable {
private Card corCard ; //正确的答案
private int time ; //可以猜的次数
public GuessCard(Card corCard, int time){
this.corCard = corCard;
this.time = time;
}
public void run(){
Scanner sc = new Scanner(System.in);
Card tempCa = null;
boolean isWin = false;
while(time>0){
time--;
String s = null;
//为了方便打印出确认,哪个线程输入了什么数据。将此块同步掉。
synchronized(corCard){
System.out.println(Thread.currentThread().getName()+" 请输入扑克牌,如红桃A或梅花6,这样的三个字符。前两个字符表示花色,后一个字符表
示牌面大小");
s = sc.next();
System.out.println(Thread.currentThread().getName()+"你输入的是:"+s);
}
if(s.length()!=3){
System.out.println(Thread.currentThread().getName()+"输入的字符:"+s+",不符合规则,浪费了一次机会了");
continue;
}
String color = s.substring(0,2);
String num = s.substring(2);
boolean inputCor = checkInput(color,num);
if(!inputCor){
System.out.println(Thread.currentThread().getName()+"输入的字符:"+s+",不符合规则,浪费了一次机会了");
continue;
}
tempCa = new Card(color,num);
if(tempCa.equals(corCard)){
System.out.println(Thread.currentThread().getName()+"哇,你猜对了,恭喜奖100元");
isWin = true;
time = -1 ; //此线程猜对,把time置为-1,标识猜完。
break;
}
if(time>0&&!isWin)
System.out.println(Thread.currentThread().getName()+"你猜的不对哦,请继续");
}
if(!isWin){
synchronized(corCard){
System.out.println(Thread.currentThread().getName()+"很遗憾,本次抽奖机会用完,明天再努力");
try{
time = -1 ;
corCard.wait();
}catch(InterruptedException ie){
}
//正确答案,不能提前告知,必须等所有线程都猜完题目
System.out.println(Thread.currentThread().getName()+"今天的正确答案是:"+corCard);
}
}
}
public boolean checkInput(String color,String num){
//System.out.println(color+"--"+num);
boolean colorCor = false ;
for(int i=0;i<ScannerTest.COLORS.length;i++){
if(ScannerTest.COLORS[i].equals(color)){
colorCor = true ;
break;
}
}
boolean numCor = false ;
for(int i=0;i<ScannerTest.NUMS.length;i++){
if(ScannerTest.NUMS[i].equals(num)){
numCor = true ;
break;
}
}
return colorCor&&numCor ;
}
public int getTime(){
return time;
}
}
/**
写个Card对象,既可以复习下常用的toString方法,equals方法,hashCode方法。
还可以作为锁对象来使用,方便实用。
*/
class Card{
private String color ;
private String num ;
public Card(String color,String num){
this.color = color;
this.num = num ;
}
public void SetColor(String color){
this.color = color;
}
public String getColor(){
return color;
}
public void setNum(String num){
this.num = num;
}
public String getNum(){
return num;
}
public int hashCode(){
int colha = color.hashCode()*37;
return colha + num.hashCode();
}
public boolean equals(Object obj){
if(getClass()!=obj.getClass())
throw new RuntimeException(obj+"类型与Card类型不匹配,不具体可比性");
Card c = (Card)obj;
if(color.equals(c.getColor())&&num.equals(c.getNum()))
return true;
return false;
}
public String toString(){
return "["+color+num+"]";
}
}