기능 요구 사항: 2048의 기본 인터페이스는 2048의 게임 기능을 실현할 수 있습니다.
일반 아이디어: 두 가지 클래스: Game 및 GameListener.
게임은 인터페이스 구현과 페인트 메서드 다시 작성을 담당합니다.
GameListener는 키보드 및 마우스 이벤트 처리 구현을 담당합니다. 이동방식, 덧셈방식, 승패판정, 난수의 출현 등은 키보드 모니터링 방식으로 구현되어야 한다.
구현 분석: 2048 게임을 구현하려면 먼저 2048에 무엇이 포함되는지 고려해야 합니까?
인터페이스 구현:
2048의 게임 인터페이스는 매우 간단하며 일부 사각형과 숫자만 있습니다. 이러한 인터페이스를 구현하기 위해 Java의 그리기 기능을 사용하는 것을 고려할 수 있습니다. 특히 JFrame 클래스에서 제공하는 Graphics 개체를 사용하여 그림을 그립니다. 2048 인터페이스는 큰 직사각형 배경과 숫자가 포함된 많은 작은 정사각형으로 구성됩니다. Graphics 개체의 그리기 방법을 사용하면 배경 및 작은 사각형 그리기를 구현할 수 있습니다. 작은 사각형의 숫자는 그래픽의 drawString 메서드를 사용하여 그릴 수 있습니다. 그릴 때 색상에주의하십시오. 인터페이스 구현에 필요한 주요 클래스는 JFrame 클래스입니다.
기본 인터페이스 구현 코드는 버튼 몇 개 정도일 뿐이라 별로 할 말이 없습니다.
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); }
사각형과 숫자 그리기:
정사각형과 숫자 그리기도 JFrame 캔버스 개체의 직사각형 그리기 방법을 사용하여 구현됩니다.
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方法中,不断的重绘会使得界面一直在闪烁。这里的解决方案就是使用图片缓冲,先在图片中绘制好,在把图片一次性绘制出来,这样就不会出现界面的闪烁问题了。
이동 구현:
그리드를 이동시키려는 경우 고려할 수 있는 방법은 아트보드 다시 그리기를 사용하는 것입니다. 사각형 안의 숫자는 2차원 배열로 저장됩니다. 배열을 이동할 때마다 배열의 값이 변경되도록 두고 배열의 값에 따라 인터페이스에 데이터를 그립니다. 물론 게임을 할 때 우리는 생각만으로 게임을 제어할 수는 없습니다. 입력 장치, 즉 키보드가 필요합니다. 따라서 인터페이스에 키보드 모니터링을 추가해야 합니다. 사용자가 다른 키를 누르면 다른 이동 알고리즘이 구현됩니다. 청취 클래스에서 해당 이동 알고리즘을 작성할 때 루프의 사용과 끝(특히 break 문의 사용)을 명확히 해야 한다는 점은 주목할 가치가 있습니다. 그렇지 않으면 다양한 버그가 나타납니다. 모바일 구현에는 keyListener 클래스를 사용해야 합니다.
다음은 위쪽 이동의 구현입니다. 다른 방향의 이동도 비슷합니다.<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>이중 레이어 루프를 통해 각 값이 0이면 루프를 돌립니다. , 올라갈 수 있습니다. 값이 있는 열을 순회하여 0이 아닌 첫 번째 값을 찾아 이 값을 이동합니다(즉, 두 숫자의 값을 교환합니다). 이동 후 내부 루프를 종료하고 다음 값을 계속 탐색합니다.
숫자 추가:
독립적인 알고리즘을 사용하여 배열을 탐색하고 이동 방향으로 인접한 두 숫자를 추가한 다음 하나를 0으로 설정합니다. 여기서 알고리즘 구현은 이동 알고리즘과 매우 유사하며 주의가 필요한 것은 중단 및 루프를 사용하는 것입니다. 또 한 가지 주의할 점은 숫자를 이동하기 전에 숫자 추가를 완료해야 한다는 것입니다. 그렇지 않으면 이동 후 숫자에 공백이 생길 수 있습니다.
<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>또한 배열의 각 값을 순회합니다. 이 값이 0이 아닌 경우 행에서 인접한
의 인접한 두 값이 다른 경우 도 가장 안쪽 루프를 종료합니다. 두 개의 break 문을 사용하면 숫자 사이의 점프와 추가를 방지할 수 있습니다. 승패 판단 :
2048의 승리 법칙은 추가된 숫자가 2048로 나오므로 배열에 2048과 같은 숫자가 있는지만 확인하면 됩니다. 그렇다면 해당하는 숫자는 당첨정보가 출력됩니다.
2048의 패배 규칙은 인터페이스가 가득 찼다는 것입니다(어레이가 가득 차고 추가할 이동 번호가 없습니다). 내 개인적인 판단 방법은 전역 변수 개수를 추가하여 배열이 가득 찼는지 확인하는 것입니다. count가 0이면 이동 및 추가를 할 수 없다는 의미이며, 배열이 가득 차면 플레이어가 패한 것으로 판단할 수 있습니다.
난수의 출현:
난수의 출현 조건은 이동 또는 덧셈이므로 개수를 판단에 사용합니다. 조건이 성립되면 해당 알고리즘이 호출됩니다.
위 내용은 Java 버전 2048에 구현된 게임 기능의 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!