CS106A Assignment4: Hangman

做完了Breakout之后,感觉做Hangman的速度明显快了不少。估计也是和用了三个类,加上stub implement有关系吧!这个程序我并没有使用太多的Decomposition,原因是整个游戏比较直观,虽然步骤多,但是一个接一个的步骤写代码基本不会错。其实写代码的风格还可以简洁一些的,这一点还要多加练习。下面贴上代码:

以下是第一部分(Hangman.java)的代码:

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

public class Hangman extends ConsoleProgram {
	
	private static final int GUESS_NUM = 8;
	
	public void init() {
		canvas = new HangmanCanvas();
		add(canvas);
	}

    public void run() {
		/**========================================
    	 * @author Andrew Garcia
    	 * 1、从列表中随机选择一个单词
    	 * 2、让用户输入猜测的字母并进行跟踪
    	 * 3、根据游戏规则进行游戏
    	 * ========================================*/
    	setFont("serif-20");
    	canvas.reset();
    	//以随机方式选取一个单词
       	int x = rgen.nextInt(0,hl.getWordCount());
    	ans = hl.getWord(x);
    	    	    	
    	//提示用户单词的形式,并进行猜测
    	hintStr = "";
    	for (int i=0;i<ans.length();i++){
    		hintStr += "-";
    	}
    	println("The word now looks like this: "+hintStr);
    	
    	//猜多个字母
    	for (int i=0;i<GUESS_NUM;i++){
    		if ((GUESS_NUM-i)!=1){
				println("You have " + (GUESS_NUM-i) + " guesses left.");
			} else println("You have only one guess left.");
    		//检查并反馈猜测的结果
    		/********************************************************/
        	while (true){
    			guess();
    			canvas.displayWord(check);  //输出图像的单词形式
    			if (done){
    				println("That guess is correct!");
    	    		check(); //检查是否已经猜到完整的单词
    	    		if (!flag){
    	    			println("The word now looks like: "+check);
    	    			if ((GUESS_NUM-i)!=1){
    	    				println("You have " + (GUESS_NUM-i) + " guesses left.");
    	    			} else println("You have only one guess left.");
    	    		} else break;
    	    	} else {
    	    		println("There are no "+ guess +"'s in the word.");
        	    	println("The word now looks like: "+check);
        	    	canvas.noteIncorrectGuess(guess.charAt(0));
    	    	}
    			if (done==false) break;
    		}
        	/***********************************************************/
        	if (flag) break;
    	}
    	/*=========End: For Block=====================================================*/
    	if (!flag) {
    		println("You lose.");
    		println("The word is "+ans);
    	}
    }

    
    private void check() {
		if (check.equals(ans)){
			println("You guessed the word: "+ans);
			println("You win!");
			flag = true;
		}
	}

	private void guess(){
    	//追踪猜测的字符
    	guess = readLine("Your guess is: ");
    	while (guess.length()!= 1 || Character.isLetter(guess.charAt(0))!= true){
    		println("Illegal guess!");
    		guess = readLine("Your guess is: ");
    	}
    	guess = guess.toUpperCase();
    	//检查并反馈猜测的结果
    	check = hintStr;
    	done = false;
    	char ch = guess.charAt(0);
    	for (int j=0;j<ans.length();j++){
    		if (ch == ans.charAt(j)){
    			check = hintStr.substring(0,j) + ch;
    			if (j != ans.length()-1){
    				check = check + hintStr.substring(j+1);
    			}
    			hintStr = check;
    			done = true;
    		}
    	}
    }
    
	
    private HangmanLexicon hl = new HangmanLexicon();
    private RandomGenerator rgen = new RandomGenerator();
    private HangmanCanvas canvas;
    private String ans;
    private String guess;
    private String hintStr;
    private boolean done;
    private String check;
    private boolean flag;
}

以下是第二部分(HangmanCanvas.java)的代码:
import acm.graphics.*;

public class HangmanCanvas extends GCanvas {

/** Resets the display so that only the scaffold appears */
	public void reset() {
		removeAll();
		x_beam = getWidth()/2 - BEAM_LENGTH;
		y_beam = 5;
		GLine beam = new GLine(x_beam,y_beam,getWidth()/2,y_beam);
		GLine scaffold = new GLine(x_beam,y_beam,x_beam,y_beam+SCAFFOLD_HEIGHT);
		GLine rope = new GLine(getWidth()/2,y_beam,getWidth()/2,y_beam+ROPE_LENGTH);
		add(beam);
		add(scaffold);
		add(rope);
	}

/**
 * Updates the word on the screen to correspond to the current
 * state of the game.  The argument string shows what letters have
 * been guessed so far; unguessed letters are indicated by hyphens.
 */
	public void displayWord(String word) {
		if (label == null){
			label = new GLabel(word);
			label.setFont("serif-24");
			add(label,x_beam,y_beam+SCAFFOLD_HEIGHT+label.getAscent()+5);
		} else {
			remove(label);
			label = new GLabel(word);
			label.setFont("serif-24");
			add(label,x_beam,y_beam+SCAFFOLD_HEIGHT+label.getAscent()+5);
		}
	}

/**
 * Updates the display to correspond to an incorrect guess by the
 * user.  Calling this method causes the next body part to appear
 * on the scaffold and adds the letter to the list of incorrect
 * guesses that appears at the bottom of the window.
 */
	public void noteIncorrectGuess(char letter) {
		str += letter;
		int x1 = getWidth()/2 - UPPER_ARM_LENGTH;
		int x2 = getWidth()/2;
		int x3 = getWidth()/2 + UPPER_ARM_LENGTH;
		int x4 = getWidth()/2 - HIP_WIDTH;
		int x5 = getWidth()/2 + HIP_WIDTH;
		int x6 = x4 - FOOT_LENGTH;
		int x7 = x5 + FOOT_LENGTH;
		int y1 = y_beam+ROPE_LENGTH+2*HEAD_RADIUS+ARM_OFFSET_FROM_HEAD;
		int y2 = y1 + LOWER_ARM_LENGTH;
		int y3 = y_beam+ROPE_LENGTH+2*HEAD_RADIUS+BODY_LENGTH;
		int y4 = y3 + LEG_LENGTH;
		switch (str.length()){
		case 1:
			GOval head = new GOval(2*HEAD_RADIUS,2*HEAD_RADIUS);
			add(head,getWidth()/2-HEAD_RADIUS,y_beam+ROPE_LENGTH);
			break;
		case 2:
			GLine body = new GLine(getWidth()/2,y_beam+ROPE_LENGTH+2*HEAD_RADIUS,
					getWidth()/2,y_beam+ROPE_LENGTH+2*HEAD_RADIUS+BODY_LENGTH);
			add(body);
			break;
		case 3:
			GLine leftArm1 = new GLine(x1,y1,x2,y1);
			GLine leftArm2 = new GLine(x1,y1,x1,y2);
			add(leftArm1);
			add(leftArm2);
			break;
		case 4:
			GLine rightArm1 = new GLine(x2,y1,x3,y1);
			GLine rightArm2 = new GLine(x3,y1,x3,y2);
			add(rightArm1);
			add(rightArm2);
			break;
		case 5:
			GLine leftLeg1 = new GLine(x4,y3,x2,y3); 
			GLine leftLeg2 = new GLine(x4,y3,x4,y4);
			add(leftLeg1);
			add(leftLeg2);
			break;
		case 6:
			GLine rightLeg1 = new GLine(x5,y3,x2,y3);
			GLine rightLeg2 = new GLine(x5,y3,x5,y4);
			add(rightLeg1);
			add(rightLeg2);
			break;
		case 7:
			GLine leftFoot = new GLine(x4,y4,x6,y4);
			add(leftFoot);
			break;
		case 8:
			GLine rightFoot = new GLine(x5,y4,x7,y4);
			add(rightFoot);
			break;
		default:
			GLabel error = new GLabel("ERROR!");
			add(error,(getWidth()-error.getWidth())/2, (getHeight()-error.getAscent())/2);
		}
		
		GLabel err = new GLabel(str);
		add(err,x_beam,y_beam+SCAFFOLD_HEIGHT+label.getAscent()+err.getAscent()+ 10);		
	}

/* Constants for the simple version of the picture (in pixels) */
	private static final int SCAFFOLD_HEIGHT = 360;
	private static final int BEAM_LENGTH = 144;
	private static final int ROPE_LENGTH = 18;
	private static final int HEAD_RADIUS = 36;
	private static final int BODY_LENGTH = 144;
	private static final int ARM_OFFSET_FROM_HEAD = 28;
	private static final int UPPER_ARM_LENGTH = 72;
	private static final int LOWER_ARM_LENGTH = 44;
	private static final int HIP_WIDTH = 36;
	private static final int LEG_LENGTH = 108;
	private static final int FOOT_LENGTH = 28;
	
/*Instance variables*/
	private int x_beam;
	private int y_beam;
	private GLabel label;
	private String str = "";
	

}

以下是第三部分(HangmanLexicon.java)的代码:
import acm.util.*;
import java.io.*;
import java.util.*;

public class HangmanLexicon {
/**Stores the wordlist.*/
	ArrayList<String> strList = new ArrayList<String>();
	BufferedReader rd = OpenFile();
	

/** Returns the number of words in the lexicon. */
	public int getWordCount() {
		BufferedReader rd = OpenFile();
		try{
			while (true){
				String line = rd.readLine();
				if (line == null) break;
				strList.add(line);
			}
			rd.close();
		} catch (IOException ex){
			throw new ErrorException(ex);
		}
		return strList.size(); 
	}

/** Returns the word at the specified index. */
	public String getWord(int index) {
		return strList.get(index);
	}
	
/**Retunes the BufferedReader pointing to HangmanLexicon.txt.*/
	private BufferedReader OpenFile(){
		BufferedReader rd = null;
		try{
			String name = "HangmanLexicon.txt";
			rd = new BufferedReader(new FileReader(name));
		} catch (IOException ex){
			throw new ErrorException(ex);
		}
		return rd;
	}
}



另外上传一张游戏的效果图做为结尾:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值