开启Android学习之旅-6-实战答题App

不经过实战,看再多理论,都是只放在笔记里,活学活用才是硬道理。同时开发应用需要循序渐进,一口气规划300个功能,400张表,会严重打击自己的自信。这里根据所学的,开发一个答题App。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题库需求分析

  1. 首页显示试卷列表;
  2. 点击试卷,开启计时,逐个显示该试卷的题目;
  3. 点击下一题,检测是否作答,未作答提示,已作答显示下一个,更新进度条显示;
  4. 最后一题,按钮显示“交卷”,作答完成,点击交卷,弹出成绩。

功能分析

  1. 首页试卷列表使用 recyclerview;
  2. 答题页面涉及进度条、卡片视图(cardview)、倒计时(CountDownTimer)
  3. 数据模型:Paper、Question。

开发

开发环境

Android Studio Giraffe | 2022.3.1 Patch 3
Android Gradle Plugin Version 8.1.3
Gradle Version 8.0
JDK 17
compileSdk: 33
targetSdk: 33
minSdk:26

  • 步骤1. 新建项目,这里选择的语言为kotlin。
    解决 gradle 卡顿问题:将 gradle/gradle-wrapper.properties 中的distributionUrl 替换为国内的:
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.0-bin.zip

settings.gradle 国内镜像设置:

pluginManagement {repositories {maven { url 'https://mirrors.cloud.tencent.com/gradle/'}maven {url 'https://maven.aliyun.com/repository/google'}maven {url 'https://maven.aliyun.com/repository/jcenter'}maven {url "https://maven.aliyun.com/repository/public"}maven {url 'https://developer.huawei.com/repo/'}maven {url "https://jitpack.io"}google()mavenCentral()gradlePluginPortal()}
}
dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {maven {url 'https://maven.aliyun.com/repository/google'}maven {url 'https://maven.aliyun.com/repository/jcenter'}maven {url "https://maven.aliyun.com/repository/public"}maven {url 'https://developer.huawei.com/repo/'}maven {url "https://jitpack.io"}google()mavenCentral()}
}rootProject.name = "Exam"
include ':app'

开启 viewBinding 在 build.gradle 中添加

buildFeatures {viewBinding = true}
  • 步骤2:建模型:ExamModel,里面建数据类,PaperModel 和 QuestionModel;
package com.alex.exam/*** @Author      : alex* @Date        : on 2024/1/6 16:59.* @Description :试卷模型*/
data class PaperModel(val id : String,val title : String,val subtitle : String,val time : String,val questionList : List<QuestionModel>
){constructor() : this("","","","", emptyList())
}data class QuestionModel(val question : String,val options : List<String>,val correct : String,
){constructor() : this ("", emptyList(),"")
}
  • 步骤3. 主题设置
    配色精美的主题是影响App评价的一个指标,这方面还是专业的人来干。这里只是参考别的,最简设置。
    配置主题色,有利于界面统一,减少在代码中写颜色。在 colors.xml 中先定义主题色、背景配色、操作成功提示配色、操作失败提示配色
<?xml version="1.0" encoding="utf-8"?>
<resources><color name="black">#FF000000</color><color name="white">#FFFFFFFF</color><color name="blue">#1890ff</color><color name="gray">#F4F4F4</color><color name="green">#52C41A</color><color name="red">#FF4D4F</color>
</resources>

再设置主题:

<resources xmlns:tools="http://schemas.android.com/tools"><!-- Base application theme. --><style name="Base.Theme.Exam" parent="Theme.Material3.DayNight.NoActionBar"><!-- Customize your light theme here. --><item name="colorPrimary">@color/blue</item></style><style name="Theme.Exam" parent="Base.Theme.Exam" />
</resources>
  • 步骤4. 首页
    在首页,主要通过RecyclerView展示试卷列表。需要自定义Adapter, 列表项布局,并在 Adapter 中将模型映射到布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardViewxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_margin="4dp"android:elevation="10dp"app:cardCornerRadius="24dp"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:padding="16dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerVertical="true"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/tvPaperTitle"tools:text="HTML 测验"android:textSize="18sp"android:textStyle="bold"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/tvPaperSubTitle"android:layout_marginTop="4dp"tools:text="HTML理论模拟考试"/></LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentEnd="true"android:layout_centerVertical="true"android:gravity="center"android:orientation="vertical"><ImageViewandroid:layout_width="32dp"android:layout_height="32dp"android:src="@drawable/icon_timer"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/tvPaperTime"tools:text="20 min"/></LinearLayout></RelativeLayout></androidx.cardview.widget.CardView>

自定义 PaperListAdapter,给每个试卷项添加点击跳转到答题页面的click事件:

package com.alex.examimport android.content.Intent
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.alex.exam.databinding.PaperRecyclerRowBinding/*** @Author      : alex* @Date        : on 2024/1/6 17:13.* @Description :描述*/
class PaperListAdapter(private val paperModelList : List<PaperModel>) :RecyclerView.Adapter<PaperListAdapter.MyViewHolder>() {class MyViewHolder(private val binding: PaperRecyclerRowBinding) : RecyclerView.ViewHolder(binding.root) {fun bind(paperModel: PaperModel) {binding.apply {tvPaperTitle.text = paperModel.titletvPaperSubTitle.text = paperModel.subtitletvPaperTime.text = paperModel.time+" min"root.setOnClickListener {val intent  = Intent(root.context,ExamActivity::class.java)ExamActivity.questionModelList = paperModel.questionListExamActivity.time = paperModel.timeroot.context.startActivity(intent)}}}}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val binding = PaperRecyclerRowBinding.inflate(LayoutInflater.from(parent.context),parent,false)return MyViewHolder(binding)}override fun getItemCount(): Int {return paperModelList.size}override fun onBindViewHolder(holder: MyViewHolder, position: Int) {holder.bind(paperModelList[position])}
}

首页布局中加入RecyclerView控件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:orientation="vertical"android:padding="16dp"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ImageViewandroid:layout_width="match_parent"android:layout_height="160dp"android:src="@drawable/ab" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="16dp"android:background="@drawable/rounded_corner"android:backgroundTint="@color/blue"android:padding="8dp"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="学考帮"android:gravity="center"android:textSize="34sp"android:letterSpacing="0.1"android:textColor="@color/white"android:textStyle="bold"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="知识改变命运,学习成就未来。"android:gravity="center"android:textSize="18sp"android:layout_margin="16dp"android:textColor="@color/white"android:textStyle="bold"/></LinearLayout><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="试卷列表"android:layout_marginTop="16dp"android:layout_marginStart="4dp"android:textSize="20sp"android:textStyle="bold"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><ProgressBarandroid:layout_width="20dp"android:layout_height="20dp"android:layout_centerInParent="true"android:visibility="gone"android:id="@+id/progress_bar"/><androidx.recyclerview.widget.RecyclerViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="16dp"android:id="@+id/recycler_view"/></RelativeLayout></LinearLayout>

在 MainActivity 中模拟加载数据,加载数据成功前,显示 progressBar,加载后填充到RecyclerView:

package com.alex.examimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.alex.exam.databinding.ActivityMainBindingclass MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBindingprivate lateinit var paperModelList : MutableList<PaperModel>private lateinit var adapter: PaperListAdapteroverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)paperModelList = mutableListOf()getPapers()}private fun setupRecyclerView(){binding.progressBar.visibility = View.GONEadapter = PaperListAdapter(paperModelList)binding.recyclerView.layoutManager = LinearLayoutManager(this)binding.recyclerView.adapter = adapter}private fun getPapers(){val listQuestionModel = mutableListOf<QuestionModel>()listQuestionModel.add(QuestionModel("被称为JAVA之父的是?",listOf("Rod Johnson","James Gosling","Marc Fleury","Gavin King"),"James Gosling"))listQuestionModel.add(QuestionModel("cmd下编译Java程序使用的命令是( )",listOf("java","javav","java -version","javac"),"java"))listQuestionModel.add(QuestionModel("byte变量的取值范围是( )",listOf("0~65535","-128~127","-256~255","0~32767"),"-128~127"))listQuestionModel.add(QuestionModel("Java的前身名字叫( )",listOf("Oracle","mysql","spring","OAK"),"OAK"))listQuestionModel.add(QuestionModel("( )可将一个java文件转换成一个class文件",listOf("调试程序","编译程序","转换器程序","JRE"),"编译程序"))val listQuestionModel2 = mutableListOf<QuestionModel>()listQuestionModel2.add(QuestionModel("C#语言中,值类型包括:基本值类型、结构类型和( )",listOf("小数类型","整数类型","类类型","枚举类型"),"类类型"))listQuestionModel2.add(QuestionModel("C#语言中,引用类型包括:类类型、接口类型、数组类型和( )",listOf("枚举类型","委托类型","结构类型","小数类型"),"委托类型"))listQuestionModel2.add(QuestionModel("C#语言中,( )是一种特殊的类,它只包含数据成员,不包含方法成员",listOf("结构类型","枚举类型","接口类型","委托类型"),"结构类型"))listQuestionModel2.add(QuestionModel("下列关于抽象类的说法错误的是(  )。",listOf("抽象类可以实例化","抽象类可以包含抽象方法","抽象类可以包含抽象属性","抽象类可以引用派生类的实例"),"抽象类可以实例化"))listQuestionModel2.add(QuestionModel("下列关于接口的说法错误的是(  )。",listOf("接口可以包含方法","接口可以包含属性","接口可以包含事件","接口可以包含索引器"),"接口可以包含方法"))paperModelList.add(PaperModel("1","Java","Java语言基础测试题","10",listQuestionModel))paperModelList.add(PaperModel("2","C#","C#理论测试题","20",listQuestionModel2))paperModelList.add(PaperModel("3","JavaScript","JavaScript自测试题","15",listQuestionModel))setupRecyclerView()}
}
  • 步骤5. 答题页
    答题页面布局,显示题号进度条、倒计时、题目、下一题按钮;同时在交卷时,需要弹出对话框,这里要自定义。
    自定义对话框:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"android:orientation="vertical"android:layout_width="match_parent"android:gravity="center"android:padding="16dp"android:layout_height="wrap_content"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"tools:text="恭喜你通过考试!"android:gravity="center"android:textSize="20sp"android:textStyle="bold"android:id="@+id/tvScoreTitle"/><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"><com.google.android.material.progressindicator.CircularProgressIndicatorandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/circlePgrScoreProgress"android:layout_centerVertical="true"app:trackColor="@color/gray"tools:progress="60"app:trackCornerRadius="20dp"app:trackThickness="8dp"app:indicatorSize="90dp"/><TextViewandroid:id="@+id/tvProgress"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textSize="18sp"android:textStyle="bold"tools:text="50%" /></RelativeLayout><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"tools:text="答题情况:6 / 10"android:gravity="center"android:id="@+id/tvScoreSubTitle"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="确定"android:layout_margin="8dp"android:id="@+id/btnFinish"/></LinearLayout>

答题页面布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"tools:context=".ExamActivity"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"tools:text="题号 7/20"android:textSize="18sp"android:textStyle="bold"android:layout_centerVertical="true"android:id="@+id/question_indicator_textview"/><ImageViewandroid:layout_width="20dp"android:layout_height="20dp"android:src="@drawable/icon_timer"app:tint="@color/blue"android:layout_marginEnd="4dp"android:layout_toStartOf="@id/timer_indicator_textview"android:layout_centerVertical="true"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"tools:text="5:46"android:textSize="18sp"android:textStyle="bold"android:textColor="@color/blue"android:layout_alignParentEnd="true"android:layout_centerVertical="true"android:id="@+id/timer_indicator_textview"/></RelativeLayout><com.google.android.material.progressindicator.LinearProgressIndicatorandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginVertical="8dp"tools:progress="40"android:id="@+id/question_progress_indicator"/><androidx.cardview.widget.CardViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginVertical="8dp"android:elevation="4dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="16dp"><TextViewandroid:layout_width="match_parent"android:layout_height="120dp"tools:text="这里是题目"android:textSize="20sp"android:textStyle="bold"android:padding="8dp"android:background="@drawable/rounded_corner"android:backgroundTint="@color/blue"android:textColor="@color/white"android:gravity="center"android:layout_marginVertical="8dp"android:id="@+id/question_textview"/><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginVertical="4dp"android:backgroundTint="@color/gray"tools:text="答案 A"android:textColor="@color/black"android:paddingVertical="12dp"android:gravity="center_vertical"android:textSize="18sp"android:id="@+id/btnA" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginVertical="4dp"android:backgroundTint="@color/gray"tools:text="答案 B"android:textColor="@color/black"android:paddingVertical="12dp"android:gravity="center_vertical"android:textSize="18sp"android:id="@+id/btnB" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginVertical="4dp"android:backgroundTint="@color/gray"tools:text="答案 C"android:textColor="@color/black"android:paddingVertical="12dp"android:gravity="center_vertical"android:textSize="18sp"android:id="@+id/btnC" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginVertical="4dp"android:backgroundTint="@color/gray"tools:text="答案 D"android:textColor="@color/black"android:paddingVertical="12dp"android:gravity="center_vertical"android:textSize="18sp"android:id="@+id/btnD" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginVertical="4dp"android:text="下一题"android:paddingVertical="12dp"android:gravity="center_vertical"android:layout_gravity="end"android:textSize="20sp"android:paddingHorizontal="40dp"android:id="@+id/btnNext" /></LinearLayout></androidx.cardview.widget.CardView></LinearLayout>

ExamActity 定义了试题列表,是从上个界面传过来的数据;首先初始化数据,包括加载第一个题目内容,设置进度条、题号、开始计时;再点击下一题时,切换题目,如果是到最后一题,则显示交卷按钮,如果最后一题作答完成,并点击交卷,则停止计时,显示成绩弹窗,确认弹窗后 ,停止计时,并销毁,退出答题页。

package com.alex.examimport android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.CountDownTimer
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.alex.exam.databinding.ActivityExamBinding
import com.alex.exam.databinding.ScoreDialogBindingclass ExamActivity : AppCompatActivity(), View.OnClickListener {private var timer : CountDownTimer? = nullcompanion object {var questionModelList : List<QuestionModel> = listOf()var time : String = ""}lateinit var binding: ActivityExamBindingprivate var currentQuestionIndex = 0;private var selectedAnswer = ""private var score = 0override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityExamBinding.inflate(layoutInflater)setContentView(binding.root)binding.apply {btnA.setOnClickListener(this@ExamActivity)btnB.setOnClickListener(this@ExamActivity)btnC.setOnClickListener(this@ExamActivity)btnD.setOnClickListener(this@ExamActivity)btnNext.setOnClickListener(this@ExamActivity)}loadQuestions()startTimer()}private fun startTimer() {val totalTimeInMillis = time.toInt() * 60 * 1000Ltimer = object : CountDownTimer(totalTimeInMillis,1000L){override fun onTick(millisUntilFinished: Long) {val seconds = millisUntilFinished /1000val minutes = seconds/60val remainingSeconds = seconds % 60binding.timerIndicatorTextview.text = String.format("%02d:%02d", minutes,remainingSeconds)}override fun onFinish() {// 结束考试finishQuiz()}}.start()}// 加载试卷中的题目private fun loadQuestions(){selectedAnswer = ""// 判断是否是最后一题,如果是最后一题,点击下一题按钮,直接交卷,设置进度条为100%if(currentQuestionIndex == questionModelList.size){binding.questionProgressIndicator.progress = 100timer?.cancel()finishQuiz()return}// 加载题目内容到界面binding.apply {questionIndicatorTextview.text = "题号 ${currentQuestionIndex+1}/ ${questionModelList.size} "questionProgressIndicator.progress =( currentQuestionIndex.toFloat() / questionModelList.size.toFloat() * 100 ).toInt()questionTextview.text = questionModelList[currentQuestionIndex].questionbtnA.text = questionModelList[currentQuestionIndex].options[0]btnB.text = questionModelList[currentQuestionIndex].options[1]btnC.text = questionModelList[currentQuestionIndex].options[2]btnD.text = questionModelList[currentQuestionIndex].options[3]}}// 结束考试private fun finishQuiz() {val totalQuestions = questionModelList.sizeval percentage = ((score.toFloat() / totalQuestions.toFloat() ) *100 ).toInt()// 弹出对话框,显示考试结果val dialogBinding  = ScoreDialogBinding.inflate(layoutInflater)dialogBinding.apply {circlePgrScoreProgress.progress = percentagetvProgress.text = "$percentage %"if(percentage>60){tvScoreTitle.text = "恭喜你通过考试!"tvScoreTitle.setTextColor(getColor(R.color.green))}else{tvScoreTitle.text = "未及格,加油哦!"tvScoreTitle.setTextColor(getColor(R.color.red))}tvScoreSubTitle.text = "答对:$score / $totalQuestions"btnFinish.setOnClickListener {finish()}}AlertDialog.Builder(this).setView(dialogBinding.root).setCancelable(false).show()}override fun onClick(view: View?) {binding.apply {//初始化选项按钮,背景颜色位灰色,文字颜色未黑色btnA.setBackgroundColor(getColor(R.color.gray))btnB.setBackgroundColor(getColor(R.color.gray))btnC.setBackgroundColor(getColor(R.color.gray))btnD.setBackgroundColor(getColor(R.color.gray))btnA.setTextColor(getColor(R.color.black))btnB.setTextColor(getColor(R.color.black))btnC.setTextColor(getColor(R.color.black))btnD.setTextColor(getColor(R.color.black))}val clickedBtn = view as Buttonif(clickedBtn.id==R.id.btnNext){// 点击下一题if(selectedAnswer.isEmpty()){Toast.makeText(applicationContext,"请选择答案",Toast.LENGTH_SHORT).show()return;}// 判断答案是否正确if(selectedAnswer == questionModelList[currentQuestionIndex].correct){score++Log.i("考试分数",score.toString())}currentQuestionIndex++// 判断是否是最后一题if(currentQuestionIndex == questionModelList.size-1){binding.btnNext.text = "交卷"}loadQuestions()}else{// 选中答案,改变背景颜色和文字颜色selectedAnswer = clickedBtn.text.toString()clickedBtn.setBackgroundColor(getColor(R.color.blue))clickedBtn.setTextColor(Color.WHITE)}}override fun onDestroy() {super.onDestroy()//取消计时器timer?.cancel()timer = null}
}

打包

打包前,先定义个logo, 在 new->Image Asset,设置个图片:
在这里插入图片描述
最后点击 build -> Generate Signed Bundle or APK, 加载 jks 打包密钥,进行apk 打包
在这里插入图片描述

夜神模拟器图标无效问题
打包后在模拟器上运行,发现图标还是小机器人,最后排查时 minSdk 对应的android 版本大于 模拟器的版本,将 minSdk降低到 25,再重新打包,就可以啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/609468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QML 模型视图

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 对于 GUI 应用程序来说,我们通常需要格式化数据并进行显示,而 QML 提供了一种很便利的显示方式 - Model-View-Delegate(简称:MVD)。该模式是 Model-View-Controller(简称:MVC)的一种变体,常被用于分…

HackTheBox - Medium - Linux - Awkward

Awkward Awkward 是一款中等难度的机器&#xff0c;它突出显示了不会导致 RCE 的代码注入漏洞&#xff0c;而是 SSRF、LFI 和任意文件写入/追加漏洞。此外&#xff0c;该框还涉及通过不良的密码做法&#xff08;例如密码重用&#xff09;以及以纯文本形式存储密码来绕过身份验…

力扣:18.四数之和

一、做题链接&#xff1a;18. 四数之和 - 力扣&#xff08;LeetCode&#xff09; 二、题目分析 1.做这一道题之前本博主建议先看上一篇《三数之和》 2.题目分析 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重…

计算机毕业设计 基于SpringBoot的项目申报系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

程序媛的mac修炼手册-- 终端(terminal)常用命令

「终端&#xff08;terminal&#xff09;」相当于macOS的一个 App &#xff0c;它的特殊之处是&#xff0c;它是管理其它App的App&#xff0c;操作主要通过命令行界面 (CLI) 。 相比于我们日常熟悉的用户界面&#xff08;User Interface&#xff0c;UI&#xff09;&#xff0c…

Redis 主从、哨兵和分片集群简单介绍

Redis 主从集群架构 单节点 redis 并发能力有上限&#xff0c;要进一步提高 redis 并发能力&#xff0c;就要搭建主从集群&#xff0c;实现读写分离 主从同步原理 Replicaition id&#xff1a;每台 master 机器都一个 repl_id&#xff0c;是数据集的表示&#xff0c;若 salv…

软件测试|如何在Pycharm中配置文件头部信息

简介 PyCharm是一款功能强大的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;在开发过程中&#xff0c;我们经常需要在代码文件的开头添加固定的文件说明信息&#xff0c;例如版权声明、作者信息、创建日期等。手动添加这些信息可能会很繁琐&#xff0c;但是PyCh…

[Vulnhub靶机] DriftingBlues: 5

[Vulnhub靶机] DriftingBlues: 5靶机渗透思路及方法&#xff08;个人分享&#xff09; 靶机下载地址&#xff1a; https://download.vulnhub.com/driftingblues/driftingblues5_vh.ova 靶机地址&#xff1a;192.168.67.24 攻击机地址&#xff1a;192.168.67.3 一、信息收集 …

探索人工智能:深度学习、人工智能安全和人工智能

深度学习是人工智能的一种重要技术&#xff0c;它模拟了人类大脑神经网络的工作原理&#xff0c;通过建立多层次的神经元网络来实现对数据的分析和处理。这种技术的引入使得人工智能的发展进入到了一个新的阶段。 现如今&#xff0c;深度学习在各个领域都有着广泛的应用。例如…

Java设计模式-访问者模式

访问者模式 一、概述二、结构三、案例实现四、优缺点五、使用场景六、扩展 一、概述 定义&#xff1a; 封装一些作用于某种数据结构中的各元素的操作&#xff0c;它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。 二、结构 访问者模式包含以下主要角色: …

Echarts——使用graphic组件在一个option内同时设置两个饼图的背景图

使用echarts的graphic原生图形元素组件&#xff0c;为两个饼图设置对应背景。 <template><div id"app"><div class"charts" ref"charts"></div></div> </template><script> import * as echarts from…

【ROS】小车机器视觉巡线行驶

摄像头 USB摄像头是最普遍的摄像头&#xff0c;如笔记本内置的摄像头&#xff0c;在ROS中使用这类设备很简单&#xff0c;可以直接使用usb_cam功能包驱动&#xff0c;USB摄像头输出的是二维图像数据。 usb_cam是针对V4L协议USB摄像头的ROS驱动包&#xff0c;核心节点是usb_cam…

2024年跨境电商上半年营销日历最全整理

2024年伊始&#xff0c;跨境电商开启新一轮的营销竞技&#xff0c;那么首先需要客户需求&#xff0c;节假日与用户需求息息相关&#xff0c;那么接下来小编为大家整理2024上半年海外都有哪些节日和假期&#xff1f;跨境卖家如何见针对营销日历选品&#xff0c;助力卖家把握2024…

软件测试|MySQL 非空约束详解

简介 MySQL中的非空约束&#xff08;NOT NULL Constraint&#xff09;是一种用于确保表中某列不允许为空值的数据库约束。非空约束的作用是保证特定列的数据始终包含有效值&#xff0c;防止在插入或更新操作时出现空值&#xff0c;从而维护数据的完整性和一致性。在本文中&…

学习笔记之——3D Gaussian Splatting及其在SLAM与自动驾驶上的应用调研

之前博客介绍了NeRF-SLAM&#xff0c;其中对于3D Gaussian Splatting没有太深入介绍。本博文对3D Gaussian Splatting相关的一些工作做调研。 学习笔记之——NeRF SLAM&#xff08;基于神经辐射场的SLAM&#xff09;-CSDN博客文章浏览阅读967次&#xff0c;点赞22次&#xff0…

matlab生成列是0-255渐变的图像

图像大小&#xff1a;640512 8位灰度图 %% 生成图像 %大小&#xff1a;640*512 %类型&#xff1a;灰度图 %灰度值&#xff1a;列按照0-255渐变&#xff0c;故命名为column shade。 clc,clear all,close all; %输入的图 imadouble(imread(lenna2.bmp));%原图 imargb2gray(ima)…

MYSQL InnoDB引擎

逻辑存储结构 架构 内存架构 磁盘结构 后台线程 事务原理 redolog undo log MVCC 基本概念 实现原理 隐藏字段 undo log readview

6个提升Python编程能力的PyCharm插件

大家好&#xff0c;PyCharm作为一款强大的集成开发环境&#xff0c;本身已经提供了许多功能&#xff0c;但一些插件将进一步扩展和增强PyCharm的能力。通过使用这些插件&#xff0c;大家能够更快速地编写代码、提高代码质量、进行调试和优化&#xff0c;并将开发体验提升到一个…

软件测试|MySQL DISTINCT关键字过滤重复数据

简介 在MySQL中&#xff0c;有时候我们需要从表中检索唯一的、不重复的数据。这时&#xff0c;我们可以使用DISTINCT关键字来过滤掉重复的数据行。在本文中&#xff0c;我们将深入探讨MySQL中DISTINCT的用法以及如何在查询中使用它来得到不重复的结果集。 基本语法 DISTINCT…

14.网络编程入门和网络应用开发

网络编程入门 计算机网络基础 计算机网络是独立自主的计算机互联而成的系统的总称&#xff0c;组建计算机网络最主要的目的是实现多台计算机之间的通信和资源共享。今天计算机网络中的设备和计算机网络的用户已经多得不可计数&#xff0c;而计算机网络也可以称得上是一个“复…