文章目录
![在这里插入图片描述](https://img-blog.csdnimg.cn/25e93580958647379494468e6c91a1c9.jpeg#pic_center)
1.1 思路框架图
1.2 新建java项目
- 新建java项目
- 引入jar包
- 程序结构图
- 测试 - 发现乱码问题
解决方案: 右下角的UTF-8改成GBK
1.3 一级菜单
先搭框架, 再填内容
public class MHLView {
//控制是否退出菜单
private boolean loop = true;//默认false
//接收用户的选择
private int key;
public static void main(String[] args) {
new MHLView().mainMenu();
}
//显示主页面
public void mainMenu() {
while (loop) {
System.out.println("=======================满汉楼=======================");
System.out.println("\t\t 1 登录满汉楼");
System.out.println("\t\t 9 退出满汉楼");
System.out.print("请输入你的选择: ");
key = Utility.readInt();
switch (key) {
case 1:
System.out.println("登录满汉楼");
break;
case 9:
loop = false;//退出
break;
default:
System.out.println("输入有误, 请重新输入");
}
}
System.out.println("=======================退出了满汉楼系统=======================");
}
}
1.4 二级菜单
先搭框架, 再填内容
public class MHLView {
//控制是否退出菜单
private boolean loop = true;//默认false
//接收用户的选择
private int key;
public static void main(String[] args) {
new MHLView().mainMenu();
}
//显示主页面
public void mainMenu() {
while (loop) {
System.out.println("=======================满汉楼=======================");
System.out.println("\t\t 1 登录满汉楼");
System.out.println("\t\t 9 退出满汉楼");
System.out.print("请输入你的选择: ");
key = Utility.readInt();
switch (key) {
case 1:
System.out.print("输入用户名: ");
String userId = Utility.readString(50);
System.out.print("输入密 码: ");
String pwd = Utility.readString(50);
//数据库判断
if ("123".equals(pwd)) {
System.out.println("登陆成功\n");
//显示二级菜单, 二级菜单是一个循环
while (loop) {
System.out.println("=======================满汉楼二级菜单=======================");
System.out.println("\t\t 1 显示餐桌状态");
System.out.println("\t\t 2 预定餐桌");
System.out.println("\t\t 3 显示所有菜品");
System.out.println("\t\t 4 点餐服务");
System.out.println("\t\t 5 查看账单");
System.out.println("\t\t 6 结账");
System.out.println("\t\t 9 退出");
System.out.print("请输入你的选择: ");
key = Utility.readInt();
switch (key) {
case 1:
System.out.println("显示餐桌状态");
break;
case 2:
System.out.println("预定餐桌");
break;
case 3:
System.out.println("显示所有菜品");
break;
case 4:
System.out.println("点餐服务");
break;
case 5:
System.out.println("查看账单");
break;
case 6:
System.out.println("结账");
break;
case 9:
loop = false;//退出
break;
default:
System.out.println("输入有误, 请重新输入");
}
}
} else {
System.out.println("登陆失败");
}
break;
case 9:
loop = false;//退出
break;
default:
System.out.println("输入有误, 请重新输入");
}
}
System.out.println("=======================退出了满汉楼系统=======================");
}
}
效果
- 登录
- 显示餐桌状态, 预定餐桌
- 显示所有菜品, 点餐服务
- 查看账单, 结账
- 退出满汉楼
1.4.1 数据库建表
- 新建mhl数据库, 新建员工表
# 创建一个数据库
CREATE DATABASE mhl;
# 查看当前数据库
SHOW CREATE DATABASE mhl;
# 创建表
CREATE TABLE employee(
id INT PRIMARY KEY AUTO_INCREMENT,
empId VARCHAR(50) UNIQUE NOT NULL DEFAULT '',
`name` VARCHAR(50) NOT NULL DEFAULT '',
pwd CHAR(32) NOT NULL DEFAULT '', # md5加密
email VARCHAR(50) NOT NULL DEFAULT ''
)
# 查看表
DESC employee;
# 删除表
DROP TABLE employee;
#添加数据
INSERT INTO employee VALUES(NULL, '6668612', MD5('123456'), '张三丰', '经理');
INSERT INTO employee VALUES(NULL, '6668622', MD5('123456'),'小龙女', '服务员');
INSERT INTO employee VALUES(NULL, '6668633', MD5('123456'), '张无忌', '收银员');
INSERT INTO employee VALUES(NULL, '666', MD5('123456'), '老韩', '经理');
- 新建餐桌表
# 创建一个数据库
CREATE DATABASE mhl;
# 查看当前数据库
SHOW CREATE DATABASE mhl;
# 创建表
CREATE TABLE diningTable (
id INT PRIMARY KEY AUTO_INCREMENT, #自增, 表示餐桌编号
state VARCHAR(20) NOT NULL DEFAULT '',#餐桌的状态
orderName VARCHAR(50) NOT NULL DEFAULT '',#预订人的名字
orderTel VARCHAR(20) NOT NULL DEFAULT ''
)
# 查看表
DESC diningTable;
# 删除表
DROP TABLE diningTable;
#添加数据
INSERT INTO diningTable VALUES(NULL, '空','','');
INSERT INTO diningTable VALUES(NULL, '空','','');
INSERT INTO diningTable VALUES(NULL, '空','','');
INSERT INTO diningTable VALUES(NULL, '空','','');
#查询数据
SELECT * FROM diningTable;
- 新建菜谱表
# 创建一个数据库
CREATE DATABASE mhl;
# 查看当前数据库
SHOW CREATE DATABASE mhl;
# 创建表
CREATE TABLE menu (
id INT PRIMARY KEY AUTO_INCREMENT, #自增主键,作为菜谱编号(唯一)
`name` VARCHAR(50) NOT NULL DEFAULT '',#菜品名称
`type` VARCHAR(50) NOT NULL DEFAULT '', #菜品种类
price DOUBLE NOT NULL DEFAULT 0#价格
);
# 查看表
DESC menu;
# 删除表
DROP TABLE menu;
#添加数据
INSERT INTO menu VALUES(NULL, '八宝饭', '主食类', 10);
INSERT INTO menu VALUES(NULL, '叉烧包', '主食类', 20);
INSERT INTO menu VALUES(NULL, '宫保鸡丁', '热菜类', 30);
INSERT INTO menu VALUES(NULL, '山药拨鱼', '凉菜类', 14);
INSERT INTO menu VALUES(NULL, '银丝卷', '甜食类', 9);
INSERT INTO menu VALUES(NULL, '水煮鱼', '热菜类', 26);
INSERT INTO menu VALUES(NULL, '甲鱼汤', '汤类', 100);
INSERT INTO menu VALUES(NULL, '鸡蛋汤', '汤类', 16);
#查询数据
SELECT * FROM menu;
- 新建账单表
# 创建一个数据库
CREATE DATABASE mhl;
# 查看当前数据库
SHOW CREATE DATABASE mhl;
# 创建表
CREATE TABLE bill (
id INT PRIMARY KEY AUTO_INCREMENT, #自增主键
billId VARCHAR(50) NOT NULL DEFAULT '', #账单号 UUID
menuid INT NOT NULL DEFAULT 0, # 菜品编号
nums INT NOT NULL DEFAULT 0, # 分数
money DOUBLE NOT NULL DEFAULT 0, # 金额
diningTableId INT NOT NULL DEFAULT 0, # 餐桌
billDate DATETIME NOT NULL, # 订单日期
state VARCHAR(50) NOT NULL DEFAULT '' # 状态 '未结账','已经结账','微信','支付宝'
);
# 查看表
DESC bill;
# 删除表
DROP TABLE bill;
#查询数据
SELECT * FROM bill;
1.4.2 idea建实体类, DAO
- 新建实体类,要有无参构造器(底层反射new instance()时需要默认[缺省(缺少省略)]构造器创建实例)和setter方法; 修改类名. 满足驼峰命名法; 将long改为Integer, 将double改为Double; 更改package;
- DiningTable实体类 同理
- Menu实体类, 同理
- Bill实体类, 同理
- 新建dao
登录功能
- service层
- view层-MHLView.java
显示餐桌状态
- service层
- view层-MHLView.java
预定餐桌
- 餐桌号是否存在,餐桌存在是否已被人预定;
- 更新餐桌信息(状态,联系方式,预定人姓名);
- service层
- view层-MHLView.java
//完成预定餐桌功能 public void orderDiningTable() { System.out.println("=======================预定餐桌======================="); System.out.print("请选择要预定餐桌的编号(-1退出): "); int orderId = Utility.readInt(); if (orderId == -1) { System.out.println("=======================放弃预定餐桌======================="); return; } //该方法得到的是'Y'或者是'N' char key = Utility.readConfirmSelection(); if ('N' == key) { System.out.println("=======================放弃预定餐桌======================="); return; } //要预定 //根据orderId返回对应的DiningTable对象, 如果为null, 说明该对象不存在 DiningTable diningTable = diningTableService.getDiningTableById(orderId); if (diningTable == null) { System.out.println("=======================预定的餐桌不存在======================="); return; } //如果不为null, 还要判断餐桌的状态 if (!"空".equals(diningTable.getState())) {//说明当前的餐桌不是null的状态 System.out.println("=======================该餐桌已经预定或正在就餐中======================="); return; } System.out.print("预定人的名字: "); String orderName = Utility.readString(50); System.out.print("预定人的电话: "); String orderTel = Utility.readString(50); //这时可以真的预定了, 更新餐桌状态 if (diningTableService.orderDiningTable(orderId, orderName, orderTel)) { System.out.println("=======================预定成功======================="); } else { System.out.println("=======================预定失败======================="); } }
Utility工具类
显示所有菜品
- service层
- view层-MHLView.java
点餐服务
- 在哪个桌子上点餐(桌号要存在),点哪个菜(菜品号要存在),点多少份;
- 更新桌子状态信息为 就餐中;
- 生成账单记录,在BillService中完成主要业务;
- serivice层
获取菜品的方法要写在MenuService里, 然后在BillService里调用MenuService
更新餐桌状态的方法要写在DiningTableService里, 然后在BillService里调用DiningTableService
BillService
- view层-MHLView.java
//点餐服务 public void orderMenu() { System.out.println("=======================点餐服务======================="); System.out.print("请输入点餐的桌号(-1退出): "); int orderDiningTableId = Utility.readInt(); if (orderDiningTableId == -1) { System.out.println("=======================取消点餐======================="); return; } System.out.print("请输入点餐的菜品号(-1退出): "); int orderMenuId = Utility.readInt(); if (orderMenuId == -1) { System.out.println("=======================取消点餐======================="); return; } System.out.print("请输入点餐的菜品量(-1退出): "); int orderNums = Utility.readInt(); if (orderNums == -1) { System.out.println("=======================取消点餐======================="); return; } //验证餐桌号是否存在 DiningTable diningTable = diningTableService.getDiningTableById(orderDiningTableId); if (diningTable == null) { System.out.println("=======================餐桌号不存在======================="); return; } //验证菜品编号是否正确 Menu menu = menuService.getMenuById(orderMenuId); if (menu == null) { System.out.println("=======================餐桌号不存在======================="); return; } //点餐 if (billService.orderMenu(orderMenuId, orderNums, orderDiningTableId)) { System.out.println("=======================点餐成功======================="); } else { System.out.println("=======================点餐失败======================="); } }
查看账单
- service层
- view层-MHLView.java
结账
- 选择结账的餐桌号,餐桌号是否存在;
- service层
在DiningTableService里提供一个方法, 将指定的餐桌设置为空闲状态, 然后在BillService里调用DiningTableService
BillService
- view层-MHLView.java
//完成结账 public void payBill() { System.out.println("=======================结账服务======================="); System.out.print("请选择要结账的餐桌编号(-1退出): "); int dindingTableId = Utility.readInt(); if (dindingTableId == -1) { System.out.println("=======================退出结账======================="); return; } //验证餐桌是否存在 DiningTable diningTable = diningTableService.getDiningTableById(dindingTableId); if (diningTable == null) { System.out.println("=======================结账的餐桌号不存在======================="); return; } //验证这个餐桌是否有未结账的账单 if (!billService.hasUnpayedBillByDiningTableId(dindingTableId)) { System.out.println("=======================结账的餐桌号不存在未结账的账单======================="); return; } System.out.print("结账方式(现金/支付宝/微信)回车表示退出: "); String payMode = Utility.readString(20, "");//如果回车返回"" if ("".equals(payMode)) { System.out.println("=======================退出结账======================="); return; } //确认是否结账(Y/N) char key = Utility.readConfirmSelection();//返回 Y/N if (key == 'N') { System.out.println("=======================退出结账======================="); return; } //完成结账 if (billService.payBill(dindingTableId, payMode)) { System.out.println("=======================结账成功======================="); return; } else { System.out.println("=======================结账失败======================="); return; } }
Utility工具类
1.5 满汉楼多表处理
多表查询怎么处理? 比如: 查看账单时, 希望显示菜品名称
网上思路: https://www.pianshen.com/article/48341042440/
个人思路
- 新建实体类
- 新建DAO
- BillService中书写逻辑
- view层-MHLView.java
- 效果
- 改进
1.5.1 多表处理细节问题
MultiTableBean实体类里的属性名是否一定要和表的列名保持一致?
答案: 可以不一致, 因为表的列名是和实体类的setter()方法相对应的
问题: 把实体类里的name属性改为name2, setName()方法改为setName2(), 如何才能将name2属性和数据库里的name字段进行对应
解决方案: 在sql查询时, 给name字段起别名name2, 这样就能对应到setName2()方法, 给相应的属性赋值
1.5.2 登陆改进
员工信息字段有很多, 而且员工数也会有很多, 为提高效率, 可以采用分表设计employee 和 login
- 数据库建表
# 创建一个数据库
CREATE DATABASE mhl;
# 查看当前数据库
SHOW CREATE DATABASE mhl;
# 创建表
CREATE TABLE login (
empId VARCHAR(50) UNIQUE NOT NULL DEFAULT '',#员工号
pwd CHAR(32) NOT NULL DEFAULT ''#密码md5
);
# 查看表
DESC login;
# 删除表
DROP TABLE login;
#添加数据
INSERT INTO login VALUES('6668612', MD5('123456'));
INSERT INTO login VALUES('6668622', MD5('123456'));
INSERT INTO login VALUES('6668633', MD5('123456'));
INSERT INTO login VALUES('666', MD5('123456'));
#查询数据
SELECT * FROM login WHERE empId = '666' AND pwd = MD5('123456');
- 新建实体类
一定要有无参构造器, and 和表的字段对应的setter()方法
- LoginDAO
- serivce层
- view层-MHLView.java
1.5.3 人事管理
- 增加一个三级菜单
1.5.3.1 显示员工信息
- 实体类添加一个toString()方法
- service层
- view层-MHLView.java
1.5.3.2 添加员工
- service层
添加员工登录信息的方法要写在LoginService里, 然后在EmployeeService里调用LoginService
EmployeeService
- view层-MHLView.java
//添加员工 public void addEmployee() { System.out.print("请输入员工 号(回车退出): "); String empId = Utility.readString(50,""); if ("".equals(empId)) { System.out.println("=======================退出添加系统======================="); return; } System.out.print("请输入员工密码(回车退出): "); String pwd = Utility.readString(50,""); if ("".equals(pwd)) { System.out.println("=======================退出添加系统======================="); return; } System.out.print("请输入员工姓名(回车退出): "); String name = Utility.readString(50,""); if ("".equals(name)) { System.out.println("=======================退出添加系统======================="); return; } System.out.print("请输入员工岗位(回车退出): "); String job = Utility.readString(50,""); if ("".equals(job)) { System.out.println("=======================退出添加系统======================="); return; } //添加员工 if (!employeeService.add(empId, pwd, name, job)) { System.out.println("=======================添加失败======================="); return; } System.out.println("=======================添加成功======================="); }
1.5.3.4 删除员工
- service层
删除员工登录信息的方法要写在LoginService里, 然后在EmployeeService里调用LoginService
EmployeeService
- view层-MHLView.java
1.6 数据库细节
pwd CHAR(32) NOT NULL DEFAULT ‘’,# 密码,32位
INSERT INTO employee VALUES(NULL, ‘666’, MD5(‘123456’), ‘老韩’, ‘经理’);
MD5(‘123456’)是经过MD5加密过后的32位的字符串,用来保存密码
select * from employee where empId = ? and pwd = MD5(?);#查询时也要加上MD5()
确保:把业务层的sql语句放到数据库查询分析器测试一下
return update > 0;简便写法
javabean中需要有无参构造器和settter方法,来供底层反射调用
一个DAO对应一个JavaBean,对应一个Service,业务层之间可以相互合作;
1.7 DBUtils底层用到反射
javabean中的属性和必须和数据库表里查询出的表名一致,如果MultiTableBean中的属性有冲突,可以在查询的时候给表里的字段起别名;
1.8 马踏棋盘
骑士周游算法
- 创建6x6的棋盘,是二维数组
- 将当前位置设置为已经访问过,根据当前位置计算马儿还能走哪些位置,并放入到一个集合(ArrayList)中,最多有8个,每走一步,setp+1
- 遍历ArrayList中存放的所有位置,看看哪个可以走,如果可以走得通,就继续,如果走不通,就回溯
- 判断马儿是否完成了任务,使用step和应该走的步数比较,如果没有达到数量,则表示没有完成任务,就将整个棋盘设置为0
public class HorseChessBoard {
//定义属性
private static int X = 6;//代表 col
private static int Y = 6;//代表 row
private static int[][] chessBoard = new int[X][Y];//棋盘
private static boolean[] visited = new boolean[X * Y];//记录某个位置是否走过
private static boolean finished = false;//记录马儿是否遍历完棋盘
public static void main(String[] args) {
int row = 6;//6行
int col = 3;//6列
//进行测试
travelsalChessBoard(chessBoard, row - 1, col - 1, 1);
//输出当前棋盘的情况
for (int[] rows : chessBoard) {
for (int step : rows) {//step 表示 这是马儿应该走的第几步
System.out.print(step + "\t");
}
System.out.println();
}
}
//编写核心算法,遍历棋盘,如果遍历成功,就把 finished 设置为true
//并且,将马儿走的每一步step,记录到 chessBoard
public static void travelsalChessBoard(int[][] chessBoard, int row, int col, int step) {
//将step记录到chessBoard
chessBoard[row][col] = step;
//将当前位置设置为已经访问
visited[row * X + col] = true;
//获取当前位置可以走的下一个位置有哪些
ArrayList<Point> ps= next(new Point(col, row));//col - X, row - Y
//遍历
while (!ps.isEmpty()) {
//取出集合中的第一个点(位置)
Point p = ps.remove(0);
//判断该位置是否走过,如果没有走过,就递归遍历
if (!visited[p.y * X + p.x]) {
//递归
travelsalChessBoard(chessBoard, p.y, p.x, step + 1);
}
}
//当退出while循环,看看是否遍历成功
if (step < X * Y && !finished) {
//如果遍历不成功,就回溯,同时重置棋盘
chessBoard[row][col] = 0;
visited[row * X + col] = false;
} else {
finished = true;
}
}
//编写方法,获取当前位置可以走的下一步的所有位置(Point表示 坐标x,y)
public static ArrayList<Point> next(Point curPoint) {
//创建集合,存放所有可以走的点
ArrayList<Point> points = new ArrayList<>();
//创建一个Point对象,点/一个位置,如果坐标匹配则放入到集合中
Point p1 = new Point();
//根据题目要求,判断在 curPoint点 是否可以走如下位置,如果可以走,就将该点(Point)放入到集合
//判断是否可以走5位置
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y - 1) >= 0) {
points.add(new Point(p1));
}
//判断是否可以走6位置
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y - 2) >= 0) {
points.add(new Point(p1));
}
//判断是否可以走7位置
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0) {
points.add(new Point(p1));
}
//判断是否可以走0位置
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0) {
points.add(new Point(p1));
}
//判断是否可以走1位置
if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y) {
points.add(new Point(p1));
}
//判断是否可以走2位置
if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y) {
points.add(new Point(p1));
}
//判断是否可以走3位置
if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y) {
points.add(new Point(p1));
}
//判断是否可以走4位置
if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < Y) {
points.add(new Point(p1));
}
return points;
}
}