Java语言与系统设计课程实验报告

写在开头:

有一说一,郭老师上课还真挺彳亍的,一方面讲得通俗易懂,另一方面还会拓展一些例子出来(比如:如何用编程方法求出圆周率的近似值)。而且备课也很充分,上课手码代码。试卷出的也很简单。别看这实验那么唬人,其实重要的组成部分他上课都讲过了(比如怎么让标签下落)。真神!!!

声明:本人java入门水平,佬们没必要浪费时间看这坨代码。

然后也希望有精力,有自信的后辈,可以把这段代码(虽然我写的一坨)精进一下。

如有任何违法的内容或地方,请立刻与我联系,我会在第一时间删除此文。

一、目的与要求

        实验题目:题:用 Java编程开发”六级单词强化记忆游戏

(0)在网上下载英语六级词汇表,中英文对应。保存在服务器端,服务器可以让1个客

广端连入。客户端初始分数为 10分。

(1)根据中文输入英文词汇。客户端界面打开,开始游戏。服务器随机选出一个英文单

词的中文单词描达,发给客广端显示。该中文单词描达,从界面顶端落下。果面底端出现四个备选单词,其中有一个正确答案。要求,其他三个备选单词 ,和正确答案的单词至少有30%的字母相同。客户端在文本框中准确输入自己认为正确的相应单词,提交。规则:在中文单词描述掉到底端之前,提交正确,该客户端增加 1分 ,进入下一局;提交错误的,该客户端扣2分,进入下一局;在掉到底端前不回答,扣1分 ,进入下一局。进入下一局之前,若回答正确,容户端显示"恭喜回答正确”;回答错误,客户端显示'回答错误 ,答案是xxx”;没回答,客户端显示”您没有回答,答案是xxx〞。用户分数扣到0分,则游戏输掉退出。注:此项考察多线程、界面开发、网络编程、字符串处理。

(2)错词保存。如果一个单词,在以上功能中,被用户答对,将其保存在“已掌握单词.txt'中;如果一个单词,在以上功能中 ,答错或没有答,则保存在“末掌握单词.txt'中(标注是答错还是没答),用户可以打开复习。对于客户端,“已掌握单词.txt”和“未掌握单词.txt”,保存在本地。注:此顶考察多线程、界面开发、IO处理。

实验要求:学习Java界面开发基础知识。利用所学到的Java编程知识和编程技巧,设计一个实际的应用软件,初步认识软件设计的基本方法,提高进行工程设计的基本技能及分析、解决实际问题的能力,为后续课程和以后的工程实践打下良好的基础。

二、实验环境

硬件: maxbook pro M1

软件:Eclipse

三、实验内容

整个文件包含两个类:

1.Server类

在这个类中包含的函数有:(1)构造函数,将文件中的英文-中文对读入到字符串数组中,然后监听本地的9999号窗口,并返回套接字。(2)compare函数,比较两个字符串是否相似度是否超过30%,相似度用的是重复字母个数除以短的字符串的串长,不区分大小写,并用两个hashmap记录字符出现次数。(3)countLetters函数,计数并返回一个hashmap,它包含着字符--字符出现次数key-value pair。(4)GetAWord函数,产生一个随机数,并返回随机数对应的字符串。(5)GetSimilar函数,从单词数组里面找出三个相似的英文。(6)main函数:实现了与客户端交流的功能,对于客户端发送过来的请求协议,若为“请求单词”,则发送四个单词和一个中文过去,若为“结束”,则跳出循环,断开与客户端的链接。

2.Client类

在这个类中包含的类有:(1)Socket_input类,用来连接本地的9999号端口。(2)myJPanel类,用来产生带背景图的JPanel。

在这个类中包含的函数有:(1)构造函数,初始化控件,并显示客户端。(2)getlife函数,获得生命值(分数)。(3)success函数,给出回答正确的提示框,并分数+1.(4)fail函数,给出回答错误的提示框,并分数-2.(5)overtime函数,给出回答超时的提示框,并分数-1.(6)run函数,修改中文所在的JLabel的Y坐标,呈现出下降的样子。(7)setjlb1函数,设置JLabel1的内容。(8)setjlb2函数,设置JLabel2的内容。(9)setjlb3函数,设置JLabel3的内容。(10)setjlb4函数,设置JLabel4的内容。(11)setjlb5函数,设置JLabel5的内容。(12)actionPerformed函数,提交按钮被点击时,记录下输入答案(13)main函数,当生命值大于0时,与服务器端进行对话,并开始每一局游戏,对于每一局游戏的结果进行提示,并记录正确答案到相应的文件中,当生命值小于等于0时,提示“您输掉了游戏”,关闭两个文件读写类,并断开链接,发送结束协议,释放所有Swing控件的资源。

四、实验结果

先运行服务器端,此时客户端未打开,输出“未连接”:

客户端运行界面,中文正在下落: 

此时服务器端输出“已连接”: 

回答正确的弹窗: 

回答错误的弹窗: 

超时的弹窗: 

游戏结束的弹窗: 

五、有待提升的地方

1.预处理:在服务器被打开的时候,就把每个单词的相似单词给筛选出来。类似于先排序,再折半查找,在查找次数较多的情况下,效益比纯乱序查找要高。

2.相似度概念的优化:或许可以做成“最长公共子串”这种形式,而不是统计相同字母出现的次数。

3.单词保存的优化:对于要保存到文件内的单词,可以加上执行保存操作时的时间;或者单词的错误/正确的次数等。

4.做一个主界面:主界面包括以下一些按钮:开始游戏;打开错题本;打开对题本;退出等等。

5.UI设计永远有待提升。

六、实验源代码

服务器端代码:

package class6;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;
import javax.swing.*;

public class Server 
{
	public ServerSocket connect;
	public Socket socket;
	int lines = 2089;
	int temp;//保存当前选出的字符的位置
	String[] danci = new String[lines+1]; 
	Server()//读入文件中的六级单词,然后监听9999号端口,
	{
		try
		{
			BufferedReader b1 = new BufferedReader(new FileReader("/Users/zpt/eclipse-workspace/六级单词.txt"));
			for(int i=0;i<lines;i++)
			{
				danci[i]= b1.readLine();
			}
			b1.close();
			connect = new ServerSocket(9999);
			System.out.println("未连接");
			socket = connect.accept();
			System.out.println("已连接");
		}catch(Exception e) {e.printStackTrace();}
	}
	public boolean compare(String str1,String str2)
	{
		str1 = str1.toLowerCase();
        str2 = str2.toLowerCase();//不区分大小写
        Map<Character, Integer> countMap1 = countLetters(str1); 
        Map<Character, Integer> countMap2 = countLetters(str2); // 统计每个字符串中字母的出现次数
        int count = 0;//记录重复字符的个数
        for (Map.Entry<Character, Integer> entry : countMap1.entrySet()) {
            char ch = entry.getKey();
            if (countMap2.containsKey(ch)) {
                count += Math.min(entry.getValue(), countMap2.get(ch));
            }
        }
        int ml = Math.min(str1.length(), str2.length());
        double similarity = (double) count / ml;// 计算相似度百分比
		return similarity>=0.3;
	}
	private Map<Character, Integer> countLetters(String str) {
        Map<Character, Integer> countMap = new HashMap<>();
        for (char ch : str.toCharArray()) {
            if (Character.isLetter(ch)) {
                countMap.put(ch, countMap.getOrDefault(ch, 0) + 1);
            }
        }
        return countMap;
    }
	public String GetAWord() 
	{
		temp = (int)(Math.random()*lines);
		return danci[temp];
	}
	public String GetSimilar(String a) throws Exception
	{
		String[] goal = new String[4];
		int num = 1;
		//int cnt=0;
		String temp1;
		while(true)
		{
			int j = (int) ((Math.random()-0.5)*100);
			//cnt++;
			while(j==0||(temp+j)>(lines-1)||(temp+j)<0)
			{
				j = (int) ((Math.random()-0.5)*100);
				//cnt++;
			}
			temp1 = danci[temp+j];
			String[] all = temp1.split("\\s+");//按一个或多个空格来分割
			goal[num] = all[0];
			if(compare(a,goal[num]))
			{
				if(num==1)
				{
					num++;
				}
				else if(num==2)
				{
					if(!goal[1].equals(goal[num]))
					{
						num++;
					}
				}
				else if(num==3)
				{
					if((!goal[1].equals(goal[num]))&&(!goal[2].equals(goal[num])))
					{
						break;
					}
				}
			}
		}
		//System.out.println(cnt);
		return goal[1]+"\t"+goal[2]+"\t"+goal[3];
	}
	public static void main(String[] args) throws Exception
	{
		Server s = new Server();
		InputStream is;
		BufferedReader br;
		String str;
		OutputStream os;
		PrintStream ps;
		while(true)
		{
			if(s.socket==null)
				continue;
			is = s.socket.getInputStream();
			br = new BufferedReader(new InputStreamReader(is));
			str = br.readLine();
			try{
			if(str.equals("请求单词"))
			{
				os = s.socket.getOutputStream();
				ps = new PrintStream(os);
				String[] goal = s.GetAWord().split("\\s+");
				ps.println(goal[1]);
				ps.println(goal[0]);
				String t1 = goal[0];
				String[] Similar = s.GetSimilar(t1).split("\\s+");
				ps.println(Similar[0]);
				ps.println(Similar[1]);
				ps.println(Similar[2]);
			}
			else if(str.equals("结束"))
			{
				System.out.println("连接已断开");
				break;
			}
			}catch(NullPointerException e) 
			{
				System.out.println("异常断开");
				break;
			}
		}
		System.out.println("服务器端退出");
		s.socket.close();
		s.connect.close();
	}
}

 客户端代码:

package class6;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.util.*;

class Socket_input
{
	public Socket socket;
	public Socket_input()
	{
		try
		{
			socket = new Socket("127.0.0.1",9999);//申请连接本机的9999号端口
		}catch(Exception e) {System.out.println("客户端出错啦");}
	}
}
class myJPanel extends JPanel//带背景图的JPanel
{
	ImageIcon icon = new ImageIcon("/Users/zpt/eclipse-workspace/photo2.png");
	public void paintComponent(Graphics g)
	{
		Graphics2D g2 = (Graphics2D) g;
		g2.drawImage(icon.getImage(), 0, 0, this.getWidth(), this.getHeight(),null);
	}
}
public class Client extends JFrame implements Runnable,ActionListener
{
	private JPanel jpn = new myJPanel();
	private JLabel jlb1 = new JLabel("这里是下坠的文本");
	private JLabel jlb2 = new JLabel("这里是选项1");
	private JLabel jlb3 = new JLabel("这里是选项2");
	private JLabel jlb4 = new JLabel("这里是选项3");
	private JLabel jlb5 = new JLabel("这里是选项4");
	private JLabel jlb6 = new JLabel("这里是生命值:");
	private JTextField jtf = new JTextField("在这里输入答案");
	private JButton jbt = new JButton("提交答案");
	public int Y=0;//单词的中文的纵坐标
	private int life=10;//得分
	public String ans;//玩家输入的答案
	public String str1;//存中文
	public String str2;//存英文1
	public String str3;//存英文2
	public String str4;//存英文3
	public String str5;//存英文4
	public String correct;//正确答案
	public boolean running;
	public Client()
	{
		this.add(jpn);
		this.setSize(700,1000);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setVisible(true);
		jpn.setLayout(null);
		jlb6.setText("得分:"+life);
		jlb1.setForeground(Color.ORANGE);
		jlb2.setForeground(Color.ORANGE);
		jlb3.setForeground(Color.ORANGE);
		jlb4.setForeground(Color.ORANGE);
		jlb5.setForeground(Color.ORANGE);
		jlb6.setForeground(Color.ORANGE);
		jtf.setBackground(Color.CYAN);
		jlb1.setBounds(400, 0, 400, 100);	jlb2.setBounds(0, 300, 200, 50);	jlb3.setBounds(0, 400, 200, 50);	jlb4.setBounds(0, 500, 200, 50);	jlb5.setBounds(0, 600, 200, 50);	jlb6.setBounds(0, 0, 200, 100);	jtf.setBounds(0, 200, 200, 50);
		jbt.setBounds(200, 200, 100, 50);
		jpn.add(jlb1);	jpn.add(jlb2);	jpn.add(jlb3);	jpn.add(jlb4);	jpn.add(jlb5);	jpn.add(jlb6);	jpn.add(jtf);	jpn.add(jbt);
		jbt.addActionListener(this);
	}
	public int getlife()
	{
		return life;
	}
	public void success()
	{
		life++;
		jlb6.setText("得分:"+life);
		JOptionPane.showMessageDialog(this, "恭喜回答正确");
	}
	public void fail()
	{
		life-=2;
		jlb6.setText("得分:"+life);
		JOptionPane.showMessageDialog(this, "回答错误,答案是"+correct+"\t"+str1);
	}
	public void overtime()
	{
		life--;
		jlb6.setText("得分:"+life);
		JOptionPane.showMessageDialog(this, "您没有回答,答案是"+correct+"\t"+str1);
	}
	public void run()
	{
		Y=1;
		while(running)
		{
				jlb1.setLocation(500, Y);
				try{
					Thread.sleep(10);
				}catch(Exception e) {e.printStackTrace();}
				if(Y>this.getHeight())
					break;
				Y++;
		}
	}
	public void setjlb1()
	{
		jlb1.setText(str1);
	}
	public void setjlb2(String a)
	{
		jlb2.setText("    "+a);
	}
	public void setjlb3(String a)
	{
		jlb3.setText("    "+a);
	}
	public void setjlb4(String a)
	{
		jlb4.setText("    "+a);
	}
	public void setjlb5(String a)
	{
		jlb5.setText("    "+a);
	}
	public void actionPerformed(ActionEvent e)
	{
		ans = jtf.getText();
	}
	public static void main(String[] args) throws Exception
	{
		Client c = new Client();
		Socket_input s = new Socket_input();
		OutputStream os;
		PrintStream ps;
		InputStream is;
		BufferedReader br;
		Thread th1;
		BufferedWriter w1 = new BufferedWriter(new FileWriter("/Users/zpt/eclipse-workspace/已掌握单词.txt",true));
		BufferedWriter w2 = new BufferedWriter(new FileWriter("/Users/zpt/eclipse-workspace/未掌握单词.txt",true));
		while(c.getlife()>0)
		{
			os = s.socket.getOutputStream();
			ps = new PrintStream(os);
			ps.println("请求单词");
			is = s.socket.getInputStream();
			br = new BufferedReader(new InputStreamReader(is));
			c.str1 = br.readLine();
			c.setjlb1();
			c.str2 = br.readLine();
			c.correct = c.str2;
			c.str3 = br.readLine();
			c.str4 = br.readLine();
			c.str5 = br.readLine();
			String[] temp = new String[4];
			temp[0] = c.str2;
			temp[1] = c.str3;
			temp[2] = c.str4;
			temp[3] = c.str5;
			for(int i=1;i<=10;i++)//打乱选项
			{
				int a = (int)(Math.random()*4);
				int b = (int)(Math.random()*4);
				if(a!=b)
				{
					String temp1 = temp[a];
					temp[a] = temp[b];
					temp[b] = temp1;
				}
			}
			c.setjlb2(temp[0]);
			c.setjlb3(temp[1]);
			c.setjlb4(temp[2]);
			c.setjlb5(temp[3]);
			//发送请求,得到一个正确答案和3个错误答案
			//蹦出开始游戏按钮,点击后开始,并显示四个选项
			c.jtf.setText(null);
			c.jtf.requestFocusInWindow();
			c.ans = null;
			c.running = true;
			th1 = new Thread(c);
			th1.start();
			//一局结束以后,弹出弹窗(正确,错误,超时)
			while(true)
			{
			Thread.sleep(100);
			if(c.ans != null||c.Y >= c.getHeight())
				break;
			}
			c.running = false;//让run能够停下来
			if(c.ans != null)
			{
				if(c.ans.equals(c.correct))
				{
					w1.write(c.correct+"\t"+c.str1);
					w1.newLine();
					c.success();
				}
				else
				{
					w2.write(c.correct+"\t"+c.str1+"\t答错");
					w2.newLine();
					c.fail();
				}
			}
			else
			{
				w2.write(c.correct+"\t"+c.str1+"\t未答");
				w2.newLine();
				c.overtime();
			}
		}
		JOptionPane.showMessageDialog(c, "您输掉了游戏");
		w1.close();
		w2.close();
		os = s.socket.getOutputStream();
		ps = new PrintStream(os);
		ps.println("结束");
		s.socket.close();
		c.dispose();
	}
}

实验5 常用类(2学时) 一、实验目的 1. 熟悉Java中的String、StringBuffer、Math、包装器类的使用方法。 2. 使用常用类解决一般性的应用问题。 3. 掌握JavaSE API文档的使用方法。 二、实验内容 1. 编写一个程序,输出一个字符串中的大写英文字母数,小写英文字母数以及非英文字母数。(字符串可以在main方法中指定) 2. 调用java.lang.Math的成员函数“public static double random()”运算下面表达式1000次,(int) (Math.random()*20+0.5),统计其中生成的整数0、1、2、……、20的个数分别是多少,并输出统计结果。 3. 编写一个方法,返回一个double型的二维数组,数组中的元素通过解析字符串参数获得。例如,字符串参数:“1,2;3,4,5;6,7,8”,对应的数组为: d[0,0] = 1.0 d[0,1] = 2.0 d[1,0] = 3.0 d[1,1] = 4.0 d[1,2] = 5.0 d[2,0] = 6.0 d[2,1] = 7.0 d[2,2] = 8.0 三、实验要求 完成程序设计并提交实验报告。 实验6 容器(2学时) 一、实验目的 1. 熟悉容器类库中常用类的使用方法。 2. 使用常用容器类解决一般性的应用问题。 二、实验内容 1. 用HashMap模拟一个网上购物车。要求:从键盘输入5本书的名称、单价、购买数量,将这些信息存入一个HashMap,然后将该HashMap作为参数调用方法getSum(HashMap books),该方法用于计算书的总价并返回。【说明:键盘输入可以使用Scanner类】 2. 使用两个Stack类(JDK容器类库中的Stack类)实现一个队列类MyQueue,提供队列的入队列和出队列操作:enQueue和deQueue。 3. 写一个彩票程序:30选7。随机(1~30之间)生成7个随机数,注意不能重复。然后从键盘输入7个数,对比7个数是否与随机数有相同的。最后显示“中了几个号”。同时,如果中了7个号,显示一等奖;如果中了6个号,显示二等奖;如果中了5个号,显示三等奖。要求:首先写出程序的实现思想,特别是程序所使用的数据结构,然后写出Java实现代码。【说明:键盘输入可以使用Scanner类】 三、实验要求 完成程序设计并提交实验报告。 实验7 流(2学时) 一、实验目的 1. 熟悉流类库中各种常用流的使用方法。 2. 能够使用流类实现基本的文件读写。 二、实验内容 1. 编写程序,在控制台窗口提示输入两个整数,然后接收这两个整数,并输出它们的和。(要求:键盘输入通过流封装System.in获取,不要使用Scanner类) 2. 设计学生类Student,属性:编号(整型);姓名(字符串),成绩(整型)。编写一个程序:要求:(1)输入5个学生的姓名和成绩,将其姓名和成绩保存到data.txt中;(2)然后从该文件中读取数据,求得这五个学生的平均成绩。 三、实验要求 完成程序设计并提交实验报告
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值