如何在Visual Basic闪卡应用中实现类似Anki的答错闪卡高频展示机制
实现Anki风格的闪卡智能调度功能
Got it, let's tackle this smart scheduling feature similar to Anki. Here's a step-by-step approach to implement weighted flashcard selection based on user feedback:
1. 数据库准备
首先给你的Access数据表添加一个Weight字段(建议用双精度数字类型),默认值设为1.0。这个值代表闪卡的展示优先级:值越高,被选中的概率越大;值越低,概率越小。
2. 代码修改与实现
2.1 添加全局变量记录当前闪卡ID
在窗体类顶部添加变量,用来追踪当前显示的闪卡,方便后续更新权重:
Private currentCardId As Integer ' 假设你的表有主键ID字段,用来唯一标识闪卡
2.2 实现加权随机选择算法
替换原来的简单随机,改用加权随机,让高权重的闪卡更易被选中:
' 加权随机选择闪卡索引的核心方法 Private Function GetWeightedRandomCardIndex() As Integer If dt.Rows.Count = 0 Then Return -1 ' 计算所有闪卡的权重总和 Dim totalWeight As Double = 0 For Each row As DataRow In dt.Rows totalWeight += CDbl(row("Weight")) Next ' 生成0到总权重之间的随机值 Dim randomValue As Double = rand.NextDouble() * totalWeight Dim cumulativeWeight As Double = 0 ' 遍历找到对应的闪卡索引 For i As Integer = 0 To dt.Rows.Count - 1 cumulativeWeight += CDbl(dt.Rows(i)("Weight")) If cumulativeWeight >= randomValue Then Return i End If Next ' 兜底返回最后一个闪卡(防止极端情况) Return dt.Rows.Count - 1 End Function
2.3 修改展示按钮逻辑
更新btnDisplay_Click,记录当前闪卡的ID:
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click btnDisplay.Enabled = False Dim index = GetWeightedRandomCardIndex() If index = -1 Then MsgBox("No flashcards available!") Return End If currentCardId = CInt(dt.Rows(index)(0)) ' 假设第0列是主键ID txtFront.Text = dt.Rows(index)(2).ToString() txtBack.Visible = False txtBack.Text = dt.Rows(index)(3).ToString() End Sub
2.4 重构反馈按钮逻辑(复用代码+更新权重)
提取公共方法处理权重更新和切换闪卡,避免重复代码:
' 公共方法:更新当前闪卡权重并切换到下一张 Private Sub UpdateCardWeightAndNext(weightMultiplier As Double) If Not txtBack.Visible Then MsgBox("Please first reveal the back of the flashcard") Return End If ' 找到当前闪卡的行,更新权重 Dim currentRow As DataRow = dt.Select($"ID = {currentCardId}")(0) Dim currentWeight As Double = CDbl(currentRow("Weight")) ' 根据用户反馈调整权重:Hard提升,Easy降低,Good保持 ' 你可以根据需求调整乘数(比如Hard用2.0,Easy用0.3) currentRow("Weight") = currentWeight * weightMultiplier ' !重要:把更新后的权重写回数据库,否则重启程序后丢失 ' 假设你用OleDbDataAdapter,调用以下代码: ' adapter.Update(dt) ' 切换到下一张加权随机闪卡 Dim index = GetWeightedRandomCardIndex() If index = -1 Then MsgBox("No flashcards available!") Return End If currentCardId = CInt(dt.Rows(index)(0)) txtFront.Text = dt.Rows(index)(2).ToString() txtBack.Visible = False txtBack.Text = dt.Rows(index)(3).ToString() End Sub Private Sub btnEasy_Click(sender As Object, e As EventArgs) Handles btnEasy.Click ' Easy:降低权重,减少后续展示概率 UpdateCardWeightAndNext(0.5) End Sub Private Sub btnGood_Click(sender As Object, e As EventArgs) Handles btnGood.Click ' Good:权重保持不变(或轻微调整,比如乘以1.1) UpdateCardWeightAndNext(1.0) End Sub Private Sub btnHard_Click(sender As Object, e As EventArgs) Handles btnHard.Click ' Hard:提升权重,增加后续展示概率 UpdateCardWeightAndNext(1.5) End Sub
3. 关键细节说明
- 权重范围限制:可以给权重加个上下限(比如最小0.1,最大5.0),避免某些闪卡永远出现或彻底消失,比如在更新权重时加判断:
currentRow("Weight") = Math.Max(0.1, Math.Min(5.0, currentWeight * weightMultiplier)) - 数据库持久化:一定要确保更新后的权重被写回数据库,否则每次重启程序都会回到初始值,这一步依赖你原来的DataAdapter配置。
- 乘数调整:你可以根据实际使用情况调整权重乘数,比如Hard用2.0让难的闪卡出现频率翻倍,Easy用0.4让简单闪卡出现频率大幅降低。
内容的提问来源于stack exchange,提问作者Idk
相关产品推荐
相关产品推荐

