實驗 2 Scala 編程初級實踐
一、實驗目的
1.掌握 Scala 語言的基本語法、數據結構和控制結構;
2.掌握面向對象編程的基礎知識,能夠編寫自定義類和特質;
3.掌握函數式編程的基礎知識,能夠熟練定義匿名函數。熟悉 Scala 的容器類庫的基本 層次結構,熟練使用常用的容器類進行數據;
4.熟練掌握 Scala 的 REPL 運行模式和編譯運行方法。
二、實驗平台
已經配置完成的 Scala 開發環境。Scala 版本為 2.11.8.
三、實驗內容和要求
1. 計算級數
請用腳本的方式編程計算並輸出下列級數的前 n 項之和 Sn,直到 Sn 剛好大於或等於 q 為止,其中 q 為大於 0 的整數,其值通過鍵盤輸入。

例 如 , 若 q 的 值 為 50.0 , 則 輸 出 應 為 : Sn=50.416695 。 請 將 源 文 件 保 存 為 exercise2-1.scala,在REPL模式下測試運行,測試樣例:q=1時,Sn=2;q=30時,Sn=30.891459; q=50 時,Sn=50.416695。
import io.StdIn._
object lab2{
def main(args:Array[String]){
var Sn:Float = 0
var n:Float = 1
println("Input a number for q:")
var q = readInt()
while(Sn < q)
{
Sn += (n+1)/n
n += 1
}
println(s"Sn = $Sn")
}
}

2. 模擬圖形繪制
對於一個圖形繪制程序,用下面的層次對各種實體進行抽象。定義一個 Drawable 的特 質,其包括一個 draw 方法,默認實現為輸出對象的字符串表示。定義一個 Point 類表示點, 其混入了 Drawable 特質,並包含一個 shift 方法,用於移動點。所有圖形實體的抽象類為 Shape,其構造函數包括一個 Point 類型,表示圖形的具體位置(具體意義對不同的具體圖 形不一樣)。Shape 類有一個具體方法 moveTo 和一個抽象方法 zoom,其中 moveTo 將圖形從 當前位置移動到新的位置, 各種具體圖形的 moveTo 可能會有不一樣的地方。zoom 方法實 現對圖形的放縮,接受一個浮點型的放縮倍數參數,不同具體圖形放縮實現不一樣。繼承 Shape 類的具體圖形類型包括直線類 Line 和圓類 Circle。Line 類的第一個參數表示其位置, 第二個參數表示另一個端點,Line 放縮的時候,其中點位置不變,長度按倍數放縮(注意, 縮放時,其兩個端點信息也改變了),另外,Line 的 move 行為影響了另一個端點,需要對 move 方法進行重載。Circle 類第一個參數表示其圓心,也是其位置,另一個參數表示其半 徑,Circle 縮放的時候,位置參數不變,半徑按倍數縮放。另外直線類 Line 和圓類 Circle 都混入了 Drawable 特質,要求對 draw 進行重載實現,其中類 Line 的 draw 輸出的信息樣式 為“Line:第一個端點的坐標--第二個端點的坐標)”,類 Circle 的 draw 輸出的信息樣式為 “Circle center:圓心坐標,R=半徑”。如下的代碼已經給出了 Drawable 和 Point 的定義, 同時也給出了程序入口 main 函數的實現,請完成 Shape 類、Line 類和 Circle 類的定義。
case class Point(var x:Double ,var y:Double) extends Drawable{
def shift(X:Double ,Y:Double){
x += X
y += Y
}
}
trait Drawable{
def draw(){println(this.toString)}
}
abstract class Shape(var location:Point)//location是shape的一個可變字段
{
def moveTo(newLocation:Point)
{
location = newLocation
}
def zoom(scale:Double)
}
class Line(beginPoint:Point,var endPoint:Point)extends Shape(beginPoint) with Drawable{
override def draw()
{
println(s"Line:(${location.x},${location.y}--(${endPoint.x},${endPoint.y})")
}
override def moveTo(newLocation:Point)
{
endPoint.shift(newLocation.x-location.x,newLocation.y-location.y)
location = newLocation
}
override def zoom(scale:Double)
{
val midPoint=Point((endPoint.x+location.x)/2,(endPoint.y+location.y)/2)
location.x=midPoint.x+scale*(location.x-midPoint.x)
location.y=midPoint.y+scale*(location.y-midPoint.y)
endPoint.x=midPoint.x+scale*(endPoint.x-midPoint.x)
endPoint.y=midPoint.y+scale*(endPoint.y-midPoint.y)
}
}
class Circle(center:Point,var radius:Double)extends Shape(center) with Drawable
{
override def draw()
{
println(s"Circle center:(${location.x},${location.y}),R=$radius")
}
override def zoom(scale :Double)
{
radius = radius*scale
}
}
object MyDraw
{
def main(args:Array[String])
{
val p = new Point(10,30)
p.draw
val line1 = new Line(Point(0,0),Point(20,20))
line1.draw
line1.moveTo(Point(5,5))
line1.draw
line1.zoom(2)
line1.draw
val circle = new Circle(Point(10,10),5)
circle.draw
circle.moveTo(Point(30,20))
circle.draw
circle.zoom(0.5)
circle.draw
}
}

3. 統計學生成績
學生的成績清單格式如下所示,第一行為表頭,各字段意思分別為學號、性別、課程名 1、課程名 2 等,后面每一行代表一個學生的信息,各字段之間用空白符隔開

給定任何一個如上格式的清單(不同清單里課程數量可能不一樣),要求盡可能采用函 數式編程,統計出各門課程的平均成績,最低成績,和最高成績;另外還需按男女同學分開, 分別統計各門課程的平均成績,最低成績,和最高成績。 測試樣例 1 如下:


import scala.collection.mutable.ArrayBuffer
object test3 {
def main(args: Array[String]): Unit = {
var students:ArrayBuffer[Student] = new ArrayBuffer[Student]()
students.append(new Student(301610, "male", 80, 64, 78))
students.append(new Student(301611, "female", 65, 87, 58))
students.append(new Student(301612, "female", 44, 71, 77))
students.append(new Student(301613, "female", 66, 71, 91))
students.append(new Student(301614, "female", 70, 71, 100))
students.append(new Student(301615, "male", 72, 77, 72))
students.append(new Student(301616, "female", 73, 81, 75))
students.append(new Student(301617, "female", 69, 77, 75))
students.append(new Student(301618, "male", 73, 61, 65))
students.append(new Student(301619, "male", 74, 69, 68))
students.append(new Student(301620, "male", 76, 62, 76))
students.append(new Student(301621, "male", 73, 69, 91))
students.append(new Student(301622, "male", 55, 69, 61))
students.append(new Student(301623, "male", 50, 58, 75))
students.append(new Student(301624, "female", 63, 83, 93))
students.append(new Student(301625, "male", 72, 54, 100))
students.append(new Student(301626, "male", 76, 66, 73))
students.append(new Student(301627, "male", 82, 87, 79))
students.append(new Student(301628, "female", 62, 80, 54))
students.append(new Student(301629, "male", 89, 77, 72))
println(students.length)
println(students(1).toString)
getData(students)
getDataMale(students)
getDataFeMale(students)
}
def getData(value: ArrayBuffer[Student]): Unit ={
var Mathaverage:Double=0;
var MathSum:Double = 0;
var MathMin:Double = value(0).Math;
var MathMax:Double = 0;
var Englishaverage:Double=0;
var EnglishSum:Double = 0;
var EnglishMin:Double = value(0).English;
var EnglishMax:Double = 0;
var Physicsaverage:Double=0;
var PhysicsSum:Double = 0;
var PhysicsMin:Double = value(0).Physics;
var PhysicsMax:Double = 0;
var number = value.length;
for (i <- 0 until value.length){
//三科總數
MathSum = value(i).Math+MathSum
EnglishSum = value(i).English+EnglishSum
PhysicsSum = value(i).Physics+PhysicsSum
//最大和最小
if(value(i).Math>MathMax){
MathMax=value(i).Math;
}
if(value(i).English>EnglishMax){
EnglishMax=value(i).English;
}
if(value(i).Physics>PhysicsMax){
PhysicsMax=value(i).Physics;
}
if(value(i).Math<MathMin){
MathMin=value(i).Math;
}
if(value(i).English<EnglishMin){
EnglishMin=value(i).English;
}
if(value(i).Physics<PhysicsMin){
PhysicsMin=value(i).Physics;
}
}
//平均值
Mathaverage=MathSum/number
Englishaverage=EnglishSum/number
Physicsaverage=PhysicsSum/number
println("course\t average\t min\t max \t")
println("Math:\t "+Mathaverage+"\t\t"+MathMin+"\t "+MathMax)
println("English:\t"+Englishaverage+"\t"+EnglishMin+"\t "+EnglishMax)
println("Physics:\t"+Physicsaverage+"\t"+PhysicsMin+"\t "+PhysicsMax)
}
def getDataMale(value: ArrayBuffer[Student]): Unit = {
var Mathaverage: Double = 0;
var MathSum: Double = 0;
var MathMin: Double = value(0).Math;
var MathMax: Double = 0;
var Englishaverage: Double = 0;
var EnglishSum: Double = 0;
var EnglishMin: Double = value(0).English;
var EnglishMax: Double = 0;
var Physicsaverage: Double = 0;
var PhysicsSum: Double = 0;
var PhysicsMin: Double = value(0).Physics;
var PhysicsMax: Double = 0;
var number = 0;
for (i <- 0 until value.length) {
if (value(i).gender.equals("male")) {
number = number + 1
//三科總數
MathSum = value(i).Math + MathSum
EnglishSum = value(i).English + EnglishSum
PhysicsSum = value(i).Physics + PhysicsSum
//最大和最小
if (value(i).Math > MathMax) {
MathMax = value(i).Math;
}
if (value(i).English > EnglishMax) {
EnglishMax = value(i).English;
}
if (value(i).Physics > PhysicsMax) {
PhysicsMax = value(i).Physics;
}
if (value(i).Math < MathMin) {
MathMin = value(i).Math;
}
if (value(i).English < EnglishMin) {
EnglishMin = value(i).English;
}
if (value(i).Physics < PhysicsMin) {
PhysicsMin = value(i).Physics;
}
}
}
//平均值
Mathaverage=MathSum/number
Englishaverage=EnglishSum/number
Physicsaverage=PhysicsSum/number
println("course\t average\t min\t max \t(Male)")
Mathaverage=Mathaverage.toInt
Englishaverage=Englishaverage.toInt
Physicsaverage=Physicsaverage.toInt
println("Math:\t "+Mathaverage+"\t\t"+MathMin+"\t "+MathMax)
println("English:\t "+Englishaverage+"\t\t"+EnglishMin+"\t "+EnglishMax)
println("Physics:\t "+Physicsaverage+"\t\t"+PhysicsMin+"\t "+PhysicsMax)
}
def getDataFeMale(value: ArrayBuffer[Student]): Unit ={
var Mathaverage:Double=0;
var MathSum:Double = 0;
var MathMin:Double = value(1).Math;
var MathMax:Double = 0;
var Englishaverage:Double=0;
var EnglishSum:Double = 0;
var EnglishMin:Double = value(1).English;
var EnglishMax:Double = 0;
var Physicsaverage:Double=0;
var PhysicsSum:Double = 0;
var PhysicsMin:Double = value(1).Physics;
var PhysicsMax:Double = 0;
var number = 0;
for (i <- 0 until value.length){
if(value(i).gender.equals("female")){
number=number+1
//三科總數
MathSum = value(i).Math+MathSum
EnglishSum = value(i).English+EnglishSum
PhysicsSum = value(i).Physics+PhysicsSum
//最大和最小
if(value(i).Math>MathMax){
MathMax=value(i).Math;
}
if(value(i).English>EnglishMax){
EnglishMax=value(i).English;
}
if(value(i).Physics>PhysicsMax){
PhysicsMax=value(i).Physics;
}
if(value(i).Math<MathMin){
MathMin=value(i).Math;
}
if(value(i).English<EnglishMin){
EnglishMin=value(i).English;
}
if(value(i).Physics<PhysicsMin){
PhysicsMin=value(i).Physics;
}
}
}
//平均值
Mathaverage=MathSum/number
Englishaverage=EnglishSum/number
Physicsaverage=PhysicsSum/number
println("course\t average\t min\t max \t(FeMale)")
Mathaverage=Mathaverage.toInt
Englishaverage=Englishaverage.toInt
Physicsaverage=Physicsaverage.toInt
println("Math:\t "+Mathaverage+"\t\t"+MathMin+"\t "+MathMax)
println("English:\t "+Englishaverage+"\t\t"+EnglishMin+"\t "+EnglishMax)
println("Physics:\t "+Physicsaverage+"\t\t"+PhysicsMin+"\t "+PhysicsMax)
}
}
class Student(id1:Int,gender1:String,Math1:Double,English1:Double,Physics1:Double){
var id:Int = id1
var gender:String = gender1
var Math:Double = Math1
var English:Double = English1
var Physics:Double = Physics1
override def toString = s"Student($id, $gender, $Math, $English, $Physics)"
}

