Java:基于Swing框架的小游戏《2048》开发过程

一,游戏的底层逻辑

游戏规则:

        每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方随机生成一个数字方块,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。

思路:

        游戏的逻辑特别简单,只有接收随机生成方块,用户输入,方块向一个方向靠拢,方块相撞4个主要功能,我们可以先在控制台把逻辑实现。

1,新建项目
    private static int[][] maps=new int[4][4];//储存游戏信息

    public static void main(String[] args) throws InterruptedException {

    }

    //将游戏信息输出到控制台
    public static void creatMap() {
        for (int i = 0; i < maps.length; i++) {
            for (int j = 0; j < maps.length; j++) {
                System.out.print("[" + String.format("%3d ", maps[i][j]) + "]");
            }
            System.out.println();
        }
        System.out.println();
    }
2,随机生成方块
    public static void newNum() throws InterruptedException {
        Random ran = new Random();
        int x, y;
        boolean flag = false;
        
        //用来检测能不能生成方块
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (maps[i][j] == 0)
                    flag = true;//遍历数组,如果有元素为0,说明还有空位
            }
        }
        if (!flag){//如果flag没有改变,说明没有空位,输出游戏结束提示语
            System.out.println("游戏结束!");
            sleep(2000);
            System.exit(0);            
        }
        
        do {
            int a = ran.nextInt(16);//随机生成一个数用来确定位置
            x = a / 4;
            y = a % 4;
        } while (maps[x][y] != 0);//如果位置上没有元素则选中这个位置
        maps[x][y] = (ran.nextInt(2) + 1) * 2;//在选中的位置上随机生成一个新数,新数为2或者4
    }
3,方块靠拢

        这里只写了一个方向的方法,其他方向的方法以此类推,这里使用了三个循环,但是因为数组的大小是确定的,所以实际循环次数并不高,不用担心时间复杂度。

    private static void moveUp() {
        for (int i = 0; i < 4; i++) {//向上移动最外层循环是列号
            for (int j = 3; j > 0; j--) {
                for (int k = 0; k < j; k++) {
                    //通过冒泡排序的逻辑把0全放到下面去
                    if (maps[k][i] == 0 && maps[k + 1][i] != 0) {
                        int temp = maps[k][i];
                        maps[k][i] = maps[k + 1][i];
                        maps[k + 1][i] = temp;
                    }
                }
            }
        }
    }
4,方块相撞
    private static void mergeUp() {
        moveUp();//进来前先把元素靠拢到上面
        for (int i = 0; i < 4; i++) {//向上合并最外层循环为列号
            for (int j = 0; j < 3; j++) {
                //检测相邻元素是否相等,相等则合并
                if (maps[j][i] == maps[j + 1][i] && maps[j][i] != 0) {
                    maps[j][i] *= 2;
                    maps[j + 1][i] = 0;
                }
            }
        }
        moveUp();//把合并出来的空位填满
    }
5,用户输入

        这里我们暂时先用直接在控制台输入wasd的方式来控制游戏。

    public static void mergeNum(char c) throws InterruptedException {
        switch (c) {
            case 'w':
                mergeUp();
                break;
            case 's':
                mergeDown();
                break;
            case 'a':
                mergeLeft();
                break;
            case 'd':
                mergeRight();
                break;
            default:
        }
        newNum();//每次用户操作完之后生成新数字
        creatMap();//重新生成游戏信息
    }
测试:

         游戏的底层逻辑写好了,测试一下没有发现问题。

二,JFrame窗口和JPanel画板

1,JFrame的基本设置

        让当前类继承JFrame类,设置一下初始属性,不用全部都设置

public class Frame extends JFrame {//继承JFrame

    int[][] maps=new int[4][4];

    public Frame() throws InterruptedException {
        this.setTitle("genshin");//标题
        this.setSize(494,517);//大小
        this.setResizable(false);//能否改变大小
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出方式
        //左上角和应用栏的图标
        this.setIconImage(new ImageIcon("C:\\dev\\work\\JavaStudy\\game\\src\\com\\lzy\\resources\\icon1.png").getImage());
        this.setVisible(true);//能否显示
        this.setLocation(500,200);//初始在屏幕上的位置
//        this.setAlwaysOnTop(true);//总是在最上面
//        this.setEnabled(false);//能不能操作
    }
}
2,JPanel面板
public class Panel extends JPanel {
    private int maps[][];

    public int[][] getMaps() {
        return maps;
    }

    public void setMaps(int[][] maps) {
        this.maps = maps;
    }

    public void paint(Graphics g){//重写JPanel的paint方法
        super.paint(g);//调用

        //drawImage方法可以生成图片
        g.drawImage(new ImageIcon("C:\\dev\\work\\JavaStudy\\game\\src\\com\\lzy\\resources\\bg.jpg").getImage(),0,0,480,480,null);
    }
}

在Frame类中add一下Panel就可以生成图片了

3,绘制游戏画面

           需要写在Panel类里面,通过重写的paint方法调用这个方法。

    public void creatGame(Graphics g){
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                //每隔120像素画一个100*100像素的颜色块,颜色根据maps中的数字自动生成
                g.drawImage(image,i*120,j*120,100,100,newColor(maps[j][i]),null);

                if (maps[j][i]!=0)//如果元素不为0的话也输出出来
                g.drawString(String.valueOf(maps[j][i]),i*120+40,j*120+55);
            }
        }
    }

    public Color newColor(int a) {
        switch (a) {
            case 0:
                return null;
            case 2:
                return new Color(200,255,200, 255);
            case 4:
                return new Color(150,150,255, 255);
            case 8:
                return new Color(255,150,150, 255);
            case 16:
                return new Color(255, 251, 0, 255);
            case 32:
                return new Color(250, 118, 43, 255);
            case 64:
                return new Color(255, 36, 36, 255);
            case 128:
                return new Color(31, 255, 12);
            case 256:
                return new Color(0, 31, 255);
            case 512:
                return new Color(255, 42, 218);
            case 1024:
                return new Color(255, 15, 81);
            case 2048:
                return new Color(255, 106, 0);
            case 4096:
                return new Color(255, 255, 255);
            case 8192:
                return new Color(200,200,255, 0);
            default:
                return null;
        }
    }

         这一步完成之后我们调用一下前面写的新生成一个数字,就能得到这种效果了

4,键盘监听

        接下来我们写一个方法调用addKeyLinstener方法,添加一个键盘监听

    public void keyboard(){
        this.addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {//键盘操作时

            }

            @Override
            public void keyPressed(KeyEvent e) {//键盘按下时

            }

            @Override
            public void keyReleased(KeyEvent e) {//键盘松开时
                if (KeyEvent.VK_W == e.getKeyCode()) {
                    mergeUp();
                    newNum();
                }
                if (KeyEvent.VK_A == e.getKeyCode()) {
                    mergeLeft();
                    newNum();
                }
                if (KeyEvent.VK_S == e.getKeyCode()) {
                    mergeDown();
                    newNum();
                }
                if (KeyEvent.VK_D == e.getKeyCode()) {
                    mergeRight();
                    newNum();
                }
            }
        });
    }

 在Frame中调用一下键盘监听功能,游戏就可以玩啦!

其他:

        把这些弄懂之后可以自己深入摸索一下,比如把数字变成其他的图片就能做出《合成涩图》之类的,或者是写一些其他游戏的底层逻辑比如《扫雷》,《数独》等等。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值