最近有一个课程设计的作业
要求如下:
用一个按键(例如空格键),代表电报按键;
给出一系列字母,让用户进行电报按键练习,给出节奏错误信息、拼写错误信息等。
因此处不限制使用何种语言,则采用了html+js来实现
如何判断按键的节奏?
此处我根据按键的快慢来判断是节奏是快的还是慢的。因此需要计算按下按键和抬起按键的耗时。
此处会遇到一个问题是,持续的按键会被识别为多次按键。因此需要加一个判断以排除持续按键的问题。
// 定义需要计算时间的参数
let keyupTime = 0,
keydownTime = 0,
keydownCount = 0;
//定义keycode是32的控制是否按起
let is32Up = false;
// 监听键盘按下的事件
$(document).keydown(function(event) {
// 输出对应的keycode
console.log('keydown event..' + event.keyCode);
// 是否为空格
if (event.keyCode == 32) {
// 用于判断是否首次按下,用于排除连续按键的情况
keydownCount++;
if (keydownCount == 1) { // 首次按下
keydownTime = new Date().getTime();
console.log('keydownTime:' + keydownTime);
}
if (!is32Up) // 按键未抬起
return;
is32Up = false;
}
});
// 监听键盘被抬起的事件
$(document).keyup(function(event) {
console.log('keyup event..' + event.keyCode);
if (event.keyCode == 32) {
keyupTime = new Date().getTime();
console.log('keyupTime:' + keyupTime);
if (keyupTime != 0 && keydownTime != 0) {
let spanTime = keyupTime - keydownTime;
console.log('spanTime:' + spanTime);
checkSpanTime(spanTime);
keyupTime = 0, keydownTime = 0, keydownCount = 0;
is32Up = false; // 重置
}
}
});
如何用数据存储摩尔斯电码表?
此处使用的是map, 用01的数组来表示长短节奏的电码。
// 定义密码表
const MOSTABLE = {
'A': [0, 1],
'B': [1, 0, 0, 0],
'C': [1, 0, 1, 0],
'D': [1, 0, 0],
'E': [0],
'F': [0, 0, 1, 0],
'G': [1, 1, 0],
'H': [0, 0, 0, 0],
'I': [0, 0],
'J': [0, 1, 1, 1],
'K': [1, 0, 1],
'L': [0, 1, 0, 0],
'M': [1, 1],
'N': [1, 0],
'O': [1, 1, 1],
'P': [0, 1, 1, 0],
'Q': [1, 1, 0, 1],
'R': [0, 1, 0],
'S': [0, 0, 0],
'T': [1],
'U': [0, 0, 1],
'V': [0, 0, 0, 1],
'W': [0, 1, 1],
'X': [1, 0, 0, 1],
'Y': [0, 1, 0, 0],
'Z': [1, 1, 0, 0],
'1': [0, 1, 1, 1, 1],
'2': [0, 0, 1, 1, 1],
'3': [0, 0, 0, 1, 1],
'4': [0, 0, 0, 0, 1],
'5': [0, 0, 0, 0, 0],
'6': [1, 0, 0, 0, 0],
'7': [1, 1, 0, 0, 0],
'8': [1, 1, 1, 0, 0],
'9': [1, 1, 1, 1, 0],
'0': [1, 1, 1, 1, 1, 1],
'?': [0, 0, 1, 1, 0, 0],
'/': [1, 0, 0, 1, 0],
'()': [1, 0, 1, 1, 0, 1],
'——': [1, 0, 0, 0, 0, 1],
'.': [0, 1, 0, 1, 0, 1]
};
随机生成待训练的字母?
// 随机生成待训练的字母
const alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '?', '/', '()', '——', '.'];
// 设置训练的个数
let num = 10;
// 存放随机训练的字符,用char类型的数组
let randomTrainTable = [];
for (let index = 0; index < num; index++) {
let idx = Math.round(Math.random() * 40);
randomTrainTable.push(alphabets[idx]);
$('.alphabet-area').append('<label title="' + getCharsFromTable(alphabets[idx]) + '">' + alphabets[idx] + '</label>');
}
整个逻辑较简单就直接贴代码了↓↓↓↓
<!DOCTYPE html>
<html>
<head>
<title>摩尔斯电码训练</title>
<style>
.area {
padding: 20px 20px;
margin: 20px 20px;
border-bottom: 1px solid lightblue;
}
.key-area label {
color: grey;
font-size: 30px;
}
.alphabet-area label {
margin: 10px 10px;
font-size: 50px;
}
</style>
</head>
<body style="text-align: center;">
<h1>摩尔斯电码训练</h1>
<div class="area alphabet-area" id="alphabet-area">
<h2>待训练的随机字符(鼠标移到字母上可查看提示,单位正确得分为10,红色为错误,绿色为正确)</h2>
</div>
<h2>请按空格↓↓↓您的输入↓↓↓</h2>
<div class="area key-area" id="key-area">
</div>
<h3>你的输入↓↓↓结果如下↓↓↓</h3>
<div class="area result-area" id="result-area">
</div>
</body>
<!-- <script src="./jquery.min.js"></script> -->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
$(function() {
// 定义密码表
const MOSTABLE = {
'A': [0, 1],
'B': [1, 0, 0, 0],
'C': [1, 0, 1, 0],
'D': [1, 0, 0],
'E': [0],
'F': [0, 0, 1, 0],
'G': [1, 1, 0],
'H': [0, 0, 0, 0],
'I': [0, 0],
'J': [0, 1, 1, 1],
'K': [1, 0, 1],
'L': [0, 1, 0, 0],
'M': [1, 1],
'N': [1, 0],
'O': [1, 1, 1],
'P': [0, 1, 1, 0],
'Q': [1, 1, 0, 1],
'R': [0, 1, 0],
'S': [0, 0, 0],
'T': [1],
'U': [0, 0, 1],
'V': [0, 0, 0, 1],
'W': [0, 1, 1],
'X': [1, 0, 0, 1],
'Y': [0, 1, 0, 0],
'Z': [1, 1, 0, 0],
'1': [0, 1, 1, 1, 1],
'2': [0, 0, 1, 1, 1],
'3': [0, 0, 0, 1, 1],
'4': [0, 0, 0, 0, 1],
'5': [0, 0, 0, 0, 0],
'6': [1, 0, 0, 0, 0],
'7': [1, 1, 0, 0, 0],
'8': [1, 1, 1, 0, 0],
'9': [1, 1, 1, 1, 0],
'0': [1, 1, 1, 1, 1, 1],
'?': [0, 0, 1, 1, 0, 0],
'/': [1, 0, 0, 1, 0],
'()': [1, 0, 1, 1, 0, 1],
'——': [1, 0, 0, 0, 0, 1],
'.': [0, 1, 0, 1, 0, 1]
};
// 从密码表中,将01转为.- 用于提示
function getCharsFromTable(c) {
return getCharsFromKeyArr(MOSTABLE[c]);
}
// 参数为01的数组 , 转换为.-的字符串
function getCharsFromKeyArr(a) {
let r = '';
for (let i = 0; i < a.length; i++) {
if (a[i] == 0)
r += '.';
else if (a[i] == 1)
r += '-';
}
return r;
}
// 输出结果
function showResult(ch, rightAnswer, userAnswer, right, curIdx) {
$('.result-area').append("<p style='color:" +
(right ? "green" : "red") + "'>字符:" + ch + " 应输入:" + getCharsFromTable(ch) + " 你的输入:" + userAnswer +
" 是否正确:" + (right ? '√' : 'x') + " 得分: " + (right ? '10' : '0') + " </p>");
let sel = "#alphabet-area > label:nth-child(" + (curIdx + 2) + ")";
if (right) {
$(sel).css("color", "green");
} else {
$(sel).css("color", "red");
}
curIndex++;
// 清空
curKeyArr = [];
$("#key-area").empty();
}
// 随机生成待训练的字母
const alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '?', '/', '()', '——', '.'];
// 设置训练的个数
let num = 10;
// 存放随机训练的字符,用char类型的数组
let randomTrainTable = [];
for (let index = 0; index < num; index++) {
let idx = Math.round(Math.random() * 40);
randomTrainTable.push(alphabets[idx]);
$('.alphabet-area').append('<label title="' + getCharsFromTable(alphabets[idx]) + '">' + alphabets[idx] + '</label>');
}
// 定义当前在训练的字符序号
let curIndex = 0;
// 存当前的输入 0 or 1
let curKeyArr = [];
// 计算得分
let score = 0;
// 处理按键时长对应的事件
function checkSpanTime(spanTime) {
if (curIndex < num) {
// 当前的字符
let curChar = randomTrainTable[curIndex];
// 当前字符的摩斯密码
let curCharArr = MOSTABLE[curChar];
console.log("curChar:", curChar, " curCharArr:", curCharArr);
if (spanTime < 120) {
curKeyArr.push(0);
$(".key-area").append("<label class='key-short'>.</label>");
} else {
curKeyArr.push(1);
$(".key-area").append("<label class='key-long'>-</label>");
}
// 密码长度
let n = curCharArr.length;
console.log("n", n, "curKeyArr:", curKeyArr.length, 'curKeyArr', curKeyArr);
if (curKeyArr.length == n) {
// 长度相同的情况下,判断密码是否正确
let isRight = true;
for (let i = 0; i < n; i++) {
if (curKeyArr[i] != curCharArr[i]) {
isRight = false;
break;
}
}
console.log('isRight:', isRight, 'curIndex:', curIndex);
// 当前字符输入的摩斯密码正确
if (isRight) {
score += 10;
// 输出到结果面板
showResult(curChar, getCharsFromTable(curChar), getCharsFromKeyArr(curKeyArr), true, curIndex);
} else {
//TODO 输出错误信息
alert('你的输入有误,正确答案为:' + getCharsFromTable(curChar));
showResult(curChar, getCharsFromTable(curChar), getCharsFromKeyArr(curKeyArr), false, curIndex);
}
} else {
// TODO 判断当前输入是否正确
for (let i = 0; i < curKeyArr.length; i++) {
if (curKeyArr[i] != curCharArr[i]) {
//输出错误
alert('当前输入输入有误,当前应输入: ' + (curCharArr[i] == 0 ? '节奏应短些 . ' : '节奏应长些 - ') + ', 完整答案为: ' + getCharsFromTable(curChar));
showResult(curChar, getCharsFromTable(curChar), getCharsFromKeyArr(curKeyArr), false, curIndex);
break;
}
}
}
} else {
//完成本次训练
alert('恭喜你已完成本次训练,本次得分:' + score);
window.location.reload();
}
}
// 定义需要计算时间的参数
let keyupTime = 0,
keydownTime = 0,
keydownCount = 0;
//定义keycode是32的控制是否按起
let is32Up = false;
// 监听键盘按下的事件
$(document).keydown(function(event) {
// 输出对应的keycode
console.log('keydown event..' + event.keyCode);
// 是否为空格
if (event.keyCode == 32) {
// 用于判断是否首次按下,用于排除连续按键的情况
keydownCount++;
if (keydownCount == 1) { // 首次按下
keydownTime = new Date().getTime();
console.log('keydownTime:' + keydownTime);
}
if (!is32Up) // 按键未抬起
return;
is32Up = false;
}
});
// 监听键盘被抬起的事件
$(document).keyup(function(event) {
console.log('keyup event..' + event.keyCode);
if (event.keyCode == 32) {
keyupTime = new Date().getTime();
console.log('keyupTime:' + keyupTime);
if (keyupTime != 0 && keydownTime != 0) {
let spanTime = keyupTime - keydownTime;
console.log('spanTime:' + spanTime);
checkSpanTime(spanTime);
keyupTime = 0, keydownTime = 0, keydownCount = 0;
is32Up = false; // 重置
}
}
});
});
</script>
</html>
效果如下: