类似金山打字的窗口打字游戏代码版--注释很多,不用讲解

本游戏兴之所起就写了几个夜,不咋地,都是自己太辣鸡

四个类,什么封装、对象也没用到,实现东西不多,代码也很少

1.主程序测试实现类:DemoTest

import javax.swing.*;

public class DemoTest {

    public static void main(String[] args) {

       //加入 while (),使程序可以失败后再次开始,不建议在这里面加,程序会很乱
        while (true) {
            if (MyPanel.rebuild == 0) {
                MyPanel.rebuild = 1;

                //创建一个窗口
                JFrame frame = new JFrame();
                //加个窗体名字
                frame.setTitle("打字游戏");
                //设置窗口的大小(先设置大小,再写居中操作,否则会出现右偏移)
                frame.setSize(1000, 800);
                //实现窗口居中
                frame.setLocationRelativeTo(null);

                //新增,点击叉号强制关闭程序,因为会有线程未结束导致控制台程序一直运行不结束
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                //新建画布对象
                MyPanel myPanel = new MyPanel();
                //将画布对象添加至窗体中
                frame.add(myPanel);

                //注册键盘事件,在Mypanel中重写方法
                frame.addKeyListener(myPanel);
                myPanel.addKeyListener(myPanel);

                //加入线程,把画布元素放入线程
                Thread thread = new Thread(myPanel);
                //运行线程
                thread.start();

                //窗口的可视化
                frame.setVisible(true);
            }
        }
    }
}

2.主要方法设计类:MyPanel

import javax.imageio.ImageIO;
import javax.swing.*;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.text.NumberFormat;

//继承面板类
public class MyPanel extends JPanel implements Runnable, KeyListener {

    //新建需要的图像对象
    private BufferedImage bg, start_img, gameover;

    private AddBackgroundImage ground1;
    private AddBackgroundImage ground2;
    private AddBackgroundImage ground3;

    //设置音乐全局变量,这样引入音乐类不会出现问题,否则不小心搞进线程里面
    // 轻则音乐播放异常,重则程序加电脑一起拜拜
    private AudioClip audioClip=null;

     //添加容器放随机数
    private char[] chars=new char[10];
    private int[] x=new int[10];
    private int[] y=new int[10];

    //新增字母颜色容器
    Color[] color=new Color[10];

    //加入积分器,初始0,成功加分
    int score=0;
    //加入生命,初始为10,失败结束游戏
    int error=10;

    //加入键入次数和键入消除成功次数变量
    double key1=0;
    volatile double key2=0;
    //加入键入正确率变量
    String errortype=null;

    //开启和暂停按钮 以及重新开始游戏按钮
    private static boolean open=false;
    private static boolean pause=false;
    static volatile int  rebuild=0;

    //重载方法
    public  MyPanel() {

            try {
                //引入AudioClip音乐类,添加音乐文件,使用play()方法播放
                //因为加载原因,刚开始会有个空白期,文件越大,加载越慢,而且会卡,慎用
                audioClip = Addmusic.loadSound("src/music/bgmusic1.mp3");
                //音乐播放
                audioClip.play();
                //这是不进入游戏时的音乐循环
                //音乐循环
                audioClip.loop();

                //加载运动图片
                ground1 = new AddBackgroundImage("src/images/ground1.png");
                ground2 = new AddBackgroundImage("src/images/ground23.jpg");
                ground3 = new AddBackgroundImage("src/images/ground3.jpg");

                //加载背景图片
                //图片加载方式对于一些ps或者电脑画图出来的图会报异常,加上绝对路径或者把src加上就行.
                /* bg=ImageIO.read(new File("images/bg2.png"));*/

                //背景会被运动图片覆盖,可以调整放置位置或者不用
                bg = ImageIO.read(new File("src/images/start.jpg"));

            /*//加载开始图片
            start_img=ImageIO.read(new File("images/start2.png"));*/
                //加载结束图片
                gameover = ImageIO.read(new File("src/images/gameover.png"));
            } catch (IOException e) {
                e.printStackTrace();
            }

            //遍历生成随机数十次
            for (int i = 0; i < 10; i++) {
                chars[i] = (char) (Math.random() * 26 + 97);
                x[i] = 10 + (int) (Math.random() * 970);
                y[i] = 50 + (int) (Math.random() * 300);

                //连接随机颜色方法为每个索引生成随机颜色
                color[i] = getrandomColor();

            }
        }

        /*
         * 重写print方法添加画板元素*/
        @Override
        public void paint (Graphics g) {
                if (!open) {
                    super.paint(g);
                    //在画笔中添加图像 (图像对象,x坐标,y坐标,通知对象)(被运动图像覆盖显示不出来)
                    g.drawImage(bg, 0, 0, null);
                }

                //设置条件,错误数大于0可以开始游戏
                if (error > 0 && open) {
                    //看资料说这个就是清除刷新闪烁问题的关键代码
                    super.paint(g);

                    //在画笔中添加图像 (图像对象,x坐标,y坐标,通知对象)(被运动图像覆盖显示不出来)
                    g.drawImage(bg, 0, 0, null);

                    if (score < 500) {

                        //加入模式字体颜色背景
                        mode(g, ground1);
                        //在窗口绘制成绩
                        g.drawString("智障模式", 800, 40);
                    }
                    if (score >= 500 && score < 1200) {

                        //加入模式字体颜色背景
                        mode(g, ground2);
                        //在窗口绘制成绩
                        g.drawString("菜鸡模式", 800, 40);
                    }
                    if (score >= 1200) {
                        //加入模式字体颜色背景
                        mode(g, ground3);
                        //在窗口绘制成绩
                        g.drawString("正常模式", 800, 40);
                    }

                    //设置积分颜色
                    g.setColor(Color.red);
                    //新增成绩显示在屏幕上以及字体和大小
                    g.setFont(new Font("华文新魏", Font.PLAIN, 20));
                    //在窗口绘制成绩
                    g.drawString("你的成绩为:" + score, 10, 20);
                    g.drawString("你还可以错:" + error + "个", 10, 50);

                    //设置元素的颜色,(放在前面,要不然第一次生成的字母没颜色) //新增添加随机色,在下面循环里
                    /*g.setColor(Color.BLUE);*/

                    for (int i = 0; i < 10; i++) {
                        //有了索引,就把他放进循环里去
                        g.setColor(color[i]);

                        //加一个显示的字母大小
                        g.setFont(new Font("TimesRoman", Font.PLAIN, 25));

                        //添加元素  出现的元素,元素的x轴,元素的y轴
                        // (char)random()*26+97就是转成ascll码是这个随机数的字符
                        //(int)(Math.random()*1000)生成随机数时候,(随机数小括号括起来,不然强转整形失败,只会是0)
                        //x,y值加点数放置是因为窗口有边缘.防止超界覆盖
                        g.drawString(new Character(chars[i]).toString().toUpperCase(), x[i], y[i]);
                    }
                }
                if (error <= 0) {
                    //成绩小于零重绘界面
                    removeAll();
                    //设置失败结束背景
                    g.drawImage(gameover, 0, 0, null);

                    //设置结束积分颜色
                    g.setColor(Color.red);

                    //新增成绩显示在屏幕上以及字体和大小
                    g.setFont(new Font("TimesRoman", Font.PLAIN, 30));

                    //在窗口绘制成绩
                    g.drawString("成绩为" + score + ",输了,败狗", 340, 300);
                    g.drawString("键入正确率为:"+errortype+"%" , 300, 340);

                    //错误数为0的时候音乐停止(自己改写时候可以在这里面加一个失败后的音乐)
                    audioClip.stop();

                }
            }
        //重写线程方法
        @Override
        public void run () {
            //线程运行时也使音乐循环
            //音乐循环
            audioClip.loop();

            //使用synchronized锁实现线程等待和唤醒,安全有保险
            synchronized (MyPanel.class) {
                  //根据成绩大于0循环
                while (score >= 0 & score < 500 & error > 0) {

                    //运动图片在x轴方法中运动
                    ground1.step1();

                    for (int i = 0; i < 10; i++) {

                        //每个y轴默认不断递增1,向下走
                        y[i] +=1;
                        //重绘窗口
                        Rebuild(i);

                        //加入暂停和开始方法
                        PauseAndOpen();
                    }
                    while (score >= 500 & score <= 1200 && error > 0) {
                        //运动图片在方法中运动
                        ground2.step2();

                        for (int i = 0; i < 10; i++) {

                            //每个y轴默认不断递增1,向下走
                            y[i] += 3;
                            //重绘窗口
                            Rebuild(i);

                            //加入暂停和开始方法
                            PauseAndOpen();
                        }
                    }

                    while (score >= 1200 && error > 0) {
                        //运动图片在方法中运动
                        ground3.step2();

                        for (int i = 0; i < 10; i++) {

                            //每个y轴默认不断递增1,向下走
                            y[i] += 5;

                            //重新生成索引元素的方法
                            Rebuild(i);

                            //加入暂停和开始方法
                            PauseAndOpen();
                        }
                    }
                }
                //待写消除窗口上全部画布信息
            }
        }

        //抽取出来的 重新生成索引元素的方法
        private void Rebuild ( int i){
            //重绘窗口
            repaint();
            //窗口超界重新生成
            if (y[i] > 780) {
                //i索引y轴归零
                y[i] = 0;
                //i索引重新生成字母
                chars[i] = (char) (Math.random() * 26 + 97);
                //i索引重新生成x轴,这样可以让他从最顶端出来
                x[i] = 10 + (int) (Math.random() * 1000);
                /*y[i]=50+(int)(Math.random()*300);*/
                //超界就减分
                error -= 1;
            }
            try {
                //暂停2秒,生成新的元素,抛出异常
                Thread.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //抽取出来的  开始暂停方法
        private void PauseAndOpen () {
            if (pause) {
                try {
                    MyPanel.class.wait(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (!pause) {
                synchronized (MyPanel.class) {
                    MyPanel.class.notifyAll();
                }
            }
        }

        //抽取出来的 加入字体颜色背景的方法
        private void mode (Graphics g, AddBackgroundImage ground){
            g.drawImage(ground.image, ground.x, ground.y, null);
            g.setColor(Color.blue);
            //新增显示在屏幕上以及字体和大小
            g.setFont(new Font("华文新魏", Font.PLAIN, 30));
        }


        //键盘录入    e.getKeyChar()就是你按得键的值
        @Override
        public void keyTyped (KeyEvent e){
            //获取输入的键值
            char keyChar = e.getKeyChar();

            //只要键入就增加变量
            if (keyChar !=0&&keyChar!=32) {
                key1++;
                System.out.println("键入次数"+key1);
            }

            //存储最下面字母的值,避免出现一次消除完画布上相同字母
            int below = -1;
            //存储最下面字母索引
            int belowindex = -1;

            //遍历复制一份
            for (int i = 0; i < 10; i++) {
                //如果输入的值等于生成的字母
                if (keyChar == chars[i]) {
                    //y[i]初始必大于-1;获取值和索引
                    if (y[i] > below) {
                        below = y[i];
                        belowindex = i;
                    }
                }
            }

            //根据belowindex,如果匹配刷新最下面元素
            if (belowindex != -1) {
                //最下面i索引y轴归零
                y[belowindex] = 0;
                //最下面i索引重新生成字母
                chars[belowindex] = (char) (Math.random() * 26 + 97);
                //最下面i索引消除,重新生成x轴从最上面落下
                x[belowindex] = 10 + (int) (Math.random() * 1000);

                //y轴用不到,如果想要直接在屏幕上随机生成,不是最上面落下可以生成的y轴
                /* y[i] = 50 + (int) (Math.random() * 300);*/
                //成功就加分
                score += 20;
                //键入成功变量
                key2++;
                System.out.println("键入成功次数"+key2);
            }

            //这个是键入的和键入正确的一个对比,判定键入正确率,看是不是乱敲
            if ((key1+key2)!=0){
                // 创建一个数值格式化对象
                NumberFormat numberFormat = NumberFormat.getInstance();
                // 设置精确到小数点后2位
                numberFormat.setMaximumFractionDigits(2);
                errortype = numberFormat.format((key2/key1 )* 100.00);
            }else {
                errortype="为什么打开不玩,渣男  0";
            }


        }

        @Override
        public void keyPressed (KeyEvent e){
            //键盘按压事件,触发开始暂停
            int action = e.getKeyCode();
            switch (action) {
                case 32:
                    //32,码为空格键
                    open = (!open);
                    System.out.println("open" + open);
                    break;
                    //10,码为enter键
                case 10:
                    pause = (!pause);
                    System.out.println("passe" + pause);
                    break;
                    //16,码为esc退出键
                case 27:
                    rebuild=0;
                    System.out.println("重置键"+rebuild);
            }
        }

        @Override
        public void keyReleased (KeyEvent e){

        }

        //添加一个生成随机r,g,b三原色的方法,必须是静态的,其他方法可调用,返回值为color类型
        public static Color getrandomColor () {
            //r,g,b三原色范围都是在255以内;
            int r, g, b;
            //取155之内,因为色值越小颜色越深,区别于背景
            r = (int) (Math.random() *155);
            g = (int) (Math.random() * 155);
            b = (int) (Math.random() * 155);
            Color color = new Color(r, g, b);
            return color;
        }
}

3.背景图片移动类(还不如放第二个里面呢,多余):AddBackgroundImage

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class AddBackgroundImage{
    //加载图像的对象
    BufferedImage image;
    int x;
    int y;
    public AddBackgroundImage (String file){
        //定义x,y轴起始方向
        x=0;
        y=0;
        //读取图像
        try {
            image= ImageIO.read(new File(file));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //写地面运动的方法,x轴移动
    public void step1(){
        x--;
        //为了保证地面重复运动我们增加判断,因为我的背景图长2000像素,减去占用的1000窗口
        //所以-1000重置刚好接上
        if (x==-1000) {
            x=0;
        }
    }
    //写地面运动的方法,y轴移动
    public void step2(){
        y--;
        //y轴-800重置刚好接上
        if (y==-800) {
            y=0;
        }
    }
}

4.背景音乐类(同3所述):Addmusic

import javax.swing.*;
import java.applet.AudioClip;
import java.net.MalformedURLException;
import java.net.URL;

public class Addmusic {
    //创建静态返回值为AudioClip音乐类的方法
    public static AudioClip loadSound(String filename) {

        //设置播放地址是URl形式
        URL url = null;
        try {
            url = new URL("file:" + filename);
        }
        catch (MalformedURLException e) {}
        //return一下AudioClip音乐类等待调用,可传输播放的格式mp3,wav都可以
        return JApplet.newAudioClip(url);
    }
}

改写牛点吧朋友们!!!!!!!!!然后教我(* 。*)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值