Java期末大作业——六级词汇学习系统

1、任务描述:
用JavaSocket编程开发英语六级词汇学习游戏系统
(1) 在网上自行下载英语六级词汇表。存到文件中,格式自定。
(2)系统支持两人连到服务器,测试学生对英语六级词汇的熟悉程度。
(3)首先运行服务器。服务器运行之后,两个客户可以加入。
(4)运行客户端。用户能够输入昵称,确定,则连接到服务器。连接成功,即可出现游戏界面。
(5)客户端游戏界面如下:用户点击开始之后,系统随机选择一个六级英文词汇(5个字母以上),空缺2个字母,用下划线,从客户端顶部落下,底部有其中文释义。

规则如下:
(1)每人初始生命值为20分。
(2)英文词汇(黑色)从界面顶部落下时,用户按下键盘,输入字母。字母(红色)快速射向单词。如果字母正确,则字母填入单词,该空字母下划线消失;错误,则该单词考试失败,出现下一个单词。用户输入正确字母,自己加1分;如果错误,自己减1分,对方加1分。
(3)用户正确将单词填写完毕,或者输入错误字母导致填写错误,该单词下落过程结束。重新出现新的单词从顶部落下,中文释义更新。
(4)词汇掉到用户界面底部,如果用户还没将单词填完,用户减1分,重新出现新词汇掉下来,中文释义更新。
(5)某用户如果生命值率先变为0分,则判输,游戏退出。
(6)游戏退出后,每个用户保存3个文件,分别存储输入正确的单词表、输入错误的单词表、未输入完即掉到底部的单词表。便于用户复习。
2、所用知识
总的来说,这次需要编写三个大类
①Server 作为服务器处理数据
②GamePanel 游戏面板,主要的游戏逻辑由他实现
③GameFrame 游戏界面,主要负责把GamePanel加上去,设置界面不可调整等微小工作

所用知识我们可以对照任务描述分条来看
①下载六次词汇表并做一定的处理:java.io.为了方便我们后续处理,必须对文件中单词和中文释义有一定的格式要求,我的预期格式是一对单词和汉语解释占单独一行,中间有空格分开,这样方便我们用BufferedReader类提供的readLine函数,一次读取一对,同时要提前把小于5个字母的单词删掉
②连接服务器需要用java.net.

③系统随机选择单词落下,空缺两个字母,从顶端落下:由于这个任务我们要运行多次,所以我选择写一个Init函数,用来完成这个任务和其他任务。
(1)随机选择单词:随机选单词如果在读的阶段就随机很麻烦,所以我选择读入后再打乱顺序,我把读取的一行数据存入一个vector(java.util.Vector)中(注意这里一定不能用java.util.
后面说为什么),然后用经典的洗牌算法:按顺序迭代,如果到了第i个,就产生一个从i—n-1的随机数(是n-1而不是n,因为这里是索引,java String里面也是从0开始计数),代码如下:

// 打乱
		for (int i = 0; i < words.size(); i++) {
			String tmp = words.get(i);
			int randIndex = (int) (Math.random() * (words.size() - i) + i);
			words.set(i, words.get(randIndex));
			words.set(randIndex, tmp);
		}

(2)任意选择位置空缺:直接使用随机数生成两个位置,把这两个位置用int变量 lackPos1, lackPos2保存下来(之后判断是否填入正确单词要用),要注意,二者一定不能相等,而且要保证lackPos1<lackPos2,有一个小于的关系是因为之后要判断用户是否输入了正确单词,填写顺序肯定是从前到后的,为了判断方便,我们之间在这里让lackPos1<lackPos2,至于空缺,可以直接把lackPos1、lackPos2对应位置的字母换成下划线,但是因为String类对于改变操作并不是很方便,所以新建一个临时变量StringBuffer类,这样方便我们修改对应位置的字母

dic = words.get(wordIndex++ % words.size()).split(" ");
		sb = new StringBuffer(dic[0]);

		// 保证二者不相等
		lackPos2 = lackPos1 = (int) (Math.random() * sb.length());
		while (lackPos2 == lackPos1) {
			lackPos2 = (int) (Math.random() * sb.length());
		}
		if (lackPos2 < lackPos1) {
			int tmp = lackPos2;
			lackPos2 = lackPos1;
			lackPos1 = tmp;
		}
		sb.setCharAt(lackPos1, '_');
		sb.setCharAt(lackPos2, '_');

(3)落下:首先设置GamePanel类的布局为空,单词我们把他加到一个JLabel上,落下这件事通过setLocation函数实现,由于落下要间隔一定的时间,但是程序并不能卡在这里,所以要用到javax.swing.Timer类,同时这个类要实现ActionListener接口,通过重写actionPerformed函数,告诉Timer间隔一定时间要做什么

//第一个参数是间隔时间,第二个参数是实现了ActionListener接口的对象
Timer timer = new Timer(250, this);

// 每隔100毫秒下落
	public void actionPerformed(ActionEvent e) {
		jlbChinese.setSize(dic[1].length() * 20, 20);
		jlbChinese.setLocation((this.getWidth() - jlbChinese.getWidth()) / 2,
				this.getHeight() - jlbChinese.getHeight());
		jlbWord.setLocation(jlbWord.getX(), jlbWord.getY() + 10);
		checkFail();
	}

④字母射向单词:因为字母射向单词的时候别的程序也要运行,单词也不可能呆滞在空中,所以这里还要用到多线程的知识,但是原先的GamePanel类已经实现了Runnable接口,处理的是接受服务器信息的任务,所以我们再新建一个类,jlbFollow,用它实现Runnable接口,需要做的就是判断字母有没有飞上去,如果飞上去就结束,如果是第二个字母飞上去了,就调用Init函数

private class jlbFollow extends JLabel implements Runnable {

		JLabel jlbWord;
		int pos;

		public jlbFollow(JLabel jlbWord, char ch, JPanel jpl, int pos) {
			this.setFont(new Font("黑体", Font.BOLD, 20));
			this.setForeground(Color.red);
			this.setText(String.valueOf(ch));
			this.setBounds((int) ((jpl.getWidth() - 20) * Math.random()), jpl.getHeight(), 20, 20);
			this.jlbWord = jlbWord;
			this.pos = pos;
		}

		public void run() {

			while (Math.pow(jlbWord.getX() - this.getX(), 2) + Math.pow(jlbWord.getY() - this.getY(), 2) > 100) {
				int x = (jlbWord.getX() - this.getX()) / 2, y = (jlbWord.getY() - this.getY()) / 2;
				this.setLocation(x + this.getX(), y + this.getY());
				try {
					Thread.sleep(50);
				} catch (Exception e) {

				}
			}
			this.setVisible(false);
			sb.setCharAt(pos, this.getText().charAt(0));
			jlbWord.setText(sb.toString());

			try {
				Thread.sleep(100);
			} catch (Exception e) {

			}

			if (lackPos1 == lackPos2)
				Init();
		}

	}

⑤如果错误,自己生命-1,对方生命+1:如果单词错误,那就给自己生命-2,然后给服务器发送+1.服务器再给加入的每一个玩家发送+1即可

**注意:**如果想要成功运行,必须要修改GamePanel类里面的一个String类的对象ip,还要保证路径下有图片和文本文档。修改是因为要匹配你所在的网络环境(想要查看首先打开CMD窗口,然后输入ipconfig 敲回车),在“ IPv4 地址”那一行查看(或者直接改成127.0.0.1 表示本机)。图片是我用来设置背景和图标的,文本文档是读取单词所用。虽然我只用了四张图,但是存了很多图片,这是因为我原本想实现一个每次登陆随机背景图的功能,但是现在处于答辩前夕,不想更改代码了。(●’◡’●)
运行情况:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

路径内容如下图:

3、代码
①Server类

package Game;

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

public class Server extends JFrame implements Runnable, ActionListener {

	private ServerSocket ss = null;
	private Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
	private Vector<ChatThread> client = new Vector<ChatThread>();
	private MyJPanel jpl = new MyJPanel();
	private JComboBox jcb = new JComboBox();
	private JLabel jlb = new JLabel();

	public Server() throws Exception {

		Image img = Toolkit.getDefaultToolkit().getImage("serverIcon.jpg");

		ss = new ServerSocket(9999);
		this.setSize(350, 400);
		jpl.setLayout(null);
		jpl.add(jcb);
		jpl.add(jlb);
		jcb.setLocation(130, 100);
		jcb.setSize(70, 20);

		jlb.setSize(200, 20);
		jlb.setFont(new Font("楷体", Font.BOLD, 20));
		jlb.setForeground(Color.red);
		jlb.setText("选择用户,请他离开");
		jlb.setLocation(80, 80);
		this.add(jpl);
		this.setIconImage(img);
		this.setLocation((int) ((screenSize.getWidth() - 350) / 2), (int) ((screenSize.getHeight() - 400) / 2));
		this.setTitle("服务器端启动,未见客户加入");
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setResizable(false);
		jcb.addItem(" ");
		jcb.setVisible(false);
		jlb.setVisible(false);
		jcb.addActionListener(this);

		new Thread(this).start();
	}

	public void run() {
		while (true) {
			try {
				Socket s = ss.accept();
				this.setTitle("客户加入");
				ChatThread ct = new ChatThread(s);
				client.add(ct);
				this.setTitle("用户" + ct.nickName + "连接成功");
				jcb.addItem(ct.nickName);
				jcb.setVisible(true);
				jlb.setVisible(true);
				ct.start();

			} catch (IOException e) {

				e.printStackTrace();
			}
		}
	}

	private class ChatThread extends Thread {

		BufferedReader br = null;
		PrintStream ps = null;
		boolean canRun = true;
		String nickName;

		public ChatThread(Socket s) throws IOException {
			br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			ps = new PrintStream(s.getOutputStream());
			nickName = br.readLine();

		}

		public void run() {

			while (canRun) {
				try {
					String str = br.readLine();
					sentMessage(str);
				} catch (Exception e) {
					canRun = false;
					client.remove(this);
					jcb.removeItem(nickName);
				}

			}
		}

		private void sentMessage(String str) {
			for (ChatThread ct : client)
				ct.ps.println(str);
		}

	}

	class MyJPanel extends JPanel {
		public void paintComponent(Graphics g) {
			Image img = new ImageIcon("gra4.jpg").getImage();
			g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), jpl);
		}
	}

	public static void main(String[] args) throws Exception {
		new Server();
	}

	@Override
	public void actionPerformed(ActionEvent e) {

		Object name = jcb.getSelectedItem();
		if (null == name || name.equals(" "))
			return;
		int choice = JOptionPane.showConfirmDialog(this, "您确定要踢出" + name + "吗?");
		if (JOptionPane.YES_OPTION == choice) {

			for (ChatThread c : client) {
				if (name.equals(c.nickName)) {
					c.ps.println("-9999");
					this.setTitle("用户" + name + "踢出成功");
					jcb.removeItem(name);
					JOptionPane.showMessageDialog(null, "踢除成功!");
				}

			}
		}
	}
}

②GamePanel类

package Game;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import sun.security.util.math.ImmutableIntegerModuloP;

import java.io.*;
import java.net.*;
import java.util.Vector;

public class GamePanel extends JPanel implements ActionListener, KeyListener, Runnable {

	final private String ip = "127.0.0.1";
	String nickName = null;
	Socket s = null;
	JLabel jlbWord = new JLabel();
	JLabel jlbChinese = new JLabel();
	JLabel jlbLife = new JLabel();
	BufferedReader br = new BufferedReader(new FileReader("word.txt"));
	Vector<String> words = new Vector<String>();
	String[] dic; // 单词及其中文释义
	int wordIndex = 0; // 下一个该读取的单词的索引
	int lackPos1, lackPos2;// 空出字母在单词内的索引
	int life = 20;
	PrintStream ps = null;
	BufferedReader brServer = null;
	StringBuffer sb = null;
	StringBuffer filePath = new StringBuffer("C:\\Users\\86132\\Desktop\\java\\clientInfo\\");
	File file = null;
	PrintStream psCorrect = null;
	PrintStream psFalse = null;
	PrintStream psForget = null;

	Timer timer = new Timer(250, this);

	public GamePanel() throws Exception {

		String str = null;

		// 读取单词
		while (null != (str = br.readLine())) {
			words.add(str);
		}
		br.close();

		// 打乱
		for (int i = 0; i < words.size(); i++) {
			String tmp = words.get(i);
			int randIndex = (int) (Math.random() * (words.size() - i) + i);
			words.set(i, words.get(randIndex));
			words.set(randIndex, tmp);
		}

		nickName = JOptionPane.showInputDialog("请输入昵称");

		if (null == nickName)
			System.exit(0);

		this.setLayout(null);
		this.setSize(500, 550);
		s = new Socket(ip, 9999);
		this.add(jlbLife);
		this.add(jlbWord);
		this.add(jlbChinese);
		this.setFocusable(true);
		this.addKeyListener(this);

		jlbLife.setFont(new Font("楷体", Font.BOLD, 20));
		jlbWord.setFont(new Font("黑体", Font.BOLD, 20));
		jlbChinese.setFont(new Font("楷体", Font.BOLD, 20));

		ps = new PrintStream(s.getOutputStream());
		brServer = new BufferedReader(new InputStreamReader(s.getInputStream()));

		JOptionPane.showMessageDialog(null, "连接成功,游戏即将开始");
		ps.println(nickName);

		filePath.append(nickName);
		file = new File(filePath.toString());
		if (!file.exists())
			file.mkdir();

		filePath.append("\\");
		psCorrect = new PrintStream(new FileOutputStream(new File(filePath.toString() + "CorrectWord.txt"), true));
		psForget = new PrintStream(new FileOutputStream(new File(filePath.toString() + "ForgetWord.txt"), true));
		psFalse = new PrintStream(new FileOutputStream(new File(filePath.toString() + "FalseWord.txt"), true));

		Init();
		timer.start();
		new Thread(this).start();
	}

	public void paintComponent(Graphics g) {
		Image img = new ImageIcon("gra1.jpg").getImage();
		g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
	}

	private void Init() {

		dic = words.get(wordIndex++ % words.size()).split(" ");
		sb = new StringBuffer(dic[0]);

		// 保证二者不相等
		lackPos2 = lackPos1 = (int) (Math.random() * sb.length());
		while (lackPos2 == lackPos1) {
			lackPos2 = (int) (Math.random() * sb.length());
		}
		if (lackPos2 < lackPos1) {
			int tmp = lackPos2;
			lackPos2 = lackPos1;
			lackPos1 = tmp;
		}
		sb.setCharAt(lackPos1, '_');
		sb.setCharAt(lackPos2, '_');

		jlbLife.setText("剩余生命值:" + life);
		jlbLife.setBounds(0, 0, 200, 20);
		jlbWord.setText(sb.toString());
		jlbWord.setBounds((int) ((this.getWidth() - 20 * dic[0].length()) * Math.random()), 20, 20 * dic[0].length(),
				40);
		jlbChinese.setText(dic[1]);

		jlbChinese.setVisible(true);
		jlbChinese.setSize(dic[1].length() * 20, 20);
		jlbChinese.setLocation((this.getWidth() - jlbChinese.getWidth()) / 2,
				this.getHeight() - jlbChinese.getHeight());

	}

	private void checkFail() {
		if (jlbWord.getY() >= jlbChinese.getY() - 20) {
			life--;
			psForget.println(words.get(wordIndex - 1));
			Init();
		}
		if (0 == life) {
			JOptionPane.showMessageDialog(null, "游戏失败");
			System.exit(0);
		} else if (life <= -100) {
			psCorrect.close();
			psFalse.close();
			psForget.close();
			JOptionPane.showMessageDialog(null, "您被房主请出房间");
			System.exit(0);
		}

	}

	// 每隔250毫秒下落
	public void actionPerformed(ActionEvent e) {
		jlbChinese.setSize(dic[1].length() * 20, 20);
		jlbChinese.setLocation((this.getWidth() - jlbChinese.getWidth()) / 2,
				this.getHeight() - jlbChinese.getHeight());
		jlbWord.setLocation(jlbWord.getX(), jlbWord.getY() + 10);
		checkFail();
	}

	@Override
	public void keyTyped(KeyEvent e) {

		if (-1 != lackPos1) {

			if (e.getKeyChar() == dic[0].charAt(lackPos1)) {

				jlbFollow jlbfollow = new jlbFollow(jlbWord, e.getKeyChar(), this, lackPos1);
				this.add(jlbfollow);
				new Thread(jlbfollow).start();

				lackPos1 = -1;
			} else {
				life -= 2;
				ps.println("+1");
				psFalse.println(words.get(wordIndex - 1));
				Init();
			}
		} else {

			//Jiayige防误触
			if (e.getKeyChar() == dic[0].charAt(lackPos2)) {
				life++;
				psCorrect.println(words.get(wordIndex - 1));
				jlbFollow jlbfollow = new jlbFollow(jlbWord, e.getKeyChar(), this, lackPos2);
				this.add(jlbfollow);
				lackPos2 = -1;
				new Thread(jlbfollow).start();

			} else {
				life -= 2;
				ps.println("+1");
				psFalse.println(words.get(wordIndex - 1));
				Init();
			}
		}
		checkFail();
	}

	@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		boolean canRun = true;

		while (canRun) {

			try {
				String str = brServer.readLine();
				life += Integer.parseInt(str);
				jlbLife.setText("剩余生命值:" + life);
			} catch (Exception e) {
				canRun = false;
				psCorrect.close();
				psFalse.close();
				psForget.close();
			}
		}

	}

	private class jlbFollow extends JLabel implements Runnable {

		JLabel jlbWord;
		int pos;

		public jlbFollow(JLabel jlbWord, char ch, JPanel jpl, int pos) {
			this.setFont(new Font("黑体", Font.BOLD, 20));
			this.setForeground(Color.red);
			this.setText(String.valueOf(ch));
			this.setBounds((int) ((jpl.getWidth() - 20) * Math.random()), jpl.getHeight(), 20, 20);
			this.jlbWord = jlbWord;
			this.pos = pos;
		}

		public void run() {

			while (Math.pow(jlbWord.getX() - this.getX(), 2) + Math.pow(jlbWord.getY() - this.getY(), 2) > 100) {
				int x = (jlbWord.getX() - this.getX()) / 2, y = (jlbWord.getY() - this.getY()) / 2;
				this.setLocation(x + this.getX(), y + this.getY());
				try {
					Thread.sleep(50);
				} catch (Exception e) {

				}
			}
			this.setVisible(false);
			sb.setCharAt(pos, this.getText().charAt(0));
			jlbWord.setText(sb.toString());

			try {
				Thread.sleep(100);
			} catch (Exception e) {

			}

			if (lackPos1 == lackPos2)
				Init();
		}

	}
}

③GameFrame类

package Game;

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

public class GameFrame extends JFrame{
	
	public GameFrame() throws Exception{
		
		Image img = Toolkit.getDefaultToolkit().getImage("clientIcon.jpeg");
		GamePanel gpl = new GamePanel();
		this.setSize(gpl.getSize());
		this.setTitle(gpl.nickName);
		this.add(gpl);
		
		this.setIconImage(img);
		this.setTitle(gpl.nickName);
		this.setVisible(true);
		this.setResizable(false);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public static void main(String[] args) throws Exception {
		new GameFrame();
	}
	
	
	
}

  • 2
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
1. 总体介绍 本次项目主要以本学期所学内容为基础,采用servlet+jsp+jdbc的技术以及mvc模式进行项目开发,本次开发的内容主要以实现CRUD核心功能为主的教务管理系统,分为学生端和教师端,前端采用jquery进行数据传输以及处理,bootstap写界面。 2. 技术架构 运行环境:tomcat9+mysql5+maven3.8+jdk8 前端技术:jquery 用以数据处理以及前端验证以及生成验证码等等 Bootstrap 前端界面处理 后端技术:servelt+jsp maven进行jar包和第三方库管理 采用jspsmart进行文件的操作处理 数据库:mysql5 基于MVC的分层思想及采用jsp+servelt技术的B/S结构的应用系统系统主要开发语言JAVA,JSP。数据库要求使用MySQL8.0,应用服务器选用Tomcat服务器 3. 功能介绍 系统能够提供用户有好的界面 系统具有良好的允许效率 系统具有良好的扩充性,灵活性 系统管理操作简单易懂 3.1 总体结构 3.2 模块详情 学生模块: 注册: 1. 用户点击注册,进行注册; 2. 用户输入注册信息; 3. 校验数据:如果用户名重复或者两次密码校验不合格或者密码规格不符合,则提示错误信息; 4. 若信息无错误,提示注册成功,跳转到登录页。 登录: 1. 用户进入系统未进行登录则自行跳转登录页面; 2. 点击忘记密码可进行密码找回; 3. 提交信息进行校验,查看用户名密码是否为空以及是否符合格式,随后在后台进行校验,合格则进行登录跳转到用户界面; 4. 若登录信息不正确,则提示登录错误信息。 查看成绩: 1. 点击查看成绩,打印成绩列表; 2. 支持到处成绩单为pdf格式。 导出成绩: 1. 点击到处按钮; 2. 系统自动处理并到处成pdf。 个人信息管理: 1. 选择上传头像 2. 修改个人信息:按需填写个人信息,随后进行保存则覆盖修改以往的个人信息。 退出登录: 1. 点击退出登录,自动退出到首页并删除本地和服务器缓存。 教师模块: 注册: 1用户点击注册,进行注册; 2用户输入注册信息; 3校验数据:如果用户名重复或者两次密码校验不合格或者密码规格不符合,则提示错误信息; 4若信息无错误,提示注册成功,跳转到登录页。 登录: 1用户进入系统未进行登录则自行跳转登录页面; 2点击忘记密码可进行密码找回; 3提交信息进行校验,查看用户名密码是否为空以及是否符合格式,随后在后台进行校验,合格则进行登录跳转到用户界面; 4若登录信息不正确,则提示登录错误信息。 个人信息管理: 1选择上传头像 2修改个人信息:按需填写个人信息,随后进行保存则覆盖修改以往的个人信息。 学生管理: 1. 点击添加学生,填写学生信息进行添加; 2. 修改学生信息,点击修改,按需填写要修改的学生信息,进行保存覆盖修改; 3. 点击删除学生数据,提示是否删除,确定则删除,取消则不删除; 4. 查看成绩,点击查看学生成绩,单独列出学生成绩列表; 成绩管理: 1. 点击成绩管理,列出所有学生成绩; 2. 点击修改,勾选需要修改的学生,按需填写修改信息,保存覆盖修改学生信息。 退出登录: 1点击退出登录,自动退出到首页并删除本地和服务器缓存。 4. 页面设计 静态jsp页面和jquery和bootstrap 5. 数据库设计 权限对照表: 表名: role 名称 类型 长度 允许空值 是否主键 注释 uid 整型 11 否 是 权限等级 utype 字符 255 否 否 用户等级名称 分数表: 表名: score 名称 类型 长度 允许空值 是否主键 注释 id 整型 200 否 是 学号 dat 字符 255 否 否 课程1分数 Android 字符 255 否 否 课程2分数 Jsp 字符 255 是 否 课程3分数 学生表: 表名: student 名称 类型 长度 允许空值 是否主键 注释 id 整型 59 否 是 学号 password 字符 255 否 否 登陆密码 Name 字符 255 否 否 学生姓名 Sex 字符 255 是 否 性别 School_date 字符 255 是 否 入学时间 Major 字符 255 是 否 专业 email 字符 255 是 否 邮箱 教师表: 表名: student 名称 类型 长度 允许空值 是否主键 注释 id 整型 59 否 是 教师工号 password 字符 255 否 否 登陆密码 Name 字符 255 否 否 教师姓名 Sex 字符 255 是 否 性别 email 字符 255 是 否 邮箱
这个Python期末大作业是一个基于协同过滤算法的电影推荐系统,采用了neo4j数据库来存储和查询电影数据。协同过滤算法是一种利用用户的历史行为和兴趣来进行推荐的方法,它可以根据用户的喜好和其他用户的相似度来推荐用户可能感兴趣的电影。 这个电影推荐系统的实现包括以下几个步骤:首先,通过爬虫从网上获取电影的相关信息,比如电影的名字、导演、演员、类型等等,并将这些信息存储到neo4j数据库中。然后,根据用户的历史行为和评分数据,计算用户之间的相似度,并将相似度的结果也存储到数据库中。接下来,当用户登录系统并选择了一个电影,系统会根据用户喜欢的电影类型和其他用户的相似度,从数据库中查找可能感兴趣的电影,并进行推荐。 通过采用neo4j数据库,这个电影推荐系统可以更高效地存储和查询大数据量的电影信息和用户数据。neo4j是一个图数据库,它的存储结构和图的结构相似,可以更好地支持复杂的关系型数据的存储和查询。同时,neo4j也提供了丰富的查询语言和API,方便我们实现各种复杂的查询和推荐算法。 总而言之,这个基于协同过滤算法的电影推荐系统使用了neo4j数据库来存储和查询电影数据,通过分析用户的历史行为和其他用户的相似度来进行推荐,可以更好地满足用户的个性化需求。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值