猜扑克的小游戏 复习多线程

闲着无事,写个小程序玩玩。随便复习下多线程的东东,黑马的视频断断续续的看,快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+"]";
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值