潜艇小游戏

编程入门 行业动态 更新时间:2024-10-18 01:38:59

潜艇<a href=https://www.elefans.com/category/jswz/34/1769974.html style=小游戏"/>

潜艇小游戏

潜艇小游戏

  • 设计一个潜艇游戏,首先来考虑一下游戏中可能会涉及到的角色。在该游戏中,潜艇包含水雷潜艇、鱼雷潜艇和侦察潜艇,水雷潜艇可以发射水雷,而战舰也可以发射炸弹对潜艇进行攻击。

  • 当炸弹打到水雷潜艇和侦察潜艇时,战舰得分;当炸弹打到鱼雷潜艇时,战舰命数增一;当水雷打到战舰时,战舰命数减一,直到命数为0时游戏结束。
    因此,该游戏中共有5种角色。
    1.水雷潜艇
    2.鱼雷潜艇
    3.侦察潜艇
    4.水雷
    5.炸弹

  • 游戏窗口只有一个,战舰只有一个,潜艇有多个,水雷有多个,炸弹有多个,所以潜艇存储在潜艇数组中、水雷存储在水雷数组中,以及炸弹存储在炸弹数组中。

  • 在该游戏中,战舰的移动和炸弹的发射是由键盘控制的,而潜艇的产生和水雷的发射是定时的。另外,三种潜艇是随机生成的,位置是从窗口的左端进入,右端出,但出现的高度也是随机的。

  • 由于这五个角色有一些共同的属性和行为,考虑到代码的复用性,设计出来一个超类SeaObject,将这些角色中共有的属性和行为写入,角色只需要继承就可以使用该变量和方法。

分析角色的属性和行为可以得到:

1)共有属性和行为:

  • 这些角色都会死亡(潜艇与炸弹碰撞时,两者都会死亡;战舰与水雷碰撞时,水雷会死亡),所以设置状态变量用于识别存活和死亡状态,设置方法判断状态。
  • 每个角色都有宽和高,移动速度和xy坐标,并且这些属性需要赋值。
  • 每个角色都会有移动的行为,但每个角色移动的速度、方向都不同。(需要重写)
  • 每个角色都需要获取图片,并且需要画出来。意味着获取图片行为为共有的行为,所以设计在SeaObject中,每个对象获取图片的行为都是不一样的,所以设计为抽象方法(因为每个角色的图片是不同的,所以获取图片需要重写。但画的行为是相同的,画就不用每个角色自己重写。另外,只有活着的对象,才需要画到窗口中)。
  • 除了战舰以外的对象都会出现越界现象(因为三种潜艇的越界都是相同的,所以后续只需要水雷、炸弹重写即可)
  • 每个角色都会发生碰撞现象,碰撞之后会死亡。
package cn.tedu.submarine;import java.util.Random;
import javax.swing.ImageIcon;
import java.awt.Graphics;
//海洋对象
public abstract class SeaObject {public static final int LIVE = 0; //活着public static final int DEAD = 1; //死了protected int state = LIVE; //当前状态(默认为活着的)protected int width;//宽protected int height;//高protected int x;//x坐标protected int y;//y坐标protected int speed;//移动速度//因为三种潜艇的宽和高是不同的,所以数据不能写死,需要传参写活//因为三种潜艇的其他属性值是相同的,所以直接将数据写死public SeaObject(int width,int height){ //专门给侦查潜艇、鱼雷潜艇、水雷潜艇设计赋值用的this.width=width;this.height=height;x=-width;Random rd = new Random();y=rd.nextInt(World.HEIGHT-height-150+1)+150; //150到460speed=rd.nextInt(3)+1; //1到3}public SeaObject(int width,int height,int x,int y,int speed){ //专门给战舰、水雷、炸弹设计赋值用的this.width=width;this.height=height;this.x=x;this.y=y;this.speed = speed;}//对象移动public abstract void move();//获取对象的图片public abstract ImageIcon getImage();//判断对象是否是活着的public boolean isLive(){return state==LIVE;}//判断对象是否是死的public boolean isDead(){return state==DEAD;}//实现画对象public void paintImage(Graphics g){ //g就是画笔if(isLive()){ //若活着的this.getImage().paintIcon(null,g,this.x,this.y); //重写看对象的行为}}//检测潜艇越界public boolean isOutOfBounds(){return x>=World.WIDTH;}public boolean isHit(SeaObject other){//碰撞  this---表示当前对象  other----表示传进来的对象int x1 = this.x-other.width; //潜艇的x-炸弹的宽int x2 = this.x+this.width;int y1 = this.y-other.height;int y2 = this.y+this.height;int x = other.x;int y = other.y;return (x>=x1 && x<=x2) && (y>=y1 && y<=y2);}public void goDead(){state = DEAD ; //将状态改为死了的410}}

2)战舰的特有属性和行为:

  • 命数(战舰的命数可以用于控制游戏的运行或结束,被设置成私有属性)
  • 发射炸弹(生成炸弹对象。炸弹是由战舰发射的,所以炸弹对象的产生是在战舰类中。)
  • 左右移动(由于战舰的移动方式与潜艇、水雷、炸弹均不同,所以自己设置了方法。战舰的移动是利用键盘的方向键←→进行控制的,当按下←键就向左移动一个坐标,当按下→键就向右移动一个坐标。注意:记得设置限制,避免战舰跑出界面。)
  • 增命 (当战舰发射的炸弹打到水雷潜艇时,水雷潜艇死亡消失,战舰增1条命)
  • 减命 (当战舰被水雷潜艇发射的水雷打中时,战舰命数减一)
  • 获取命数 (由于命数这个变量是战舰私有的,所以外界想要调用只能借助公共方法)
  • 重写获取图片的方法(由于每个角色的图片都是不一样的,超类中只是提供了获取图片的方法,需要各个对象自己重写)
package cn.tedu.submarine;import javax.swing.*;public class BattleShip extends SeaObject{//战舰类private int life;//生命数public BattleShip(){//构造方法super(66,26,270,124,20);life=5;}//重写@Overridepublic void move(){//对象移动}public void moveLeft(){if(x>0) x-=speed;}public void moveRight(){if(x<641-width) x+=speed;}//重写getImage()获取对象的图片@Overridepublic  ImageIcon getImage(){return Images.battleship;// 返回战舰图片}//战舰发射炸弹--------生成炸弹对象public Bomb shoot (){return new Bomb(this.x,this.y); // 炸弹的坐标就是战舰的坐标}//战舰增命public void addLife(int num){life +=num;}//获取命数public int getLife(){return life;}//战舰减命public void subtractLife(){life--;}
}

3)水雷的特有属性和行为:

  • 重写移动方法 (水雷的移动是当水雷潜艇发射水雷后,从水雷潜艇发射位置匀速向上移动,直至打到战舰或者碰到水平面消失)
  • 重写获取图片的方法
  • 重写越界方法(水雷的越界与潜艇越界不同,水雷碰到水平面后就算越界)
package cn.tedu.submarine;import javax.swing.*;
import java.util.Random;public class Mine extends SeaObject{//水雷public Mine(int x,int y){//构造方法super(11,11,x,y,1);}//重写@Overridepublic void move(){//对象移动y -= speed; //向上移动}//重写getImage()获取对象的图片@Overridepublic ImageIcon getImage(){return Images.mine;// 返回水雷图片}//重写@Overridepublic boolean isOutOfBounds(){return y<=150-height;}
}

4)炸弹的特有属性和行为:

  • 重写移动方法(炸弹的移动是当战舰发射出炸弹后,炸弹从发射位置匀速向下移动,直到打到潜艇或者到达窗口的最低端)
  • 重写获取图片的方法
  • 重写越界方法(炸弹的越界是到达窗口最低端就算越界)
package cn.tedu.submarine;import javax.swing.*;public class Bomb extends SeaObject{ //炸弹public Bomb(int x,int y){super(9,12,x,y,2);}//重写移动方法@Overridepublic void move(){//对象移动y += speed; //向下移动}//重写getImage()获取对象的图片@Overridepublic ImageIcon getImage(){return Images.bomb;// 返回炸弹图片}//重写越界方法@Overridepublic boolean isOutOfBounds(){return y>=World.HEIGHT;}
}

5)水雷潜艇的特有属性和行为:

  • 重写移动方法(潜艇的移动都是从左到右,速度各有不同。)
  • 重写获取图片的方法
  • 发射水雷(生成水雷对象)(水雷是由水雷潜艇发射的,所以产生水雷对象的方法就写在了水雷潜艇中。根据当前对象的位置发射水雷,并存入水雷数组中。)
  • 实现得命的接口 (当战舰发射的炸弹与水雷潜艇发生碰撞时,水雷潜艇死亡消失,战舰可以增一条命)
package cn.tedu.submarine;import javax.swing.*;
import java.util.Random;public class MineSubmarine extends SeaObject implements EnemyLife{//水雷潜艇public MineSubmarine(){ //构造方法super(63,19);}//重写@Overridepublic void move(){//对象移动x+= speed; //向右移动}//重写getImage()获取对象的图片@Overridepublic ImageIcon getImage(){return Images.minesubm;// 返回水雷潜艇图片}//生成水雷对象-----水雷潜艇发射水雷public Mine shootMine(){int x = this.x+this.width; //水雷潜艇的位置+水雷潜艇的宽int y = this.y-11;return new Mine(x,y); //返回水雷对象}@Override  //重写public int getLife(){return 1; //打掉鱼雷潜艇,可以得到1条命}}

6)鱼雷潜艇的特有属性和行为:

  • 重写移动方法
  • 重写获取图片的方法
  • 实现得分的接口 (当战舰发射的炸弹与鱼雷潜艇发生碰撞时,鱼雷潜艇死亡消失,战舰可以增40分)
package cn.tedu.submarine;import javax.swing.*;
import java.util.Random;public class TorpedoSubmarine extends SeaObject implements EnemyScore{//鱼雷潜艇public TorpedoSubmarine(){super(64,20);}//重写@Overridepublic void move(){//对象移动x+= speed; //向右移动}//重写getImage()获取对象的图片@Overridepublic ImageIcon getImage(){return Images.torpesubm;// 返回鱼雷潜艇图片}@Overridepublic int getScore(){return 40; //打掉鱼雷潜艇,玩家得40分}
}

7)侦察潜艇的特有属性和行为:

  • 重写移动方法
  • 重写获取图片的方法
  • 实现得分的接口 (当战舰发射的炸弹与侦察潜艇发生碰撞时,侦察潜艇死亡消失,战舰可以增10分)
package cn.tedu.submarine;import javax.swing.*;
import java.util.Random;public class ObserveSubmarine extends SeaObject implements EnemyScore{//侦察潜艇public ObserveSubmarine(){//构造方法super(63,19);}//重写@Overridepublic void move(){//对象移动x+= speed; //向右移动}//重写getImage()获取对象的图片@Overridepublic ImageIcon getImage(){return Images.obsersubm;// 返回侦查潜艇图片}@Override  //重写getScore()得分public int getScore(){return 10; //打掉侦查潜艇,玩家得10分}}

8)图片类:

图片类导入成功,应该显示为8。如果显示其他,则没有成功,注意可能是路径或者名字匹配错误。

import  javax.swing.ImageIcon;
//图片类
public class Images {//公开的  静态的   图片数据类型  变量名public static ImageIcon battleship; //战舰图片public static ImageIcon obsersubm;  //侦察潜艇图片public static ImageIcon torpesubm;  //鱼雷潜艇图片public static ImageIcon minesubm;  //水雷潜艇图片public static ImageIcon mine;      //水雷图片public static ImageIcon bomb;      //炸弹图片public static ImageIcon sea;       //海洋图public static ImageIcon gameover;  //游戏结束图static { //给静态图片赋值battleship = new ImageIcon("img/battleship.png");obsersubm = new ImageIcon("img/obsersubm.png");torpesubm = new ImageIcon("img/torpesubm.png");minesubm = new ImageIcon("img/minesubm.png");mine = new ImageIcon("img/mine.png");bomb = new ImageIcon("img/bomb.png");sea = new ImageIcon("img/sea.png");gameover = new ImageIcon("img/gameover.png");}public static void main(String[] args) { //测试图片System.out.println(battleship.getImageLoadStatus()); //返回8表示读取成功,否则失败System.out.println(obsersubm.getImageLoadStatus()); //返回8表示读取成功,否则失败System.out.println(torpesubm.getImageLoadStatus()); //返回8表示读取成功,否则失败System.out.println(minesubm.getImageLoadStatus()); //返回8表示读取成功,否则失败System.out.println(mine.getImageLoadStatus()); //返回8表示读取成功,否则失败System.out.println(bomb.getImageLoadStatus()); //返回8表示读取成功,否则失败System.out.println(sea.getImageLoadStatus()); //返回8表示读取成功,否则失败System.out.println(gameover.getImageLoadStatus()); //返回8表示读取成功,否则失败}
}

9)得分接口:

由于得分、增命不是所有对象的共性行为,所以不能写在超类中。超类中是所有派生类共有的属性和行为,如果只是部分派生类需要的属性和行为,此时写在超类中,就会被所有派生类继承,不够合理。另外,类和类之间只能单一继承,如果把部分派生类需要的属性和行为写在另一个类中,没有意义。所以就提供了接口,可以让其实现。接口中只包含常量和抽象方法,较之普通类和抽象类等更简单,当需要使用时实现重写抽象方法就行,不用管其他的,换句话说,接口就是专门设计用来帮助类直接快速使用功能的。

public interface EnemyScore {public int getScore();
}

10)得命接口:

//得命接口
public interface EnemyLife {public int getLife();
}

11)窗口:

  • 本游戏是在窗口中实现的,窗口的大小宽高是固定的,我们将其设置成了常量。
  • 同样,整个游戏存在两种状态,当战舰命数不为0时,则游戏继续;当战舰命数减到0时,游戏结束。我们将运行状态和结束状态也设置为了常量,并且设置了一个私有变量用于表示当前状态(默认为运行状态)。
  • 分析可以发现,海洋背景对象是一直存在于窗口的,战舰也是在游戏启动时就存在于窗口中。而潜艇对象是被定时随机生成后,从窗口的左端进入,一直移动到窗口右端,因此我们可以抽象理解为潜艇、战舰、海洋对象是由窗口产生的,应该在窗口类中new。(注:水雷是由水雷潜艇发射的,所以应该由水雷潜艇产生,即水雷对象的生成被放在了水雷潜艇类中。炸弹是由战舰发射的,所以应该由战舰产生,即战舰对象的生成被放在了战舰类中)
  • 画窗口被放在了main方法中,又由于main方法是静态方法,无法访问实例变量(定义出来的各个对象),所以我们设置了一个启动程序执行的方法。在这个方法中分为定时需要调用的方法和由键盘监听器控制调用的方法。
  • 需要定时调用的方法包括
    1.生成潜艇对象
    2.生成水雷对象(由于潜艇的产生是由窗口产生的,炸弹是由战舰发射的,均是只有一个。只有水雷是由水雷潜艇发射的,水雷潜艇不止一个,所以需要遍历潜艇数组。但潜艇数组中不是只有水雷潜艇,发射水雷的行为是水雷潜艇所特有的,因此将潜艇数组中的水雷潜艇向下造型,让其可以使用自己特有的方法。注意:这里不能一来就把潜艇数组中的都强转为水雷潜艇,里面的鱼雷潜艇和侦察潜艇与水雷潜艇是无关的,会报类型转换异常错误。)
    3.潜艇、水雷、炸弹的移动
    4.炸弹与潜艇的碰撞(碰撞是所有对象都有的行为,并且碰撞的方式都是一样的,所以写在超类中。碰撞产生时,应该有两个对象。碰撞这个行为,就是只要是接触到,就为碰撞。所以给定一个范围,只要进入这个范围就可以识别为碰撞。)
    5.水雷与战舰的碰撞
    6.删除越界或死亡的潜艇、水雷、炸弹对象(此处需要时时检测对象的行为,一旦检测到越界或者死亡,就将数组中的该对象删除掉,减轻内存压力。由于检测行为是共有的,所以写在超类中。检测行为各有各的不同,但因为三种潜艇的检测行为是相同的,所以不写成抽象,水雷和炸弹的检测行为方法重写即可。)
    7.检测游戏结束
    8.重新画所有对象(对象要动起来,就需要定时重画所有对象,在一定时间范围内不停重画,就可以肉眼看到潜艇的移动,水雷和炸弹的发射。)
    注意:定时调用的方法,会每10毫秒就全部调用一次。但10毫秒的时间太快,因此为避免产生过多潜艇和水雷对象,所以在生成对象时,会设置一个变量进行控制。
  • 键盘监听的方法包括:
    1.战舰的移动(战舰的移动是由键盘控制的,当监听到键盘的左右键被操作,就相应的更改x坐标即可。同理,战舰肉眼上的移动来源于每10毫秒重画所有对象。)
    2.发射炸弹(当监听到键盘有操作且按下的是空格时,就会产生炸弹对象,并将炸弹存入炸弹数组中。由于每10毫秒就会重画一次所有对象,所以炸弹也就可以随之产生出现。)
package cn.tedu.submarine;import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Arrays;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;public class World extends JPanel{//整个游戏世界public static final int WIDTH = 641;  //窗口的宽public static final int HEIGHT = 479; //窗口的高public static final int RUNNING = 0; //运行状态public static final int GAME_OVER = 1; //游戏结束状态private int state = RUNNING;//当前状态----默认为运行状态//对象private BattleShip ship = new BattleShip(); //战舰private SeaObject[] submarines = {}; //潜艇数组private Mine[] mines = {}; //水雷数组private Bomb[] bombs = {}; // 炸弹数组//生成潜艇对象(侦查潜艇、鱼雷潜艇、水雷潜艇)public SeaObject nextSubmarine(){Random rd = new Random();int type = rd.nextInt(20); //0-19  数字大一些,概率可以控制if(type<10){ //0-9return new ObserveSubmarine();}else if(type<15){ //10-14return new TorpedoSubmarine();}else{ //15-19return new MineSubmarine();}}//潜艇入场private int subEnterIndex = 0;public void submarineEnterAction(){ //每10毫秒被调用一次这个方法subEnterIndex++; //每10毫秒增1if(subEnterIndex%40==0){ //用于控制时间,避免短时间产生太多对象//400毫秒走一次SeaObject object=nextSubmarine(); //生成潜艇对象submarines = Arrays.copyOf(submarines,submarines.length+1); //扩容submarines[submarines.length-1] = object;}}//水雷入场private int mineEnterIndex = 0;public void mineEnterAction(){ //每10毫秒被调用一次mineEnterIndex++; //每10毫秒增1if(mineEnterIndex%100==0){ //每1000毫秒发射一次for (int i = 0; i < submarines.length; i++) {if(submarines[i] instanceof MineSubmarine){MineSubmarine ms = (MineSubmarine)submarines[i];Mine m = ms.shootMine();mines = Arrays.copyOf(mines,mines.length+1);mines[mines.length-1] = m;}}}}//海洋对象移动public void moveAction(){//每10毫秒被调用一次for (int i = 0; i < submarines.length; i++) {submarines[i].move();}for (int i = 0; i < mines.length; i++) {mines[i].move();}for (int i = 0; i < bombs.length; i++) {bombs[i].move();}}//删除越界的海洋对象public void outOfBoundsAction(){ //每10毫秒调用一次for (int i = 0; i <submarines.length ; i++) {if(submarines[i].isOutOfBounds() || submarines[i].isDead()){  //判断是否越界或者潜艇已死submarines[i]=submarines[submarines.length-1]; //将越界潜艇替换成最后一个元素submarines = Arrays.copyOf(submarines,submarines.length-1); //把最后一个元素删除}}for (int i = 0; i < bombs.length; i++) {if(bombs[i].isOutOfBounds() || bombs[i].isDead()){ //越界或死亡bombs[i]=bombs[bombs.length-1];bombs = Arrays.copyOf(bombs,bombs.length-1);}}for (int i = 0; i < mines.length; i++) {if(mines[i].isOutOfBounds() || mines[i].isDead()){ //越界或死亡mines[i]=mines[mines.length-1];mines = Arrays.copyOf(mines,mines.length-1);}}}private int score = 0;public void bombBangAction(){//每10毫秒被调用一次for (int i = 0; i < bombs.length; i++) { //遍历炸弹数组Bomb b = bombs[i]; //获取每个炸弹for (int j = 0; j < submarines.length ; j++) {  //遍历潜艇数组SeaObject s = submarines[j]; //获取每个潜艇if(b.isLive() && s.isLive() && s.isHit(b)){ //判断是否都活着并且碰撞s.goDead();b.goDead();if(s instanceof EnemyScore){//ObserveSubmarine和TorpedoSubmarine均实现了EnemyScore接口EnemyScore es = (EnemyScore)s; //向下造型score += es.getScore();}if(s instanceof EnemyLife){EnemyLife el = (EnemyLife)s;int num = el.getLife();ship.addLife(num); //由于life变量是私有的,所以不能直接加,需要通过方法调用。}}}}}//水雷与战舰的碰撞public void mineBangAction(){ //每10毫秒被调用一次for (int i = 0; i <mines.length ; i++) {Mine m = mines[i];if(m.isLive() && ship.isLive() && m.isHit(ship)){m.goDead();ship.subtractLife();}}}//检测游戏结束public void checkGameOverAction(){ //每10毫秒被调用一次if(ship.getLife()<=0){ //若战舰的命数小于等于0,表示游戏结束state = GAME_OVER; //将当前状态修改为GAME_OVER状态}}//启动程序执行(由于main方法是静态的,无法调用非静态资源,所以创建了一个普通方法action用于控制操作)public void action(){Timer timer = new Timer();//定时器对象int interval = 10; //定时间隔(以毫秒为单位)//定时计划timer.schedule(new TimerTask() { //TimerTask是抽象类@Overridepublic void run() { //定时干的事(每10毫米自动发生)submarineEnterAction();//潜艇入场mineEnterAction(); //水雷入场moveAction();outOfBoundsAction(); //删除越界的海洋对象//System.out.println("潜艇:"+submarines.length+" 水雷:"+mines.length+" 炸弹:"+bombs.length);bombBangAction();//炸弹与潜艇的碰撞mineBangAction(); //水雷与战舰的碰撞checkGameOverAction(); //检测游戏结束repaint(); //重新画一次}}, interval, interval);//第一个interval表示从程序启动到第一次出发的间隔,第二个interval表示后续每次出发间隔(以毫秒为单位)KeyAdapter key = new KeyAdapter() {@Override //重写keyReleased()案件抬起事件public void keyReleased(KeyEvent e) { //当按键抬起时会自动触发if(e.getKeyCode()==KeyEvent.VK_SPACE){ //若按下的是空格键Bomb b = ship.shoot(); // 获取炸弹对象bombs = Arrays.copyOf(bombs,bombs.length+1);bombs[bombs.length-1] = b;}if(e.getKeyCode()==KeyEvent.VK_LEFT){ship.moveLeft();}if(e.getKeyCode()==KeyEvent.VK_RIGHT){ship.moveRight();}}};this.addKeyListener(key);}//重写paint()方法public void paint(Graphics g){ //每10毫秒调用一次switch (state) { //根据当前状态做不同的处理case GAME_OVER: //游戏结束时,画结束图Images.gameover.paintIcon(null,g,0,0); //游戏结束图break;case RUNNING: //运行状态时,画海洋图、对象、分和命Images.sea.paintIcon(null, g, 0, 0); //画海洋图ship.paintImage(g); //画战舰for (int i = 0; i < submarines.length; i++) { //画潜艇submarines[i].paintImage(g);}for (int i = 0; i < mines.length; i++) { //画水雷mines[i].paintImage(g);}for (int i = 0; i < bombs.length; i++) { //画炸弹bombs[i].paintImage(g);}g.drawString("SCORE:" + score, 200, 50);g.drawString("LIFE:" + ship.getLife(), 400, 50);}}public static void main(String[] args) {JFrame frame = new JFrame();World world = new World();world.setFocusable(true);frame.add(world);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(WIDTH+16,HEIGHT+39);frame.setLocationRelativeTo(null);frame.setVisible(true);  //调用paint方法world.action();}
}

测试:运行World

更多推荐

潜艇小游戏

本文发布于:2023-06-28 04:07:35,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/921523.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:小游戏   潜艇

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!