这次的作业是做小时候经常玩的猜单词游戏。

/*
 * File: Hangman.java
 * ------------------
 * This program will eventually play the Hangman game from
 * Assignment #4.
 */

import acm.graphics.*;
import acm.program.*;
import acm.util.*;

import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Hangman extends ConsoleProgram {

	/***********************************************************
	 *              CONSTANTS                                  *
	 ***********************************************************/
	
	/* The number of guesses in one game of Hangman */
	private static final int N_GUESSES = 7;
	/* The width and the height to make the karel image */
	private static final int KAREL_SIZE = 150;
	/* The y-location to display karel */
	private static final int KAREL_Y = 230;
	/* The width and the height to make the parachute image */
	private static final int PARACHUTE_WIDTH = 300;
	private static final int PARACHUTE_HEIGHT = 130;
	/* The y-location to display the parachute */
	private static final int PARACHUTE_Y = 50;
	/* The y-location to display the partially guessed string */
	private static final int PARTIALLY_GUESSED_Y = 430;
	/* The y-location to display the incorrectly guessed letters */
	private static final int INCORRECT_GUESSES_Y = 460;
	/* The fonts of both labels */
	private static final String PARTIALLY_GUESSED_FONT = "Courier-36";
	private static final String INCORRECT_GUESSES_FONT = "Courier-26";
	
	/***********************************************************
	 *              Instance Variables                         *
	 ***********************************************************/
	
	/* An object that can produce pseudo random numbers */
	private RandomGenerator rg = new RandomGenerator();
	
	private GCanvas canvas = new GCanvas();
	private GLine line1;
	private GLine line2;
	private GLine line3;
	private GLabel label1;
	private GLabel label2;

	
	/***********************************************************
	 *                    Methods                              *
	 ***********************************************************/
	
	public void init() {
		add(canvas);
		}
	
	public void run() {
		// shall we?
		//初始化
		drawBackground();
		addKAREL(karel);
		parachute();
		addline();
		
		BufferedReader rd=openFileReader();
		ArrayList<String> list=read(rd);
		String word = newgetRandomWord(list);
		//String word = getRandomWord();
		//String word = "AMBASSADOR";
		game(word);
	}
	
	//增加图形
	private void drawBackground() {
		GImage bg=new GImage("background.jpg");
		bg.setSize(canvas.getWidth(), canvas.getHeight());
		canvas.add(bg);
	}
	
	private void addKAREL(GImage a) {
		//GImage karel=new GImage("karel.png");
		a.setSize(KAREL_SIZE,KAREL_SIZE);
		double x=(canvas.getWidth()-a.getWidth())/2;
		canvas.add(a,x,KAREL_Y);
	}
	
	private void parachute() {
		//GImage parachute=new GImage("parachute.png");
		parachute.setSize(PARACHUTE_WIDTH,PARACHUTE_HEIGHT);
		double x=(canvas.getWidth()-parachute.getWidth())/2;
		canvas.add(parachute,x,PARACHUTE_Y);
	}
	
	private void addline() {
		double x1=canvas.getWidth()/2;
		double sep=50;
		double y=PARACHUTE_Y+parachute.getHeight();
		line1=new GLine(x1,KAREL_Y,x1,y);
		line2=new GLine(x1,KAREL_Y,x1-sep,y);
		line3=new GLine(x1,KAREL_Y,x1+sep,y);
		canvas.add(line1);
		canvas.add(line2);
		canvas.add(line3);
	}
	
	private void showword(String word1,String word2,double y1,double y2) {
		//canvas.remove(label1);
		label1=new GLabel(word1);
		label2=new GLabel(word2);
		double x1=(canvas.getWidth()-label1.getWidth())/2;
		double x2=(canvas.getWidth()-label2.getWidth())/2;
		canvas.add(label1,x1,y1);
		canvas.add(label2,x2,y2);
	}
	
	
	//游戏的方法
	private void game(String word) {
		int n = word.length();
		boolean flag = false;
		//记录错误次数
		int count = 0;
		//记录正确猜出的个数
		int j = 0;
		//记录结果
		String ans = "";
		for (int i=0;i<n;i++) {
			ans+="_";
		}
		//记录已经猜过的字母,防止重复
		String haveguess="";
		
		//在图形界面画图
		showword(show(ans),show(haveguess),PARTIALLY_GUESSED_Y,INCORRECT_GUESSES_Y);
		
		println("Welcome to Hangman");
		
		while(count<N_GUESSES && j<n) {
			//记录展示的结果
			String show = show(ans);
			println("Your word now looks like this:"+show);
			println("You have "+(N_GUESSES-count)+" guesses left.");
			String temp = readLine("Your guess: ");
			
			//先判断是否是字符和字母
			char s = temp.charAt(0);
			while(temp.length()!=1 || !Character.isLetter(s)||
					haveguess.indexOf(Character.toUpperCase(s))!=-1) {
				if(temp.length()!=1|| !Character.isLetter(s)) {
					temp = readLine("This is not a single letter,please guesses again: ");
					s = temp.charAt(0);
				}else {
					temp = readLine("You have guessed letter,please guesses again: ");
					s = temp.charAt(0);
				}
			}

			//转换为小写
			s = Character.toUpperCase(s);
			String tempword = word.toUpperCase();
			
			int index = tempword.indexOf(s);
			//更新已经猜过的字母,注意大小写都要
			haveguess+=s;
			
			if(index==-1) {
				println("There are no "+s+"' in the word.");
				count++;
			}else {
				println("That guess is correct.");
				//要考虑这个字母多次出现的情形
				String tempans="";
				for(int i =0;i<word.length();i++) {
					if(tempword.charAt(i)!=s) {
						if (ans.charAt(i)=='_') {
							tempans+="_";
						}else {
							tempans+=ans.charAt(i);
						}
					}else {
						tempans+=word.charAt(i);
						//猜对的个数增加
						j++;
					}
				}
				ans=tempans;
			}
			
			//更新展示的结果
			canvas.remove(label1);
			canvas.remove(label2);
			showword(show(ans),show(haveguess),PARTIALLY_GUESSED_Y,INCORRECT_GUESSES_Y);
		}
		
		if(j<n) {
			println("You're completely hung.");
			canvas.remove(line1);
			canvas.remove(line2);
			canvas.remove(line3);
			canvas.remove(karel);
			addKAREL(karel1);
		}else {
			println("You win.");
		}
		println("The word was:"+word);
	}
	
	//将数据读取到ArrayList
	private ArrayList<String> read(BufferedReader rd){
		ArrayList<String> list=new ArrayList<String>();
		try {
			while(true) {
				String line=rd.readLine();
				if(line==null) {
					break;
				}
				list.add(line);
			}
		}catch(IOException ex) {
			println("Can't open that file.");
		}
		return list;
	}
	
	//读数据
	private BufferedReader openFileReader() {
	      BufferedReader rd = null;
	      while (rd == null) {
	         try {
	            String name = "HangmanLexicon.txt";
	            rd = new BufferedReader(new FileReader(name));
	         } catch (IOException ex) {
	            println("Can't open that file.");
	         }
	      }
	      return rd;
	   }

	
	/**
	 * Method: Get Random Word
	 * -------------------------
	 * This method returns a word to use in the hangman game. It randomly 
	 * selects from among 10 choices.
	 */
	private String getRandomWord() {
		int index = rg.nextInt(10);
		if(index == 0) return "BUOY";
		if(index == 1) return "COMPUTER";
		if(index == 2) return "CONNOISSEUR";
		if(index == 3) return "DEHYDRATE";
		if(index == 4) return "FUZZY";
		if(index == 5) return "HUBBUB";
		if(index == 6) return "KEYHOLE";
		if(index == 7) return "QUAGMIRE";
		if(index == 8) return "SLITHER";
		if(index == 9) return "ZIRCON";
		throw new ErrorException("getWord: Illegal index");
	}
	
	private String newgetRandomWord(ArrayList list) {
		int index = rg.nextInt(list.size());
		return (String) (list.get(index));
	}
	
	private String show(String s) {
		String result="";
		for(int i=0;i<s.length();i++) {
			result+=s.charAt(i)+" ";
		}
		return result;
	}
	
	private static final GImage parachute=new GImage("parachute.png");
	private static final GImage karel=new GImage("karel.png");
	private static final GImage karel1=new GImage("karelFlipped.png");
}