Functional requirements: The basic interface of 2048 can realize the game functions of 2048.
General idea: two classes: Game and GameListener.
Game is responsible for the implementation of the interface and the rewriting of the paint method
GameListener is responsible for the processing of keyboard and mouse events. The movement method, addition method, winning and losing judgment and the appearance of random numbers must be implemented in the keyboard monitoring method.
Implementation analysis: To realize the 2048 game, you first need to consider what is in 2048?
Interface implementation:
The game interface of 2048 is very simple, just some squares and numbers. To implement such an interface, we can consider using Java's drawing function. Specifically, the Graphics object provided by the JFrame class is used for drawing. The 2048 interface consists of a large rectangular background and many small squares containing numbers. The drawing method of the Graphics object can realize the drawing of background and small squares. The numbers in the small squares can be drawn using the drawString method of graphics. Just pay attention to the colors when drawing. The main classes required for interface implementation are the JFrame classes.
The basic interface implementation code is just some buttons and the like, nothing much to say.
private void initUI() { setTitle("2048"); setDefaultCloseOperation(3); setSize(600, 700); setLocationRelativeTo(null);this.setLayout(null);//添加分数jl2 = new JLabel("分数:0"); jl2.setFont(new Font("黑体", Font.BOLD, 30)); jl2.setBounds(20, 30, 200, 50);this.add(jl2);//添加开始按钮ImageIcon start=new ImageIcon("res/start.png");//开始游戏图标,随意替换就好startJB=new JButton(start); startJB.setBounds(280, 40, 120, 30); startJB.setFocusable(false); startJB.setBorderPainted(false);//设置按钮的边框为空startJB.setFocusPainted(false); startJB.setContentAreaFilled(false);//设置按钮的边框内填充颜色 //添加退一步按钮ImageIcon back=new ImageIcon("res/backicon.png");//游戏结束图标,随意替换就好backJB=new JButton(back); backJB.setBounds(430, 40, 120, 30); backJB.setFocusable(false); backJB.setBorderPainted(false); backJB.setFocusPainted(false); backJB.setContentAreaFilled(false); this.add(startJB);this.add(backJB); setVisible(true); GameListener gl = new GameListener(this, arry, jl2,startJB,backJB); addKeyListener(gl); startJB.addActionListener(gl); backJB.addActionListener(gl); }
Drawing of squares and numbers:
Drawing of squares and numbers also uses the JFrame canvas The object's method of drawing a rectangle is implemented.
public void buffPaint(Graphics g) { Image image = createImage(600, 600); Graphics g2 = image.getGraphics(); g2.setColor(Color.LIGHT_GRAY); Graphics2D g2d = (Graphics2D) g2; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.fillRoundRect(0, 0, Draw2048.RD, Draw2048.RD, 20, 20); g2.setColor(Color.GRAY);for (int r = 0; r < arry.length; r++) {for (int c = 0; c < arry[r].length; c++) { g2.fillRect(20 + c * (Draw2048.D + Draw2048.space), 20 + r* (Draw2048.D + Draw2048.space), Draw2048.D, Draw2048.D); } }for (int r = 0; r < arry.length; r++) {for (int c = 0; c < arry[r].length; c++) {if (arry[r][c] != 0) { g2.setColor(255, 250, 240); g2.fillRect(20 + c * (Draw2048.D + Draw2048.space), 20 + r* (Draw2048.D + Draw2048.space), Draw2048.D, Draw2048.D); g2.setColor(new Color(0, 191, 255)); g2.setFont(new Font("楷体", Font.BOLD, Draw2048.FSIZE)); g2.drawString(arry[r][c] + "", 50 + c* (Draw2048.D + Draw2048.space), 90 + r* (Draw2048.D + Draw2048.space)); } } } g.drawImage(image, 50, 150, this); }
Draw2048是一个接口,里面定义了关于方格绘制的相关常量,D方格边长,space方格间间隔。RD背景大矩形的边长。使用接口的好处就是使得界面的更改(如改成5*5的格子)可以更加方便的实现,提高程序的扩展性。另外界面需要不断的更新,所以要调用paint方法不断的重绘。如果直接把这里的绘制写在paint方法中,不断的重绘会使得界面一直在闪烁。这里的解决方案就是使用图片缓冲,先在图片中绘制好,在把图片一次性绘制出来,这样就不会出现界面的闪烁问题了。
Movement implementation:
If you want to move the squares, one way to consider is to use the drawing board redraw. The numbers in the square are stored in a two-dimensional array. Just let the value of the array change every time you move it, and then draw the data to the interface based on the value of the array. Of course, when playing games, we cannot rely on our thoughts to control them. We need an input device, that is, a keyboard. Therefore, keyboard monitoring needs to be added to the interface. When the user presses different keys, different movement algorithms are implemented. It is worth noting that when writing the corresponding movement algorithm in the listening class, you must clarify the use and end of loops (especially the use of break statements) , otherwise various bugs will appear. Mobile implementation requires the use of keyListener class.
The following is the implementation of upward movement. Movement in other directions is similar. Just think about it yourself:
<span style="font-size: 16px"><span style="color: #0000ff"><span style="color: #339966">//向上移动的算法</span><br/>for</span> (<span style="color: #0000ff">int</span> r = 0; r < arry.length; r++<span style="color: #000000">) </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> c = 0; c < arry[r].length; c++<span style="color: #000000">) {</span><span style="color: #0000ff">if</span> (arry[r][c] > max)<span style="color: #008000">//</span><span style="color: #008000">找出数组最大值,用于判断玩家的方块是否达到2048</span>max =<span style="color: #000000"> arry[r][c];</span><span style="color: #0000ff">if</span> (arry[r][c] == 0<span style="color: #000000">) {</span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> r1 = r + 1; r1 < arry[c].length; r1++<span style="color: #000000">) </span><span style="color: #0000ff">if</span> (arry[r1][c] != 0<span style="color: #000000">) { arry[r][c] </span>=<span style="color: #000000"> arry[r1][c]; arry[r1][c] </span>= 0<span style="color: #000000">; count</span>++<span style="color: #000000">;<span style="color: #339966">//判断是否发生移动,并且作为输赢判断的标准之一</span></span><span style="color: #0000ff">break</span><span style="color: #000000">; } } }</span>
Through the double-layer loop, loop through each value. If it is 0, you can move up. Traverse the column where the value is located, find the first value that is not 0, and move this value (that is, exchange the values of the two numbers). After the move, exit the inner loop and continue traversing the next value.
Addition of numbers:
Use an independent algorithm to traverse the array, add two adjacent numbers in the moving direction, and then One is set to 0. The algorithm implementation here is very similar to the moving algorithm. What needs attention is also the use of break and loop. Another thing to note is that the addition of numbers must be completed before moving the numbers, otherwise there will be spaces in the numbers after the movement.
<span style="font-size: 16px"><span style="color: #0000ff"><span style="color: #339966">//向左的相加算法</span><br>for</span> (<span style="color: #0000ff">int</span> r = 0; r < arry.length; r++<span style="color: #000000">)</span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> c = 0; c < arry[r].length; c++<span style="color: #000000">)</span><span style="color: #0000ff">if</span> (arry[r][c] != 0<span style="color: #000000">)</span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> c1 = c + 1; c1 < arry[r].length; c1++<span style="color: #000000">)</span><span style="color: #0000ff">if</span> (arry[r][c] ==<span style="color: #000000"> arry[r][c1]) { arry[r][c] </span>*= 2<span style="color: #000000">; score </span>+=<span style="color: #000000"> arry[r][c]; arry[r][c1] </span>= 0<span style="color: #000000">; count</span>++<span style="color: #000000">;<span style="color: #339966">//判断是否发生相加,并作为输赢判断条件之一。</span></span><span style="color: #0000ff">break</span><span style="color: #000000">; } </span><span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (arry[r][c1] != 0<span style="color: #000000">) { </span><span style="color: #0000ff">break</span><span style="color: #000000">; }</span></span>
It also traverses each value of the array. If the value is not 0, find the location. The adjacent rows with the same value are added, ending the innermost loop. If the two adjacent values are different, also ends the innermost loop. The use of two break statements avoids jumping and adding between numbers.
Judgment of winning or losing:
The winning rule for 2048 is that when the added numbers appear 2048, you only need to determine whether there is one in the array As long as the number is equal to 2048, if so, the corresponding winning information will be output.
The losing rule for 2048 is that the interface is full (the array is full and there is no way to move the numbers added). My personal judgment method is to add the global variable count to determine whether the array is full. If count is equal to 0, it means that movement and addition cannot be performed. If the array is full, it can be judged that the player has lost.
The appearance of random numbers:
The condition for the appearance of random numbers is movement or addition, so count is used for judgment. If the condition is established, the corresponding algorithm is called.
The above is the detailed content of Examples of game functions implemented in Java version 2048. For more information, please follow other related articles on the PHP Chinese website!